如何从debian 64位上的tcphdr(sk_buff)结构访问数据/有效负载?

我正在使用一个小型防火墙,我必须从端口80(http)中的每个tcp数据包中检索数据以进行解析。 这个代码适用于debian 32位虚拟机,我可以打印每个网页的标题,但是当我尝试加载我的内核模块并通过http端口传输一些数据时,它不打印任何数据。

当我编译时,它只在我的64位计算机上显示那些警告:

/home/dev3/C/FIREWALL/firewall.c: In function 'hook_func': /home/dev3/C/FIREWALL/firewall.c:179: warning: cast from pointer to integer of different size /home/dev3/C/FIREWALL/firewall.c:179: warning: cast to pointer from integer of different size 

有人有任何想法吗?

谢谢。

代码:

 #include  #include  #include  #undef __KERNEL__ #include  #define __KERNEL__ #include  #include  static struct nf_hook_ops nfho; 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 *)) { struct iphdr * iph; struct tcphdr * tcph; unsigned char * http_port = "\x00\x50"; char * data; if (skb) { iph = ip_hdr(skb); if (iph && iph->protocol && (iph->protocol == IPPROTO_TCP)) { tcph = (struct tcphdr *)((__u32 *)iph + iph->ihl); if ((tcph->source) == *(unsigned short *)http_port) { data = (char *)((int)tcph + (int)(tcph->doff * 4)); printk(KERN_DEBUG "TCP source : %hu, TCP dest : %hu\n", ntohs(tcph->source), ntohs(tcph->dest)); printk(KERN_DEBUG "TCP seq : %u, TCP ack_seq : %u\n", ntohl(tcph->seq), ntohl(tcph->ack_seq)); printk(KERN_DEBUG "TCP doff : %hu, TCP window : %hu\n", ntohs(tcph->doff), ntohs(tcph->window)); printk(KERN_DEBUG "TCP check : 0x%hx, TCP urg_ptr : %hu\n", ntohs(tcph->check), ntohs(tcph->urg_ptr)); printk(KERN_DEBUG "FLAGS=%c%c%c%c%c%c\n\n", tcph->urg ? 'U' : '-', tcph->ack ? 'A' : '-', tcph->psh ? 'P' : '-', tcph->rst ? 'R' : '-', tcph->syn ? 'S' : '-', tcph->fin ? 'F' : '-'); //printk(KERN_DEBUG "sending packet to : %pI4\n", &iph->daddr); printk(KERN_DEBUG "data len : %d\ndata : \n", (int) strlen(data)); printk(KERN_DEBUG "%s\n", data); } } } return NF_ACCEPT; } int init_module() { int result; nfho.hook = (nf_hookfn *) hook_func; nfho.hooknum = NF_IP_POST_ROUTING; nfho.pf = PF_INET; nfho.priority = NF_IP_PRI_FIRST; result = nf_register_hook(&nfho); if(result) { printk(KERN_DEBUG "firewall : erreur nf_register_hook !\n"); return 1; } printk(KERN_DEBUG "firewall : module charge.\n"); return 0; } void cleanup_module() { nf_unregister_hook(&nfho); printk(KERN_DEBUG "firewall : module decharge.\n"); } 

(char *)((int)tcph + (int)(tcph->doff * 4)); 是错的,应该是

 (char *)((unsigned char *)tcph + (tcph->doff * 4)); 

注意printk(KERN_DEBUG "data len : %d\ndata : \n", (int) strlen(data)); 这根本不是一件安全的事情。 您不知道数据是否包含文本,如果包含文本,它可能不包含0终止的字符串,strlen(数据)需要按预期工作。

在比较端口和可能的其他字段时,您可能还需要关心字节顺序。

改变这一行:

data =(char *)((int)tcph +(int)(tcph-> doff * 4));

至:

data =(char *)((void *)tcph +(int)(tcph-> doff * 4));

使用

 printk(KERN_INFO ...); 

而不是

 printk(KERN_DEBUG ...);