|From:||gregoa [...] cpan.org|
|Subject:||libnet-rawip-perl: miscalculates header checksums|
[ This bug has been forwarded from] From: "Steinar H. Gunderson" <firstname.lastname@example.org> To: Debian Bug Tracking System <email@example.com> Subject: Bug#623634: libnet-rawip-perl: miscalculates header checksums Date: Fri, 22 Apr 2011 01:28:29 +0200 Reply-To: "Steinar H. Gunderson" <firstname.lastname@example.org>, email@example.com Hi, It seems Net::RawIP, if you run a script using it long enough (as in millions of generated UDP packets), eventually generates bogus UDP checksums in the packets it's sending out (tcpdump freaks out, the end hosts start ignoring them). I took a look at the source, and it seems the following fragment from RawIP.xs in the udp_pkt_creat() function is the culprit: memcpy(ptr,(u_char*)&piu,20); memcpy(ptr+20,SvPV(ip_opts,PL_na),SvCUR(ip_opts)); memcpy(ptr+20+SvCUR(ip_opts),(u_char*)&piu + 20,8); ((struct iphdr*)ptr)->check = in_cksum((unsigned short *)ptr,iplen); RETVAL = newSVpv((char*)ptr, sizeof(IUPKT)+SvCUR(ip_opts)); You can't use cast-as-lvalue like this; it is an aliasing violation, and with newer gcc seemingly something wrong happens here. The easiest way to fix this is usually by using memcpy (which has specific exceptions in POSIX from the aliasing rules), like this: unsigned short cksum; [...] cksum = in_cksum((unsigned short *)ptr,iplen); memcpy(&((struct iphdr*)ptr)->check, &cksum, sizeof(cksum)); Adding this fragment seems to have fixed the issue for us; at least it's running stable for a day or so. Granted, we also run with noopt nostrip, so it _could_ be something else, but it really sticks out as a sore thumb. FWIW, there are similar fragments many other places in the code, so you should probably fix all of them.