暂时回退oaf到原始版本,解决7621出现不断重启的问题

This commit is contained in:
Derry 2019-11-04 09:31:12 +08:00
parent a837b0284a
commit ed07f06293
2 changed files with 3 additions and 888 deletions

View File

@ -11,7 +11,6 @@
#include <net/tcp.h>
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_acct.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <linux/types.h>
@ -37,8 +36,7 @@ DEFINE_RWLOCK(af_feature_lock);
#define feature_list_read_unlock() read_unlock_bh(&af_feature_lock);
#define feature_list_write_lock() write_lock_bh(&af_feature_lock);
#define feature_list_write_unlock() write_unlock_bh(&af_feature_lock);
// ×¢ÒâÓÐÖØ´«±¨ÎÄ
#define MAX_PARSE_PKT_NUM 16
#define MIN_HTTP_DATA_LEN 16
#define MAX_APP_NAME_LEN 64
#define MAX_FEATURE_NUM_PER_APP 16
@ -773,7 +771,6 @@ int app_filter_match(flow_info_t *flow)
return AF_FALSE;
}
#define APP_FILTER_DROP_BITS 0xf0000000
/* ÔÚnetfilter¿ò¼Ü×¢²áµÄ¹³×Ó */
@ -789,57 +786,24 @@ static u_int32_t app_filter_hook(unsigned int hook,
const struct net_device *out,
int (*okfn)(struct sk_buff *)){
#endif
unsigned long long total_packets = 0;
flow_info_t flow;
// 4.10-->4.11 nfct-->_nfct
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)
struct nf_conn *ct = (struct nf_conn *)skb->_nfct;
#else
struct nf_conn *ct = (struct nf_conn *)skb->nfct;
#endif
if (ct == NULL) {
//AF_ERROR("ct is null\n");
return NF_ACCEPT;
}
#if defined(CONFIG_NF_CONNTRACK_MARK)
if (ct->mark != 0)
if (APP_FILTER_DROP_BITS == (ct->mark & APP_FILTER_DROP_BITS)){
return NF_DROP;
}
#endif
// 3.12.74-->3.13-rc1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
struct nf_conn_acct *acct;
acct = nf_conn_acct_find(ct);
if (!acct)
return NF_ACCEPT;
total_packets = (unsigned long long)atomic64_read(&acct->counter[IP_CT_DIR_ORIGINAL].packets)
+ (unsigned long long)atomic64_read(&acct->counter[IP_CT_DIR_REPLY].packets);
#else
struct nf_conn_counter *counter;
counter = nf_conn_acct_find(ct);
if (!counter)
return NF_ACCEPT;
total_packets = (unsigned long long)atomic64_read(&counter[IP_CT_DIR_ORIGINAL].packets)
+ (unsigned long long)atomic64_read(&counter[IP_CT_DIR_REPLY].packets);
#endif
if (total_packets > MAX_PARSE_PKT_NUM){
return NF_ACCEPT;
}
flow_info_t flow;
memset((char *)&flow, 0x0, sizeof(flow_info_t));
parse_flow_base(skb, &flow);
parse_http_proto(&flow);
parse_https_proto(&flow);
//dump_flow_info(&flow);
if (app_filter_match(&flow)){
#if defined(CONFIG_NF_CONNTRACK_MARK)
ct->mark |= APP_FILTER_DROP_BITS;
#endif
if (app_filter_match(&flow))
return NF_DROP;
}
return NF_ACCEPT;
}

View File

