How to access data/payload from tcphdr (sk_buff) struct on debian 64 bits?

11,630

(char *)((int)tcph + (int)(tcph->doff * 4)); is wrong, it should be

(char *)((unsigned char *)tcph + (tcph->doff * 4));

Note that printk(KERN_DEBUG "data len : %d\ndata : \n", (int) strlen(data)); is not at all a safe thing to do. You don't know if the data contains text, and if it does, it might not contain a 0 terminated string which strlen(data) would need to work as you expect.

You probably need to care about endianess as well, when comparing the ports and possibly other fields.

Share:
11,630

Related videos on Youtube

Shark
Author by

Shark

I'm a young SharePoint Engineer.

Updated on October 17, 2022

Comments

  • Shark
    Shark over 1 year

    I'm working on a small firewall, i had to retrieve the datas from each tcp packet from port 80 (http) for parsing them. This code works well on a debian 32 bits virtual machine, i'm able to print the headers of each web page, but when i try to load my kernel module and to transfer some datas through the http port, it prints no datas.

    When i compile, it shows those warnings only on my 64bits computer :

    /home/dev3/C/FIREWALL/firewall.c: In function ‘hook_func’:
    /home/dev3/C/FIREWALL/firewall.c:179: warning: cast from pointer to integer of different size
    /home/dev3/C/FIREWALL/firewall.c:179: warning: cast to pointer from integer of different size
    

    Anyone got any ideas, please ?

    Thanks.

    Code :

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/netfilter.h>
    
    #undef __KERNEL__
    #include <linux/netfilter_ipv4.h>
    #define __KERNEL__
    
    #include <linux/ip.h>
    #include <linux/tcp.h>
    
    static struct nf_hook_ops nfho;
    
    unsigned int hook_func( 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;
        struct tcphdr   * tcph;
        unsigned char   * http_port = "\x00\x50";
        char            * data;
    
        if (skb)
        {
            iph = ip_hdr(skb);
    
            if (iph && iph->protocol && (iph->protocol == IPPROTO_TCP))
            {
                tcph = (struct tcphdr *)((__u32 *)iph + iph->ihl);
    
                if ((tcph->source) == *(unsigned short *)http_port)
                {
                    data    = (char *)((int)tcph + (int)(tcph->doff * 4));
    
                    printk(KERN_DEBUG "TCP source : %hu, TCP  dest : %hu\n", ntohs(tcph->source), ntohs(tcph->dest));
                    printk(KERN_DEBUG "TCP seq : %u, TCP ack_seq : %u\n", ntohl(tcph->seq), ntohl(tcph->ack_seq));
                    printk(KERN_DEBUG "TCP doff : %hu, TCP window : %hu\n", ntohs(tcph->doff), ntohs(tcph->window));
                    printk(KERN_DEBUG "TCP check : 0x%hx, TCP urg_ptr : %hu\n", ntohs(tcph->check), ntohs(tcph->urg_ptr));
                    printk(KERN_DEBUG "FLAGS=%c%c%c%c%c%c\n\n",
                            tcph->urg ? 'U' : '-',
                            tcph->ack ? 'A' : '-',
                            tcph->psh ? 'P' : '-',
                            tcph->rst ? 'R' : '-',
                            tcph->syn ? 'S' : '-',
                            tcph->fin ? 'F' : '-');
                    //printk(KERN_DEBUG "sending packet to : %pI4\n", &iph->daddr);
                    printk(KERN_DEBUG "data len : %d\ndata : \n", (int) strlen(data));
                    printk(KERN_DEBUG "%s\n", data);
                }
            }
        }
    
        return NF_ACCEPT;
    }
    
    int init_module()
    {
        int result;
    
        nfho.hook   = (nf_hookfn *) hook_func;
        nfho.hooknum    = NF_IP_POST_ROUTING;
        nfho.pf     = PF_INET;
        nfho.priority   = NF_IP_PRI_FIRST;
    
        result = nf_register_hook(&nfho);
    
        if(result)
        {
            printk(KERN_DEBUG "firewall : erreur nf_register_hook !\n");
            return 1;
        }
    
        printk(KERN_DEBUG "firewall : module charge.\n");
    
        return 0;
    }
    
    void cleanup_module()
    {
        nf_unregister_hook(&nfho);
        printk(KERN_DEBUG "firewall : module decharge.\n");
    }
    
  • Zzz0_o
    Zzz0_o over 7 years
    Someone please explain me Why we are adding tcph with tcph->doff*4. Since doff is already telling us about the tcp header length.
  • Zzz0_o
    Zzz0_o over 7 years
    How it is different from [IP Total Length] - ( ([IP IHL] + [TCP Data offset]) * 4 )??