struct in_addr *from, unsigned int flags)
{
struct ip *ip = packet;
- struct ip pseudo_ip = {
- .ip_p = IPPROTO_UDP,
- .ip_src = ip->ip_src,
- .ip_dst = ip->ip_dst
+ union pip {
+ struct ip ip;
+ uint16_t w[sizeof(struct ip)];
+ } pip = {
+ .ip.ip_p = IPPROTO_UDP,
+ .ip.ip_src = ip->ip_src,
+ .ip.ip_dst = ip->ip_dst,
};
size_t ip_hlen;
- uint16_t udp_len, uh_sum;
struct udphdr udp;
char *udpp, *uh_sump;
uint32_t csum;
/* UDP checksum is based on a pseudo IP header alongside
* the UDP header and payload. */
- udp_len = ntohs(udp.uh_ulen);
- uh_sum = udp.uh_sum;
+ pip.ip.ip_len = udp.uh_ulen;
+ csum = 0;
/* Need to zero the UDP sum in the packet for the checksum to work. */
uh_sump = udpp + offsetof(struct udphdr, uh_sum);
memset(uh_sump, 0, sizeof(udp.uh_sum));
- pseudo_ip.ip_len = udp.uh_ulen;
- csum = 0;
- in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum);
- csum = in_cksum(udpp, udp_len, &csum);
+ /* Checksum psuedo header and then UDP + payload. */
+ in_cksum(pip.w, sizeof(pip.w), &csum);
+ csum = in_cksum(udpp, ntohs(udp.uh_ulen), &csum);
+#if 0 /* Not needed, just here for completeness. */
/* Put the checksum back. */
- memcpy(uh_sump, &uh_sum, sizeof(udp.uh_sum));
+ memcpy(uh_sump, &udp.uh_sum, sizeof(udp.uh_sum));
+#endif
- return csum == uh_sum;
+ return csum == udp.uh_sum;
}
static void