@ -1,849 +0,0 @@
/*
author: destan19@126.com
: wifi开发者
date:2019/1/10
*/
#include <linux/init.h>
#include <linux/module.h>
#include <net/tcp.h>
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <linux/types.h>
#include <net/sock.h>
#include <linux/etherdevice.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include "app_filter.h"
#include "af_utils.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("destan19@126.com");
MODULE_DESCRIPTION("app filter module");
MODULE_VERSION("1.0.2");
struct list_head af_feature_head = LIST_HEAD_INIT(af_feature_head);
#define AF_FEATURE_CONFIG_FILE "/etc/appfilter/feature.cfg"
#define AF_DEV_NAME "appfilter"
DEFINE_RWLOCK(af_feature_lock);
#define feature_list_read_lock() read_lock_bh(&af_feature_lock);
#define feature_list_read_unlock() read_unlock_bh(&af_feature_lock);
#define feature_list_write_lock() write_lock_bh(&af_feature_lock);
#define feature_list_write_unlock() write_unlock_bh(&af_feature_lock);
#define MIN_HTTP_DATA_LEN 16
#define MAX_APP_NAME_LEN 64
#define MAX_FEATURE_NUM_PER_APP 16
#define MAX_FEATURE_STR_LEN 128
#define MAX_HOST_URL_LEN 128
#define MAX_REQUEST_URL_LEN 128
#define MAX_MATH_DATA_LEN 1600
#define MAX_FEATURE_BITS 16
#define MAX_POS_INFO_PER_FEATURE 16
#define MAX_FEATURE_LINE_LEN 256
#define MIN_FEATURE_LINE_LEN 16
typedef struct af_pos_info{
int pos;
unsigned char value;
}af_pos_info_t;
typedef struct af_feature_node{
struct list_head head;
int app_id;
char app_name[MAX_APP_NAME_LEN];
char feature_str[MAX_FEATURE_NUM_PER_APP][MAX_FEATURE_STR_LEN];
int proto;
int dport;
char host_url[MAX_HOST_URL_LEN];
char request_url[MAX_REQUEST_URL_LEN];
int pos_num;
af_pos_info_t pos_info[MAX_POS_INFO_PER_FEATURE];
}af_feature_node_t;
struct af_config_dev {
dev_t id;
struct cdev char_dev;
struct class *c;
};
struct af_config_dev g_af_dev;
static void show_feature_list(void)
{
af_feature_node_t *n,*node;
unsigned int count = 0;
feature_list_read_lock();
if(!list_empty(&af_feature_head)) { // handle qos
list_for_each_entry_safe(node, n, &af_feature_head, head) {
count ++;
printk("[%d] id=%d appname:%s, dport:%d, host:%s, request:%s\n",
count,
node->app_id, node->app_name,
node->dport,node->host_url, node->request_url);
int i;
for (i = 0;i < node->pos_num;i++){
printk("(%d:%x)-->",
node->pos_info[i].pos,
node->pos_info[i].value);
}
printk("\n----------------------------------------\n\n\n");
}
}
feature_list_read_unlock();
}
static af_feature_node_t* af_find_feature(char *app_id)
{
af_feature_node_t *node;
feature_list_read_lock();
if (!list_empty(&af_feature_head)) {
list_for_each_entry(node, &af_feature_head, head) {
if (node->app_id == app_id){
feature_list_read_unlock();
return node;
}
}
}
feature_list_read_unlock();
return NULL;
}
enum AF_FEATURE_PARAM_INDEX{
AF_PROTO_PARAM_INDEX,
AF_DST_PORT_PARAM_INDEX,
AF_HOST_URL_PARAM_INDEX,
AF_REQUEST_URL_PARAM_INDEX,
AF_DICT_PARAM_INDEX,
};
int __add_app_feature(int appid,
char *name,
int proto,
int dst_port,
char *host_url,
char *request_url,
char *dict)
{
af_feature_node_t *node = NULL;
node = kzalloc(sizeof(af_feature_node_t), GFP_KERNEL);
if (node == NULL) {
printk("malloc feature memory error\n");
return -1;
}
else {
node->app_id = appid;
strcpy(node->app_name, name);
node->proto = proto;
node->dport = dst_port;
strcpy(node->host_url, host_url);
strcpy(node->request_url, request_url);
// 00:0a-01:11
char *p = dict;
char *begin = dict;
char pos[32] = {0};
int index = 0;
int value = 0;
while (*p++) {
if (*p == '-'){
memset(pos, 0x0, sizeof(pos));
strncpy(pos, begin, p - begin);
k_sscanf(pos, "%d:%x",&index, &value);
begin = p + 1;
node->pos_info[node->pos_num].pos = index;
node->pos_info[node->pos_num].value = value;
node->pos_num++;
}
}
if (begin != dict) {
strncpy(pos, begin, p - begin);
k_sscanf(pos, "%d:%x",&index, &value);
node->pos_info[node->pos_num].pos = index;
node->pos_info[node->pos_num].value = value;
node->pos_num++;
}
feature_list_write_lock();
list_add(&(node->head), &af_feature_head);
feature_list_write_unlock();
}
}
int add_app_feature(int appid, char *name, char *feature)
{
char proto_str[16] = {0};
int port_str[16] = {0};
char host_url[32] = {0};
char request_url[128] = {0};
char dict[128] = {0};
int proto = IPPROTO_TCP;
if (!name || !feature) {
printk("error, name or feature is null\n");
return -1;
}
// tcp;8000;www.sina.com;0:get_name;00:0a-01:11
char *p = feature;
char *begin = feature;
int param_num = 0;
while(*p++) {
if (*p != ';')
continue;
switch(param_num){
case AF_PROTO_PARAM_INDEX:
strncpy(proto_str, begin, p - begin);
break;
case AF_DST_PORT_PARAM_INDEX:
strncpy(port_str, begin, p - begin);
break;
case AF_HOST_URL_PARAM_INDEX:
strncpy(host_url, begin, p - begin);
break;
case AF_REQUEST_URL_PARAM_INDEX:
strncpy(request_url, begin, p - begin);
break;
}
param_num ++;
begin = p + 1;
}
if (AF_DICT_PARAM_INDEX != param_num) {
printk("invalid feature:%s\n", feature);
return -1;
}
strncpy(dict, begin, p - begin);
//sscanf(feature, "%[^;];%d;%[^;];%[^;];%s", proto, &dst_port, host, url, dict);
//printk("proto = %s, port = %s, host = %s, url = %s, dict = %s\n",
// proto_str, port_str, host_url, request_url, dict);
if (0 == strcmp(proto_str, "tcp"))
proto = IPPROTO_TCP;
else if (0 == strcmp(proto_str, "udp"))
proto = IPPROTO_UDP;
else {
printk("proto %s is not support\n", proto_str);
return -1;
}
int dst_port = 0;
sscanf(port_str, "%d", &dst_port);
__add_app_feature(appid,
name,
proto,
dst_port,
host_url,
request_url,
dict);
return 0;
}
void af_init_feature(char *feature_str)
{
// char * qq_config_str = "1001 qq :[tcp;8000;r:www.baidu.com;4:get_status;00:0a-01:11]";
// char * qq_config_str = "1001 qq:[tcp;443;baidu.com;get_status;00:0a-01:11,tcp;8000;www.sina.com;0:22222get;00:0a-01:11,tcp;8000;www.sina.com;hao123;00:0a-01:11-02:ff]";
// char * qq_config_str = "1001 qq:[tcp;443;r:www.baidu.com;4:get_status;00:0a-01:11,tcp;8000;www.sina.com;0:22222get;00:0a-01:11,tcp;8000;www.sina.com;hao123;00:0a-01:11-02:ff]";
int app_id;
char app_name[128] = {0};
char feature_buf[MAX_FEATURE_LINE_LEN] = {0};
printk("feature_str=%s\n",feature_str);
k_sscanf(feature_str, "%d%[^:]", &app_id, app_name);
printk("id = %d, name = %s\n",app_id, app_name);
char *p = feature_str;
char *pos = NULL;
int len = 0;
while(*p++) {
if (*p == '['){
pos = p + 1;
continue;
}
if (*p == ']' && pos != NULL) {
len = p - pos;
}
}
if (pos && len )
strncpy(feature_buf, pos, len);
char feature[MAX_FEATURE_STR_LEN];;
int i;
memset(feature, 0x0, sizeof(feature));
p = feature_buf;
char *begin = feature_buf;
while(*p++){
if (*p == ',') {
memset(feature, 0x0, sizeof(feature));
strncpy((char *)feature, begin, p - begin);
add_app_feature(app_id, app_name, feature);
begin = p + 1;
}
}
if (p != begin){
memset(feature, 0x0, sizeof(feature));
strncpy((char *)feature, begin, p - begin);
add_app_feature(app_id, app_name, feature);
}
}
void load_feature_buf_from_file(char **config_buf)
{
struct inode *inode;
struct file *fp;
mm_segment_t fs;
off_t size;
fp = filp_open(AF_FEATURE_CONFIG_FILE, O_RDONLY, 0);
if(IS_ERR(fp)) {
printk("open feature file failed\n");
return -1;
}
inode = fp->f_dentry->d_inode;
size = inode->i_size;
printk("file size: %d\n", size);
*config_buf = (char *) kzalloc( sizeof(char) * size, GFP_KERNEL);
if(NULL == *config_buf ) {
printk("alloc buf fail\n");
filp_close(fp, NULL);
return -1;
}
fs = get_fs();
set_fs(KERNEL_DS);
fp->f_op->read(fp, *config_buf, size, &(fp->f_pos));
set_fs(fs);
filp_close(fp, NULL);
return size;
}
void load_feature_config(void)
{
printk("begin load feature config.....\n");
char *feature_buf = NULL;
load_feature_buf_from_file(&feature_buf);
if (!feature_buf) {
printk("error, feature buf is null\n");
return;
}
printk("feature_buf = %s\n", feature_buf);
char *p;
char *begin;
p = begin = feature_buf;
char line[MAX_FEATURE_LINE_LEN] = {0};
while(*p++) {
if (*p == '\n'){
if (p - begin < MIN_FEATURE_LINE_LEN || p - begin > MAX_FEATURE_LINE_LEN ) {
begin = p + 1;
continue;
}
memset(line, 0x0, sizeof(line));
strncpy(line, begin, p - begin);
af_init_feature(line);
begin = p + 1;
}
}
if (p != begin) {
if (p - begin < MIN_FEATURE_LINE_LEN || p - begin > MAX_FEATURE_LINE_LEN )
return;
memset(line, 0x0, sizeof(line));
strncpy(line, begin, p - begin);
af_init_feature(line);
begin = p + 1;
}
if (feature_buf)
kfree(feature_buf);
}
static void af_clean_feature_list()
{
af_feature_node_t *n,*node;
feature_list_write_lock();
while(!list_empty(&af_feature_head)) {
node = list_first_entry(&af_feature_head, af_feature_node_t, head);
list_del(&(node->head));
kfree(node);
}
feature_list_write_unlock();
}
int parse_flow_base(struct sk_buff *skb, flow_info_t *flow)
{
struct tcphdr * tcph = NULL;
struct udphdr * udph = NULL;
struct nf_conn *ct = NULL;
struct iphdr *iph = NULL;
if (!skb) {
return -1;
}
ct = (struct nf_conn *)skb->nfct;
if (!ct) {
return -1;
}
iph = ip_hdr(skb);
if ( !iph ) {
return -1;
}
flow->ct = ct;
flow->src = iph->saddr;
flow->dst = iph->daddr;
flow->l4_protocol = iph->protocol;
switch (iph->protocol) {
case IPPROTO_TCP:
tcph = (struct tcphdr *)(iph + 1);
flow->l4_data = skb->data + iph->ihl * 4 + tcph->doff * 4;
flow->l4_len = ntohs(iph->tot_len) - iph->ihl * 4 - tcph->doff * 4;
flow->dport = htons(tcph->dest);
flow->sport = htons(tcph->source);
break;
case IPPROTO_UDP:
udph = (struct udphdr *)(iph + 1);
flow->l4_data = skb->data + iph->ihl * 4 + 8;
flow->l4_len = ntohs(udph->len) - 8;
flow->dport = htons(udph->dest);
flow->sport = htons(udph->source);
break;
case IPPROTO_ICMP:
break;
default:
return -1;
}
return -1;
}
/*
desc: https url信息flow中
return:
-1: error
0: match
author: Derry
Date:2018/12/19
*/
int parse_https_proto(flow_info_t *flow) {
int i ;
short url_len = 0 ;
char * p = flow->l4_data;
int data_len = flow->l4_len;
if (NULL == flow) {
AF_ERROR("flow is NULL\n");
return -1;
}
if (NULL == p || data_len == 0) {
return -1;
}
if (!(p[0] == 0x16 && p[1] == 0x03 && p[2] == 0x01))
return -1;
for(i = 0; i < data_len; i++) {
if(i + HTTPS_URL_OFFSET >= data_len) {
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) {
continue ;
}
if(i + HTTPS_URL_OFFSET + ntohs(url_len) < data_len) {
//dump_hex("https hex", p, data_len);
flow->https.match = AF_TRUE;
flow->https.url_pos = p + i + HTTPS_URL_OFFSET;
//dump_str("https url", flow->https.url_pos, 5);
flow->https.url_len = ntohs(url_len);
return 0;
}
}
}
return -1;
}
void parse_http_proto(flow_info_t *flow)
{
if (!flow) {
AF_ERROR("flow is null\n");
return;
}
if (flow->l4_protocol != IPPROTO_TCP) {
return;
}
int i = 0;
int start = 0;
char *data = flow->l4_data;
int data_len = flow->l4_len;
if (data_len < MIN_HTTP_DATA_LEN) {
return;
}
if (flow->sport != 80 && flow->dport != 80)
return;
for (i = 0; i < data_len - 4; i++) {
if (data[i] == 0x0d && data[i + 1] == 0x0a){
if (0 == memcmp(&data[start], "POST ", 5)) {
flow->http.match = AF_TRUE;
flow->http.method = HTTP_METHOD_POST;
flow->http.url_pos = data + start + 5;
flow->http.url_len = i - start - 5;
//dump_str("get request", flow->http.url_pos, flow->http.url_len);
}
else if(0 == memcmp(&data[start], "GET ", 4)) {
flow->http.match = AF_TRUE;
flow->http.method = HTTP_METHOD_GET;
flow->http.url_pos = data + start + 4;
flow->http.url_len = i - start - 4;
//dump_str("post request", flow->http.url_pos, flow->http.url_len);
}
else if (0 == memcmp(&data[start], "Host: ", 6) ){
flow->http.host_pos = data + start + 6;
flow->http.host_len = i - start - 6;
//dump_str("host ", flow->http.host_pos, flow->http.host_len);
}
// 判断http头部结束
if (data[i + 2] == 0x0d && data[i + 3] == 0x0a){
flow->http.data_pos = data + i + 4;
flow->http.data_len = data_len - i - 4;
break;
}
// 0x0d 0x0a
start = i + 2;
}
}
}
static void dump_http_flow_info(http_proto_t *http) {
if (!http) {
AF_ERROR("http ptr is NULL\n");
return ;
}
if (!http->match)
return;
if (http->method == HTTP_METHOD_GET){
printk("Http method: "HTTP_GET_METHOD_STR"\n");
}
else if (http->method == HTTP_METHOD_POST) {
printk("Http method: "HTTP_POST_METHOD_STR"\n");
}
if (http->url_len > 0 && http->url_pos){
dump_str("Request url", http->url_pos, http->url_len);
}
if (http->host_len > 0 && http->host_pos){
dump_str("Host", http->host_pos, http->host_len);
}
printk("--------------------------------------------------------\n\n\n");
}
static void dump_https_flow_info(https_proto_t *https) {
if (!https) {
AF_ERROR("https ptr is NULL\n");
return ;
}
if (!https->match)
return;
if (https->url_len > 0 && https->url_pos){
printk("url len = %d\n",https->url_len);
dump_str("https server name", https->url_pos, https->url_len);
}
printk("--------------------------------------------------------\n\n\n");
}
static void dump_flow_info(flow_info_t *flow)
{
if (!flow) {
AF_ERROR("flow is null\n");
return;
}
#if 0
if (check_local_network_ip(ntohl(flow->src))) {
printk("src ip(inner net):"NIPQUAD_FMT", dst ip = "NIPQUAD_FMT"\n", NIPQUAD(flow->src), NIPQUAD(flow->dst));
}
else {
printk("src ip(outer net):"NIPQUAD_FMT", dst ip = "NIPQUAD_FMT"\n", NIPQUAD(flow->src), NIPQUAD(flow->dst));
}
#endif
if (flow->l4_protocol == IPPROTO_TCP) {
if (AF_TRUE == flow->http.match) {
printk("-------------------http protocol-------------------------\n");
printk("protocol:TCP , sport: %-8d, dport: %-8d, data_len: %-8d\n",
flow->sport, flow->dport, flow->l4_len);
dump_http_flow_info(&flow->http);
}
if (AF_TRUE == flow->https.match) {
dump_https_flow_info(&flow->https);
}
}
else if (flow->l4_protocol == IPPROTO_UDP) {
// printk("protocol:UDP ,sport: %-8d, dport: %-8d, data_len: %-8d\n",
// flow->sport, flow->dport, flow->l4_len);
}
else {
return;
}
}
int app_filter_match(flow_info_t *flow)
{
af_feature_node_t *n,*node;
feature_list_read_lock();
if(!list_empty(&af_feature_head)) {
list_for_each_entry_safe(node, n, &af_feature_head, head) {
if (flow->https.match == AF_TRUE) {
if (flow->https.url_pos &&
strnstr(flow->https.url_pos, node->host_url, flow->https.url_len)){
dump_str("Drop https url ",flow->https.url_pos, flow->https.url_len);
feature_list_read_unlock();
return 1;
}
}
}
}
feature_list_read_unlock();
return 0;
}
/* 在netfilter框架注册的钩子 */
static u_int32_t app_filter_hook(unsigned int hook,
struct sk_buff *pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct nf_conn *ct = (struct nf_conn *)pskb->nfct;
if (ct == NULL) {
AF_ERROR("ct is null\n");
return NF_ACCEPT;
}
flow_info_t flow;
memset((char *)&flow, 0x0, sizeof(flow_info_t));
parse_flow_base(pskb, &flow);
parse_http_proto(&flow);
parse_https_proto(&flow);
dump_flow_info(&flow);
// todo: match url rules
// this is example
#if 0
if (flow.http.match == AF_TRUE) {
if (flow.http.host_pos &&
strnstr(flow.http.host_pos, "sohu", flow.http.host_len)){
dump_str("Drop http url ",flow.http.host_pos, flow.http.host_len);
return NF_DROP;
}
}
if (flow.https.match == AF_TRUE) {
if (flow.https.url_pos &&
strnstr(flow.https.url_pos, "hao123", flow.https.url_len)){
dump_str("Drop https url ",flow.https.url_pos, flow.https.url_len);
return NF_DROP;
}
}
#endif
if (app_filter_match(&flow))
return NF_DROP;
return NF_ACCEPT;
}
static struct nf_hook_ops app_filter_ops[] __read_mostly = {
{
.hook = app_filter_hook,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_MANGLE + 10,
},
};
#include "cJSON.h"
void TEST_cJSON(void)
{
cJSON * root = NULL;
root = cJSON_CreateObject();
if (!root) {
AF_ERROR("create obj failed\n");
return;
}
cJSON_AddNumberToObject(root, "id", 123);
cJSON_AddStringToObject(root, "name", "derry");
char * out = cJSON_Print(root);
printk("out = %s\n", out);
cJSON_Delete(root);
kfree(out);
}
static struct mutex af_cdev_mutex;
struct af_cdev_file {
size_t size;
char buf[256 << 10];
};
static int af_cdev_open(struct inode *inode, struct file *filp)
{
struct af_cdev_file *file;
printk("cdev open\n");
file = vzalloc(sizeof(*file));
if (!file)
return -EINVAL;
mutex_lock(&af_cdev_mutex);
filp->private_data = file;
return 0;
}
static ssize_t af_cdev_read(struct file *filp, char *buf, size_t count, loff_t *off)
{
return 0;
}
static int af_cdev_release(struct inode *inode, struct file *filp)
{
struct af_cdev_file *file = filp->private_data;
int ret;
printk("config size: %d,data = %s\n", (int)file->size, file->buf);
filp->private_data = NULL;
mutex_unlock(&af_cdev_mutex);
vfree(file);
return 0;
}
static ssize_t af_cdev_write(struct file *filp, const char *buffer, size_t count, loff_t *off)
{
struct af_cdev_file *file = filp->private_data;
int ret;
printk("cdev write\n");
if (file->size + count > sizeof(file->buf)) {
printk("config overflow, cur_size: %d, block_size: %d, max_size: %d",
(int)file->size, (int)count, (int)sizeof(file->buf));
return -EINVAL;
}
ret = copy_from_user(file->buf + file->size, buffer, count);
if (ret != 0)
return -EINVAL;
file->size += count;
return count;
}
static struct file_operations af_cdev_ops = {
owner: THIS_MODULE,
release: af_cdev_release,
open: af_cdev_open,
write: af_cdev_write,
read: af_cdev_read,
};
void af_register_dev(void)
{
struct device *dev;
int res;
mutex_init(&af_cdev_mutex);
res = alloc_chrdev_region(&g_af_dev.id, 0, 1, AF_DEV_NAME);
if (res != 0) {
return -EINVAL;
}
cdev_init(&g_af_dev.char_dev, &af_cdev_ops);
res = cdev_add(&g_af_dev.char_dev, g_af_dev.id, 1);
if (res < 0) {
goto REGION_OUT;
}
g_af_dev.c= class_create(THIS_MODULE, AF_DEV_NAME);
if (IS_ERR_OR_NULL(g_af_dev.c)) {
goto CDEV_OUT;
}
dev = device_create(g_af_dev.c, NULL, g_af_dev.id, NULL, AF_DEV_NAME);
if (IS_ERR_OR_NULL(dev)) {
goto CLASS_OUT;
}
printk("register char dev....ok\n");
return 0;
CLASS_OUT:
class_destroy(g_af_dev.c);
CDEV_OUT:
cdev_del(&g_af_dev.char_dev);
REGION_OUT:
unregister_chrdev_region(g_af_dev.id, 1);
printk("register char dev....fail\n");
return -EINVAL;
}
void af_unregister_dev(void)
{
device_destroy(g_af_dev.c, g_af_dev.id);
class_destroy(g_af_dev.c);
cdev_del(&g_af_dev.char_dev);
unregister_chrdev_region(g_af_dev.id, 1);
printk("unregister char dev....ok\n");
}
extern void TEST_regexp();
/*
*/
static int __init app_filter_init(void)
{
AF_INFO("appfilter version:"AF_VERSION"\n");
AF_DEBUG("app filter module init\n");
//TEST_regexp();
af_register_dev();
load_feature_config();
show_feature_list();
TEST_cJSON();
nf_register_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops));
printk("init app filter ........ok\n");
return 0;
}
/*
退
*/
static void app_filter_fini(void)
{
AF_DEBUG("app filter module exit\n");
nf_unregister_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops));
af_clean_feature_list();
af_unregister_dev();
return ;
}
module_init(app_filter_init);
module_exit(app_filter_fini);