Dear all, I spend some time to further investigate on this bug. For example, I checked also with the Free/Swan implementation of a dhcp relay agent.
During my investigations I found out that this bug also applies for bind9 when sending over the loopback interface. This applies of you run applications and a DNS server on the same machine. The attched example shows fetchmail querying for a DNS lookup: All tests were done using Ubuntu gutsy, but I believe they apply to Debian systems in general. The dhcpd bug can easily be solved by patching the function decode_udp_ip_header in packet.c: ------------------------------------------------------------------------------------------------------------------------- ssize_t decode_udp_ip_header (interface, buf, bufix, from, buflen) struct interface_info *interface; unsigned char *buf; unsigned bufix; struct sockaddr_in *from; unsigned buflen; { [...] /* Check the IP header checksum - it should be zero. */ ++ip_packets_seen; if (wrapsum (checksum (buf + bufix, ip_len, 0))) { ++ip_packets_bad_checksum; if (ip_packets_seen > 4 && (ip_packets_seen / ip_packets_bad_checksum) < 2) { log_info ("%d bad IP checksums seen in %d packets", ip_packets_bad_checksum, ip_packets_seen); ip_packets_seen = ip_packets_bad_checksum = 0; } return -1; } [...] /* 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 = buf + bufix + ip_len + sizeof *udp; len = ulen - sizeof *udp; ++udp_packets_length_checked; if (len + data > buf + bufix + buflen) { ++udp_packets_length_overflow; if (udp_packets_length_checked > 4 && (udp_packets_length_checked / udp_packets_length_overflow) < 2) { log_info ("%d udp packets in %d too long - dropped", udp_packets_length_overflow, udp_packets_length_checked); udp_packets_length_overflow = udp_packets_length_checked = 0; } return -1; } if (len + data < buf + bufix + buflen && len + data != buf + bufix + buflen && !ignore) log_debug ("accepting packet with data after udp payload."); if (len + data > buf + bufix + buflen) { log_debug ("dropping packet with bogus uh_ulen %ld", (long)(len + sizeof *udp)); return -1; } usum = udp -> uh_sum; udp -> uh_sum = 0; sum = wrapsum (checksum ((unsigned char *)udp, sizeof *udp, checksum (data, len, checksum ((unsigned char *) &ip.ip_src, 2 * sizeof ip.ip_src, IPPROTO_UDP + (u_int32_t)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; } // Ignore the udp checksum bug in debian systems // return -1; } /* Copy out the port... */ memcpy (&from -> sin_port, &udp -> uh_sport, sizeof udp -> uh_sport); return ip_len + sizeof *udp; } ------------------------------------------------------------------------------------------------------------------------- I haven't checked the bind9 code, yet. I'm also not sure if this problem is a global one, i. e. all applications that send udp packets via loopback have this problem. Free/Swan dhcp relay agent by the way uses the socket datagram service. Whereas dhcpd uses a raw socket. I hope this helps you. Best regards Thomas
No. Time Source Destination Protocol Info 79 09:18:37.877047 192.168.0.65 192.168.0.65 DNS Standard query A pop3.strato.de Frame 79 (74 bytes on wire, 74 bytes captured) Arrival Time: Feb 25, 2008 09:18:37.877047000 Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 192.168.0.65 (192.168.0.65), Dst: 192.168.0.65 (192.168.0.65) Version: 4 Header length: 20 bytes Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00) 0000 00.. = Differentiated Services Codepoint: Default (0x00) .... ..0. = ECN-Capable Transport (ECT): 0 .... ...0 = ECN-CE: 0 Total Length: 60 Identification: 0x771f (30495) Flags: 0x04 (Don't Fragment) 0... = Reserved bit: Not set .1.. = Don't fragment: Set ..0. = More fragments: Not set Fragment offset: 0 Time to live: 64 Protocol: UDP (0x11) Header checksum: 0x41bf [correct] [Good: True] [Bad : False] Source: 192.168.0.65 (192.168.0.65) Destination: 192.168.0.65 (192.168.0.65) User Datagram Protocol, Src Port: 32781 (32781), Dst Port: domain (53) Source port: 32781 (32781) Destination port: domain (53) Length: 40 Checksum: 0x820c [incorrect, should be 0x0f18 (maybe caused by "UDP checksum offload"?)] [Good Checksum: False] [Bad Checksum: True] Domain Name System (query) [Response In: 80] Transaction ID: 0x84dd Flags: 0x0100 (Standard query) 0... .... .... .... = Response: Message is a query .000 0... .... .... = Opcode: Standard query (0) .... ..0. .... .... = Truncated: Message is not truncated .... ...1 .... .... = Recursion desired: Do query recursively .... .... .0.. .... = Z: reserved (0) .... .... ...0 .... = Non-authenticated data OK: Non-authenticated data is unacceptable Questions: 1 Answer RRs: 0 Authority RRs: 0 Additional RRs: 0 Queries pop3.strato.de: type A, class IN Name: pop3.strato.de Type: A (Host address) Class: IN (0x0001)