Skip to content

Commit

Permalink
支持基于用户的过滤
Browse files Browse the repository at this point in the history
  • Loading branch information
destan19 committed Jun 15, 2020
1 parent 5de87b9 commit 11f3335
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 23 deletions.
64 changes: 51 additions & 13 deletions luci-app-oaf/luasrc/model/cbi/appfilter/appfilter.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--

local ds = require "luci.dispatcher"

Expand Down Expand Up @@ -81,6 +68,57 @@ if class_fd then
end
class_fd:close()
end


s=m:section(TypedSection,"user",translate("Select users"))
s.anonymous = true
users = s:option(MultiValue, "users", "", translate("Select at least one user, otherwise it will take effect for all users"))
users.widget="checkbox"

function get_hostname_by_mac(dst_mac)
leasefile="/tmp/dhcp.leases"
local fd = io.open(leasefile, "r")
if not fd then return end
while true do
local ln = fd:read("*l")
if not ln then
break
end
local ts, mac, ip, name, duid = ln:match("^(%d+) (%S+) (%S+) (%S+) (%S+)")
print(ln)
if dst_mac == mac then
fd:close()
return name
end
end
fd:close()
return nil
end

users.widget="checkbox"
--users.widget="select"
users.size=1

local fd = io.open("/proc/net/arp", "r")
if not fd then return end
while true do
local line = fd:read("*l")
if not line then
break
end
if not line:match("Ip*") then
local ip, hw_type, flags, mac, mask, device = line:match("(%S+) %s+ (%S+) %s+ (%S+) %s+ (%S+) %s+ (%S+) %s+ (%S+)")
if device:match("lan") then
local hostname=get_hostname_by_mac(mac)
if not hostname then
users:value(mac, mac);
else
users:value(mac, hostname);
end
end
end
end

m:section(SimpleSection).template = "admin_network/user_status"


Expand Down
7 changes: 6 additions & 1 deletion luci-app-oaf/po/zh-cn/oaf.po
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ msgstr "基本设置"
msgid "App Filter Rules"
msgstr "应用过滤规则"

msgid "Select at least one user, otherwise it will take effect for all users"
msgstr "至少选择一个用户,否则对所有用户生效"

msgid "Select users"
msgstr "选择用户"

msgid "Enable App Filter"
msgstr "开启应用过滤"



7 changes: 7 additions & 0 deletions luci-app-oaf/root/etc/uci-defaults/92_add_user_section
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

uci -q batch <<-EOF >/dev/null
set appfilter.user=user
commit appfilter
EOF
exit 0
1 change: 1 addition & 0 deletions oaf/src/af_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "af_client_fs.h"
#include "af_log.h"
#include "af_utils.h"
#include "app_filter.h"

DEFINE_RWLOCK(af_client_lock);

Expand Down
5 changes: 2 additions & 3 deletions oaf/src/af_client.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#ifndef __AF_CLIENT_H__
#define __AF_CLIENT_H__
#include "app_filter.h"

extern rwlock_t af_client_lock;

extern u32 nfc_debug_level;

#define MAX_AF_CLIENT_HASH_SIZE 64
#define MAC_ADDR_LEN 6
#define NF_CLIENT_TIMER_EXPIRE 1
#define MAX_CLIENT_ACTIVE_TIME 90

Expand Down Expand Up @@ -53,8 +53,7 @@ typedef struct af_client_info {
app_visit_info_t visit_info[MAX_RECORD_APP_NUM];
}af_client_info_t;

#define MAC_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"



int af_client_init(void);
Expand Down
1 change: 1 addition & 0 deletions oaf/src/af_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ static int k_vsscanf(const char *buf, const char *fmt, va_list args)
return num;
}


