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