#ifdef __KERNEL__ #include #include #include #include #include #include #include #include #include #include "../proc_api/proc_api.h" #include "../../common/cJSON/cJSON.h" #include "obj_api.h" #define OBJ_DEV_MAJOR (220) #define OBJ_DEV_NAME ("isg_objs") #define VERSION ("obj0.0.0.2") #define SHM_MEM_SIZE (1024 * 1024) #define OBJ_DBG_DIR ("obj") typedef struct { struct class *dev_class; atomic_t ref_count; unsigned int mem_size; unsigned char *mem_buf; } OBJECT_DRV, *POBJECT_DRV; static OBJECT_DRV g_obj_device; static PCMHI_OBJECT g_obj_data = NULL; static int server_obj_show(struct seq_file *seq, void *token) { PCMHI_OBJECT obj, tmp; PSERVER_OBJ_CONTENT req = NULL; seq_printf(seq, "Total server items: %u\n", HASH_COUNT(g_obj_data)); seq_printf(seq, "API root direcotry: /proc/%s/\n", PROC_API_DIR_NAME); HASH_ITER(hh, g_obj_data, obj, tmp) { seq_printf(seq, " Name: %s\n", obj->name); seq_printf(seq, " Type: %d\n", obj->type); seq_printf(seq, " RefCount: %d\n", atomic_read(&obj->ref_count)); list_for_each_entry(req, &obj->data->content, list) { seq_printf(seq, " Min Port: %d\n", req->min_port); seq_printf(seq, " Max Port: %d\n", req->max_port); seq_printf(seq, " Pro Port: %d\n", req->pro_type); } } #if 0 PPROC_INFO pInfo = NULL, tmp = NULL; int i = 0; seq_printf(seq, "Total API items: %u\n", HASH_COUNT(g_proc_items)); seq_printf(seq, "API root direcotry: /proc/%s/\n", PROC_API_DIR_NAME); seq_puts(seq, "-------------------------------------" "-------------------------------------\n"); seq_puts(seq, "| ID | Direcotry | Name | Show | IOCtrl | Help |\n"); seq_puts(seq, "|------------------------------------" "------------------------------------|\n"); read_lock(&g_proc_lock); HASH_ITER(hh, g_proc_items, pInfo, tmp) { seq_printf(seq, "| %03d | %14s | %14s | %1s | %1s | %1s |\n", i++, pInfo->dir_name ? pInfo->dir_name : "", pInfo->data->name, pInfo->data->show ? "*" : "-", pInfo->data->ioctl ? "*" : "-", pInfo->data->help ? "*" : "-"); } read_unlock(&g_proc_lock); #endif seq_puts(seq, "-------------------------------------" "-------------------------------------\n"); return 0; } static int server_obj_ioctl(struct seq_file *seq, void *token) { char *json_str = NULL; PCMHI_OBJECT obj = NULL; PSERVER_OBJ_CONTENT req = NULL; PDBGFS_PRIV priv = (PDBGFS_PRIV)(seq->private); seq_printf(seq, "Run Command [%s] with (%s)\n", priv->cmd, priv->cmd_data); if(strcmp(priv->cmd, "get") == 0) { if(strcmp(priv->cmd_data, "all") == 0) { PCMHI_OBJECT obj, tmp; cJSON *top_array, *top_root = cJSON_CreateObject(); if(!top_root) { return -ENOMEM; } top_array = cJSON_CreateArray(); if(!top_array) { cJSON_Delete(top_root); return -ENOMEM; } HASH_ITER(hh, g_obj_data, obj, tmp) { cJSON *array, *root = cJSON_CreateObject(); if(!root) { cJSON_Delete(top_root); cJSON_Delete(top_array); return -ENOMEM; } array = cJSON_CreateArray(); if(!array) { cJSON_Delete(top_root); cJSON_Delete(top_array); cJSON_Delete(root); return -ENOMEM; } cJSON_AddStringToObject(root, "name", obj->name); cJSON_AddNumberToObject(root, "type", obj->type); cJSON_AddNumberToObject(root, "ref_count", atomic_read(&obj->ref_count)); list_for_each_entry(req, &obj->data->content, list) { cJSON *item = cJSON_CreateObject(); if(item) { cJSON_AddNumberToObject(item, "min_port", req->min_port); cJSON_AddNumberToObject(item, "max_port", req->max_port); cJSON_AddNumberToObject(item, "pro_type", req->pro_type); cJSON_AddItemToArray(array, item); } } cJSON_AddItemToObject(root, "content", array); cJSON_AddItemToArray(top_array, root); } cJSON_AddItemToObject(top_root, "data", top_array); json_str = cJSON_Print(top_root); seq_printf(seq, "%s\n", json_str); memcpy(g_obj_device.mem_buf, json_str, strlen(json_str)); g_obj_device.mem_buf[strlen(json_str)] = 0; cJSON_Delete(top_root); kfree(json_str); } else { HASH_FIND_STR(g_obj_data, priv->cmd_data, obj); if(obj) { cJSON *array, *root = cJSON_CreateObject(); if(!root) { return -ENOMEM; } array = cJSON_CreateArray(); if(!array) { return -ENOMEM; } cJSON_AddStringToObject(root, "name", obj->name); cJSON_AddNumberToObject(root, "type", obj->type); cJSON_AddNumberToObject(root, "ref_count", atomic_read(&obj->ref_count)); list_for_each_entry(req, &obj->data->content, list) { cJSON *item = cJSON_CreateObject(); if(item) { cJSON_AddNumberToObject(item, "min_port", req->min_port); cJSON_AddNumberToObject(item, "max_port", req->max_port); cJSON_AddNumberToObject(item, "pro_type", req->pro_type); cJSON_AddItemToArray(array, item); } } cJSON_AddItemToObject(root, "content", array); json_str = cJSON_Print(root); seq_printf(seq, "%s\n", json_str); memcpy(g_obj_device.mem_buf, json_str, strlen(json_str)); g_obj_device.mem_buf[strlen(json_str)] = 0; cJSON_Delete(root); kfree(json_str); } } } return 0; } static int server_obj_help(struct seq_file *seq, void *token) { PDBGFS_PRIV priv = (PDBGFS_PRIV)(seq->private); seq_puts(seq, "==============Options Helps=============\n"); seq_printf(seq, "usage: echo \"\" > /proc/%s/%s/%s\n", PROC_API_DIR_NAME, OBJ_DBG_DIR, priv->name); return 0; } static DBGFS_PRIV g_DbgConfig[] = { { "server", 0, 0L, NULL, NULL, server_obj_show, server_obj_ioctl, server_obj_help }, }; static PROC_API g_object_dbg = { OBJ_DBG_DIR, g_DbgConfig, sizeof(g_DbgConfig) / sizeof(g_DbgConfig[0]), }; static int obj_proc_init(void) { if(proc_api_register(&g_object_dbg) != ERR_DBGFS_NO_ERROR) { printk(KERN_ERR "Regisetr %s Error\n", g_object_dbg.dir_name); return -EINVAL; } return 0; } static int obj_proc_uninit(void) { return proc_api_unregister(&g_object_dbg); } const char *obj_version(void) { return VERSION; } PCMHI_OBJECT new_object(void) { PCMHI_OBJECT obj = (PCMHI_OBJECT)kmalloc(sizeof(CMHI_OBJECT), GFP_KERNEL); if(obj == NULL) { printk(KERN_ERR "Malloc CMHI_OBJECT Error\n"); } else { memset(obj, 0, sizeof(CMHI_OBJECT)); rwlock_init(&obj->lock); atomic_set(&obj->ref_count, 0); } return obj; } void free_object(PCMHI_OBJECT pObj) { if(pObj) { kfree(pObj); } } void object_init(void) { PCMHI_OBJECT pObj = create_server_object("list1", OBJ_TYPE_SERVER); if(!pObj) { printk(KERN_ERR "%s(%d): Create Object Error\n", __FUNCTION__, __LINE__); return; } HASH_ADD_STR(g_obj_data, name, pObj); if(add_server_obj_data(pObj, 10000, 20000, IPPROTO_IP) != 0) { printk(KERN_ERR "%s(%d): Add Server Object error\n", __FUNCTION__, __LINE__); return; } if(add_server_obj_data(pObj, 80, 80, IPPROTO_TCP) != 0) { printk(KERN_ERR "%s(%d): Add Server Object error\n", __FUNCTION__, __LINE__); return; } if(add_server_obj_data(pObj, 443, 443, IPPROTO_UDP) != 0) { printk(KERN_ERR "%s(%d): Add Server Object error\n", __FUNCTION__, __LINE__); return; } } void object_uninit(void) { PCMHI_OBJECT obj, tmp; HASH_ITER(hh, g_obj_data, obj, tmp) { HASH_DEL(g_obj_data, obj); cleanup_server_object(obj); } } static int obj_open(struct inode *inode, struct file *filp) { atomic_inc(&g_obj_device.ref_count); return 0; } static int obj_release(struct inode *inode, struct file *filp) { atomic_dec(&g_obj_device.ref_count); return 0; } int obj_mmap(struct file *fd, struct vm_area_struct *vma) { int ret = remap_pfn_range(vma, vma->vm_start, virt_to_phys(g_obj_device.mem_buf) >> PAGE_SHIFT, g_obj_device.mem_size, PAGE_SHARED); return ret; } static struct file_operations obj_fops = { .open = obj_open, .release = obj_release, .mmap = obj_mmap, }; static int object_module_init(void) { struct page *p = NULL; printk(KERN_INFO "Hello ISG objects manager version: %s\n", VERSION); memset(&g_obj_device, 0, sizeof(OBJECT_DRV)); atomic_set(&g_obj_device.ref_count, 0); g_obj_device.mem_size = PAGE_ALIGN(SHM_MEM_SIZE); g_obj_device.mem_buf = (unsigned char *)__get_free_pages(GFP_KERNEL, get_order(g_obj_device.mem_size)); if(g_obj_device.mem_buf == NULL) { printk(KERN_ERR "Malloc %d pages error\n", get_order(g_obj_device.mem_size)); return -ENOMEM; } for(p = virt_to_page(g_obj_device.mem_buf); p < virt_to_page(g_obj_device.mem_buf + g_obj_device.mem_size); p++) { SetPageReserved(virt_to_page(p)); } memset(g_obj_device.mem_buf, 0, g_obj_device.mem_size); register_chrdev(OBJ_DEV_MAJOR, OBJ_DEV_NAME, &obj_fops); g_obj_device.dev_class = class_create(THIS_MODULE, "obj"); device_create(g_obj_device.dev_class, NULL, MKDEV(OBJ_DEV_MAJOR, 0), NULL, "obj/dev%d", 0); /* if(proc_api_register(&g_ProcApi) != ERR_DBGFS_NO_ERROR) { printk(KERN_ERR "Regisetr %s Error\n", g_ProcApi.dir_name); } */ obj_proc_init(); object_init(); return 0; } module_init(object_module_init); static void __exit object_module_exit(void) { struct page *p = NULL; printk(KERN_INFO "Bye ISG objects manager version: %s\n", VERSION); object_uninit(); if(atomic_read(&g_obj_device.ref_count) != 0) { printk(KERN_ERR "Device used, please close it first.\n"); while(atomic_read(&g_obj_device.ref_count) != 0) { schedule(); } } obj_proc_uninit(); if(g_obj_device.mem_buf) { for(p = virt_to_page(g_obj_device.mem_buf); p < virt_to_page(g_obj_device.mem_buf + g_obj_device.mem_size); p++) { ClearPageReserved(virt_to_page(g_obj_device.mem_buf)); } free_pages((unsigned long)g_obj_device.mem_buf, get_order(g_obj_device.mem_size)); } device_destroy(g_obj_device.dev_class, MKDEV(OBJ_DEV_MAJOR, 0)); class_destroy(g_obj_device.dev_class); unregister_chrdev(OBJ_DEV_MAJOR, OBJ_DEV_NAME); // proc_api_unregister(&g_ProcApi); } module_exit(object_module_exit); MODULE_LICENSE("Dual BSD/GPL"); #endif // __KERNEL__