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.
This commit is contained in:
@@ -366,13 +366,22 @@ static int send_dhcp_raw(struct dhcpmsg *payload)
|
|||||||
size_t padding = DHCP_OPTIONS_BUFSIZE - 1 - endloc;
|
size_t padding = DHCP_OPTIONS_BUFSIZE - 1 - endloc;
|
||||||
size_t iud_len = sizeof(struct ip_udp_dhcp_packet) - padding;
|
size_t iud_len = sizeof(struct ip_udp_dhcp_packet) - padding;
|
||||||
size_t ud_len = sizeof(struct 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 = {
|
struct ip_udp_dhcp_packet iudmsg = {
|
||||||
.ip = {
|
.ip = {
|
||||||
.protocol = IPPROTO_UDP,
|
|
||||||
.saddr = INADDR_ANY,
|
.saddr = INADDR_ANY,
|
||||||
.daddr = INADDR_BROADCAST,
|
.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 = {
|
.udp = {
|
||||||
.source = htons(DHCP_CLIENT_PORT),
|
.source = htons(DHCP_CLIENT_PORT),
|
||||||
@@ -381,12 +390,9 @@ static int send_dhcp_raw(struct dhcpmsg *payload)
|
|||||||
},
|
},
|
||||||
.data = *payload,
|
.data = *payload,
|
||||||
};
|
};
|
||||||
iudmsg.udp.check = net_checksum(&iudmsg, iud_len);
|
uint16_t udpcs = net_checksum(&iudmsg.udp, ud_len);
|
||||||
// Set the true IP packet length for the final packet.
|
uint16_t phcs = net_checksum(&ph, sizeof ph);
|
||||||
iudmsg.ip.tot_len = htons(iud_len);
|
iudmsg.udp.check = net_checksum_add(udpcs, phcs);
|
||||||
iudmsg.ip.ihl = sizeof iudmsg.ip >> 2;
|
|
||||||
iudmsg.ip.version = IPVERSION;
|
|
||||||
iudmsg.ip.ttl = IPDEFTTL;
|
|
||||||
iudmsg.ip.check = net_checksum(&iudmsg.ip, sizeof iudmsg.ip);
|
iudmsg.ip.check = net_checksum(&iudmsg.ip, sizeof iudmsg.ip);
|
||||||
|
|
||||||
r = safe_sendto(fd, (const char *)&iudmsg, iud_len, 0,
|
r = safe_sendto(fd, (const char *)&iudmsg, iud_len, 0,
|
||||||
|
Reference in New Issue
Block a user