File dhcpcd-3.2.3-xen-checksum.diff of Package dhcpcd

--- socket.c
+++ socket.c
@@ -48,7 +48,8 @@
 # include <net/bpf.h>
 #elif __linux__
 # include <linux/filter.h>
-# include <netpacket/packet.h>
+# include <linux/if_packet.h>
+/* # include <netpacket/packet.h> */
 # define bpf_insn sock_filter
 #endif
 
@@ -202,7 +203,7 @@ void make_dhcp_packet(struct udp_dhcp_packet *packet,
 	ip->ip_sum = checksum ((unsigned char *) ip, sizeof (*ip));
 }
 
-static int valid_dhcp_packet (unsigned char *data)
+static int valid_dhcp_packet (unsigned char *data, int nocsum)
 {
 	union
 	{
@@ -242,7 +243,7 @@ static int valid_dhcp_packet (unsigned char *data)
 	memcpy (&d.packet->ip.ip_src, &source, sizeof (d.packet->ip.ip_src));
 	memcpy (&d.packet->ip.ip_dst, &dest, sizeof (d.packet->ip.ip_dst));
 	d.packet->ip.ip_len = d.packet->udp.uh_ulen;
-	if (udpsum && udpsum != checksum (d.data, bytes)) {
+	if (!nocsum && udpsum && udpsum != checksum (d.data, bytes)) {
 		logger (LOG_ERR, "bad UDP checksum, ignoring");
 		retval = -1;
 	}
@@ -409,7 +410,7 @@ ssize_t get_packet (const interface_t *iface, unsigned char *data,
 			memcpy (data, payload, len);
 			have_data = true;
 		} else {
-			if (valid_dhcp_packet (payload) >= 0) {
+			if (valid_dhcp_packet (payload, 0) >= 0) {
 				union
 				{
 					unsigned char *buffer;
@@ -535,6 +536,16 @@ int open_socket (interface_t *iface, int protocol)
 		return (-1);
 	}
 
+	n = 1;
+	if (setsockopt (fd, SOL_PACKET, PACKET_AUXDATA, &n, sizeof(n)) < 0) {
+		if (errno != ENOPROTOOPT) {
+			logger (LOG_ERR, "failed to set auxiliary packet data: %s",
+				strerror (errno));
+			close (fd);
+			return (-1);
+		}
+	}
+
 	if (iface->fd > -1)
 		close (iface->fd);
 	iface->fd = fd;
@@ -594,13 +605,26 @@ ssize_t get_packet (const interface_t *iface, unsigned char *data,
 		unsigned char *buffer;
 		struct udp_dhcp_packet *packet;
 	} pay;
+	unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
+	struct iovec iov = {
+		.iov_base = buffer,
+		.iov_len  = iface->buffer_length,
+	};
+	struct msghdr msg = {
+		.msg_iov = &iov,
+		.msg_iovlen = 1,
+		.msg_control = cmsgbuf,
+		.msg_controllen = sizeof(cmsgbuf),
+	};
+	struct cmsghdr *cmsg;
+	int nocsum = 0;
 
 	/* We don't use the given buffer, but we need to rewind the position */
 	*buffer_pos = 0;
 
 	memset (buffer, 0, iface->buffer_length);
-	bytes = read (iface->fd, buffer, iface->buffer_length);
 
+	bytes = recvmsg (iface->fd, &msg, 0);
 	if (bytes == -1) {
 		struct timespec ts;
 		logger (LOG_ERR, "read: %s", strerror (errno));
@@ -609,6 +633,13 @@ ssize_t get_packet (const interface_t *iface, unsigned char *data,
 		nanosleep (&ts, NULL);
 		return (-1);
 	}
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+		if (cmsg->cmsg_level == SOL_PACKET &&
+		    cmsg->cmsg_type == PACKET_AUXDATA) {
+			struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
+			nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY;
+		}
+	}
 
 	*buffer_len = bytes;
 	/* If it's an ARP reply, then just send it back */
@@ -630,7 +661,7 @@ ssize_t get_packet (const interface_t *iface, unsigned char *data,
 		return (-1);
 	}
 
-	if (valid_dhcp_packet (buffer) == -1)
+	if (valid_dhcp_packet (buffer, nocsum) == -1)
 		return (-1);
 
 	bytes = ntohs (pay.packet->ip.ip_len) -
openSUSE Build Service is sponsored by