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)

Reply via email to