Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/roy]: src/external/bsd/dhcpcd/dist/src Import dhcpcd-8.1.1 with the foll...



details:   https://anonhg.NetBSD.org/src/rev/e6497c01ad11
branches:  roy
changeset: 455419:e6497c01ad11
user:      roy <roy%NetBSD.org@localhost>
date:      Wed Oct 16 14:50:27 2019 +0000

description:
Import dhcpcd-8.1.1 with the following changes:

 * IPv6: Fix a potential crash when learning interface addresses.
 * DHCP: Fix fallout from dhcpcd-8.1.0 for checksum calculation.

diffstat:

 external/bsd/dhcpcd/dist/src/defs.h       |    4 +
 external/bsd/dhcpcd/dist/src/dhcp.c       |  220 ++++++++++++++++++------------
 external/bsd/dhcpcd/dist/src/dhcp.h       |    2 +
 external/bsd/dhcpcd/dist/src/dhcp6.c      |  120 ++++++++++------
 external/bsd/dhcpcd/dist/src/dhcp6.h      |    2 +
 external/bsd/dhcpcd/dist/src/dhcpcd.c     |   29 +++-
 external/bsd/dhcpcd/dist/src/dhcpcd.h     |    7 +
 external/bsd/dhcpcd/dist/src/if-options.h |    2 +-
 external/bsd/dhcpcd/dist/src/ipv6.c       |    8 +-
 external/bsd/dhcpcd/dist/src/ipv6nd.c     |  150 ++++++++++++--------
 external/bsd/dhcpcd/dist/src/ipv6nd.h     |    2 +
 11 files changed, 349 insertions(+), 197 deletions(-)

diffs (truncated from 938 to 300 lines):

diff -r 172d4006803d -r e6497c01ad11 external/bsd/dhcpcd/dist/src/defs.h
--- a/external/bsd/dhcpcd/dist/src/defs.h       Fri Oct 11 11:00:49 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/defs.h       Wed Oct 16 14:50:27 2019 +0000
@@ -31,6 +31,10 @@
 #define PACKAGE                        "dhcpcd"
 #define VERSION                        "8.1.0"
 
+#ifndef DHCPCD_USER
+# define DHCPCD_USER           "_dhcpcd"
+#endif
+
 #ifndef CONFIG
 # define CONFIG                        SYSCONFDIR "/" PACKAGE ".conf"
 #endif
diff -r 172d4006803d -r e6497c01ad11 external/bsd/dhcpcd/dist/src/dhcp.c
--- a/external/bsd/dhcpcd/dist/src/dhcp.c       Fri Oct 11 11:00:49 2019 +0000
+++ b/external/bsd/dhcpcd/dist/src/dhcp.c       Wed Oct 16 14:50:27 2019 +0000
@@ -67,6 +67,7 @@
 #include "ipv4.h"
 #include "ipv4ll.h"
 #include "logerr.h"
+#include "privsep.h"
 #include "sa.h"
 #include "script.h"
 
@@ -164,8 +165,6 @@
        }
 }
 
