diff --git a/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf b/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf index 1900656..37d5dc4 100755 --- a/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf +++ b/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf @@ -4,7 +4,7 @@ uci -q batch <<-EOF >/dev/null del ucitrack.@appfilter[-1] add ucitrack appfilter - set ucitrack.@appfilter[-1].exec="/etc/init.d/appfilter restart" + set ucitrack.@appfilter[-1].exec="/usr/bin/oaf_rule reload" commit ucitrack EOF diff --git a/oaf/src/af_client.c b/oaf/src/af_client.c index 90fe9c7..b03f4f2 100755 --- a/oaf/src/af_client.c +++ b/oaf/src/af_client.c @@ -66,6 +66,24 @@ nf_client_list_clear(void) AF_CLIENT_UNLOCK_W(); } + +void af_client_list_reset_report_num(void) +{ + int i; + af_client_info_t * node = NULL; + char mac_str[32] = {0}; + + AF_INFO("reset report num"); + AF_CLIENT_LOCK_W(); + for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE;i++){ + list_for_each_entry(node, &af_client_list_table[i], hlist){ + node->report_count = 0; + printk("reset mac="MAC_FMT" report num to 0\n", MAC_ARRAY(node->mac)); + } + } + AF_CLIENT_UNLOCK_W(); +} + int get_mac_hash_code(unsigned char *mac) { if (!mac) @@ -184,7 +202,7 @@ void flush_expired_visit_info(af_client_info_t *node) } -int af_report_visit_info(af_client_info_t *node){ +int __af_visit_info_report(af_client_info_t *node){ unsigned char mac_str[32] = {0}; unsigned char ip_str[32] = {0}; int i, j; @@ -235,7 +253,7 @@ int af_report_visit_info(af_client_info_t *node){ kfree(out); return 0; } -void af_visit_info_timer_handle(void){ +void af_visit_info_report(void){ af_client_info_t *node; int i; AF_CLIENT_LOCK_W(); @@ -243,7 +261,7 @@ void af_visit_info_timer_handle(void){ list_for_each_entry(node, &af_client_list_table[i], hlist) { //flush_expired_visit_info(node); AF_INFO("report %s\n", node->mac); - af_report_visit_info(node); + __af_visit_info_report(node); } } AF_CLIENT_UNLOCK_W(); @@ -259,11 +277,11 @@ static inline int get_packet_dir(struct net_device *in) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) -static u_int32_t nfclient_hook(void *priv, +static u_int32_t af_client_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { #else -static u_int32_t nfclient_hook(unsigned int hook, +static u_int32_t af_client_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, @@ -334,7 +352,7 @@ static u_int32_t nfclient_hook(unsigned int hook, #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) static struct nf_hook_ops af_client_ops[] = { { - .hook = nfclient_hook, + .hook = af_client_hook, .pf = PF_INET, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_FIRST + 1, @@ -343,7 +361,7 @@ static struct nf_hook_ops af_client_ops[] = { #else static struct nf_hook_ops af_client_ops[] = { { - .hook = nfclient_hook, + .hook = af_client_hook, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_FORWARD, diff --git a/oaf/src/af_client.h b/oaf/src/af_client.h index 7afd211..d56f0c3 100755 --- a/oaf/src/af_client.h +++ b/oaf/src/af_client.h @@ -66,6 +66,8 @@ af_client_info_t * find_af_client_by_ip(unsigned int ip); void check_client_expire(void); -void af_visit_info_timer_handle(void); +void af_visit_info_report(void); + +void af_client_list_reset_report_num(void); #endif diff --git a/oaf/src/af_client_fs.c b/oaf/src/af_client_fs.c index 0b482c3..01306c5 100755 --- a/oaf/src/af_client_fs.c +++ b/oaf/src/af_client_fs.c @@ -95,7 +95,7 @@ static void *af_client_seq_next(struct seq_file *s, void *v, loff_t *pos) static void af_client_seq_stop(struct seq_file *s, void *v) { - seq_printf(s, "%s", "]"); +// seq_printf(s, "%s", "]"); AF_CLIENT_UNLOCK_R(); } @@ -104,74 +104,22 @@ static int af_client_seq_show(struct seq_file *s, void *v) unsigned char mac_str[32] = {0}; unsigned char ip_str[32] = {0}; static int index = 0; - int i; - int j; - cJSON *visit_info_array = NULL; - cJSON *root_obj = NULL; - cJSON *visit_obj = NULL; - cJSON *history_array = NULL; - cJSON *history_obj = NULL; - char *out = NULL; af_client_info_t *node = (af_client_info_t *)v; - if (v == SEQ_START_TOKEN) { index = 0; - seq_printf(s, "%s", "["); + seq_printf(s, "%-4s %-20s %-20s\n", "Id", "Mac", "Ip"); return 0; } - if(index > 0) - seq_printf(s, "%s", ","); +// if(index > 0) + // seq_printf(s, "%s", ","); index++; - - root_obj = cJSON_CreateObject(); - if(!root_obj){ - AF_ERROR("create json obj failed"); - return 0; - } sprintf(mac_str, MAC_FMT, MAC_ARRAY(node->mac)); sprintf(ip_str, "%pI4", &node->ip); - cJSON_AddStringToObject(root_obj, "mac", mac_str); - cJSON_AddStringToObject(root_obj, "ip", ip_str); - cJSON_AddNumberToObject(root_obj, "app_num", node->visit_app_num); - visit_info_array = cJSON_CreateArray(); - - for(i = 0; i < MAX_RECORD_APP_NUM; i++){ - if(node->visit_info[i].app_id == 0) - continue; - if(node->visit_info[i].total_num < 3) - continue; - visit_obj = cJSON_CreateObject(); - cJSON_AddNumberToObject(visit_obj, "appid", node->visit_info[i].app_id); - cJSON_AddNumberToObject(visit_obj, "latest_action", node->visit_info[i].latest_action); - cJSON_AddNumberToObject(visit_obj, "latest_time", node->visit_info[i].latest_time); - cJSON_AddNumberToObject(visit_obj, "total_num", node->visit_info[i].total_num); - cJSON_AddNumberToObject(visit_obj, "drop_num", node->visit_info[i].drop_num); - history_array = cJSON_CreateArray(); - for(j = 0; j < MAX_VISIT_HISTORY_TIME; j++){ - if(node->visit_info[i].history_time[j] <= 0) - continue; - history_obj = cJSON_CreateObject(); - cJSON_AddNumberToObject(visit_obj, "action", node->visit_info[i].history_time[j]); - cJSON_AddNumberToObject(visit_obj, "time", node->visit_info[i].action[j]); - cJSON_AddItemToArray(history_array, history_obj); - } - - cJSON_AddItemToObject(visit_obj, "history_info", history_array); - cJSON_AddItemToArray(visit_info_array, visit_obj); - } - - cJSON_AddItemToObject(root_obj, "visit_info", visit_info_array); - out = cJSON_Print(root_obj); - if(!out) - return 0; - cJSON_Minify(out); - seq_printf(s, "%s", out); - kfree(out); - - cJSON_Delete(root_obj); + seq_printf(s, "%-4d %-20s %-20s\n", index, mac_str, ip_str); return 0; } + static const struct seq_operations nf_client_seq_ops = { .start = af_client_seq_start, .next = af_client_seq_next, diff --git a/oaf/src/app_filter.c b/oaf/src/app_filter.c index 39e8434..afebd33 100755 --- a/oaf/src/app_filter.c +++ b/oaf/src/app_filter.c @@ -927,16 +927,22 @@ void TEST_cJSON(void) struct timer_list oaf_timer; - -#define OAF_TIMER_INTERVAL 60 +int report_flag = 0; +#define OAF_TIMER_INTERVAL 1 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0) static void oaf_timer_func(struct timer_list *t) #else static void oaf_timer_func(unsigned long ptr) #endif { - check_client_expire(); - af_visit_info_timer_handle(); + static int count = 0; + if (count % 60 == 0) + check_client_expire(); + if (count % 60 == 0 || report_flag){ + report_flag = 0; + af_visit_info_report(); + } + count++; mod_timer(&oaf_timer, jiffies + OAF_TIMER_INTERVAL * HZ); } @@ -961,12 +967,7 @@ void fini_oaf_timer(void) static struct sock *oaf_sock = NULL; -struct af_msg_hdr{ - int magic; - int len; -}; -#define OAF_NETLINK_ID 29 -#define MAX_OAF_NL_MSG_LEN 1024 + int af_send_msg_to_user(char *pbuf, uint16_t len) { struct sk_buff *nl_skb; @@ -1003,30 +1004,51 @@ int af_send_msg_to_user(char *pbuf, uint16_t len) ret = netlink_unicast(oaf_sock, nl_skb, 999, MSG_DONTWAIT); return ret; } +#define MAX_OAF_NETLINK_MSG_LEN 1024 +static void oaf_user_msg_handle(af_msg_t *msg){ + printk("oaf msg handle, action = %d\n", msg->action); + switch(msg->action){ + case AF_MSG_INIT: + printk("module init.........\n"); + af_client_list_reset_report_num(); + report_flag = 1; + break; + default: + break; + } +} static void oaf_msg_rcv(struct sk_buff *skb) { struct nlmsghdr *nlh = NULL; char *umsg = NULL; - char *kmsg = "ok"; - + printk("recv user msg\n"); if(skb->len >= nlmsg_total_size(0)) { nlh = nlmsg_hdr(skb); umsg = NLMSG_DATA(nlh); - if(umsg) - { - AF_INFO("kernel recv from user: %s\n", umsg); - af_send_msg_to_user(kmsg, strlen(kmsg)); - } + + struct af_msg_hdr *af_hdr = (struct af_msg_hdr *)umsg; + if (af_hdr->magic != 0xa0b0c0d0){ + printk("magic error %x\n", af_hdr->magic); + return; + } + if (af_hdr->len <= 0 || af_hdr->len >= MAX_OAF_NETLINK_MSG_LEN){ + printk("data len error\n"); + return; + } + void *udata = umsg + sizeof(struct af_msg_hdr); + + if(udata) + oaf_user_msg_handle((af_msg_t *)udata); } } int netlink_oaf_init(void) { - struct netlink_kernel_cfg bm_nl_cfg = {0}; - bm_nl_cfg.input = oaf_msg_rcv; - oaf_sock = netlink_kernel_create(&init_net, OAF_NETLINK_ID, &bm_nl_cfg); + struct netlink_kernel_cfg nl_cfg = {0}; + nl_cfg.input = oaf_msg_rcv; + oaf_sock = netlink_kernel_create(&init_net, OAF_NETLINK_ID, &nl_cfg); if (NULL == oaf_sock) { diff --git a/oaf/src/app_filter.h b/oaf/src/app_filter.h index 5aee063..e5c15de 100755 --- a/oaf/src/app_filter.h +++ b/oaf/src/app_filter.h @@ -51,6 +51,25 @@ enum AF_FEATURE_PARAM_INDEX{ AF_DICT_PARAM_INDEX, }; + +#define OAF_NETLINK_ID 29 +#define MAX_OAF_NL_MSG_LEN 1024 + +enum E_MSG_TYPE{ + AF_MSG_INIT, + AF_MSG_MAX +}; + +typedef struct af_msg{ + int action; + void *data; +}af_msg_t; + +struct af_msg_hdr{ + int magic; + int len; +}; + enum e_http_method{ HTTP_METHOD_GET = 1, HTTP_METHOD_POST, diff --git a/open-app-filter/Makefile b/open-app-filter/Makefile index 4647545..a52d9d0 100755 --- a/open-app-filter/Makefile +++ b/open-app-filter/Makefile @@ -49,6 +49,7 @@ define Package/appfilter/install $(CP) ./files/feature.cfg $(1)/etc/appfilter/ $(CP) ./files/app_class.txt $(1)/etc/appfilter/ $(INSTALL_BIN) ./files/appfilter.init $(1)/etc/init.d/appfilter + $(INSTALL_BIN) ./files/oaf_rule $(1)/usr/bin $(INSTALL_BIN) ./files/gen_class.sh $(1)/usr/bin $(INSTALL_BIN) ./files/appfilter.config $(1)/etc/config/appfilter $(INSTALL_BIN) $(PKG_BUILD_DIR)/oafd $(1)/usr/bin diff --git a/open-app-filter/files/appfilter.init b/open-app-filter/files/appfilter.init index 361675a..4c31f5e 100755 --- a/open-app-filter/files/appfilter.init +++ b/open-app-filter/files/appfilter.init @@ -6,104 +6,18 @@ START=96 USE_PROCD=1 OAFD_BIN="/usr/bin/oafd" -config_apply() -{ - test -z "$1" && return 1 - - if [ -e "/dev/appfilter" ];then - echo "config json str=$1" - echo "$1" >/dev/appfilter - fi -} - -clean_rule() -{ - json_init - echo "clean appfilter rule..." - - json_add_int "op" 3 - json_add_object "data" - json_str=`json_dump` - - config_apply "$json_str" - - json_cleanup -} - -load_rule() -{ - json_init - json_add_int "op" 1 - json_add_object "data" - json_add_array "apps" - - for file in `ls /tmp/appfilter/*.class` - do - class_name=`echo "$file" | awk -F/ '{print $4}'| awk -F. '{print $1}'` - config_get appid_list "appfilter" "${class_name}apps" - echo "appid_list=$appid_list" - - if ! test -z "$appid_list";then - for appid in $appid_list: - do - json_add_int "" $appid - done - fi - done - - json_str=`json_dump` - config_apply "$json_str" - json_cleanup -} - -load_mac_list() -{ - json_init - config_load appfilter - json_add_int "op" 4 - json_add_object "data" - json_add_array "mac_list" - config_get appid_list "user" "users" - echo "appid list=$appid_list" - for appid in $appid_list: - do - echo "appid=$appid" - json_add_string "" $appid - done - json_str=`json_dump` - config_apply "$json_str" - echo "json str=$json_str" - json_cleanup -} - - service_triggers() { procd_add_reload_trigger "appfilter" } stop_service(){ - clean_rule + killall -9 $OAFD_BIN } start_service(){ gen_class.sh /etc/appfilter/feature.cfg - - config_load appfilter - config_get enable "global" enable - echo "enable = $enable" - - if [ x"$enable" != x"1" ];then - echo "appfilter is disabled" - echo 0 >/proc/sys/oaf/enable>/dev/null - return 0 - else - insmod oaf >/dev/null - echo 1 >/proc/sys/oaf/enable - fi - - load_rule - load_mac_list + insmod oaf procd_open_instance procd_set_param respawn 60 5 5 procd_set_param stderr 1 diff --git a/open-app-filter/files/oaf_rule b/open-app-filter/files/oaf_rule new file mode 100755 index 0000000..a9ac5ea --- /dev/null +++ b/open-app-filter/files/oaf_rule @@ -0,0 +1,88 @@ +. /usr/share/libubox/jshn.sh +. /lib/functions.sh + + +config_apply() +{ + test -z "$1" && return 1 + + if [ -e "/dev/appfilter" ];then + echo "config json str=$1" + echo "$1" >/dev/appfilter + fi +} + +clean_rule() +{ + json_init + echo "clean appfilter rule..." + + json_add_int "op" 3 + json_add_object "data" + json_str=`json_dump` + + config_apply "$json_str" + + json_cleanup +} + +load_rule() +{ + json_init + json_add_int "op" 1 + json_add_object "data" + json_add_array "apps" + + for file in `ls /tmp/appfilter/*.class` + do + class_name=`echo "$file" | awk -F/ '{print $4}'| awk -F. '{print $1}'` + config_get appid_list "appfilter" "${class_name}apps" + echo "appid_list=$appid_list" + + if ! test -z "$appid_list";then + for appid in $appid_list: + do + json_add_int "" $appid + done + fi + done + + json_str=`json_dump` + config_apply "$json_str" + json_cleanup +} + +load_mac_list() +{ + json_init + config_load appfilter + json_add_int "op" 4 + json_add_object "data" + json_add_array "mac_list" + config_get appid_list "user" "users" + echo "appid list=$appid_list" + for appid in $appid_list: + do + echo "appid=$appid" + json_add_string "" $appid + done + json_str=`json_dump` + config_apply "$json_str" + echo "json str=$json_str" + json_cleanup +} + +reload_rule(){ + config_load appfilter + clean_rule + load_rule + load_mac_list +} + + +case $1 in +"reload") + echo "reload appfilter rule..." + reload_rule +;; +esac diff --git a/open-app-filter/src/appfilter_netlink.c b/open-app-filter/src/appfilter_netlink.c index 763ece0..e15bf97 100755 --- a/open-app-filter/src/appfilter_netlink.c +++ b/open-app-filter/src/appfilter_netlink.c @@ -153,6 +153,43 @@ void appfilter_nl_handler(struct uloop_fd *u, unsigned int ev) json_object_put(root); } +#define MAX_NL_MSG_LEN 1024 +int send_msg_to_kernel(int fd, void *msg, int len){ + struct sockaddr_nl saddr, daddr; + memset(&daddr, 0, sizeof(daddr)); + daddr.nl_family = AF_NETLINK; + daddr.nl_pid = 0; // to kernel + daddr.nl_groups = 0; + + int ret = 0; + struct nlmsghdr *nlh = NULL; + nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_NL_MSG_LEN)); + nlh->nlmsg_len = NLMSG_SPACE(MAX_NL_MSG_LEN); + nlh->nlmsg_flags = 0; + nlh->nlmsg_type = 0; + nlh->nlmsg_seq = 0; + nlh->nlmsg_pid = DEFAULT_USR_NL_PID; + + char msg_buf[MAX_NL_MSG_LEN] = {0}; + struct af_msg_hdr *hdr = (struct af_msg_hdr *)msg_buf; + hdr->magic = 0xa0b0c0d0; + hdr->len = len; + char *p_data = msg_buf + sizeof(struct af_msg_hdr); + memcpy(p_data, msg, len); + + + // memset(nlh, 0, sizeof(struct nlmsghdr)); + + memcpy(NLMSG_DATA(nlh), msg_buf, len + sizeof(struct af_msg_hdr)); + + ret = sendto(fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&daddr, sizeof(struct sockaddr_nl)); + if(!ret) + { + perror("sendto error\n"); + return -1; + } + return 0; +} int appfilter_nl_init(void) { @@ -173,6 +210,7 @@ int appfilter_nl_init(void) printf("Bind failed %s\n", strerror(errno)); exit(1); } + return fd; } diff --git a/open-app-filter/src/appfilter_netlink.h b/open-app-filter/src/appfilter_netlink.h index cdbf81f..fbaf950 100755 --- a/open-app-filter/src/appfilter_netlink.h +++ b/open-app-filter/src/appfilter_netlink.h @@ -29,6 +29,17 @@ struct af_msg_hdr{ int magic; int len; }; + +enum E_MSG_TYPE{ + AF_MSG_INIT, + AF_MSG_MAX +}; + +typedef struct af_msg{ + int action; + void *data; +}af_msg_t; int appfilter_nl_init(void); void appfilter_nl_handler(struct uloop_fd *u, unsigned int ev); +int send_msg_to_kernel(int fd, void *msg, int len); #endif \ No newline at end of file diff --git a/open-app-filter/src/appfilter_user.c b/open-app-filter/src/appfilter_user.c index bbb3347..668b75e 100755 --- a/open-app-filter/src/appfilter_user.c +++ b/open-app-filter/src/appfilter_user.c @@ -129,7 +129,8 @@ char * format_time(int timetamp){ return strdup(time_buf); } -void update_dev_from_dhcp_lease_file(void){ + +void update_dev_hostname(void){ char line_buf[256] = {0}; char hostname_buf[128] = {0}; char mac_buf[32] = {0}; @@ -145,14 +146,10 @@ void update_dev_from_dhcp_lease_file(void){ continue; sscanf(line_buf, "%*s %s %s %s", mac_buf, ip_buf, hostname_buf); dev_node_t *node = find_dev_node(mac_buf); - if (!node){ - node = add_dev_node(mac_buf); - } - if (node && strlen(ip_buf) > 0) - strcpy(node->ip, ip_buf); - - if (node && strlen(hostname_buf) > 0) - strcpy(node->hostname, hostname_buf); + if (!node) + continue; + if (strlen(hostname_buf) > 0) + strncpy(node->hostname, hostname_buf, sizeof(node->hostname)); } fclose(fp); } @@ -160,7 +157,7 @@ void update_dev_from_dhcp_lease_file(void){ void dump_dev_list(void){ int i, j; int count = 0; - update_dev_from_dhcp_lease_file(); + update_dev_hostname(); FILE *fp = fopen(OAF_DEV_LIST_FILE, "w"); if (!fp){ return; diff --git a/open-app-filter/src/main.c b/open-app-filter/src/main.c index a2d8bd8..a86ecbc 100755 --- a/open-app-filter/src/main.c +++ b/open-app-filter/src/main.c @@ -95,6 +95,10 @@ int main(int argc, char **argv) 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();