update 2023-04-03 16:47:27

This commit is contained in:
github-actions[bot] 2023-04-03 16:47:27 +08:00
parent c86be0f9e7
commit 7b3dece064
29 changed files with 751 additions and 916 deletions

View File

@ -1,93 +0,0 @@
# luci-app-adguardhome
复杂的AdGuardHome的openwrt的luci界面
- 可以管理网页端口
- luci下载/更新核心版本(支持自定义链接下载)
- 如果为tar.gz文件需要与官方的文件结构一致
- 或者直接为主程序二进制
- upx 压缩核心xz依赖脚本自动下载如果opkg源无法连接请在编译时加入此包
- dns重定向
- 作为dnsmasq的上游服务器(在AGH中统计到的ip都为127.0.0.1无法统计客户端及对应调整设置ssr-plus正常)
- 重定向53端口到 AdGuardHomeipv6需要开启ipv6 nat redirect 否则如果客户端使用ipv6过滤无效不以dnsmasq为上游ssr-plus失效
- 使用53端口替换 dnsmasq(需要设置AGH的dnsip为0.0.0.0, AGH和dnsmasq的端口将被交换不以dnsmasq为上游ssr-plus失效)
- 自定义执行文件路径支持tmp每次重启后自动下载bin
- 自定义配置文件路径
- 自定义工作路径
- 自定义运行日志路径
- gfwlist 删除/添加/定义上游dns服务器 另外安利一下https://github.com/rufengsuixing/luci-app-autoipsetadder
- 修改网页登陆密码
- 倒序/正序 查看/删除/备份 每3秒更新显示运行日志 + 本地浏览器时区转换
- 手动修改配置文件
- 支持yaml编辑器
- 模板快速配置
- 系统升级保留勾选文件
- 开机启动后当网络准备好时重启adh(3分钟超时主要用于防止过滤器更新失败)
- 关机时备份勾选的工作目录中的文件须知在ipk更新的时候也会触发备份
- 计划任务(以下为默认值,时间和参数可以在计划任务中调整)
- 自动更新核心(最好谨慎使用)(3:30/天)
- 自动截短查询日志 (每小时 限制到2000行)
- 自动截短运行日志3:30/天 限制到2000行
- 自动更新ipv6主机并重启adh (每小时,无更新不重启)
- 自动更新gfw列表并重启adh 3:30/天,无更新不重启)
#### 已知问题:
- db数据库不支持放在不支持mmap的文件系统上比如 jffs2 data-stk-oo请修改工作目录本软件如果检测到jffs2会自动ln(软连接)到/tmp将会导致重启丢失dns数据库
- AdGuardHome 不支持ipset 设置在使用ipset的情况下无法替代dnsmasq只能作为dnsmasq上游存在如果你想要这个功能就去投票吧<br>
https://github.com/AdguardTeam/AdGuardHome/issues/1191
- 反馈出现大量127.0.0.1查询了localhost的请求问题出现原因是ddns插件如果不用ddns插件请删除或者注释掉\etc\hotplug.d\iface\95-ddns的内容如果还有其他来自本机的异常查询情况高级玩家可以使用kmod来查找原因https://github.com/rufengsuixing/kmod-plog-port
- 如果出现需要多次提交才有反应的现象请及时提交issue
#### 使用方法
- 下载release使用opkg安装即可
- 或者编译op时clone本项目加入软件包并勾选
#### 关于压缩
本着较真的想法我测试了在jffs2的压缩文件系统上进行upx压缩结果的内存占用与空间占用(单位kb使用最好压缩)<br>
文件大小<br>
源文件 14112 使用upx 压缩后 5309 <br>
实际占用 6260 使用upx 压缩后 5324 差值为 936<br>
VmRSS运存占用值<br>
不压缩 14380 使用upx 压缩后 18496 差值 -4116 <br>
对于压缩文件系统来说开启收益有,但不大<br>
如果是非压缩文件系统,性价比还是比较高的<br>
所以压缩是用运存空间来换rom空间觉得值得就可以开启
#### 关于ssr配合
- 方法一gfw代理dns重定向-作为dnsmasq的上游服务器
- 方法二gfw代理手动设置adh上游dns为自己即127.0.0.1:[自己监听的端口],然后使用 dns重定向-使用53端口替换dnsmasq因为端口互换后就是dnsmasq为上游了
- 方法三国外ip代理任意重定向方式adh加入gfw列表开启计划任务定时更新gfw即可
- 方法四gfw代理dns重定向-重定向53端口到AdGuardHome,设置adh上游dns 为127.0.0.1:53
#### 项目已经基本稳定有bug欢迎主动反馈
Complex openwrt AdGuardHome luci
- can manage browser port
- download/update core in luci
- compress core with upx
- redirect dns
- as the upstream of dnsmasq
- redirect port 53 to AdGuardHomeipv6 need to install ipv6 nat redirect or if client use ipv6 redirect is invalid
- replace dnsmasq with port 53 (need to set AGH,dnsip=0.0.0.0,the port of dnsmasq and AGH will be exchange)
- change bin path
- change config path
- change work dir(support tmp,auto redownload after reboot)
- change runtime log path
- gfwlist query to specific dns server
- modify browser login passord
- Positive/reverse order see/del/backup runtime log which update every 3 second
- modify config manually(support yaml editor)
- use template to fast config(when no config file)
- Keep bin file and config when system upgrade (database and querylog can be choose)
- when boot wait for network access 3min timeout
- backup workdir when shutdown
#### known issues:
- db database not support filesystem which not support mmap such as jffs2 and data-stk-oo,please modify work dir,if jffs2 is found,will auto ln (soft link)the dbs to /tmp ,will lost dns database after reboot
- AdGuardhome not support ipset,when we use ipset ,it can\`t be the repacement of dnsmasq but the upstream of dnsmasq ,if you want it,vote for it.<br>
https://github.com/AdguardTeam/AdGuardHome/issues/1191<br>
- find so many localhost query from 127.0.0.1,the ddns plugin is the reason,if you don\`t use ddns, please remove or comment \etc\hotplug.d\iface\95-ddns
#### usage
- download releaseinstall it with opkg
- or when make op,clone the code to the package path and set it as y or m
#### pic
example in zh-cn:<br>
![Screenshot_2019-12-23 newifi-d1 - 基础设置 - LuCI](https://user-images.githubusercontent.com/22387141/71361626-81d60900-25ce-11ea-91d5-ac4e35d5c41e.png)
![图片](https://user-images.githubusercontent.com/22387141/71361650-90242500-25ce-11ea-9727-9306a3da1357.png)
![Screenshot_2019-12-23 newifi-d1 - 日志 - LuCI(1)](https://user-images.githubusercontent.com/22387141/71361700-b944b580-25ce-11ea-8562-f68c28952b2b.png)
![Screenshot_2019-12-23 newifi-d1 - 手动设置 - LuCI](https://user-images.githubusercontent.com/22387141/71361704-bb0e7900-25ce-11ea-8042-6dd396607030.png)

View File

@ -0,0 +1 @@
zh-cn

View File

@ -1,299 +0,0 @@
#/cgi-bin/luci/admin/services/AdGuardHome
msgid "Base Setting"
msgstr "基础设置"
msgid "Log"
msgstr "日志"
msgid "AdGuardHome's version"
msgstr "AdGuardHome 版本"
msgid "Needed to click 'save&apply' to generate the configuration file"
msgstr "需要点击“保存并应用”才能生成配置文件"
msgid "In case of the latest realease is a source code that can not download the binary file"
msgstr "防止最新release只有源码导致下载不成功"
msgid "Manual Config"
msgstr "手动设置"
msgid "Free and open source, powerful network-wide ads & trackers blocking DNS server."
msgstr "全网络广告和跟踪程序拦截DNS服务器默认账号和密码均为admin"
msgid "RUNNING"
msgstr "运行中"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "Redirected"
msgstr "已重定向"
msgid "Not redirect"
msgstr "未重定向"
msgid "Collecting data..."
msgstr "获取数据中..."
msgid "Enable"
msgstr "启用"
msgid "Browser management port"
msgstr "网页管理账号和密码:admin ,端口:"
msgid "Upgrade Core"
msgstr "更新核心"
#button change
msgid "Update core version"
msgstr "更新核心版本"
msgid "Check..."
msgstr "检查中..."
msgid "Updated"
msgstr "已更新"
#button hide
msgid "Force update"
msgstr "强制更新核心"
msgid "Fast config"
msgstr "快速配置"
msgid "Core Version"
msgstr "核心版本"
msgid "Latest Version"
msgstr "最新版"
msgid "Beta Version"
msgstr "测试版"
msgid "Current core version:"
msgstr "当前核心版本:"
msgid "no config"
msgstr "没有配置文件"
msgid "no core"
msgstr "没有核心"
#
msgid "Redirect"
msgstr "重定向"
#inlist
msgid "none"
msgstr "无"
msgid "Run as dnsmasq upstream server"
msgstr "作为dnsmasq的上游服务器"
msgid "Redirect 53 port to AdGuardHome"
msgstr "重定向53端口到AdGuardHome"
msgid "Use port 53 replace dnsmasq"
msgstr "使用53端口替换dnsmasq"
#
msgid "AdGuardHome redirect mode"
msgstr "AdGuardHome重定向模式"
msgid "Bin Path"
msgstr "执行文件路径"
msgid "AdGuardHome Bin path if no bin will auto download"
msgstr "AdGuardHome 执行文件路径 如果没有执行文件将自动下载"
msgid "use upx to compress bin after download"
msgstr "下载后使用upx压缩执行文件"
#inlist
msgid "compress faster"
msgstr "快速压缩"
msgid "compress better"
msgstr "更好的压缩"
msgid "compress best(can be slow for big files)"
msgstr "最好的压缩(大文件可能慢)"
msgid "try all available compression methods & filters [slow]"
msgstr "尝试所有可能的压缩方法和过滤器[慢]"
msgid "try even more compression variants [very slow]"
msgstr "尝试更多变体压缩手段[很慢]"
msgid "bin use less space,but may have compatibility issues"
msgstr "减小执行文件空间占用,但是可能压缩后有兼容性问题"
#
msgid "Config Path"
msgstr "配置文件路径"
msgid "AdGuardHome config path"
msgstr "AdGuardHome 配置文件路径"
msgid "Work dir"
msgstr "工作目录"
msgid "AdGuardHome work dir include rules,audit log and database"
msgstr "AdGuardHome 工作目录包含规则,审计日志和数据库"
msgid "Runtime log file"
msgstr "运行日志路径"
msgid "AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log"
msgstr "AdGuardHome 运行日志, 如果填 syslog 将写入系统日志; 如果该项为空则不记录运行日志"
msgid "Verbose log"
msgstr "输出详细日志"
#hide div
msgid "Add gfwlist"
msgstr "添加 GFW 列表"
msgid "Add"
msgstr "添加"
msgid "Added"
msgstr "已添加"
msgid "Not added"
msgstr "未添加"
#hide div
msgid "Del gfwlist"
msgstr "删除gfw列表"
msgid "Del"
msgstr "删除"
#hide div
msgid "Gfwlist upstream dns server"
msgstr "gfw列表上游服务器"
msgid "Gfwlist domain upstream dns service"
msgstr "gfw列表域名上游服务器"
#hide div
msgid "Change browser management password"
msgstr "更改网页登录密码"
msgid "Culculate"
msgstr "计算"
##button change
msgid "Load culculate model"
msgstr "载入计算模块"
msgid "loading..."
msgstr "载入中"
msgid "Please save/apply"
msgstr "请点击[保存/应用]"
msgid "is empty"
msgstr "为空"
msgid "Press load culculate model and culculate finally save/apply"
msgstr "先输入你想要的密码, 点击[载入计算模块], 然后点击[计算], 最后点击下方[保存&应用]"
#
msgid "Keep files when system upgrade"
msgstr "系统升级时保留文件"
#checkbox
msgid "core bin"
msgstr "核心执行文件"
msgid "config file"
msgstr "配置文件"
msgid "log file"
msgstr "日志文件"
msgid "querylog.json"
msgstr "审计日志.json"
#
msgid "On boot when network ok restart"
msgstr "开机后网络准备好时重启"
msgid "Backup workdir files when shutdown"
msgstr "在关机时备份工作目录文件"
msgid "Will be restore when workdir/data is empty"
msgstr "在工作目录/data为空的时候恢复"
msgid "Backup workdir path"
msgstr "工作目录备份路径"
msgid "Crontab task"
msgstr "计划任务"
msgid "Auto update core"
msgstr "自动升级核心"
msgid "Auto tail querylog"
msgstr "自动截短查询日志"
msgid "Auto tail runtime log"
msgstr "自动截短运行日志"
msgid "Auto update ipv6 hosts and restart adh"
msgstr "自动更新ipv6主机并重启adh"
msgid "Auto update gfwlist and restart adh"
msgstr "自动更新gfw列表并重启adh"
msgid "Please change time and args in crontab"
msgstr "请在计划任务中修改时间和参数"
msgid "Core Update URL"
msgstr "核心更新地址"
#/cgi-bin/luci/admin/services/AdGuardHome/log/
msgid "reverse"
msgstr "逆序"
msgid "localtime"
msgstr "本地时间"
msgid "Please add log path in config to enable log"
msgstr "请在设置里填写日志路径以启用日志"
msgid "dellog"
msgstr "删除日志"
msgid "download log"
msgstr "下载日志"
#/cgi-bin/luci//admin/services/AdGuardHome/manual/
msgid "Use template"
msgstr "使用模板"
#hide button
msgid "Reload Config"
msgstr "重新载入配置"
msgid "WARNING!!! no bin found apply config will not be test"
msgstr "警告!!!未找到执行文件,提交配置将不会进行校验"
#unused
msgid "Change browser management username"
msgstr "改变网页登录用户名"
msgid "Username"
msgstr "用户名"
msgid "Check Config"
msgstr "检查配置"
msgid "unknown"
msgstr "未知"
msgid "Keep database when system upgrade"
msgstr "系统升级时保留数据"
msgid "Boot delay until network ok"
msgstr "开机时直到网络准备好再启动"

0
luci-app-adguardhome/root/etc/config/AdGuardHome Normal file → Executable file
View File

0
luci-app-adguardhome/root/etc/init.d/AdGuardHome Normal file → Executable file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@ -148,9 +148,15 @@
name: "<%:Visit Time%>",
type: 'pie',
center: ['35%', '50%'],
radius: ['40%', '65%'],
radius: ['58%', '70%'],
clockwise: false,
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 2,
borderColor: "#fff",
borderWidth: 1,
},
label: {
normal: {
show: true,
@ -249,9 +255,14 @@
name: "<%:Visit Time%>",
type: 'pie',
center: ['35%', '50%'],
radius: ['40%', '65%'],
radius: ['58%', '70%'],
clockwise: false,
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 2,
borderColor: "#fff",
borderWidth: 1,
},
label: {
normal: {
show: true,

View File

@ -11,7 +11,8 @@ int af_test_mode = 0;
// todo: rename af_log.c
int g_oaf_enable __read_mostly = 0;
int af_work_mode = AF_MODE_GATEWAY;
int af_lan_ip = 0;
unsigned int af_lan_ip = 0;
unsigned int af_lan_mask = 0;
/*
cat /proc/sys/oaf/debug
*/
@ -47,9 +48,16 @@ static struct ctl_table oaf_table[] = {
{
.procname = "lan_ip",
.data = &af_lan_ip,
.maxlen = sizeof(int),
.maxlen = sizeof(unsigned int),
.mode = 0666,
.proc_handler = proc_dointvec,
.proc_handler = proc_douintvec,
},
{
.procname = "lan_mask",
.data = &af_lan_mask,
.maxlen = sizeof(unsigned int),
.mode = 0666,
.proc_handler = proc_douintvec,
},
{
}

View File

@ -3,7 +3,8 @@
extern int af_log_lvl;
extern int af_test_mode;
extern int af_work_mode;
extern int af_lan_ip;
extern unsigned int af_lan_ip;
extern unsigned int af_lan_mask;
#define LOG(level, fmt, ...) do { \
if ((level) <= af_log_lvl) { \
printk(fmt, ##__VA_ARGS__); \

View File

@ -473,6 +473,8 @@ int parse_flow_proto(struct sk_buff *skb, flow_info_t *flow)
}
return -1;
}
#define MAX_HOST_LEN 32
#define MIN_HOST_LEN 4
int dpi_https_proto(flow_info_t *flow)
{
@ -500,12 +502,14 @@ int dpi_https_proto(flow_info_t *flow)
{
return -1;
}
if (p[i] == 0x0 && p[i + 1] == 0x0 && p[i + 2] == 0x0 && p[i + 3] != 0x0)
{
// 2 bytes
memcpy(&url_len, p + i + HTTPS_LEN_OFFSET, 2);
if (ntohs(url_len) <= 0 || ntohs(url_len) > data_len)
if (ntohs(url_len) <= MIN_HOST_LEN || ntohs(url_len) > data_len || ntohs(url_len) > MAX_HOST_LEN)
{
continue;
}
@ -887,7 +891,29 @@ void af_get_smac(struct sk_buff *skb, u_int8_t *smac){
else
memcpy(smac, &skb->cb[40], ETH_ALEN);
}
int is_ipv4_broadcast(uint32_t ip) {
return (ip & 0x00FFFFFF) == 0x00FFFFFF;
}
int is_ipv4_multicast(uint32_t ip) {
return (ip & 0xF0000000) == 0xE0000000;
}
int af_check_bcast_ip(flow_info_t *f)
{
if (0 == f->src || 0 == f->dst)
return 1;
if (is_ipv4_broadcast(ntohl(f->src)) || is_ipv4_broadcast(ntohl(f->dst))){
return 1;
}
if (is_ipv4_multicast(ntohl(f->src)) || is_ipv4_multicast(ntohl(f->dst))){
return 1;
}
return 0;
}
#define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *dev){
flow_info_t flow;
u_int8_t smac[ETH_ALEN];
@ -896,16 +922,24 @@ u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *
if (!skb || !dev)
return NF_ACCEPT;
if (0 == af_lan_ip || 0 == af_lan_mask)
return NF_ACCEPT;
if (dev->name && strstr(dev->name, "docker"))
return NF_ACCEPT;
memset((char *)&flow, 0x0, sizeof(flow_info_t));
if (parse_flow_proto(skb, &flow) < 0)
return NF_ACCEPT;
if (af_match_bcast_packet(&flow) || af_match_local_packet(&flow))
return NF_ACCEPT;
if (af_lan_ip == flow.src || af_lan_ip == flow.dst){
return NF_ACCEPT;
}
if (af_check_bcast_ip(&flow) || af_match_local_packet(&flow))
return NF_ACCEPT;
if ((flow.src & af_lan_mask) != (af_lan_ip & af_lan_mask)){
return NF_ACCEPT;
}
af_get_smac(skb, smac);
AF_CLIENT_LOCK_W();

View File

@ -1,4 +1,4 @@
OBJS:=appfilter_user.o appfilter_netlink.o appfilter_ubus.o appfilter_config.o main.o
OBJS:=appfilter_user.o appfilter_netlink.o appfilter_ubus.o appfilter_config.o utils.o main.o
EXEC:=oafd
all: $(OBJS)
$(CC) -o $(EXEC) $(OBJS) $(LIBS)

View File

@ -0,0 +1,7 @@
#ifndef __APPFILTER_H__
#define __APPFILTER_H__
#define MIN_INET_ADDR_LEN 7
#define CMD_GET_LAN_IP "ifconfig br-lan | grep 'inet addr' | awk '{print $2}' | awk -F: '{print $2}'"
#define CMD_GET_LAN_MASK "ifconfig br-lan | grep 'inet addr' | awk '{print $4}' | awk -F: '{print $2}'"
#endif

View File

@ -1,342 +1,352 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "appfilter_config.h"
#include <uci.h>
app_name_info_t app_name_table[MAX_SUPPORT_APP_NUM];
int g_app_count = 0;
int g_cur_class_num = 0;
char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN];
const char *config_path = "./config";
static struct uci_context *uci_ctx = NULL;
static struct uci_package *uci_appfilter;
int uci_get_int_value(struct uci_context *ctx, char *key)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = -1;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
goto done;
}
e = ptr.last;
switch(e->type) {
case UCI_TYPE_SECTION:
ret = -1;
goto done;
case UCI_TYPE_OPTION:
ret = atoi(ptr.o->v.string);
goto done;
default:
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int uci_get_value(struct uci_context *ctx, char *key, char *output, int out_len)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
ret = 1;
goto done;
}
e = ptr.last;
switch(e->type) {
case UCI_TYPE_SECTION:
snprintf(output, out_len, "%s", ptr.s->type);
break;
case UCI_TYPE_OPTION:
snprintf(output, out_len, "%s", ptr.o->v.string);
break;
default:
ret = 1;
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
//
static struct uci_package *
config_init_package(const char *config)
{
struct uci_context *ctx = uci_ctx;
struct uci_package *p = NULL;
if (!ctx)
{
ctx = uci_alloc_context();
uci_ctx = ctx;
ctx->flags &= ~UCI_FLAG_STRICT;
//if (config_path)
// uci_set_confdir(ctx, config_path);
}
else
{
p = uci_lookup_package(ctx, config);
if (p)
uci_unload(ctx, p);
}
if (uci_load(ctx, config, &p))
return NULL;
return p;
}
char *get_app_name_by_id(int id)
{
int i;
for (i = 0; i < g_app_count; i++)
{
if (id == app_name_table[i].id)
return app_name_table[i].name;
}
return "";
}
void init_app_name_table(void)
{
int count = 0;
char line_buf[2048] = {0};
FILE *fp = fopen("/tmp/feature.cfg", "r");
if (!fp)
{
printf("open file failed\n");
return;
}
while (fgets(line_buf, sizeof(line_buf), fp))
{
if (strstr(line_buf, "#"))
continue;
if (strlen(line_buf) < 10)
continue;
if (!strstr(line_buf, ":"))
continue;
char *pos1 = strstr(line_buf, ":");
char app_info_buf[128] = {0};
int app_id;
char app_name[64] = {0};
memset(app_name, 0x0, sizeof(app_name));
strncpy(app_info_buf, line_buf, pos1 - line_buf);
sscanf(app_info_buf, "%d %s", &app_id, app_name);
app_name_table[g_app_count].id = app_id;
strcpy(app_name_table[g_app_count].name, app_name);
g_app_count++;
}
fclose(fp);
}
void init_app_class_name_table(void)
{
char line_buf[2048] = {0};
int class_id;
char class_name[64] = {0};
FILE *fp = fopen("/tmp/app_class.txt", "r");
if (!fp)
{
printf("open file failed\n");
return;
}
while (fgets(line_buf, sizeof(line_buf), fp))
{
sscanf(line_buf, "%d %*s %s", &class_id, class_name);
printf("line buf = %s, class_name = %s\n", line_buf, class_name);
strcpy(CLASS_NAME_TABLE[class_id - 1], class_name);
g_cur_class_num++;
}
fclose(fp);
}
//00:00 9:1
int check_time_valid(char *t)
{
if (!t)
return 0;
if (strlen(t) < 3 || strlen(t) > 5 || (!strstr(t, ":")))
return 0;
else
return 1;
}
void dump_af_time(af_ctl_time_t *t)
{
int i;
printf("---------dump af time-------------\n");
printf("%d:%d ---->%d:%d\n", t->start.hour, t->start.min,
t->end.hour, t->end.min);
for (i = 0; i < 7; i++)
{
printf("%d ", t->days[i]);
}
printf("\n");
}
af_ctl_time_t *load_appfilter_ctl_time_config(void)
{
char start_time_str[64] = {0};
char end_time_str[64] = {0};
char start_time_str2[64] = {0};
char end_time_str2[64] = {0};
char days_str[64] = {0};
int value = 0;
int ret = 0;
af_ctl_time_t *t = NULL;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return NULL;
memset(start_time_str, 0x0, sizeof(start_time_str));
memset(end_time_str, 0x0, sizeof(end_time_str));
memset(start_time_str2, 0x0, sizeof(start_time_str2));
memset(end_time_str2, 0x0, sizeof(end_time_str2));
uci_get_value(ctx, "appfilter.time.start_time", start_time_str, sizeof(start_time_str));
uci_get_value(ctx, "appfilter.time.end_time", end_time_str, sizeof(end_time_str));
uci_get_value(ctx, "appfilter.time.start_time2", start_time_str2, sizeof(start_time_str2));
uci_get_value(ctx, "appfilter.time.end_time2", end_time_str2, sizeof(end_time_str2));
uci_get_value(ctx, "appfilter.time.days", days_str, sizeof(days_str));
t = malloc(sizeof(af_ctl_time_t));
value = uci_get_int_value(ctx, "appfilter.time.time_mode");
if (value < 0)
t->time_mode = 0;
else
t->time_mode = value;
if (check_time_valid(start_time_str) && check_time_valid(end_time_str)){
sscanf(start_time_str, "%d:%d", &t->start.hour, &t->start.min);
sscanf(end_time_str, "%d:%d", &t->end.hour, &t->end.min);
}
if (check_time_valid(start_time_str2) && check_time_valid(end_time_str2)){
sscanf(start_time_str2, "%d:%d", &t->start2.hour, &t->start2.min);
sscanf(end_time_str2, "%d:%d", &t->end2.hour, &t->end2.min);
}
char *p = strtok(days_str, " ");
if (!p)
goto EXIT;
do
{
int day = atoi(p);
if (day >= 0 && day <= 6)
t->days[day] = 1;
else
ret = 0;
} while (p = strtok(NULL, " "));
EXIT:
uci_free_context(ctx);
return t;
}
int config_get_appfilter_enable(void)
{
int enable = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return NULL;
enable = uci_get_int_value(ctx, "appfilter.global.enable");
if (enable < 0)
enable = 0;
uci_free_context(ctx);
return enable;
}
int config_get_lan_ip(char *lan_ip, int len)
{
int ret = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return -1;
ret = uci_get_value(ctx, "network.lan.ipaddr", lan_ip, len);
uci_free_context(ctx);
return ret;
}
int appfilter_config_alloc(void)
{
char *err;
uci_appfilter = config_init_package("appfilter");
if (!uci_appfilter)
{
uci_get_errorstr(uci_ctx, &err, NULL);
printf("Failed to load appfilter config (%s)\n", err);
free(err);
return -1;
}
return 0;
}
int appfilter_config_free(void)
{
if (uci_appfilter)
{
uci_unload(uci_ctx, uci_appfilter);
uci_appfilter = NULL;
}
if (uci_ctx)
{
uci_free_context(uci_ctx);
uci_ctx = NULL;
}
}
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "appfilter_config.h"
#include <uci.h>
app_name_info_t app_name_table[MAX_SUPPORT_APP_NUM];
int g_app_count = 0;
int g_cur_class_num = 0;
char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN];
const char *config_path = "./config";
static struct uci_context *uci_ctx = NULL;
static struct uci_package *uci_appfilter;
int uci_get_int_value(struct uci_context *ctx, char *key)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = -1;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
goto done;
}
e = ptr.last;
switch(e->type) {
case UCI_TYPE_SECTION:
ret = -1;
goto done;
case UCI_TYPE_OPTION:
ret = atoi(ptr.o->v.string);
goto done;
default:
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
int uci_get_value(struct uci_context *ctx, char *key, char *output, int out_len)
{
struct uci_element *e;
struct uci_ptr ptr;
int ret = UCI_OK;
int dummy;
char *parameters ;
char param_tmp[128] = {0};
strcpy(param_tmp, key);
if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) {
ret = 1;
return ret;
}
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
ctx->err = UCI_ERR_NOTFOUND;
ret = 1;
goto done;
}
e = ptr.last;
switch(e->type) {
case UCI_TYPE_SECTION:
snprintf(output, out_len, "%s", ptr.s->type);
break;
case UCI_TYPE_OPTION:
snprintf(output, out_len, "%s", ptr.o->v.string);
break;
default:
ret = 1;
break;
}
done:
if (ptr.p)
uci_unload(ctx, ptr.p);
return ret;
}
//
static struct uci_package *
config_init_package(const char *config)
{
struct uci_context *ctx = uci_ctx;
struct uci_package *p = NULL;
if (!ctx)
{
ctx = uci_alloc_context();
uci_ctx = ctx;
ctx->flags &= ~UCI_FLAG_STRICT;
//if (config_path)
// uci_set_confdir(ctx, config_path);
}
else
{
p = uci_lookup_package(ctx, config);
if (p)
uci_unload(ctx, p);
}
if (uci_load(ctx, config, &p))
return NULL;
return p;
}
char *get_app_name_by_id(int id)
{
int i;
for (i = 0; i < g_app_count; i++)
{
if (id == app_name_table[i].id)
return app_name_table[i].name;
}
return "";
}
void init_app_name_table(void)
{
int count = 0;
char line_buf[2048] = {0};
FILE *fp = fopen("/tmp/feature.cfg", "r");
if (!fp)
{
printf("open file failed\n");
return;
}
while (fgets(line_buf, sizeof(line_buf), fp))
{
if (strstr(line_buf, "#"))
continue;
if (strlen(line_buf) < 10)
continue;
if (!strstr(line_buf, ":"))
continue;
char *pos1 = strstr(line_buf, ":");
char app_info_buf[128] = {0};
int app_id;
char app_name[64] = {0};
memset(app_name, 0x0, sizeof(app_name));
strncpy(app_info_buf, line_buf, pos1 - line_buf);
sscanf(app_info_buf, "%d %s", &app_id, app_name);
app_name_table[g_app_count].id = app_id;
strcpy(app_name_table[g_app_count].name, app_name);
g_app_count++;
}
fclose(fp);
}
void init_app_class_name_table(void)
{
char line_buf[2048] = {0};
int class_id;
char class_name[64] = {0};
FILE *fp = fopen("/tmp/app_class.txt", "r");
if (!fp)
{
printf("open file failed\n");
return;
}
while (fgets(line_buf, sizeof(line_buf), fp))
{
sscanf(line_buf, "%d %*s %s", &class_id, class_name);
strcpy(CLASS_NAME_TABLE[class_id - 1], class_name);
g_cur_class_num++;
}
fclose(fp);
}
//00:00 9:1
int check_time_valid(char *t)
{
if (!t)
return 0;
if (strlen(t) < 3 || strlen(t) > 5 || (!strstr(t, ":")))
return 0;
else
return 1;
}
void dump_af_time(af_ctl_time_t *t)
{
int i;
printf("---------dump af time-------------\n");
printf("%d:%d ---->%d:%d\n", t->start.hour, t->start.min,
t->end.hour, t->end.min);
for (i = 0; i < 7; i++)
{
printf("%d ", t->days[i]);
}
printf("\n");
}
af_ctl_time_t *load_appfilter_ctl_time_config(void)
{
char start_time_str[64] = {0};
char end_time_str[64] = {0};
char start_time_str2[64] = {0};
char end_time_str2[64] = {0};
char days_str[64] = {0};
int value = 0;
int ret = 0;
af_ctl_time_t *t = NULL;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return NULL;
memset(start_time_str, 0x0, sizeof(start_time_str));
memset(end_time_str, 0x0, sizeof(end_time_str));
memset(start_time_str2, 0x0, sizeof(start_time_str2));
memset(end_time_str2, 0x0, sizeof(end_time_str2));
uci_get_value(ctx, "appfilter.time.start_time", start_time_str, sizeof(start_time_str));
uci_get_value(ctx, "appfilter.time.end_time", end_time_str, sizeof(end_time_str));
uci_get_value(ctx, "appfilter.time.start_time2", start_time_str2, sizeof(start_time_str2));
uci_get_value(ctx, "appfilter.time.end_time2", end_time_str2, sizeof(end_time_str2));
uci_get_value(ctx, "appfilter.time.days", days_str, sizeof(days_str));
t = malloc(sizeof(af_ctl_time_t));
value = uci_get_int_value(ctx, "appfilter.time.time_mode");
if (value < 0)
t->time_mode = 0;
else
t->time_mode = value;
if (check_time_valid(start_time_str) && check_time_valid(end_time_str)){
sscanf(start_time_str, "%d:%d", &t->start.hour, &t->start.min);
sscanf(end_time_str, "%d:%d", &t->end.hour, &t->end.min);
}
if (check_time_valid(start_time_str2) && check_time_valid(end_time_str2)){
sscanf(start_time_str2, "%d:%d", &t->start2.hour, &t->start2.min);
sscanf(end_time_str2, "%d:%d", &t->end2.hour, &t->end2.min);
}
char *p = strtok(days_str, " ");
if (!p)
goto EXIT;
do
{
int day = atoi(p);
if (day >= 0 && day <= 6)
t->days[day] = 1;
else
ret = 0;
} while (p = strtok(NULL, " "));
EXIT:
uci_free_context(ctx);
return t;
}
int config_get_appfilter_enable(void)
{
int enable = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return NULL;
enable = uci_get_int_value(ctx, "appfilter.global.enable");
if (enable < 0)
enable = 0;
uci_free_context(ctx);
return enable;
}
int config_get_lan_ip(char *lan_ip, int len)
{
int ret = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return -1;
ret = uci_get_value(ctx, "network.lan.ipaddr", lan_ip, len);
uci_free_context(ctx);
return ret;
}
int config_get_lan_mask(char *lan_mask, int len)
{
int ret = 0;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
return -1;
ret = uci_get_value(ctx, "network.lan.netmask", lan_mask, len);
uci_free_context(ctx);
return ret;
}
int appfilter_config_alloc(void)
{
char *err;
uci_appfilter = config_init_package("appfilter");
if (!uci_appfilter)
{
uci_get_errorstr(uci_ctx, &err, NULL);
printf("Failed to load appfilter config (%s)\n", err);
free(err);
return -1;
}
return 0;
}
int appfilter_config_free(void)
{
if (uci_appfilter)
{
uci_unload(uci_ctx, uci_appfilter);
uci_appfilter = NULL;
}
if (uci_ctx)
{
uci_free_context(uci_ctx);
uci_ctx = NULL;
}
}

View File

@ -57,5 +57,6 @@ int appfilter_config_free(void);
af_ctl_time_t *load_appfilter_ctl_time_config(void);
int config_get_appfilter_enable(void);
int config_get_lan_ip(char *lan_ip, int len);
int config_get_lan_mask(char *lan_mask, int len);
#endif

View File

@ -29,6 +29,7 @@ THE SOFTWARE.
#include <linux/netlink.h>
#include <linux/socket.h>
#include <sys/socket.h>
#include "appfilter.h"
#include "appfilter_user.h"
dev_node_t *dev_hash_table[MAX_DEV_NODE_HASH_SIZE];
@ -190,7 +191,8 @@ void clean_dev_online_status(void)
dev_node_t *node = dev_hash_table[i];
while (node)
{
if (node->online){
if (node->online)
{
node->offline_time = get_timestamp();
node->online = 0;
}
@ -200,10 +202,10 @@ void clean_dev_online_status(void)
}
/*
Id Mac Ip
1 10:bf:48:37:0c:94 192.168.66.244
Id Mac Ip
1 10:bf:48:37:0c:94 192.168.66.244
*/
void update_dev_online_status(void)
void update_dev_from_oaf(void)
{
char line_buf[256] = {0};
char mac_buf[32] = {0};
@ -237,6 +239,59 @@ void update_dev_online_status(void)
fclose(fp);
}
void update_dev_from_arp(void)
{
char line_buf[256] = {0};
char mac_buf[32] = {0};
char ip_buf[32] = {0};
char lan_ip[32] = {0};
char lan_mask[32] = {0};
exec_with_result_line(CMD_GET_LAN_IP, lan_ip, sizeof(lan_ip));
exec_with_result_line(CMD_GET_LAN_MASK, lan_mask, sizeof(lan_mask));
if (strlen(lan_ip) < MIN_INET_ADDR_LEN || strlen(lan_mask) < MIN_INET_ADDR_LEN)
{
return;
}
FILE *fp = fopen("/proc/net/arp", "r");
if (!fp)
{
printf("open dev file....failed\n");
return;
}
fgets(line_buf, sizeof(line_buf), fp); // title
while (fgets(line_buf, sizeof(line_buf), fp))
{
sscanf(line_buf, "%s %*s %*s %s", ip_buf, mac_buf);
if (strlen(mac_buf) < 17 || strlen(ip_buf) < MIN_INET_ADDR_LEN)
{
printf("invalid mac:%s or ip:%s\n", mac_buf, ip_buf);
continue;
}
if (0 == strcmp(mac_buf, "00:00:00:00:00:00"))
continue;
if (!check_same_network(lan_ip, lan_mask, ip_buf) || 0 == strcmp(lan_ip, ip_buf))
{
continue;
}
dev_node_t *node = find_dev_node(mac_buf);
if (!node)
{
node = add_dev_node(mac_buf);
if (!node)
continue;
strncpy(node->ip, ip_buf, sizeof(node->ip));
}
}
fclose(fp);
}
void update_dev_online_status(void)
{
update_dev_from_oaf();
update_dev_from_arp();
}
#define DEV_OFFLINE_TIME (SECONDS_PER_DAY * 3)
@ -272,7 +327,7 @@ int check_dev_expire(void)
}
expire_count++;
printf("dev:%s expired, offline time = %ds, count=%d, visit_count=%d\n",
node->mac, offline_time, expire_count, visit_count);
node->mac, offline_time, expire_count, visit_count);
}
NEXT:
node = node->next;
@ -389,10 +444,10 @@ EXIT:
fclose(fp);
}
// 记录最大保存时间 todo: support config
#define MAX_RECORD_TIME (7 * 24 * 60 * 60) // 7day
#define MAX_RECORD_TIME (3 * 24 * 60 * 60) // 7day
// 超过1天后清除短时间的记录
#define RECORD_REMAIN_TIME (24 * 60 * 60) // 1day
#define INVALID_RECORD_TIME (5 * 60) // 5min
#define INVALID_RECORD_TIME (5 * 60) // 5min
void check_dev_visit_info_expire(void)
{
@ -410,11 +465,13 @@ void check_dev_visit_info_expire(void)
while (p_info)
{
int total_time = p_info->latest_time - p_info->first_time;
int interval_time = cur_time - p_info->first_time;
if (interval_time > MAX_RECORD_TIME || interval_time < 0){
int interval_time = cur_time - p_info->first_time;
if (interval_time > MAX_RECORD_TIME || interval_time < 0)
{
p_info->expire = 1;
}
else if (interval_time > RECORD_REMAIN_TIME){
else if (interval_time > RECORD_REMAIN_TIME)
{
if (total_time < INVALID_RECORD_TIME)
p_info->expire = 1;
}
@ -442,24 +499,27 @@ void flush_expire_visit_info(void)
prev = NULL;
while (p_info)
{
if (p_info->expire){
if (NULL == prev){
if (p_info->expire)
{
if (NULL == prev)
{
node->visit_htable[j] = p_info->next;
free(p_info);
p_info = node->visit_htable[j];
prev = NULL;
}
else{
else
{
prev->next = p_info->next;
free(p_info);
p_info = prev->next;
}
}
else{
else
{
prev = p_info;
p_info = p_info->next;
}
}
}
node = node->next;
@ -467,9 +527,6 @@ void flush_expire_visit_info(void)
}
}
void dump_dev_visit_list(void)
{
int i, j;

View File

@ -1,153 +1,175 @@
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libubox/uloop.h>
#include <libubox/utils.h>
#include <libubus.h>
#include "appfilter_user.h"
#include "appfilter_netlink.h"
#include "appfilter_ubus.h"
#include "appfilter_config.h"
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void check_appfilter_enable(void)
{
int enable = 1;
struct tm *t;
af_ctl_time_t *af_t = NULL;
time_t tt;
time(&tt);
enable = config_get_appfilter_enable();
if (0 == enable)
goto EXIT;
af_t = load_appfilter_ctl_time_config();
if (!af_t)
{
enable = 0;
goto EXIT;
}
t = localtime(&tt);
if (af_t->days[t->tm_wday] != 1)
{
if (af_t->time_mode == 0){
enable = 0;
goto EXIT;
}
}
int cur_mins = t->tm_hour * 60 + t->tm_min;
if (((af_t->start.hour * 60 + af_t->start.min < cur_mins) && (cur_mins < af_t->end.hour * 60 + af_t->end.min))
|| ((af_t->start2.hour * 60 + af_t->start2.min < cur_mins) && (cur_mins < af_t->end2.hour * 60 + af_t->end2.min))
)
{
if (af_t->time_mode == 0){
enable = 1;
}
else{
enable = 0;
}
}
else{
if (af_t->time_mode == 0){
enable = 0;
}
else{
enable = 1;
}
}
EXIT:
if (enable)
{
system("echo 1 >/proc/sys/oaf/enable ");
}
else
system("echo 0 >/proc/sys/oaf/enable ");
if (af_t)
free(af_t);
}
void update_lan_ip(void){
char ip_str[32] = {0};
struct in_addr addr;
char cmd_buf[128] = {0};
u_int32_t lan_ip = 0;
config_get_lan_ip(ip_str, sizeof(ip_str));
inet_aton(ip_str, &addr);
lan_ip =addr.s_addr;
sprintf(cmd_buf, "echo %d >/proc/sys/oaf/lan_ip", lan_ip);
system(cmd_buf);
}
void dev_list_timeout_handler(struct uloop_timeout *t)
{
dump_dev_list();
check_dev_visit_info_expire();
flush_expire_visit_info();
//dump_dev_visit_list();
update_lan_ip();
check_appfilter_enable();
if (check_dev_expire()){
flush_expire_visit_info();
flush_dev_expire_node();
}
uloop_timeout_set(t, 10000);
}
struct uloop_timeout dev_tm = {
.cb = dev_list_timeout_handler};
static struct uloop_fd appfilter_nl_fd = {
.cb = appfilter_nl_handler,
};
int main(int argc, char **argv)
{
int ret = 0;
uloop_init();
printf("init appfilter\n");
init_dev_node_htable();
init_app_name_table();
init_app_class_name_table();
if (appfilter_ubus_init() < 0)
{
fprintf(stderr, "Failed to connect to ubus\n");
return 1;
}
appfilter_nl_fd.fd = appfilter_nl_init();
uloop_fd_add(&appfilter_nl_fd, ULOOP_READ);
af_msg_t msg;
msg.action = AF_MSG_INIT;
send_msg_to_kernel(appfilter_nl_fd.fd, (void *)&msg, sizeof(msg));
uloop_timeout_set(&dev_tm, 5000);
uloop_timeout_add(&dev_tm);
uloop_run();
uloop_done();
return 0;
}
/*
Copyright (C) 2020 Derry <destan19@126.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libubox/uloop.h>
#include <libubox/utils.h>
#include <libubus.h>
#include "appfilter_user.h"
#include "appfilter_netlink.h"
#include "appfilter_ubus.h"
#include "appfilter_config.h"
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "appfilter.h"
void check_appfilter_enable(void)
{
int enable = 1;
struct tm *t;
af_ctl_time_t *af_t = NULL;
time_t tt;
time(&tt);
enable = config_get_appfilter_enable();
if (0 == enable)
goto EXIT;
af_t = load_appfilter_ctl_time_config();
if (!af_t)
{
enable = 0;
goto EXIT;
}
t = localtime(&tt);
if (af_t->days[t->tm_wday] != 1)
{
if (af_t->time_mode == 0){
enable = 0;
goto EXIT;
}
}
int cur_mins = t->tm_hour * 60 + t->tm_min;
if (((af_t->start.hour * 60 + af_t->start.min < cur_mins) && (cur_mins < af_t->end.hour * 60 + af_t->end.min))
|| ((af_t->start2.hour * 60 + af_t->start2.min < cur_mins) && (cur_mins < af_t->end2.hour * 60 + af_t->end2.min))
)
{
if (af_t->time_mode == 0){
enable = 1;
}
else{
enable = 0;
}
}
else{
if (af_t->time_mode == 0){
enable = 0;
}
else{
enable = 1;
}
}
EXIT:
if (enable)
{
system("echo 1 >/proc/sys/oaf/enable ");
}
else
system("echo 0 >/proc/sys/oaf/enable ");
if (af_t)
free(af_t);
}
void update_lan_ip(void){
char ip_str[32] = {0};
char mask_str[32] = {0};
struct in_addr addr;
struct in_addr mask_addr;
char cmd_buf[128] = {0};
u_int32_t lan_ip = 0;
u_int32_t lan_mask = 0;
exec_with_result_line(CMD_GET_LAN_IP, ip_str, sizeof(ip_str));
if (strlen(ip_str) < MIN_INET_ADDR_LEN){
sprintf(cmd_buf, "echo 0 >/proc/sys/oaf/lan_ip");
}
else{
inet_aton(ip_str, &addr);
lan_ip = addr.s_addr;
sprintf(cmd_buf, "echo %u >/proc/sys/oaf/lan_ip", lan_ip);
}
system(cmd_buf);
exec_with_result_line(CMD_GET_LAN_MASK, mask_str, sizeof(mask_str));
if (strlen(mask_str) < MIN_INET_ADDR_LEN){
sprintf(cmd_buf, "echo 0 >/proc/sys/oaf/lan_mask");
}
else{
inet_aton(mask_str, &mask_addr);
lan_mask = mask_addr.s_addr;
sprintf(cmd_buf, "echo %u >/proc/sys/oaf/lan_mask", lan_mask);
}
system(cmd_buf);
}
void dev_list_timeout_handler(struct uloop_timeout *t)
{
dump_dev_list();
check_dev_visit_info_expire();
flush_expire_visit_info();
//dump_dev_visit_list();
update_lan_ip();
check_appfilter_enable();
if (check_dev_expire()){
flush_expire_visit_info();
flush_dev_expire_node();
}
uloop_timeout_set(t, 10000);
}
struct uloop_timeout dev_tm = {
.cb = dev_list_timeout_handler};
static struct uloop_fd appfilter_nl_fd = {
.cb = appfilter_nl_handler,
};
int main(int argc, char **argv)
{
int ret = 0;
uloop_init();
printf("init appfilter\n");
init_dev_node_htable();
init_app_name_table();
init_app_class_name_table();
if (appfilter_ubus_init() < 0)
{
fprintf(stderr, "Failed to connect to ubus\n");
return 1;
}
appfilter_nl_fd.fd = appfilter_nl_init();
uloop_fd_add(&appfilter_nl_fd, ULOOP_READ);
af_msg_t msg;
msg.action = AF_MSG_INIT;
send_msg_to_kernel(appfilter_nl_fd.fd, (void *)&msg, sizeof(msg));
uloop_timeout_set(&dev_tm, 5000);
uloop_timeout_add(&dev_tm);
uloop_run();
uloop_done();
return 0;
}

69
open-app-filter/src/utils.c Executable file
View File

@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *str_trim(char *s) {
char *start, *last, *bk;
int len;
start = s;
while (isspace(*start))
start++;
bk = last = s + strlen(s) - 1;
while (last > start && isspace(*last))
last--;
if ((s != start) || (bk != last)) {
len = last - start + 1;
strncpy(s, start, len);
s[len] = '\0';
}
return s;
}
int exec_with_result_line(char *cmd, char *result, int len)
{
FILE *fp = NULL;
if (!cmd || !result || !len)
return -1;
fp = popen(cmd, "r");
if (!fp)
return -1;
fgets(result, len, fp);
str_trim(result);
pclose(fp);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
int check_same_network(char *ip1, char *netmask, char *ip2) {
struct in_addr addr1, addr2, mask;
if (inet_pton(AF_INET, ip1, &addr1) != 1) {
printf("Invalid IP address: %s\n", ip1);
return -1;
}
if (inet_pton(AF_INET, netmask, &mask) != 1) {
printf("Invalid netmask: %s\n", netmask);
return -1;
}
if (inet_pton(AF_INET, ip2, &addr2) != 1) {
printf("Invalid IP address: %s\n", ip2);
return -1;
}
if ((addr1.s_addr & mask.s_addr) == (addr2.s_addr & mask.s_addr)) {
return 1;
} else {
return 0;
}
}

6
open-app-filter/src/utils.h Executable file
View File

@ -0,0 +1,6 @@
#ifndef __UTILS_H__
#define __UTILS_H__
char *str_trim(char *s);
int exec_with_result_line(char *cmd, char *result, int len);
int check_same_network(char *ip1, char *netmask, char *ip2);
#endif