int k_sscanf(const char *buf, const char *fmt, ...)
{
va_list args;
Expand Down
19 changes: 15 additions & 4 deletions oaf/src/app_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,27 +681,36 @@ int af_match_one(flow_info_t *flow, af_feature_node_t *node)
int app_filter_match(flow_info_t *flow)
{
af_feature_node_t *n,*node;
af_client_info_t *client = NULL;
feature_list_read_lock();
if(!list_empty(&af_feature_head)) {
list_for_each_entry_safe(node, n, &af_feature_head, head) {
if(af_match_one(flow, node))
{
flow->app_id = node->app_id;
client = find_af_client_by_ip(flow->src);
if (!client){
goto EXIT;
}
// 如果开启了基于用户的过滤,但没有匹配到用户
if (is_user_match_enable() && !find_af_mac(client->mac)){
AF_ERROR("not match mac:"MAC_FMT"\n", MAC_ARRAY(client->mac));
goto EXIT;
}
if (af_get_app_status(node->app_id)){
flow->drop = AF_TRUE;
feature_list_read_unlock();
return AF_TRUE;
}
else {
flow->drop = AF_FALSE;
feature_list_read_unlock();
return AF_FALSE;
goto EXIT;
}
}


}
}
EXIT:
flow->drop = AF_FALSE;
feature_list_read_unlock();
return AF_FALSE;
}
Expand Down Expand Up @@ -940,6 +949,7 @@ static int __init app_filter_init(void)
AF_INFO("appfilter version:"AF_VERSION"\n");
af_log_init();
af_register_dev();
af_mac_list_init();
af_init_app_status();
load_feature_config();
init_af_client_procfs();
Expand Down Expand Up @@ -970,6 +980,7 @@ static void app_filter_fini(void)
#endif

af_clean_feature_list();
af_mac_list_clear();
af_unregister_dev();
af_log_exit();
af_client_exit();
Expand Down
12 changes: 11 additions & 1 deletion oaf/src/app_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#define NIPQUAD_FMT "%u.%u.%u.%u"
#define MAC_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"

#define AF_TRUE 1
#define AF_FALSE 0

#define AF_APP_TYPE(a) (a) / 1000
#define AF_APP_ID(a) (a) % 1000
#define MAC_ADDR_LEN 6

#define HTTPS_URL_OFFSET 9
#define HTTPS_LEN_OFFSET 7
Expand Down Expand Up @@ -105,13 +108,20 @@ typedef struct af_feature_node{
af_pos_info_t pos_info[MAX_POS_INFO_PER_FEATURE];
}af_feature_node_t;

typedef struct af_mac_info {
struct list_head hlist;
unsigned char mac[MAC_ADDR_LEN];
}af_mac_info_t;

int af_register_dev(void);
void af_unregister_dev(void);
void af_init_app_status(void);
int af_get_app_status(int appid);
int regexp_match(char *reg, char *text);

void af_mac_list_init(void);
void af_mac_list_clear(void);
af_mac_info_t * find_af_mac(unsigned char *mac);
int is_user_match_enable(void);
extern int g_oaf_enable;

#endif
144 changes: 144 additions & 0 deletions oaf/src/app_filter_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ enum AF_CONFIG_CMD{
AF_CMD_ADD_APPID = 1,
AF_CMD_DEL_APPID,
AF_CMD_CLEAN_APPID,
AF_CMD_SET_MAC_LIST,
};

char g_app_id_array[AF_MAX_APP_TYPE_NUM][AF_MAX_APP_NUM] = {0};
Expand Down Expand Up @@ -104,7 +105,147 @@ int af_change_app_status(cJSON * data_obj, int status)

return 0;
}
DEFINE_RWLOCK(af_mac_lock);
#define MAX_AF_MAC_HASH_SIZE 64
#define AF_MAC_LOCK_R() read_lock_bh(&af_mac_lock);
#define AF_MAC_UNLOCK_R() read_unlock_bh(&af_mac_lock);
#define AF_MAC_LOCK_W() write_lock_bh(&af_mac_lock);
#define AF_MAC_UNLOCK_W() write_unlock_bh(&af_mac_lock);

u32 total_mac = 0;
struct list_head af_mac_list_table[MAX_AF_MAC_HASH_SIZE];

void
af_mac_list_init(void)
{
int i;
AF_MAC_LOCK_W();
for(i = 0; i < MAX_AF_MAC_HASH_SIZE; i ++){
INIT_LIST_HEAD(&af_mac_list_table[i]);
}
AF_MAC_UNLOCK_W();
AF_INFO("client list init......ok\n");
}

