-
netfilter problem
i'm developing a kernel module, basically i have to put 12 bytes at the end of the packet on the tx side and then take them off on the rx side,
after a while of http navigation the kernel crashes and i don't know why..can anybody help me?
here's the code:
Code:
// funzione per il calcolo del checksum a livello IP
unsigned short csum (u16 *buf, int nwords) {
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
// calcolo checksum a livello transport
unsigned short transport_csum (struct sk_buff *sk) {
unsigned long sum;
unsigned char *addr, *p;
unsigned short len;
unsigned short provacheck;
struct iphdr *ip_h = ip_hdr(sk);
//inizializzo la somma
sum = 0;
//pseudo header
p = (unsigned char *) &(ip_h->saddr);
sum += ((*p << 8) + *(p + 1));
sum += ((*(p + 2) << 8) + *(p + 3));
p = (unsigned char *) &(ip_h->daddr);
sum += ((*p << 8) + *(p + 1));
sum += ((*(p + 2) << 8) + *(p + 3));
sum += (0 + ip_h->protocol);
len = ntohs(ip_h->tot_len) - 20;
sum += len;
if(ip_h->protocol == 0x06){
memset(sk->data + 36, 0, 2);
addr = (unsigned char *) (sk->data + 20);
while(len > 1){
sum += ((*addr << 8) + *(addr + 1));
addr += 2;
len -= 2;
}
if(len > 0)
sum += (*addr << 8);
while(sum >> 16)
sum = (sum &0xFFFF) + (sum >> 16);
provacheck = htons(~sum);
memcpy(sk->data + 36, &provacheck, 2);
}
else{
memset(sk->data + 26, 0, 2);
addr = (unsigned char *) (sk->data + 20);
while(len > 1){
sum += ((*addr << 8) + *(addr + 1));
addr += 2;
len -= 2;
}
if(len > 0)
sum += (*addr << 8);
while(sum >> 16)
sum = (sum &0xFFFF) + (sum >> 16);
provacheck = htons(~sum);
memcpy(sk->data + 26, &provacheck, 2);
}
return 0;
}
// Hook RX side
unsigned int hook_pre_routing(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *)) {
struct iphdr *iph = ip_hdr(skb);
ushort ip_new_len;
uint controllo;
ushort pippo, pippo1;
unsigned char *pport;
printk(KERN_ALERT "Received a new packet %p\n", skb);
if(!strcmp(in->name,DEVICE_MESH)) {
if(!skb) {
printk(KERN_ALERT " - skb is null\n");
return NF_ACCEPT;
}
pport = (unsigned char *) (skb->data +20);
pippo = (*pport << 8) + *(pport + 1);
pippo1 = (*(pport + 2) << 8) + *(pport + 3);
if(pippo == 0x01bb || pippo1 == 0x01bb)
return NF_ACCEPT;
if(skb->mark != 0x000000bb){
memcpy(&controllo, skb->tail - 12, 4);
memcpy(&t_arrive, skb->tail - 8, 8);
ip_new_len = ntohs(iph->tot_len) - 12;
iph->tot_len = htons(ip_new_len);
iph->check = 0;
iph->check = csum ((u16*) iph, 10);
skb_trim(skb, ip_new_len);
if(skb_is_nonlinear(skb))
skb_linearize(skb);
if(iph->protocol == 0x06 || iph->protocol == 0x11)
transport_csum(skb);
skb->mark = 0x000000bb;
}
}
else
printk(KERN_ALERT"Packet not processed RX\n");
return NF_ACCEPT;
}
// hook TX SIDE
unsigned int hook_post_routing(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *)) {
struct iphdr *iph=ip_hdr(skb);
ushort ip_new_len;
ushort pippo, pippo1;
unsigned char *pport;
printk(KERN_ALERT "Sent a new packet\n");
if(!strcmp(out->name,DEVICE_MESH)) {
if(!skb) {
printk(KERN_ALERT " - skb is null\n"); /*controllo che skb contenga il pacchetto*/
return NF_ACCEPT;
}
pport = (unsigned char *) (skb->data +20);
pippo = (*pport << 8) + *(pport + 1);
pippo1 = (*(pport + 2) << 8) + *(pport + 3);
if(pippo == 0x01bb || pippo1 == 0x01bb)
return NF_ACCEPT;
if(skb->mark != 0x000000aa){
//in caso non ci sia abbastanza spazio per i 12 byte nella tailroom aggiungo spazio
if(skb_tailroom(skb) < 12){
struct sk_buff *pkt = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + 12, GFP_KERNEL);
if(!pkt){
printk(KERN_ALERT "attenzione, non c'è spazio per il clone del pacchetto!!!\n");
return -1;
}
kfree_skb(skb);
skb = pkt;
}
// inserisco i 12 byte necessari, aggiorno i campi e ricalcolo il checksum
skb_put(skb,12);
ip_new_len = ntohs(iph->tot_len) + 12;
iph->tot_len = htons(ip_new_len);
iph->check = 0;
iph->check = csum ((u16*) iph, 10);
memcpy(skb->tail - 12, &counter, 4);
//counter++;
do_gettimeofday(&t_sent);
memcpy(skb->tail - 8, &t_sent, 8);
skb->mark = 0x000000aa;
}
}
else
printk(KERN_ALERT "Packed not processed TX\n");
return NF_ACCEPT;
}
//register and unregister modules
int init_test(void) {
int ret = 0;
// t_stamp = (struct timeval *) kmalloc(sizeof(struct timeval), GFP_KERNEL);
printk(KERN_ALERT "Loading module %s...\n", DESC);
printk(KERN_ALERT "NF_IP_NUMHOOKS = %d\n", NF_INET_NUMHOOKS);
netfilter_ops_in.hook = hook_pre_routing;
netfilter_ops_in.pf = PF_INET;
netfilter_ops_in.hooknum = NF_INET_PRE_ROUTING;
netfilter_ops_in.priority = NF_IP_PRI_FIRST;
netfilter_ops_local_in.hook = hook_pre_routing;
netfilter_ops_local_in.pf = PF_INET;
netfilter_ops_local_in.hooknum = NF_INET_LOCAL_IN;
netfilter_ops_local_in.priority = NF_IP_PRI_LAST;
netfilter_ops_out.hook = hook_post_routing;
netfilter_ops_out.pf = PF_INET;
netfilter_ops_out.hooknum = NF_INET_POST_ROUTING;
netfilter_ops_out.priority = NF_IP_PRI_LAST;
netfilter_ops_local_out.hook = hook_post_routing;
netfilter_ops_local_out.pf = PF_INET;
netfilter_ops_local_out.hooknum = NF_INET_LOCAL_OUT;
netfilter_ops_local_out.priority = NF_IP_PRI_FIRST;
ret = nf_register_hook(&netfilter_ops_in); /* register NF_IP_PRE_ROUTING hook */
printk(KERN_ALERT " PRE_ROUTING hook registered (%d)!\n", ret);
ret = nf_register_hook(&netfilter_ops_local_in); /* register NF_IP_PRE_ROUTING hook */
printk(KERN_ALERT " LOCAL_IN hook registered (%d)!\n", ret);
ret = nf_register_hook(&netfilter_ops_out); /* register NF_IP_POST_ROUTING hook */
printk(KERN_ALERT " POST_ROUTING hook registered (%d)!\n", ret);
ret = nf_register_hook(&netfilter_ops_local_out); /* register NF_IP_POST_ROUTING hook */
printk(KERN_ALERT " LOCAL_OUT hook registered (%d)!\n", ret);
return 0;
}
void cleanup_test(void) {
// remove_proc_entry(PROCFS_NAME, &proc_root);
printk(KERN_ALERT "Unloading module %s...\n", DESC);
nf_unregister_hook(&netfilter_ops_in); /*unregister NF_IP_PRE_ROUTING hook*/
memset(&netfilter_ops_in, 0, sizeof(struct nf_hook_ops));
//kfree(netfilter_ops_in);
printk(KERN_ALERT " PRE_ROUTING hook released.\n");
nf_unregister_hook(&netfilter_ops_local_in); /*unregister NF_IP_PRE_ROUTING hook*/
memset(&netfilter_ops_local_in, 0, sizeof(struct nf_hook_ops));
//kfree(netfilter_ops_in);
printk(KERN_ALERT " LOCAL_IN hook released.\n");
nf_unregister_hook(&netfilter_ops_out); /*unregister NF_IP_POST_ROUTING hook*/
memset(&netfilter_ops_out, 0, sizeof(struct nf_hook_ops));
//kfree(netfilter_ops_out);
printk(KERN_ALERT " POST_ROUTING hook released.\n");
nf_unregister_hook(&netfilter_ops_local_out); /*unregister NF_IP_POST_ROUTING hook*/
memset(&netfilter_ops_local_out, 0, sizeof(struct nf_hook_ops));
//kfree(netfilter_ops_out);
printk(KERN_ALERT " LOCAL_OUT hook released.\n");
// kfree(t_stamp);
}
module_init(init_test);
module_exit(cleanup_test);
#endif
:eek::eek::eek::eek: