From 057211d5f5170394020b5becdeee88754fa789c2 Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Sun, 26 Jun 2011 17:50:35 -0400 Subject: [PATCH] Make IP and UDP checksum calculations for sending raw packets much less confusing. They are now calculated without mutating the underlying structures so that there is no longer any tricky operation order dependence. --- ndhc/packet.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ndhc/packet.c b/ndhc/packet.c index 85b2087..25703b5 100644 --- a/ndhc/packet.c +++ b/ndhc/packet.c @@ -366,13 +366,22 @@ static int send_dhcp_raw(struct dhcpmsg *payload) size_t padding = DHCP_OPTIONS_BUFSIZE - 1 - endloc; size_t iud_len = sizeof(struct ip_udp_dhcp_packet) - padding; size_t ud_len = sizeof(struct udp_dhcp_packet) - padding; - // UDP checksumming needs a temporary pseudoheader with a fake length. + + struct iphdr ph = { + .saddr = INADDR_ANY, + .daddr = INADDR_BROADCAST, + .protocol = IPPROTO_UDP, + .tot_len = htons(ud_len), + }; struct ip_udp_dhcp_packet iudmsg = { .ip = { - .protocol = IPPROTO_UDP, .saddr = INADDR_ANY, .daddr = INADDR_BROADCAST, - .tot_len = htons(ud_len), + .protocol = IPPROTO_UDP, + .tot_len = htons(iud_len), + .ihl = sizeof iudmsg.ip >> 2, + .version = IPVERSION, + .ttl = IPDEFTTL, }, .udp = { .source = htons(DHCP_CLIENT_PORT), @@ -381,12 +390,9 @@ static int send_dhcp_raw(struct dhcpmsg *payload) }, .data = *payload, }; - iudmsg.udp.check = net_checksum(&iudmsg, iud_len); - // Set the true IP packet length for the final packet. - iudmsg.ip.tot_len = htons(iud_len); - iudmsg.ip.ihl = sizeof iudmsg.ip >> 2; - iudmsg.ip.version = IPVERSION; - iudmsg.ip.ttl = IPDEFTTL; + uint16_t udpcs = net_checksum(&iudmsg.udp, ud_len); + uint16_t phcs = net_checksum(&ph, sizeof ph); + iudmsg.udp.check = net_checksum_add(udpcs, phcs); iudmsg.ip.check = net_checksum(&iudmsg.ip, sizeof iudmsg.ip); r = safe_sendto(fd, (const char *)&iudmsg, iud_len, 0,