secgateway/Product/modules/object_manager/obj_api.c

402 lines
12 KiB
C
Raw Normal View History

#ifdef __KERNEL__
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/in.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#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 \"<params>\" > /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__