Not sure if I sent this before, but I found it sitting in a tree. dhcrelay missed out on some of the changes made to dhcpd/dhclient's packet.c. OK to sync them up? After this set of patches, the only difference from dhcpd's is the intentional ipsec-related one.
OK? "Remove unused (a.k.a. always passed NULL) parameter 'data' from decode_udp_ip_header() and the useless check of it. Part of original diff from pelikan about udp length errors." dhcpd/bpf.c:1.8->1.9 dhcpd/dhcpd.h:1.45->1.46 dhcpd/packet.c:1.4->1.5 diff --git bpf.c bpf.c index fad2e0a..298d3ec 100644 --- bpf.c +++ bpf.c @@ -377,7 +377,7 @@ receive_packet(struct interface_info *interface, unsigned char *buf, /* Decode the IP and UDP headers... */ offset = decode_udp_ip_header(interface, interface->rbuf, - interface->rbuf_offset, from, NULL, hdr.bh_caplen); + interface->rbuf_offset, from, hdr.bh_caplen); /* If the IP or UDP checksum was bad, skip the packet... */ if (offset < 0) { diff --git dhcpd.h dhcpd.h index c1d6917..b80e984 100644 --- dhcpd.h +++ dhcpd.h @@ -162,7 +162,7 @@ void remove_protocol(struct protocol *); void assemble_hw_header(struct interface_info *, unsigned char *, int *, struct hardware *); void assemble_udp_ip_header(struct interface_info *, unsigned char *, - int *, u_int32_t, u_int32_t, unsigned int, unsigned char *, int); + int *, u_int32_t, u_int32_t, unsigned int, int); ssize_t decode_hw_header(struct interface_info *, unsigned char *, int, struct hardware *); ssize_t decode_udp_ip_header(struct interface_info *, unsigned char *, diff --git packet.c packet.c index 6352f0c..c0e7432 100644 --- packet.c +++ packet.c @@ -178,10 +178,11 @@ decode_hw_header(struct interface_info *interface, unsigned char *buf, ssize_t decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, - int bufix, struct sockaddr_in *from, unsigned char *data, int buflen) + int bufix, struct sockaddr_in *from, int buflen) { struct ip *ip; struct udphdr *udp; + unsigned char *data; u_int32_t ip_len = (buf[bufix] & 0xf) << 2; u_int32_t sum, usum; static int ip_packets_seen; @@ -190,7 +191,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, static int udp_packets_bad_checksum; static int udp_packets_length_checked; static int udp_packets_length_overflow; - int len = 0; + int len; ip = (struct ip *)(buf + bufix); udp = (struct udphdr *)(buf + bufix + ip_len); @@ -216,30 +217,28 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, /* * Compute UDP checksums, including the ``pseudo-header'', the - * UDP header and the data. If the UDP checksum field is zero, + * UDP header and the data. If the UDP checksum field is zero, * we're not supposed to do a checksum. */ - if (!data) { - data = buf + bufix + ip_len + sizeof(*udp); - len = ntohs(udp->uh_ulen) - sizeof(*udp); - udp_packets_length_checked++; - if ((len < 0) || (len + data > buf + bufix + buflen)) { - udp_packets_length_overflow++; - if (udp_packets_length_checked > 4 && - udp_packets_length_overflow != 0 && - (udp_packets_length_checked / - udp_packets_length_overflow) < 2) { - note("%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); + data = buf + bufix + ip_len + sizeof(*udp); + len = ntohs(udp->uh_ulen) - sizeof(*udp); + udp_packets_length_checked++; + if ((len < 0) || (len + data > buf + bufix + buflen)) { + udp_packets_length_overflow++; + if (udp_packets_length_checked > 4 && + udp_packets_length_overflow != 0 && + (udp_packets_length_checked / + udp_packets_length_overflow) < 2) { + note("%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; } - if (len + data != buf + bufix + buflen) - debug("accepting packet with data after udp payload."); + return (-1); } + if (len + data != buf + bufix + buflen) + debug("accepting packet with data after udp payload."); usum = udp->uh_sum; udp->uh_sum = 0; "Nuke local #define ETHER_HEADER_SIZE and use the identical value'd ETHER_HDR_LEN from if_ether.h. dhclient change ok matthew@ as part of larger diff." dhcpd/packet.c:1.5->1.6 diff --git packet.c packet.c index c0e7432..cbb7c8d 100644 --- packet.c +++ packet.c @@ -47,8 +47,6 @@ #include <netinet/udp.h> #include <netinet/if_ether.h> -#define ETHER_HEADER_SIZE (ETHER_ADDR_LEN * 2 + sizeof(u_int16_t)) - u_int32_t checksum(unsigned char *, unsigned, u_int32_t); u_int32_t wrapsum(u_int32_t); @@ -101,8 +99,8 @@ assemble_hw_header(struct interface_info *interface, unsigned char *buf, eh.ether_type = htons(ETHERTYPE_IP); - memcpy(&buf[*bufix], &eh, ETHER_HEADER_SIZE); - *bufix += ETHER_HEADER_SIZE; + memcpy(&buf[*bufix], &eh, ETHER_HDR_LEN); + *bufix += ETHER_HDR_LEN; } void @@ -165,7 +163,7 @@ decode_hw_header(struct interface_info *interface, unsigned char *buf, bzero(&eh, sizeof(eh)); offset = ENC_HDRLEN + ip_len; } else { - memcpy(&eh, buf + bufix, ETHER_HEADER_SIZE); + memcpy(&eh, buf + bufix, ETHER_HDR_LEN); offset = sizeof(eh); } "Variables to count seen packets should be unsigned." dhcpd/packet.c:1.7->1.8 diff --git packet.c packet.c index cbb7c8d..a71d79f 100644 --- packet.c +++ packet.c @@ -183,12 +183,12 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, unsigned char *data; u_int32_t ip_len = (buf[bufix] & 0xf) << 2; u_int32_t sum, usum; - static int ip_packets_seen; - static int ip_packets_bad_checksum; - static int udp_packets_seen; - static int udp_packets_bad_checksum; - static int udp_packets_length_checked; - static int udp_packets_length_overflow; + static unsigned int ip_packets_seen; + static unsigned int ip_packets_bad_checksum; + static unsigned int udp_packets_seen; + static unsigned int udp_packets_bad_checksum; + static unsigned int udp_packets_length_checked; + static unsigned int udp_packets_length_overflow; int len; ip = (struct ip *)(buf + bufix); @@ -200,7 +200,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, ip_packets_bad_checksum++; if (ip_packets_seen > 4 && ip_packets_bad_checksum != 0 && (ip_packets_seen / ip_packets_bad_checksum) < 2) { - note("%d bad IP checksums seen in %d packets", + note("%u bad IP checksums seen in %u packets", ip_packets_bad_checksum, ip_packets_seen); ip_packets_seen = ip_packets_bad_checksum = 0; } @@ -227,7 +227,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, udp_packets_length_overflow != 0 && (udp_packets_length_checked / udp_packets_length_overflow) < 2) { - note("%d udp packets in %d too long - dropped", + note("%u udp packets in %u too long - dropped", udp_packets_length_overflow, udp_packets_length_checked); udp_packets_length_overflow = @@ -251,7 +251,7 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf, udp_packets_bad_checksum++; if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 && (udp_packets_seen / udp_packets_bad_checksum) < 2) { - note("%d bad udp checksums in %d packets", + note("%u bad udp checksums in %u packets", udp_packets_bad_checksum, udp_packets_seen); udp_packets_seen = udp_packets_bad_checksum = 0; }