4

netfilter problem

view full story
linux-howto

http://www.linuxforums.org – 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: (HowTos)