Hi,
I want to add or subtract 40bytes to the end of the
data in sk_buff.
So I made a module to do this.
Actually, I hooked up a packet LOCAL_OUT for the
outgoing packet and added data structure, sip_tag to the sk_buff like
below.
I added data using skb_put().
When I install the module and run the scp to
transfer some data, it starts well.
But, after it sent about 320KB, the connection is
stalled and freezed.
Is there any error in my code?
I appreciate any comments.
Thanks,
Changho Choi
ps: The reception part(sip_input) is also
below.
------------------------------------------------------------------------------
sip_output(unsigned int hook, struct sk_buff
**pskb,
const struct net_device *indev, const struct net_device *outdev, int (*okfn)(struct sk_buff *)) { sip_tag *stag; struct iphdr *ip_hdr; int stag_len;
ip_hdr = (*pskb)->nh.iph; //
ip header
stag_len =
sizeof(sip_tag);
// new packet size check if (stag_len > skb_tailroom(*pskb)) { struct sk_buff *newskb; printk("...sip_output: newskb...\n"); newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), stag_len, GFP_ATOMIC); if (!newskb)
{
printk("error: sip_output: resize the pskb...\n"); return 0; } else { kfree_skb(*pskb); *pskb = newskb; } } // make a room for the security
tag
stag = (sip_tag *) skb_put(*pskb, stag_len); // assign some values to the stag if(init_stag(ip_hdr, stag) == 0) return NF_DROP; // initialize the security tag // update ip
header
ip_hdr->tot_len = htons(ntohs(ip_hdr->tot_len) + stag_len); ip_send_check(ip_hdr); // calculate new checksum (*pskb)->nfcache |= NFC_ALTERED; return NF_ACCEPT; } // module install
static struct nf_hook_ops secureIP_output
= { { NULL, NULL }, sip_output, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_FILTER-1 }; int init_module(void)
{ /* Register hooks */ int ret; ret = nf_register_hook(&secureIP_output); if (ret < 0) goto cleanup_output; return ret; cleanup_output: nf_unregister_hook(&secureIP_output); return 0; } void
cleanup_module(void)
{ nf_unregister_hook(&secureIP_output); } ---- reception part
I removed my data using skb_trim() and update the
ip packet length.
static unsigned int
sip_input(unsigned int hook, struct sk_buff **pskb, const struct net_device *indev, const struct net_device *outdev, int (*okfn)(struct sk_buff *)) { sip_tag *stag; struct iphdr *ip_hdr; unsigned char mac[8]; int i, stag_len; ip_hdr = (*pskb)->nh.iph;
stag_len = sizeof(sip_tag);
//
get_sip_info()
stag = (sip_tag *) ((*pskb)->data + (*pskb)->len - stag_len); if(calculate_mac(ip_hdr, stag, mac) ==
0)
return NF_DROP; // mac calculation failed // check mac
value
if(memcmp(stag->mac, mac, 8) != 0){ return NF_DROP; } // remove stag skb_trim(*pskb, (*pskb)->len-stag_len); ip_hdr->tot_len = ip_hdr->tot_len - stag_len; ip_send_check(ip_hdr); // calculate new checksum (*pskb)->nfcache |= NFC_ALTERED; return NF_ACCEPT; } // module installation part
static struct nf_hook_ops secureIP_input
= { { NULL, NULL }, sip_input, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_FILTER-2 }; int init_module(void)
{ /* Register hooks */ int ret; ret = nf_register_hook(&secureIP_input); if (ret < 0) goto cleanup_output; return ret; cleanup_output: nf_unregister_hook(&secureIP_input); return 0; } void
cleanup_module(void)
{ nf_unregister_hook(&secureIP_input); } |