- 论坛徽章:
- 0
|
如题,用Netfilter写了一段代码来打印HOST和URI信息,编译后可正常打印出URL,当浏览器打开腾讯视频等一些内容的时候,内核就崩溃了,麻烦各位大牛帮忙分析一下,谢谢!
- #ifndef __KERNEL__
- #define __KERNEL__
- #endif
- #ifndef MODULE
- #define MODULE
- #endif
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/skbuff.h>
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <linux/icmp.h>
- #include <linux/netdevice.h>
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/if_arp.h>
- #include <linux/if_ether.h>
- #include <linux/if_packet.h>
- #include <linux/mm.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h>
- #include <asm/uaccess.h>
- //#define DEBUG
- MODULE_LICENSE("GPL");
- char* h_tmp ; //HOST
- char* u_tmp ; //URI
- static struct nf_hook_ops nfho;
- //获取HOST
- void print_host(const unsigned char* start,unsigned int len)
- {
- char* host_tmp ;
- char* url_tmp ;
- int i = 0;
- int j = 0;
- if (len > 4)
- {
- if (0 == strncmp(start, "GET", 3) || 0 == strncmp(start, "POST", 4))
- {
- /*获取HOST的值*/
- host_tmp = strstr(start,"Host:");
- if(memcmp(host_tmp,"Host:",5) == 0)
- {
- host_tmp = host_tmp + 6; // 跳过HOST: 这6个字符
- while(*host_tmp!='\r')
- {
- host_tmp++;
- i++;
- }
- host_tmp -= i;
- h_tmp = kmalloc((i + 1)*sizeof(char),GFP_KERNEL);
- memcpy(h_tmp,host_tmp,i);
- *(h_tmp+i) ='\0';
- printk(">>>Host:%s",h_tmp);
- kfree(h_tmp);
- }
- /*获取GET后面的参数*/
- url_tmp = strstr(start,"/"); /*从/开始获取GET后面的URI部分*/
- while(*url_tmp!=' ') /*到空格的地方结束*/
- {
- url_tmp++;
- j++;
- }
- url_tmp -=j;
- u_tmp = kmalloc((j + 1)*sizeof(char),GFP_KERNEL);
- memcpy(u_tmp,url_tmp,j);
- *(u_tmp+j) ='\0';
- printk("%s\n",u_tmp);
- kfree(u_tmp);
- }
- }
- }
- /* HOOK函数 */
- unsigned int hook_func(unsigned int hooknum,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
- {
- char * payload = NULL;
- struct sk_buff* sb = skb; //定义一个Linux网络数据包缓存
- struct iphdr *iph = ip_hdr(sb); //定义一个ip报文的数据报头
- /*读取文件结束,过滤掉skb_buf为空以及iph为空的数据包*/
- if(sb == NULL)
- return NF_ACCEPT;
- if(iph == NULL)
- return NF_ACCEPT;
- /*判断是否为TCP协议,不是TCP协议的数据包直接return NF_ACCEPT*/
- if (iph && iph->protocol && (iph->protocol == IPPROTO_TCP)) {
- //struct tcphdr* tcph = (void *)iph + iph->ihl*4; //TCP报文的头部
- struct tcphdr* tcph =(void *)iph +(iph->ihl<<2);
- unsigned int srcport = tcph->source; //源端口
- unsigned int dstport = tcph->dest; //目的端口
- unsigned int ack_seq_num = tcph->ack_seq; //ACK-SEQ的值
- unsigned int seq_num = tcph->seq; //SEQ的值
- unsigned int ip_saddr = ntohl(iph->saddr); //源IP
- unsigned int ip_daddr = ntohl(iph->daddr); //目的IP
- unsigned int len_tot = ntohs(iph->tot_len); //包总长度
- unsigned int len_tcp = len_tot - iph->ihl*4 - tcph->doff*4; //TCP包的长度
- /*判断tcph是否为空,为空直接返回NF_ACCEPT*******/
- if(tcph == NULL)
- return NF_ACCEPT;
- /*判断目的端口是否为80************************/
- if (ntohs(dstport) == 80 ) //筛选远端口或者目的
- {
- if (0 != skb_linearize(sb))
- return NF_ACCEPT;
- // payload = (char*)iph+(iph->ihl*4) + tcph->doff*4;
- payload = (void *)tcph + (tcph->doff<<2);
- print_host(payload,len_tcp); //DEBUG模式下打印HOST 和 URL
- if (0 == strncmp(payload, "GET", 3) || 0 == strncmp(payload, "POST", 4))
- {
- printk("**************Request**************\n");
- printk("In-Device :%s Out-Device:%s\n",in->name,out->name);
- printk("Src IP :%d.%d.%d.%d \n", (ip_saddr & 0xff000000) >> 24,
- (ip_saddr & 0x00ff0000) >> 16,
- (ip_saddr & 0x0000ff00) >> 8,
- (ip_saddr & 0x000000ff));
- printk("Dst IP :%d.%d.%d.%d \n", (ip_daddr & 0xff000000) >> 24,
- (ip_daddr & 0x00ff0000) >> 16,
- (ip_daddr & 0x0000ff00) >> 8,
- (ip_daddr & 0x000000ff));
- printk("ID :%u\n",ntohs(iph->id));
- printk("Src-Port :%d Dst-Port:%d\n", ntohs(srcport), ntohs(dstport));
- printk("Seq :0x%2x\n", ntohl(seq_num));
- printk("Ack_Seq :0x%2x\n", ntohl(ack_seq_num));
- printk("Tcp len :%u\n",len_tcp);
- printk("Next ack :%u\n",ntohl(seq_num + len_tcp ));
- printk("*******************************\n");
- return NF_ACCEPT;
- }
- return NF_ACCEPT;
- }
- }
- return NF_ACCEPT;
- }
- /* 加载模块 */
- int init_module() {
- nfho.hook = hook_func; //钩子函数指针
- nfho.hooknum = NF_INET_POST_ROUTING; //hook类型
- nfho.pf = PF_INET; //协议簇,对于ipv4而言,是PF_INET
- nfho.priority = NF_IP_PRI_FIRST; //优先级
- nf_register_hook(&nfho);
- pr_info("Filter add into kernel!\r\n");
- return 0;
- }
- /* 清除模块 */
- void cleanup_module() {
- nf_unregister_hook(&nfho);
- pr_info("Filter removed from kernel!\r\n");
- }
复制代码 |
|