This commit is contained in:
sbwml 2023-04-28 05:00:39 +08:00
commit 1c783bce41
13 changed files with 751 additions and 525 deletions

View File

@ -49,6 +49,6 @@ Unzip thie OAF package and then install ipks in order
- luci-i18n-oaf-zh-cn(Chinese Language Pack, optional)
### Notice
If there is no version you need, you need to compile and generate it yourself, and I will release more architecture ipks later.
If there is no version you need, you need to compile and generate it yourself, and I will release more architecture ipks later.

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