From owner-freebsd-net@FreeBSD.ORG Tue Jun 28 19:09:11 2011 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 96C21106566C for ; Tue, 28 Jun 2011 19:09:11 +0000 (UTC) (envelope-from sthaug@nethelp.no) Received: from bizet.nethelp.no (bizet.nethelp.no [195.1.209.33]) by mx1.freebsd.org (Postfix) with SMTP id EC7888FC1A for ; Tue, 28 Jun 2011 19:09:10 +0000 (UTC) Received: (qmail 2808 invoked from network); 28 Jun 2011 19:09:09 -0000 Received: from bizet.nethelp.no (HELO localhost) (195.1.209.33) by bizet.nethelp.no with SMTP; 28 Jun 2011 19:09:09 -0000 Date: Tue, 28 Jun 2011 21:09:09 +0200 (CEST) Message-Id: <20110628.210909.74655931.sthaug@nethelp.no> To: benoit.panizzon@imp.ch From: sthaug@nethelp.no In-Reply-To: <1658896945.9968.1309271076776.JavaMail.root@erie.cs.uoguelph.ca> References: <201106281148.36754.benoit.panizzon@imp.ch> <1658896945.9968.1309271076776.JavaMail.root@erie.cs.uoguelph.ca> X-Mailer: Mew version 3.3 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Cc: freebsd-net@freebsd.org Subject: Re: udp checksum implementation error in FreeBSD 7.2? X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Jun 2011 19:09:11 -0000 > > What we observe is: > > > > DHCP Request with UDP checksum set => Packet reaches DHCP Daemon and > > is being > > answered. > > DHCP Request with UDP checksum 0x0000 => ICMP Port Unreachable from > > FreeBSD. > > > > Can someone confirm this non RFC conform behaviour and knows how to > > fix it? > > > Well, I took a quick look at the sources (which are in sys/netinet/udp_usrreq.c > in a function called udp_input() at about line#300) and it only does the > checksum if it is non-zero. It looks like: > if (uh->uh_sum) { > ....do checksum > (If you don't have kernel sources handy, you can find them here: > http://svn.freebsd.org/viewvc/base/releng/7.2) As another poster commented, ISC dhcpd by default uses BPF, *not* the kernel UDP implementation - this is done to be able to handle broadcast packets. However, the mystery doesn't end here - because the ISC dhcpd implementation *also* only cares about UDP packets with a non-zero checksum. The code is in common/packet.c, routine decode_udp_ip_header() which is used by BPF and other link level access methods (e.g. DLPI on Solaris). From dhcp-4.2.0-P2/common/packet.c: ---------------------------------------------------------------------- /* Compute UDP checksums, including the ``pseudo-header'', the UDP header and the data. If the UDP checksum field is zero, we're not supposed to do a checksum. */ data = upp + sizeof(udp); len = ulen - sizeof(udp); usum = udp.uh_sum; udp.uh_sum = 0; /* XXX: We have to pass &udp, because we have to zero the checksum * field before calculating the sum...'upp' isn't zeroed. */ sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp), checksum(data, len, checksum((unsigned char *)&ip.ip_src, 8, IPPROTO_UDP + ulen)))); udp_packets_seen++; if (usum && usum != sum) { udp_packets_bad_checksum++; if (udp_packets_seen > 4 && (udp_packets_seen / udp_packets_bad_checksum) < 2) { log_info ("%d bad udp checksums in %d packets", udp_packets_bad_checksum, udp_packets_seen); udp_packets_seen = udp_packets_bad_checksum = 0; } return -1; } ---------------------------------------------------------------------- The way I read the code - the UDP checksum is computed in all cases, but is only *compared* with the original checksum field of the packet if this field is non-zero. Returning to the original claim of > DHCP Request with UDP checksum 0x0000 => ICMP Port Unreachable from > FreeBSD. I can see (e.g. using tcpdump) FreeBSD handle packets with a UDP checksum field of 0 just fine - for instance on a busy name server. So I am quite confident that your observed ICMP Port Unreachable is not generated by the FreeBSD kernel, as long as you have the DHCP server listening on UDP port 67. Steinar Haug, Nethelp consulting, sthaug@nethelp.no