TCP checksum not transmited to the wire!
Hello, I am trying to use netfilter to program my own firewall. To make a forwarding test to the local machine, I made a test program that change a certain destination IP address in the PRE ROUTING HOOK to my local machine, I changed back the source IP address in the POST ROUTING hook to the old destination address. I computed TCP and IP checksums in this hook but I still have a bad TCP checksum on the receiver. I can see in the POST ROUTING hook that my checksum was changed! Below is my code #include <linux/module.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/list.h> #include <asm/uaccess.h> #include <linux/udp.h> #include <linux/tcp.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <net/ip.h> static struct nf_hook_ops nfho; static struct nf_hook_ops nfho_out; unsigned int hook_func_in(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { u32 local = 1090627776; //my machine IP 192.168.1.65 struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb); struct tcphdr *tcp_header = (struct tcphdr *)skb_transport_header(skb); unsigned int src_port = (unsigned int)ntohs(tcp_header->source); ip_header->daddr = local; //printk(KERN_INFO "PRE: saddr: %pI4 %u, daddr: %pI4, %u", &ip_header->saddr, ip_header->saddr, &ip_header->daddr, ip_header->daddr); //printk("IN saddr: %pI4 daddr: %pI4 len: %u check: %x\n", &ip_header->saddr, &ip_header->daddr, src_port, tcp_header->check); return NF_ACCEPT; } unsigned int hook_func_out(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb); u32 dest = 388809389; //the old destination ip ip_header->saddr = dest; struct tcphdr *tcp_header = (struct tcphdr *)skb_transport_header(skb); tcp_header->check = 0; int len = skb->len-20; unsigned int src_port = (unsigned int)ntohs(tcp_header->source); tcp_header->check = csum_tcpudp_magic(ip_header->saddr, ip_header->daddr, len, IPPROTO_TCP, csum_partial((char *)tcp_header, len, 0)); ip_header->check = 0; ip_send_check (ip_header); //to check changes printk( "saddr: %pI4 daddr: %pI4 check: %x\n", &ip_header->saddr, &ip_header->daddr, tcp_header->check); int i; for (i=0; i<skb->len; i++) printk("%x", skb->data[i]); printk("\n"); return NF_ACCEPT; } /* Initialization routine */ int init_module() { printk(KERN_INFO "initialize kernel module\n"); /* Fill in the hook structure for incoming packet hook*/ nfho.hook = hook_func_in; nfho.hooknum = NF_INET_PRE_ROUTING; nfho.pf = PF_INET; nfho.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho); // Register the hook /* Fill in the hook structure for outgoing packet hook*/ nfho_out.hook = hook_func_out; nfho_out.hooknum = NF_INET_POST_ROUTING; nfho_out.pf = PF_INET; nfho_out.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho_out); // Register the hook return 0; } /* Cleanup routine */ void cleanup_module() { nf_unregister_hook(&nfho); nf_unregister_hook(&nfho_out); printk(KERN_INFO "kernel module unloaded.\n"); } Would you please help me, I spent 10 days working on this issue and not solved yet. Best,
Many server-grade systems these days have TCP checksum offloads. Could this be what you're seeing? Craig Jackson
Thanks Graig for your reply. I suspected it. I disabled TCP offload using ethtool but nothing changed. below is the ethtool output: sudo ethtool -k eth0 Offload parameters for eth0: rx-checksumming: off tx-checksumming: off scatter-gather: off tcp-segmentation-offload: off udp-fragmentation-offload: off generic-segmentation-offload: off generic-receive-offload: on large-receive-offload: off rx-vlan-offload: on tx-vlan-offload: on ntuple-filters: off receive-hashing: off Thanks,
Subject: RE: TCP checksum not transmited to the wire! Date: Mon, 28 Jan 2013 11:22:22 -0500 From: cjackson@ebscohost.com To: thisiskd@hotmail.com CC: kernelnewbies@kernelnewbies.org
Many server-grade systems these days have TCP checksum offloads. Could this be what you're seeing?
Craig Jackson
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
participants (2)
-
Craig Jackson -
Khaled Dassouki