#include "../api/conntrack_api.h" /* 说明: 测试前提: 1、之前必须有相应的流经过,而且链接跟踪必须没有老化,否则 根据五元组是获取不到ct的,获取不到ct,就无法设置ct里的aid 比如tcp,比如在调用之前要先建立三次握手,只要状态为ESTABLISHED 则ct不会老化. 2、根据五元组获取到ct之后,必须有相应的流经过,才会找到 对应的ct,才能将之前设置的aid查找出来. 测试步骤 1、加载conntrack_api.ko 2、建立tcp三次握手,看状态为ESTABLISHED 3、test中的设置aid的函数dpi_set_aid_test_tcp放在init中 在加载模块的时候只运行一次,get_aid_test放在netfilter的钩子 中,因为这个在将来业务模块调用时会由报文触发 4、加载test.ko(此处的test为在init函数中只设置一次aid,所以 如果未设置tcp三次握手,也就是说没有在链接跟踪中记录到 这个五元组对应的流,则test找不到ct,设置aid失败; 如果dpi_set_aid_test_tcp放在netfilter的钩子中,由报文触发, 则加载test.ko和链接跟踪创建的时序就无所谓了) keypoint: 流触发建立链接跟踪和test的加载顺序,如果设置aid 放在init,只设置一次,那么执行顺序很重要;如果设置aid在netfilter 钩子中,由报文触发,又不断有这个流经过,则执行顺序无所谓,因为只 要找到有一次,设置进去就可以了 测试的时候可以写个tcp程序,server端一直循环recv,不close fd, client端也不close fd,等待终端输入调用send;三次握手创建ct,后续 查询靠send触发. TCP报文记录链接跟踪的前提是建立三次握手成功,如果单方面打流是 不行的.但是UDP可以单方面打流来创建ct. 输入:无 输出:无 返回值: 0或-1 */ enum test_proto_type{ TEST_PROTO_TCP, TEST_PROTO_UDP, }; /********************************************************** * 函数功能:测试获取应用aid,挂在netfilter的hook上 * 输入:void *, struct sk_buff *, const struct nf_hook_state * * 输出: 无 * 返回值: 无 **********************************************************/ static unsigned int get_aid_test(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { int ret; uint16_t aid; printk(KERN_INFO"[test]: test get app_id\n"); ret = cmhi_get_conntrack_u16(skb, &aid, APP_ID); if(ret == CMHI_EXT_ERR){ printk(KERN_INFO"[test]: get app_id failed\n"); goto out; } printk(KERN_INFO"[test]: get app_id: %d successed\n", aid); goto out; out: return NF_ACCEPT; } /********************************************************** * 函数功能:测试根据TCP的DPI五元组获取链接跟踪指针ct * 输入: 无 * 输出: 无 * 返回值: 0或-1 **********************************************************/ int dpi_get_ct_test_tcp(void) { int ret; struct nf_conn *ct; struct dpi_tuple dpi_tuple; dpi_tuple.sip = htonl(0xc0a840bc);//192.168.64.188 dpi_tuple.dip = htonl(0xc0a840c2);//192.168.64.194 dpi_tuple.protonum = IPPROTO_TCP; dpi_tuple.sport = htons(179); dpi_tuple.dport = htons(10020); printk(KERN_INFO"[Test-tcp]dpi_tuple sip=%u, dip=%u, proto=%d, sport=%du, dport=%du\n", dpi_tuple.sip, dpi_tuple.dip, dpi_tuple.protonum, dpi_tuple.sport, dpi_tuple.dport); ct = get_conntrack_from_tuple(&dpi_tuple); if(!ct){ printk(KERN_ERR"[Test-tcp]get ct failed!!\n"); ret = CMHI_EXT_ERR; } else { printk(KERN_INFO"[Test-tcp]Find it!!\n"); ret = CMHI_EXT_OK; } goto out; out: return ret; } /********************************************************** * 函数功能:测试根据UDP的DPI五元组获取链接跟踪指针ct * 输入: 无 * 输出: 无 * 返回值: 0或-1 **********************************************************/ int dpi_get_ct_test_udp(void) { int ret; struct nf_conn *ct; struct dpi_tuple dpi_tuple; dpi_tuple.sip = htonl(0xc0a840c7);//192.168.64.199 dpi_tuple.dip = htonl(0xc0a840c2);//192.168.64.194 dpi_tuple.protonum = IPPROTO_UDP; dpi_tuple.sport = htons(7); dpi_tuple.dport = htons(520); printk(KERN_INFO"[Test-udp]dpi_tuple sip=%x, dip=%x, proto=%d, sport=%x, dport=%x\n", dpi_tuple.sip, dpi_tuple.dip, dpi_tuple.protonum, dpi_tuple.sport, dpi_tuple.dport); ct = get_conntrack_from_tuple(&dpi_tuple); if(!ct){ printk(KERN_ERR"[Test-udp]get ct failed!!\n"); ret = CMHI_EXT_ERR; } else { printk(KERN_INFO"[Test-udp]Find it!!\n"); ret = CMHI_EXT_OK; } goto out; out: return ret; } /********************************************************** * 函数功能:测试根据TCP的DPI五元组设置链接跟踪ct里的aid * 输入: 无 * 输出: 无 * 返回值: 0或-1 **********************************************************/ int dpi_set_aid_test_tcp(void) { int ret; // uint16_t aid; struct dpi dpi; dpi.tuple.sip = htonl(0xc0a840bc);//192.168.64.188 dpi.tuple.dip = htonl(0xc0a840c2);//192.168.64.194 dpi.tuple.protonum = IPPROTO_TCP; dpi.tuple.sport = htons(179); dpi.tuple.dport = htons(10020); dpi.aid = 3; printk(KERN_INFO"[Test]dpi_tuple sip=%x, dip=%x, proto=%d, sport=%du, dport=%du,aid=%d\n", dpi.tuple.sip, dpi.tuple.dip, dpi.tuple.protonum, dpi.tuple.sport, dpi.tuple.dport, dpi.aid); ret = set_aid_by_dpi_tuple(&dpi); if(CMHI_EXT_OK != ret){ printk(KERN_ERR"[Test]set_aid_by_dpi_tuple failed.\n"); return CMHI_EXT_ERR; } return CMHI_EXT_OK; } /********************************************************** * 函数功能:测试根据UDP的DPI五元组设置链接跟踪ct里的aid * 输入: 无 * 输出: 无 * 返回值: 0或-1 **********************************************************/ int dpi_set_aid_test_udp(void) { int ret; // uint16_t aid; struct dpi dpi; dpi.tuple.sip = htonl(0xc0a840c7);//192.168.64.199 dpi.tuple.dip = htonl(0xc0a840c2);//192.168.64.194 dpi.tuple.protonum = IPPROTO_UDP; dpi.tuple.sport = htons(7); dpi.tuple.dport = htons(520); dpi.aid = 5; printk(KERN_INFO"[Test]dpi_set_aid_test_udp: dpi_tuple sip=%x, dip=%x, proto=%d, sport=%d, dport=%d,aid=%d\n", dpi.tuple.sip, dpi.tuple.dip, dpi.tuple.protonum, dpi.tuple.sport, dpi.tuple.dport, dpi.aid); ret = set_aid_by_dpi_tuple(&dpi); if(CMHI_EXT_OK != ret){ printk(KERN_ERR"[Test]dpi_set_aid_test_udp: set_aid_by_dpi_tuple failed.\n"); return CMHI_EXT_ERR; } return CMHI_EXT_OK; } /********************************************************** * 函数功能:测试根据协议类型是TCP还是UDP来调用TCP或UDP的设置 * aid的函数 * 输入: 协议类型enum test_proto_type * 输出: 无 * 返回值: 无 **********************************************************/ void dpi_set_aid_test(enum test_proto_type type) { if(TEST_PROTO_TCP == type){ dpi_set_aid_test_tcp(); } else if(TEST_PROTO_UDP == type){ dpi_set_aid_test_udp(); } return; } /********************************************************** * 函数功能:测试根据协议类型是TCP还是UDP来调用TCP或UDP的获取 * 链接跟踪指针ct * 输入: 协议类型enum test_proto_type * 输出: 无 * 返回值: 无 **********************************************************/ void dpi_get_ct_test(enum test_proto_type type) { if(TEST_PROTO_TCP == type){ dpi_get_ct_test_tcp(); } else if(TEST_PROTO_UDP == type){ dpi_get_ct_test_udp(); } return; } static struct nf_hook_ops nfho[] __read_mostly = { //{ //.hook = (nf_hookfn *)demoB, //.hooknum = NF_INET_PRE_ROUTING, //.pf = NFPROTO_IPV4, //.priority = (NF_IP_PRI_FILTER-1), //}, { .hook = (nf_hookfn *)get_aid_test, .hooknum = NF_INET_PRE_ROUTING, .pf = NFPROTO_IPV4, .priority = NF_IP_PRI_FILTER, }, }; static int __init test_init(void) { dpi_set_aid_test(TEST_PROTO_TCP); nf_register_net_hooks(&init_net, nfho, ARRAY_SIZE(nfho)); printk(KERN_INFO"[Test] Module_init\n"); return 0; } static void __exit test_clean(void) { nf_unregister_net_hooks(&init_net, nfho, ARRAY_SIZE(nfho)); printk(KERN_INFO"[Test]Module_clean\n"); return; } module_init(test_init); module_exit(test_clean); MODULE_LICENSE("GPL");