#include #include #include #include #include #include #include #include #include #include #include "k-userhash.h" //#include "../modules/usercfgrcv/usercfg_kinit.h" #include #include #include "conntrack_api.h" #include "nf_conntrack.h" #include "k-matchrule.h" #include #include #include #define AUTH_MARK_VALUE 1 #define agingtime 30*60 /*内核在线用户hash表*/ extern struct list_head khash_array[]; /*免认证规则以数组方式存储,用户态增删改移之后通过共享内存同步到内核*/ freeauth_configure_t freeauth_array[10] = {0}; int match_rule(const struct sk_buff *skb, u_int16_t l3num, struct net *net,struct nf_conntrack_tuple *tuple) { const struct nf_conntrack_l3proto *l3proto; const struct nf_conntrack_l4proto *l4proto; unsigned int nhoff; /*nhoff表示L3首部在skb中的偏移 */ unsigned int protoff; u_int8_t protonum; unsigned int dataoff; /*dataoff表示L4首部在skb中的偏移 */ int ret; int result; int match_num; cmhi_ext_type type = AUTH_MARK; int ret_result; int i; K_USERINFO *kresult; kresult = (K_USERINFO *)kmalloc(sizeof(K_USERINFO), GFP_KERNEL); if (NULL == kresult) { return ENOMEM; } /*获取版本号、源端口、目的端口、源IP、目的IP */ /*nf_ct_get_tuple函数主要根据协议号调用pkt_to_tuple生成一个tuple */ /*tcp/udp协议就是生成五元组(源ip、目的ip、源端口、目的端口、协议号),icmp协议就是(id、code、type) */ ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, net, tuple, l3proto, l4proto); if(ret == 0) { printk("resolve_normal_ct: can't get tuple\n"); return EIO; } /*1.判断用户认证成功 ——非重定向 2.判断是否符合免认证规则 ——非重定向 3.判断目的端口是否是80—— 重定向标记 4.目的端口不是80的情况下,判断协议是否是DHCP和DNS,如果是DHCP和DNS——非重定向 5.其余包 drop*/ kresult = search_user(tuple->src.u3.ip); /*用户已经认证通过 */ if(kresult != NULL) { struct timex txc; struct rtc_time tm; do_gettimeofday(&(txc.time)); printk("online time:%d\n", txc.time.tv_sec); /* seconds */ rtc_time_to_tm(txc.time.tv_sec,&tm); printk("UTC time:%d-%d-%d %d-%d-%d\n", tm.tm_year + 1900 , tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); if(txc.time.tv_sec >= agingtime) { /*用户下线*/ del_user(tuple->src.u3.ip); printk("user offline success\n"); } else { int r = add_user(tuple->src.u3.ip, kresult->k_user.kuser_name, kresult->k_user.kuser_id, kresult->k_user.kgroup_id, kresult->k_user.kmessage_num, kresult->k_user.kgroup_id, txc.time.tv_sec); if(r == 0) { printk("add user success\n"); } } /*认证通过后获取下行字节数,存入在线用户hash表*/ #if 0 int r1 = add_user(tuple->src.u3.ip, kresult->k_user.kuser_name, kresult->k_user.kuser_id, kresult->k_user.kgroup_id, ddd kresult->k_user.kgroup_id, txc.time.tv_sec); if(r1 == 0) { printk("add user success\n"); } #endif kfree(kresult); return NF_ACCEPT; } /*报文按优先级匹配免认证规则 */ for(i; i < 10; i++) { /*匹配免认证规则 协议为HTTP协议,HTTP基于TCP, 源IP地址、目的IP地址、目的端口号依次匹配免认证规则*/ printk("number of freeauth rule:%d\n", i); if((tuple->dst.protonum == 6) && (tuple->src.u3.ip == freeauth_array[i].sip) && (tuple->dst.u3.ip = freeauth_array[i].dip) && (tuple->dst.u.tcp.port == freeauth_array[i].dport)) { match_num++; printk("value of match number:%d\n", match_num); break; } } if(match_num == 0) { /*80端口接入的HTTP报文重定向到Web Server */ if((tuple->dst.protonum == 6) && (tuple->dst.u.tcp.port == 80)) { /*打重定向Mark标记 */ printk(KERN_INFO"[test_set_correct_value] test set auth_mark 1\n"); ret_result = cmhi_set_conntrack_u32(skb, AUTH_MARK_VALUE, type); if(ret_result == CMHI_EXT_ERR) { printk(KERN_INFO"[test_set_correct_value] set auth_mark failed\n"); } printk(KERN_INFO"[test_set_correct_value] set auth_mark successed\n"); return NF_ACCEPT; } else if((tuple->dst.u.tcp.port == 67) || (tuple->dst.u.tcp.port == 68) || (tuple->dst.u.tcp.port ==53)) { printk("dhcp or dns\n"); return NF_ACCEPT; } else { printk("drop\n"); return NF_DROP; } } }