diff --git a/luci-app-oaf/luasrc/view/admin_network/dev_status.htm b/luci-app-oaf/luasrc/view/admin_network/dev_status.htm index 0bb46ad..b7522c9 100755 --- a/luci-app-oaf/luasrc/view/admin_network/dev_status.htm +++ b/luci-app-oaf/luasrc/view/admin_network/dev_status.htm @@ -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, diff --git a/oaf/src/af_log.c b/oaf/src/af_log.c index 7c6b8b4..cf5aebc 100755 --- a/oaf/src/af_log.c +++ b/oaf/src/af_log.c @@ -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, }, { } diff --git a/oaf/src/af_log.h b/oaf/src/af_log.h index f05c7bd..d9380ea 100755 --- a/oaf/src/af_log.h +++ b/oaf/src/af_log.h @@ -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__); \ diff --git a/oaf/src/app_filter.c b/oaf/src/app_filter.c index 70671db..c27dd23 100755 --- a/oaf/src/app_filter.c +++ b/oaf/src/app_filter.c @@ -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(); diff --git a/open-app-filter/src/Makefile b/open-app-filter/src/Makefile index 3f0cdce..2236bab 100755 --- a/open-app-filter/src/Makefile +++ b/open-app-filter/src/Makefile @@ -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) diff --git a/open-app-filter/src/appfilter.h b/open-app-filter/src/appfilter.h new file mode 100755 index 0000000..d291635 --- /dev/null +++ b/open-app-filter/src/appfilter.h @@ -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 \ No newline at end of file diff --git a/open-app-filter/src/appfilter_config.c b/open-app-filter/src/appfilter_config.c index 5c464c9..dc219bc 100755 --- a/open-app-filter/src/appfilter_config.c +++ b/open-app-filter/src/appfilter_config.c @@ -1,342 +1,352 @@ -/* -Copyright (C) 2020 Derry - -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 -#include -#include -#include "appfilter_config.h" -#include - -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 + +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 +#include +#include +#include "appfilter_config.h" +#include + +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; + } +} diff --git a/open-app-filter/src/appfilter_config.h b/open-app-filter/src/appfilter_config.h index e2770c3..4a29d3b 100755 --- a/open-app-filter/src/appfilter_config.h +++ b/open-app-filter/src/appfilter_config.h @@ -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 diff --git a/open-app-filter/src/appfilter_user.c b/open-app-filter/src/appfilter_user.c index 6b1e217..6a5c4a9 100755 --- a/open-app-filter/src/appfilter_user.c +++ b/open-app-filter/src/appfilter_user.c @@ -29,6 +29,7 @@ THE SOFTWARE. #include #include #include +#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; diff --git a/open-app-filter/src/main.c b/open-app-filter/src/main.c index a506b0f..4532f52 100755 --- a/open-app-filter/src/main.c +++ b/open-app-filter/src/main.c @@ -1,153 +1,175 @@ -/* -Copyright (C) 2020 Derry - -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 -#include -#include -#include -#include -#include -#include "appfilter_user.h" -#include "appfilter_netlink.h" -#include "appfilter_ubus.h" -#include "appfilter_config.h" -#include -#include -#include -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 + +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 +#include +#include +#include +#include +#include +#include "appfilter_user.h" +#include "appfilter_netlink.h" +#include "appfilter_ubus.h" +#include "appfilter_config.h" +#include +#include +#include +#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; +} diff --git a/open-app-filter/src/utils.c b/open-app-filter/src/utils.c new file mode 100755 index 0000000..7b0463f --- /dev/null +++ b/open-app-filter/src/utils.c @@ -0,0 +1,69 @@ + +#include +#include +#include +#include + + +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 +#include +#include +#include + +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; + } +} diff --git a/open-app-filter/src/utils.h b/open-app-filter/src/utils.h new file mode 100755 index 0000000..7c5d4fd --- /dev/null +++ b/open-app-filter/src/utils.h @@ -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 \ No newline at end of file