Keep oafd running all the time

This commit is contained in:
Derry 2021-03-20 08:40:48 -07:00
parent 0a5d53133b
commit e1b21d21e7
13 changed files with 247 additions and 185 deletions

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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)
{

View File

@ -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,

View File

@ -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

View File

@ -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

88
open-app-filter/files/oaf_rule Executable file
View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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();