-#define get_option_raw(ctx, bootp, bootp_len, opt)     \
-       get_option((ctx), (bootp), (bootp_len), NULL)
 static const uint8_t *
 get_option(struct dhcpcd_ctx *ctx,
     const struct bootp *bootp, size_t bootp_len,
@@ -1650,39 +1649,43 @@
 dhcp_sendudp(struct interface *ifp, struct in_addr *to, void *data, size_t len)
 {
        int s;
-       struct msghdr msg;
-       struct sockaddr_in sin;
-       struct iovec iov[1];
+       struct sockaddr_in sin = {
+               .sin_family = AF_INET,
+               .sin_addr = *to,
+               .sin_port = htons(BOOTPS),
+#ifdef HAVE_SA_LEN
+               .sin_len = sizeof(sin),
+#endif
+       };
+       struct iovec iov[] = {
+               { .iov_base = data, .iov_len = len }
+       };
+       struct msghdr msg = {
+               .msg_name = (void *)&sin,
+               .msg_namelen = sizeof(sin),
+               .msg_iov = iov,
+               .msg_iovlen = 1,
+       };
        struct dhcp_state *state = D_STATE(ifp);
        ssize_t r;
 
-       iov[0].iov_base = data;
-       iov[0].iov_len = len;
-
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr = *to;
-       sin.sin_port = htons(BOOTPS);
-#ifdef HAVE_SA_LEN
-       sin.sin_len = sizeof(sin);
+#ifdef PRIVSEP
+       if (ifp->ctx->options & DHCPCD_PRIVSEP)
+               return privsep_sendmsg(ifp->ctx, PS_BOOTP, &msg);
+       else
 #endif
-
-       memset(&msg, 0, sizeof(msg));
-       msg.msg_name = (void *)&sin;
-       msg.msg_namelen = sizeof(sin);
-       msg.msg_iov = iov;
-       msg.msg_iovlen = 1;
-
-       s = state->udp_fd;
-       if (s == -1) {
-               s = dhcp_openudp(ifp);
-               if (s == -1)
-                       return -1;
+       {
+               s = state->udp_fd;
+               if (s == -1) {
+                       s = dhcp_openudp(ifp);
+                       if (s == -1)
+                               return -1;
+               }
+               r = sendmsg(s, &msg, 0);
+               if (state->udp_fd == -1)
+                       close(s);
+               return r;
        }
-       r = sendmsg(s, &msg, 0);
-       if (state->udp_fd == -1)
-               close(s);
-       return r;
 }
 
 static void
@@ -3275,26 +3278,35 @@
 {
        struct ip *ip = packet;
        size_t ip_hlen;
-       struct udphdr *udp;
-
-       if (sizeof(*ip) > plen)
+       struct udphdr udp;
+
+       if (plen < sizeof(*ip))
                return false;
 
        if (ip->ip_v != IPVERSION || ip->ip_p != IPPROTO_UDP)
                return false;
 
        /* Sanity. */
-       if (ntohs(ip->ip_len) != plen)
+       if (ntohs(ip->ip_len) > plen)
                return false;
 
        ip_hlen = (size_t)ip->ip_hl * 4;
+       if (ip_hlen < sizeof(*ip))
+               return false;
+
        /* Check we have a UDP header and BOOTP. */
-       if (ip_hlen + sizeof(*udp) + offsetof(struct bootp, vend) > plen)
+       if (ip_hlen + sizeof(udp) + offsetof(struct bootp, vend) > plen)
+               return false;
+
+       /* Sanity. */
+       memcpy(&udp, (char *)ip + ip_hlen, sizeof(udp));
+       if (ntohs(udp.uh_ulen) < sizeof(udp))
+               return false;
+       if (ip_hlen + ntohs(udp.uh_ulen) > plen)
                return false;
 
        /* Check it's to and from the right ports. */
-       udp = (struct udphdr *)(void *)((char *)ip + ip_hlen);
-       if (udp->uh_dport != htons(BOOTPC) || udp->uh_sport != htons(BOOTPS))
+       if (udp.uh_dport != htons(BOOTPC) || udp.uh_sport != htons(BOOTPS))
                return false;
 
        return true;
@@ -3306,14 +3318,17 @@
     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;
+       struct udphdr udp;
+       char *udpp, *uh_sump;
        uint32_t csum;
 
        if (from != NULL)
@@ -3324,22 +3339,32 @@
                return false;
 
        if (flags & BPF_PARTIALCSUM)
-               return 0;
-
-       udp = (struct udphdr *)(void *)((char *)ip + ip_hlen);
-       if (udp->uh_sum == 0)
-               return 0;
+               return true;
+
+       udpp = (char *)ip + ip_hlen;
+       memcpy(&udp, udpp, sizeof(udp));
+       if (udp.uh_sum == 0)
+               return true;
 
        /* 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;
-       udp->uh_sum = 0;
-       pseudo_ip.ip_len = udp->uh_ulen;
+       pip.ip.ip_len = udp.uh_ulen;
        csum = 0;
-       in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum);
-       csum = in_cksum(udp, udp_len, &csum);
-       return csum == uh_sum;
+
+       /* 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));
+
+       /* 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, &udp.uh_sum, sizeof(udp.uh_sum));
+#endif
+
+       return csum == udp.uh_sum;
 }
 
 static void
@@ -3430,6 +3455,40 @@
                state->bpf_flags &= ~BPF_READING;
 }
 
+void
+dhcp_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
+{
+#ifdef IP_PKTINFO
+       struct sockaddr_in *from = (struct sockaddr_in *)msg->msg_name;
+       struct iovec *iov = &msg->msg_iov[0];
+       char sfrom[INET_ADDRSTRLEN];
+       struct interface *ifp;
+       const struct dhcp_state *state;
+
+       inet_ntop(AF_INET, &from->sin_addr, sfrom, sizeof(sfrom));
+
+       ifp = if_findifpfromcmsg(ctx, msg, NULL);
+       if (ifp == NULL) {
+               logerr(__func__);
+               return;
+       }
+       state = D_CSTATE(ifp);
+       if (state == NULL) {
+               logdebugx("%s: received BOOTP for inactive interface",
+                   ifp->name);
+               return;
+       }
+
+       if (state->bpf_fd != -1) {
+               /* Avoid a duplicate read if BPF is open for the interface. */
+               return;
+       }
+
+       dhcp_handlebootp(ifp, (struct bootp *)iov->iov_base, iov->iov_len,
+           &from->sin_addr);
+#endif
+}
+
 static void
 dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
 {
@@ -3442,7 +3501,6 @@
        };
 #ifdef IP_PKTINFO
        unsigned char ctl[CMSG_SPACE(sizeof(struct in_pktinfo))] = { 0 };
-       char sfrom[INET_ADDRSTRLEN];
 #endif
        struct msghdr msg = {
            .msg_name = &from, .msg_namelen = sizeof(from),
@@ -3466,31 +3524,8 @@
                return;
        }
 
-#ifdef IP_PKTINFO
-       inet_ntop(AF_INET, &from.sin_addr, sfrom, sizeof(sfrom));
-
-       if (ifp == NULL) {
-               ifp = if_findifpfromcmsg(ctx, &msg, NULL);
-               if (ifp == NULL) {
-                       logerr(__func__);
-                       return;
-               }
-               state = D_CSTATE(ifp);
-               if (state == NULL) {
-                       logdebugx("%s: received BOOTP for inactive interface",
-                           ifp->name);
-                       return;
-               }
-       }
-
-       if (state->bpf_fd != -1) {
-               /* Avoid a duplicate read if BPF is open for the interface. */
-               return;
-       }
-
-       dhcp_handlebootp(ifp, (struct bootp *)(void *)buf, (size_t)bytes,
-           &from.sin_addr);
-#endif
+       iov.iov_len = (size_t)bytes;
+       dhcp_recvmsg(ctx, &msg);
 }
 



Home | Main Index | Thread Index | Old Index