skb_put(): add some data to the end of the data in sk_buff

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 receiver 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);
}


[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux