1 2#include <linux/init.h> 3#include <linux/module.h> 4#include <net/tcp.h> 5#include <linux/netfilter.h> 6#include <net/netfilter/nf_conntrack.h> 7#include <linux/skbuff.h> 8#include <net/ip.h> 9#include <linux/types.h> 10#include <net/sock.h> 11#include <linux/etherdevice.h> 12#include <linux/cdev.h> 13#include <linux/vmalloc.h> 14#include <linux/device.h> 15#include "cJSON.h" 16#include "app_filter.h" 17#include "af_utils.h" 18#include "af_log.h" 19#define AF_MAX_APP_TYPE_NUM 16 20#define AF_MAX_APP_NUM 256 21#define AF_DEV_NAME "appfilter" 22 23DEFINE_RWLOCK(af_rule_lock); 24 25#define af_rule_read_lock() read_lock_bh(&af_rule_lock); 26#define af_rule_read_unlock() read_unlock_bh(&af_rule_lock); 27#define af_rule_write_lock() write_lock_bh(&af_rule_lock); 28#define af_rule_write_unlock() write_unlock_bh(&af_rule_lock); 29 30static struct mutex af_cdev_mutex; 31struct af_config_dev 32{ 33 dev_t id; 34 struct cdev char_dev; 35 struct class *c; 36}; 37struct af_config_dev g_af_dev; 38 39struct af_cdev_file 40{ 41 size_t size; 42 char buf[256 << 10]; 43}; 44 45enum AF_CONFIG_CMD 46{ 47 AF_CMD_ADD_APPID = 1, 48 AF_CMD_DEL_APPID, 49 AF_CMD_CLEAN_APPID, 50 AF_CMD_SET_MAC_LIST, 51}; 52 53char g_app_id_array[AF_MAX_APP_TYPE_NUM][AF_MAX_APP_NUM] = {0}; 54 55void af_show_app_status(void) 56{ 57 int i, j; 58 AF_DEBUG("#########show app status##########\n"); 59 for (i = 0; i < AF_MAX_APP_TYPE_NUM; i++) 60 { 61 for (j = 0; j < AF_MAX_APP_NUM; j++) 62 { 63 64 af_rule_read_lock(); 65 if (g_app_id_array[i][j] == AF_TRUE) 66 { 67 AF_DEBUG("%d, %d\n", i, j); 68 } 69 af_rule_read_unlock(); 70 } 71 } 72 73 AF_DEBUG("\n\n\n"); 74} 75 76int af_change_app_status(cJSON *data_obj, int status) 77{ 78 int i; 79 int id; 80 int type; 81 cJSON *appid_arr = NULL; 82 if (!data_obj) 83 { 84 AF_ERROR("data obj is null\n"); 85 return -1; 86 } 87 appid_arr = cJSON_GetObjectItem(data_obj, "apps"); 88 if (!appid_arr) 89 { 90 AF_ERROR("apps obj is null\n"); 91 return -1; 92 } 93 for (i = 0; i < cJSON_GetArraySize(appid_arr); i++) 94 { 95 cJSON *appid_obj = cJSON_GetArrayItem(appid_arr, i); 96 if (!appid_obj) 97 return -1; 98 id = AF_APP_ID(appid_obj->valueint); 99 type = AF_APP_TYPE(appid_obj->valueint); 100 af_rule_write_lock(); 101 g_app_id_array[type][id] = status; 102 af_rule_write_unlock(); 103 } 104 105 return 0; 106} 107DEFINE_RWLOCK(af_mac_lock); 108#define MAX_AF_MAC_HASH_SIZE 64 109#define AF_MAC_LOCK_R() read_lock_bh(&af_mac_lock); 110#define AF_MAC_UNLOCK_R() read_unlock_bh(&af_mac_lock); 111#define AF_MAC_LOCK_W() write_lock_bh(&af_mac_lock); 112#define AF_MAC_UNLOCK_W() write_unlock_bh(&af_mac_lock); 113 114u32 total_mac = 0; 115struct list_head af_mac_list_table[MAX_AF_MAC_HASH_SIZE]; 116 117void af_mac_list_init(void) 118{ 119 int i; 120 AF_MAC_LOCK_W(); 121 for (i = 0; i < MAX_AF_MAC_HASH_SIZE; i++) 122 { 123 INIT_LIST_HEAD(&af_mac_list_table[i]); 124 } 125 AF_MAC_UNLOCK_W(); 126 AF_INFO("client list init......ok\n"); 127} 128 129void af_mac_list_clear(void) 130{ 131 int i; 132 af_mac_info_t *p = NULL; 133 char mac_str[32] = {0}; 134 135 AF_DEBUG("clean list\n"); 136 AF_MAC_LOCK_W(); 137 for (i = 0; i < MAX_AF_MAC_HASH_SIZE; i++) 138 { 139 while (!list_empty(&af_mac_list_table[i])) 140 { 141 p = list_first_entry(&af_mac_list_table[i], af_mac_info_t, hlist); 142 memset(mac_str, 0x0, sizeof(mac_str)); 143 sprintf(mac_str, MAC_FMT, MAC_ARRAY(p->mac)); 144 AF_DEBUG("clean mac:%s\n", mac_str); 145 list_del(&(p->hlist)); 146 kfree(p); 147 } 148 } 149 total_mac = 0; 150 AF_MAC_UNLOCK_W(); 151} 152 153int hash_mac(unsigned char *mac) 154{ 155 if (!mac) 156 return 0; 157 else 158 return mac[5] & (MAX_AF_MAC_HASH_SIZE - 1); 159} 160 161af_mac_info_t *find_af_mac(unsigned char *mac) 162{ 163 af_mac_info_t *node; 164 unsigned int index; 165 166 index = hash_mac(mac); 167 list_for_each_entry(node, &af_mac_list_table[index], hlist) 168 { 169 if (0 == memcmp(node->mac, mac, 6)) 170 { 171 AF_DEBUG("match mac:" MAC_FMT "\n", MAC_ARRAY(node->mac)); 172 return node; 173 } 174 } 175 return NULL; 176} 177 178static af_mac_info_t * 179af_mac_add(unsigned char *mac) 180{ 181 af_mac_info_t *node; 182 int index = 0; 183 184 node = (af_mac_info_t *)kmalloc(sizeof(af_mac_info_t), GFP_ATOMIC); 185 if (node == NULL) 186 { 187 AF_ERROR("kmalloc failed\n"); 188 return NULL; 189 } 190 191 memset(node, 0, sizeof(af_mac_info_t)); 192 memcpy(node->mac, mac, MAC_ADDR_LEN); 193 194 index = hash_mac(mac); 195 196 AF_LMT_INFO("new client mac=" MAC_FMT "\n", MAC_ARRAY(node->mac)); 197 total_mac++; 198 list_add(&(node->hlist), &af_mac_list_table[index]); 199 return node; 200} 201 202int is_user_match_enable(void) 203{ 204 return total_mac > 0; 205} 206int mac_to_hex(u8 *mac, u8 *mac_hex) 207{ 208 u32 mac_tmp[MAC_ADDR_LEN]; 209 int ret = 0, i = 0; 210 ret = sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", 211 (unsigned int *)&mac_tmp[0], 212 (unsigned int *)&mac_tmp[1], 213 (unsigned int *)&mac_tmp[2], 214 (unsigned int *)&mac_tmp[3], 215 (unsigned int *)&mac_tmp[4], 216 (unsigned int *)&mac_tmp[5]); 217 if (MAC_ADDR_LEN != ret) 218 return -1; 219 for (i = 0; i < MAC_ADDR_LEN; i++) 220 { 221 mac_hex[i] = mac_tmp[i]; 222 } 223 return 0; 224} 225int af_set_mac_list(cJSON *data_obj) 226{ 227 int i; 228 cJSON *mac_arr = NULL; 229 u8 mac_hex[MAC_ADDR_LEN] = {0}; 230 if (!data_obj) 231 { 232 AF_ERROR("data obj is null\n"); 233 return -1; 234 } 235 mac_arr = cJSON_GetObjectItem(data_obj, "mac_list"); 236 if (!mac_arr) 237 { 238 AF_ERROR("apps obj is null\n"); 239 return -1; 240 } 241 af_mac_list_clear(); 242 for (i = 0; i < cJSON_GetArraySize(mac_arr); i++) 243 { 244 cJSON *mac_obj = cJSON_GetArrayItem(mac_arr, i); 245 if (!mac_obj) 246 { 247 AF_ERROR("appid obj is null\n"); 248 return -1; 249 } 250 if (-1 == mac_to_hex(mac_obj->valuestring, mac_hex)) 251 { 252 continue; 253 } 254 af_mac_add(mac_hex); 255 } 256 AF_DEBUG("## mac num = %d\n", total_mac); 257 return 0; 258} 259 260void af_init_app_status(void) 261{ 262 int i, j; 263 264 for (i = 0; i < AF_MAX_APP_TYPE_NUM; i++) 265 { 266 for (j = 0; j < AF_MAX_APP_NUM; j++) 267 { 268 af_rule_write_lock(); 269 g_app_id_array[i][j] = AF_FALSE; 270 af_rule_write_unlock(); 271 } 272 } 273} 274int af_get_app_status(int appid) 275{ 276 int status = 0; 277 int id = AF_APP_ID(appid); 278 int type = AF_APP_TYPE(appid); 279 af_rule_read_lock(); 280 status = g_app_id_array[type][id]; 281 af_rule_read_unlock(); 282 return status; 283} 284/* 285add: 286{ 287 "op":1, 288 "data"{ 289 "apps":[] 290 } 291} 292clean 293{ 294 "op":3, 295} 296 297*/ 298int af_config_handle(char *config, unsigned int len) 299{ 300 cJSON *config_obj = NULL; 301 cJSON *cmd_obj = NULL; 302 cJSON *data_obj = NULL; 303 if (!config || len == 0) 304 { 305 AF_ERROR("config or len is invalid\n"); 306 return -1; 307 } 308 config_obj = cJSON_Parse(config); 309 if (!config_obj) 310 { 311 AF_ERROR("config_obj is NULL\n"); 312 return -1; 313 } 314 cmd_obj = cJSON_GetObjectItem(config_obj, "op"); 315 if (!cmd_obj) 316 { 317 AF_ERROR("not find op object\n"); 318 return -1; 319 } 320 data_obj = cJSON_GetObjectItem(config_obj, "data"); 321 322 switch (cmd_obj->valueint) 323 { 324 case AF_CMD_ADD_APPID: 325 if (!data_obj) 326 break; 327 af_change_app_status(data_obj, AF_TRUE); 328 break; 329 case AF_CMD_DEL_APPID: 330 if (!data_obj) 331 break; 332 af_change_app_status(data_obj, AF_FALSE); 333 break; 334 case AF_CMD_CLEAN_APPID: 335 af_init_app_status(); 336 break; 337 case AF_CMD_SET_MAC_LIST: 338 af_set_mac_list(data_obj); 339 break; 340 default: 341 AF_ERROR("invalid cmd %d\n", cmd_obj->valueint); 342 return -1; 343 } 344 af_show_app_status(); 345 return 0; 346} 347 348static int af_cdev_open(struct inode *inode, struct file *filp) 349{ 350 struct af_cdev_file *file; 351 file = vzalloc(sizeof(*file)); 352 if (!file) 353 return -EINVAL; 354 355 mutex_lock(&af_cdev_mutex); 356 filp->private_data = file; 357 return 0; 358} 359 360static ssize_t af_cdev_read(struct file *filp, char *buf, size_t count, loff_t *off) 361{ 362 return 0; 363} 364 365static int af_cdev_release(struct inode *inode, struct file *filp) 366{ 367 struct af_cdev_file *file = filp->private_data; 368 AF_DEBUG("config size: %d,data = %s\n", (int)file->size, file->buf); 369 af_config_handle(file->buf, file->size); 370 filp->private_data = NULL; 371 mutex_unlock(&af_cdev_mutex); 372 vfree(file); 373 return 0; 374} 375 376static ssize_t af_cdev_write(struct file *filp, const char *buffer, size_t count, loff_t *off) 377{ 378 struct af_cdev_file *file = filp->private_data; 379 int ret; 380 if (file->size + count > sizeof(file->buf)) 381 { 382 AF_ERROR("config overflow, cur_size: %d, block_size: %d, max_size: %d", 383 (int)file->size, (int)count, (int)sizeof(file->buf)); 384 return -EINVAL; 385 } 386 387 ret = copy_from_user(file->buf + file->size, buffer, count); 388 if (ret != 0) 389 return -EINVAL; 390 391 file->size += count; 392 return count; 393} 394 395static struct file_operations af_cdev_ops = { 396 owner : THIS_MODULE, 397 release : af_cdev_release, 398 open : af_cdev_open, 399 write : af_cdev_write, 400 read : af_cdev_read, 401}; 402 403int af_register_dev(void) 404{ 405 struct device *dev; 406 int res; 407 mutex_init(&af_cdev_mutex); 408 409 res = alloc_chrdev_region(&g_af_dev.id, 0, 1, AF_DEV_NAME); 410 if (res != 0) 411 { 412 return -EINVAL; 413 } 414 415 cdev_init(&g_af_dev.char_dev, &af_cdev_ops); 416 res = cdev_add(&g_af_dev.char_dev, g_af_dev.id, 1); 417 if (res < 0) 418 { 419 goto REGION_OUT; 420 } 421 422 g_af_dev.c = class_create(THIS_MODULE, AF_DEV_NAME); 423 if (IS_ERR_OR_NULL(g_af_dev.c)) 424 { 425 goto CDEV_OUT; 426 } 427 428 dev = device_create(g_af_dev.c, NULL, g_af_dev.id, NULL, AF_DEV_NAME); 429 if (IS_ERR_OR_NULL(dev)) 430 { 431 goto CLASS_OUT; 432 } 433 AF_INFO("register char dev....ok\n"); 434 435 return 0; 436 437CLASS_OUT: 438 class_destroy(g_af_dev.c); 439CDEV_OUT: 440 cdev_del(&g_af_dev.char_dev); 441REGION_OUT: 442 unregister_chrdev_region(g_af_dev.id, 1); 443 444 AF_ERROR("register char dev....fail\n"); 445 return -EINVAL; 446} 447 448void af_unregister_dev(void) 449{ 450 device_destroy(g_af_dev.c, g_af_dev.id); 451 class_destroy(g_af_dev.c); 452 cdev_del(&g_af_dev.char_dev); 453 unregister_chrdev_region(g_af_dev.id, 1); 454 AF_INFO("unregister char dev....ok\n"); 455} 456