Sunday, April 17, 2011

IP Address from sk_buff

I am writing a kernel module which registers a netfilter hook. I am trying to get the ip address of the caller by using the sk_buff->saddr member. Is there a way I can get the IP in human readable i.e. x.x.x.x format?

I found the function inet_ntop() but it doesn't seem to be available in kernel headers. How do I convert \xC0\xA8\x00\x01 to 192.168.0.1 ?

From stackoverflow
  • You can use strtol to convert each piece to it's integer form.

    Tim Post : I'm almost positive that a macro exists which does just that, I just can't find it ATM.
  • Simple. The IP address in "x.x.x.x" format is called dotted-quad for a reason. Each number represents a byte, for a total of 4 bytes in your address.

    So, with the 4 byte address, you would simply print the decimal value of each byte.

    Quick and dirty example (replace printf with your output function of choice):

    unsigned char *addr = (unsigned char*)sk_buff->addr;
    printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
    
    Rohit : this crashed the kernel
  • /* Convinience union to __be32 to ip address  */
    union ip_address {
        u8 a[4];
        __be32 saddr;
    };
    

    IP Address could be obtained a[0].a[1].a[2].a[3]

  • There are two macros defined in include/linux/kernel.h

    NIPQUAD for ipv4 addresses and NIP6 for ipv6 addresses.

    #define NIPQUAD(addr) \
        ((unsigned char *)&addr)[0], \
        ((unsigned char *)&addr)[1], \
        ((unsigned char *)&addr)[2], \
        ((unsigned char *)&addr)[3]
    
    #define NIP6(addr) \
        ntohs((addr).s6_addr16[0]), \
        ntohs((addr).s6_addr16[1]), \
        ntohs((addr).s6_addr16[2]), \
        ntohs((addr).s6_addr16[3]), \
        ntohs((addr).s6_addr16[4]), \
        ntohs((addr).s6_addr16[5]), \
        ntohs((addr).s6_addr16[6]), \
        ntohs((addr).s6_addr16[7])
    

    There are ample examples in the kernel sources that make use of these to print ip addresses in human-readable format. For instance:

    printk(KERN_DEBUG "Received packet from source address: %d.%d.%d.%d!\n",NIPQUAD(iph->saddr));
    

    Hope this helps.

0 comments:

Post a Comment