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) -