pythonudplibnet

libnet creates UDP packets with invalid checksums


I'm using pylibnet to construct and send UDP packets. The UDP packets I construct in this way all seem to have invalid checksums. Example:

# python
Python 2.4.3 (#1, Sep  3 2009, 15:37:12)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> import libnet
>>> from libnet.constants import *
>>> 
>>> net = libnet.context(RAW4, 'venet0:0')
>>> ip = net.name2addr4('www.stackoverflow.com', RESOLVE)
>>> data = 'This is my payload.'
>>> udptag = net.build_udp(sp=54321, dp=54321, payload=data)
>>> packetlen = IPV4_H + UDP_H + len(data)
>>> iptag = net.autobuild_ipv4(len=packetlen, prot=IPPROTO_UDP, dst=ip)
>>> 
>>> net.write() 

Capturing the above packet on the sending host reveals an invalid checksum:

# tcpdump -i venet0:0 -n -v -v port 54321
tcpdump: WARNING: arptype 65535 not supported by libpcap - falling back to cooked socket
tcpdump: listening on venet0:0, link-type LINUX_SLL (Linux cooked), capture size 96 bytes
08:16:10.303719 IP (tos 0x0, ttl  64, id 1, offset 0, flags [none], proto: UDP (17), length: 47) 192.168.55.10.54321 > 69.59.196.211.54321: [bad udp cksum 50c3!] UDP, length 0

Am I doing something wrong here?


Solution

  • It's nothing to do with tcpdump bugs or checksum offloading. Libnet calculates the checksum in user mode as well (FYI). The problem has to do with the fact that you did not specify a length for the UDP header. This is not automagically calculated in pylibnet or libnet so you have to specify it for the time being. Below is the corrected version of your code. I will apply a patch to pylibnet to automagically detect the header length in rc6. Stay tuned to http://sourceforge.net/projects/pylibnet for updates. I will be pushing a new release fixing this issue. By the way, please feel free to contact me via sourceforge's pylibnet page if you have bug or feature requests. I love to hear from developers using my software :)


    import libnet
    from libnet.constants import *
    
    net = libnet.context(RAW4, 'venet0:0')
    ip = net.name2addr4('www.stackoverflow.com', RESOLVE)
    data = 'This is my payload.'
    udptag = net.build_udp(len=UDP_H+len(data), sp=54321, dp=54321, payload=data)
    packetlen = IPV4_H + UDP_H + len(data)
    iptag = net.autobuild_ipv4(len=packetlen, prot=IPPROTO_UDP, dst=ip)
    
    net.write()