void
af_mac_list_clear(void)
{
int i;
af_mac_info_t * p = NULL;
char mac_str[32] = {0};

AF_DEBUG("clean list\n");
AF_MAC_LOCK_W();
for (i = 0; i < MAX_AF_MAC_HASH_SIZE;i++){
while(!list_empty(&af_mac_list_table[i])){
p = list_first_entry(&af_mac_list_table[i], af_mac_info_t, hlist);
memset(mac_str, 0x0, sizeof(mac_str));
sprintf(mac_str, MAC_FMT, MAC_ARRAY(p->mac));
AF_DEBUG("clean mac:%s\n", mac_str);
list_del(&(p->hlist));
kfree(p);
}
}
total_mac = 0;
AF_MAC_UNLOCK_W();
}


int hash_mac(unsigned char *mac)
{
if (!mac)
return 0;
else
return mac[5] & (MAX_AF_MAC_HASH_SIZE - 1);
}

af_mac_info_t * find_af_mac(unsigned char *mac)
{
af_mac_info_t *node;
unsigned int index;

index = hash_mac(mac);
list_for_each_entry(node, &af_mac_list_table[index], hlist){
if (0 == memcmp(node->mac, mac, 6)){
AF_ERROR("match mac:"MAC_FMT"\n", MAC_ARRAY(node->mac));
return node;
}
}
return NULL;
}

static af_mac_info_t *
af_mac_add(unsigned char *mac)
{
af_mac_info_t *node;
int index = 0;

node = (af_mac_info_t *)kmalloc(sizeof(af_mac_info_t), GFP_ATOMIC);
if (node == NULL) {
AF_ERROR("kmalloc failed\n");
return NULL;
}

memset(node, 0, sizeof(af_mac_info_t));
memcpy(node->mac, mac, MAC_ADDR_LEN);

index = hash_mac(mac);

AF_LMT_INFO("new client mac="MAC_FMT"\n", MAC_ARRAY(node->mac));
total_mac++;
list_add(&(node->hlist), &af_mac_list_table[index]);
return node;
}

int is_user_match_enable(void){
return total_mac > 0;
}
int mac_to_hex(u8 *mac, u8 *mac_hex){
u8 mac_tmp[MAC_ADDR_LEN];
int ret = 0;
ret = sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned int *)&mac_tmp[0],
(unsigned int *)&mac_tmp[1],
(unsigned int *)&mac_tmp[2],
(unsigned int *)&mac_tmp[3],
(unsigned int *)&mac_tmp[4],
(unsigned int *)&mac_tmp[5]);
if (MAC_ADDR_LEN != ret)
return -1;
memcpy(mac_hex, mac_tmp, MAC_ADDR_LEN);
return 0;
}
int af_set_mac_list(cJSON * data_obj)
{
int i;
int id;
int type;
u8 mac_hex[MAC_ADDR_LEN] = {0};
if (!data_obj) {
AF_ERROR("data obj is null\n");
return -1;
}
cJSON *mac_arr = cJSON_GetObjectItem(data_obj, "mac_list");
if (!mac_arr){
AF_ERROR("apps obj is null\n");
return -1;
}
af_mac_list_clear();
for (i = 0; i < cJSON_GetArraySize(mac_arr); i++) {
cJSON *mac_obj = cJSON_GetArrayItem(mac_arr, i);
if (!mac_obj){
AF_ERROR("appid obj is null\n");
return -1;
}
if (-1 == mac_to_hex(mac_obj->valuestring, mac_hex)){
AF_ERROR("mac format error: %s\n", mac_obj->valuestring);
continue;
}
af_mac_add(mac_hex);
}
printk("## mac num = %d\n", total_mac);
return 0;
}

void af_init_app_status(void)
{
Expand Down Expand Up @@ -177,6 +318,9 @@ int af_config_handle(char *config, unsigned int len)
case AF_CMD_CLEAN_APPID:
af_init_app_status();
break;
case AF_CMD_SET_MAC_LIST:
af_set_mac_list(data_obj);
break;
default:
AF_ERROR("invalid cmd %d\n", cmd_obj->valueint);
return -1;
Expand Down
Loading

0 comments on commit 11f3335

Please sign in to comment.