I'm trying to write kernel module which will add two bytes to the end of any TCP packet and send it to the network interface. The IMPORTANT POINT is that network device will remove these bytes in hardware (simply throw them out without any modification of the packet), so there is no need to take these bytes into account in the TCP header (recalculate checksum and so). I'm doing it with help of NF_INET_POST_ROUTING netfilter hook. I just use skb_put() and then return NF_ACCEPT. Two bytes are added successfully but TCP checksum at the receiver end is wrong. What am I doing wrong? Is TCP checksum get recalculated after NF_INET_POST_ROUTING hook? Does packet go directly to the interface after this hook or it also goes through TCP stack? Is it really necessary in my case to create new skb buffer, consume old, and send new buffer out using dev_queue_xmit(). So how can I do my job properly? The entire code is below:
Code:
static struct nf_hook_ops *nfho3 = NULL;
static unsigned int ksz_prp_tx(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
u8 *trailer;
trailer = skb_put(skb, 2);
trailer[0] = 0x00;
trailer[1] = 0x0C;
return NF_ACCEPT;
}
static int __init ipv4_prp_init(void)
{
nfho3 = (struct nf_hook_ops*)kcalloc(1, sizeof(struct nf_hook_ops), GFP_KERNEL);
/* Initialize netfilter tx hook for IPv4*/
nfho3->hook = (nf_hookfn*)ksz_prp_tx; /* hook function */
nfho3->hooknum = NF_INET_POST_ROUTING; /* received packets */
nfho3->pf = PF_INET; /* IPv4 */
nfho3->priority = NF_IP_PRI_FIRST; /* max hook priority */
nf_register_net_hook(&init_net, nfho3);
}
static void __exit ipv4_prp_exit(void)
{
nf_unregister_net_hook(&init_net, nfho3);
kfree(nfho3);
}
module_init(ipv4_prp_init);
module_exit(ipv4_prp_exit);