Source-Changes-HG archive

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

[src/trunk]: src/external/bsd/dhcpcd/dist/src Sync



details:   https://anonhg.NetBSD.org/src/rev/bb8c480c1343
branches:  trunk
changeset: 828272:bb8c480c1343
user:      roy <roy%NetBSD.org@localhost>
date:      Wed Dec 06 10:35:05 2017 +0000

description:
Sync

diffstat:

 external/bsd/dhcpcd/dist/src/bpf.c    |    5 +-
 external/bsd/dhcpcd/dist/src/dhcp.c   |  213 +++++++++++++++++++++------------
 external/bsd/dhcpcd/dist/src/dhcpcd.c |   68 ++++------
 3 files changed, 164 insertions(+), 122 deletions(-)

diffs (truncated from 468 to 300 lines):

diff -r a92455ebcd6f -r bb8c480c1343 external/bsd/dhcpcd/dist/src/bpf.c
--- a/external/bsd/dhcpcd/dist/src/bpf.c        Wed Dec 06 10:33:29 2017 +0000
+++ b/external/bsd/dhcpcd/dist/src/bpf.c        Wed Dec 06 10:35:05 2017 +0000
@@ -194,7 +194,8 @@
 /* BPF requires that we read the entire buffer.
  * So we pass the buffer in the API so we can loop on >1 packet. */
 ssize_t
-bpf_read(struct interface *ifp, int fd, void *data, size_t len, int *flags)
+bpf_read(struct interface *ifp, int fd, void *data, size_t len,
+    unsigned int *flags)
 {
        ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
        ssize_t bytes;
@@ -203,7 +204,7 @@
        struct bpf_hdr packet;
        const char *payload;
 
-       *flags = 0;
+       *flags &= ~BPF_EOF;
        for (;;) {
                if (state->buffer_len == 0) {
                        bytes = read(fd, state->buffer, state->buffer_size);
diff -r a92455ebcd6f -r bb8c480c1343 external/bsd/dhcpcd/dist/src/dhcp.c
--- a/external/bsd/dhcpcd/dist/src/dhcp.c       Wed Dec 06 10:33:29 2017 +0000
+++ b/external/bsd/dhcpcd/dist/src/dhcp.c       Wed Dec 06 10:35:05 2017 +0000
@@ -428,7 +428,6 @@
 
                if ((rt = rt_new(ifp)) == NULL)
                        return -1;
-               TAILQ_INSERT_TAIL(routes, rt, rt_next);
 
                /* If we have ocets then we have a destination and netmask */
                dest.s_addr = 0;
@@ -461,6 +460,8 @@
                /* If CIDR is 32 then it's a host route. */
                if (cidr == 32)
                        rt->rt_flags = RTF_HOST;
+
+               TAILQ_INSERT_TAIL(routes, rt, rt_next);
                n++;
        }
        return n;
@@ -1408,27 +1409,24 @@
                        continue;
                if (dhcp_getoverride(ifo, opt->option))
                        continue;
-               if ((p = get_option(ifp->ctx, bootp, bootp_len,
-                   opt->option, &pl)))
-               {
-                       ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
-                           opt, dhcp_getoption, p, pl);
-                       if (opt->option == DHO_VIVSO &&
-                           pl > (int)sizeof(uint32_t))
-                       {
-                               memcpy(&en, p, sizeof(en));
-                               en = ntohl(en);
-                               vo = vivso_find(en, ifp);
-                               if (vo) {
-                                       /* Skip over en + total size */
-                                       p += sizeof(en) + 1;
-                                       pl -= sizeof(en) + 1;
-                                       ep += dhcp_envoption(ifp->ctx,
-                                           ep, prefix, ifp->name,
-                                           vo, dhcp_getoption, p, pl);
-                               }
-                       }
-               }
+               p = get_option(ifp->ctx, bootp, bootp_len, opt->option, &pl);
+               if (p == NULL)
+                       continue;
+               ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+                   opt, dhcp_getoption, p, pl);
+
+               if (opt->option != DHO_VIVSO || pl <= (int)sizeof(uint32_t))
+                       continue;
+               memcpy(&en, p, sizeof(en));
+               en = ntohl(en);
+               vo = vivso_find(en, ifp);
+               if (vo == NULL)
+                       continue;
+               /* Skip over en + total size */
+               p += sizeof(en) + 1;
+               pl -= sizeof(en) + 1;
+               ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+                   vo, dhcp_getoption, p, pl);
        }
 
        for (i = 0, opt = ifo->dhcp_override;
@@ -1437,10 +1435,11 @@
        {
                if (has_option_mask(ifo->nomask, opt->option))
                        continue;
-               if ((p = get_option(ifp->ctx, bootp, bootp_len,
-                   opt->option, &pl)))
-                       ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
-                           opt, dhcp_getoption, p, pl);
+               p = get_option(ifp->ctx, bootp, bootp_len, opt->option, &pl);
+               if (p == NULL)
+                       continue;
+               ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+                   opt, dhcp_getoption, p, pl);
        }
 
        return ep - env;
@@ -1519,6 +1518,8 @@
 dhcp_new_xid(struct interface *ifp)
 {
        struct dhcp_state *state;
+       const struct interface *ifp1;
+       const struct dhcp_state *state1;
 
        state = D_STATE(ifp);
        if (ifp->options->options & DHCPCD_XID_HWADDR &&
@@ -1527,8 +1528,30 @@
                memcpy(&state->xid,
                    (ifp->hwaddr + ifp->hwlen) - sizeof(state->xid),
                    sizeof(state->xid));
-       else
+       else {
+again:
                state->xid = arc4random();
+       }
+
+       /* Ensure it's unique */
+       TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
+               if (ifp == ifp1)
+                       continue;
+               if ((state1 = D_CSTATE(ifp1)) == NULL)
+                       continue;
+               if (state1->xid == state->xid)
+                       break;
+       }
+       if (ifp1 != NULL) {
+               if (ifp->options->options & DHCPCD_XID_HWADDR &&
+                   ifp->hwlen >= sizeof(state->xid))
+               {
+                       logerrx("%s: duplicate xid on %s",
+                           ifp->name, ifp1->name);
+                           return;
+               }
+               goto again;
+       }
 
        /* We can't do this when sharing leases across interfaes */
 #if 0
@@ -1552,6 +1575,7 @@
                eloop_event_delete(ifp->ctx->eloop, state->bpf_fd);
                bpf_close(ifp, state->bpf_fd);
                state->bpf_fd = -1;
+               state->bpf_flags |= BPF_EOF;
        }
 
        state->interval = 0;
@@ -2464,11 +2488,43 @@
        }
 }
 
+#ifdef ARP
+static int
+dhcp_activeaddr(const struct interface *ifp, const struct in_addr *addr)
+{
+       const struct interface *ifp1;
+       const struct dhcp_state *state;
+
+       TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
+               if (ifp1 == ifp)
+                       continue;
+               if ((state = D_CSTATE(ifp1)) == NULL)
+                       continue;
+               switch(state->state) {
+               case DHS_REBOOT:
+               case DHS_RENEW:
+               case DHS_REBIND:
+               case DHS_BOUND:
+               case DHS_INFORM:
+                       break;
+               default:
+                       continue;
+               }
+               if (state->lease.addr.s_addr == addr->s_addr)
+                       return 1;
+       }
+       return 0;
+}
+#endif
+
 static void
 dhcp_reboot(struct interface *ifp)
 {
        struct if_options *ifo;
        struct dhcp_state *state = D_STATE(ifp);
+#ifdef ARP
+       struct ipv4_addr *ia;
+#endif
 
        if (state == NULL || state->state == DHS_NONE)
                return;
@@ -2499,6 +2555,20 @@
 
        loginfox("%s: rebinding lease of %s",
            ifp->name, inet_ntoa(state->lease.addr));
+
+#ifdef ARP
+       /* If the address exists on the interface and no other interface
+        * is currently using it then announce it to ensure this
+        * interface gets the reply. */
+       ia = ipv4_iffindaddr(ifp, &state->lease.addr, NULL);
+       if (ia != NULL &&
+#ifdef IN_IFF_NOTUSEABLE
+           !(ia->addr_flags & IN_IFF_NOTUSEABLE) &&
+#endif
+           dhcp_activeaddr(ifp, &state->lease.addr) == 0)
+               arp_ifannounceaddr(ifp, &state->lease.addr);
+#endif
+
        dhcp_new_xid(ifp);
        state->lease.server.s_addr = 0;
        eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -3147,7 +3217,7 @@
        if (data_len < sizeof(p->ip) + sizeof(p->udp)) {
                if (from)
                        from->s_addr = INADDR_ANY;
-               errno = EINVAL;
+               errno = ERANGE;
                return -1;
        }
        p = (struct bootp_pkt *)data;
@@ -3160,7 +3230,7 @@
 
        bytes = ntohs(p->ip.ip_len);
        if (bytes > data_len) {
-               errno = EINVAL;
+               errno = ENOBUFS;
                return -1;
        }
 
@@ -3191,17 +3261,22 @@
 }
 
 static void
-dhcp_handlepacket(struct interface *ifp, uint8_t *data, size_t len, int flags)
+dhcp_handlepacket(struct interface *ifp, uint8_t *data, size_t len)
 {
        struct bootp *bootp;
        struct in_addr from;
        size_t udp_len;
        const struct dhcp_state *state = D_CSTATE(ifp);
 
-       if (valid_udp_packet(data, len, &from, flags & RAW_PARTIALCSUM) == -1)
+       if (valid_udp_packet(data, len, &from,
+                            state->bpf_flags & RAW_PARTIALCSUM) == -1)
        {
-               logerrx("%s: invalid UDP packet from %s",
-                   ifp->name, inet_ntoa(from));
+               if (errno == EINVAL)
+                       logerrx("%s: UDP checksum failure from %s",
+                         ifp->name, inet_ntoa(from));
+               else
+                       logerr("%s: invalid UDP packet from %s",
+                         ifp->name, inet_ntoa(from));
                return;
        }
        if (ifp->flags & IFF_POINTOPOINT &&
@@ -3243,27 +3318,30 @@
        struct interface *ifp = arg;
        uint8_t buf[MTU_MAX];
        ssize_t bytes;
-       int flags;
-       const struct dhcp_state *state = D_CSTATE(ifp);
+       struct dhcp_state *state = D_STATE(ifp);
 
        /* Some RAW mechanisms are generic file descriptors, not sockets.
         * This means we have no kernel call to just get one packet,
         * so we have to process the entire buffer. */
-       flags = 0;
-       while (!(flags & BPF_EOF)) {
-               bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf), &flags);
+       state->bpf_flags &= ~BPF_EOF;
+       state->bpf_flags |= BPF_READING;
+       while (!(state->bpf_flags & BPF_EOF)) {
+               bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf),
+                                &state->bpf_flags);
                if (bytes == -1) {
                        if (state->state != DHS_NONE) {
                                logerr("%s: %s", __func__, ifp->name);
                                dhcp_close(ifp);
                        }
-                       return;
+                       break;
                }
-               dhcp_handlepacket(ifp, buf, (size_t)bytes, flags);
+               dhcp_handlepacket(ifp, buf, (size_t)bytes);
                /* Check we still have a state after processing. */
-               if ((state = D_CSTATE(ifp)) == NULL || state->bpf_fd == -1)
+               if ((state = D_STATE(ifp)) == NULL)
                        break;
        }
+       if (state != NULL)
+               state->bpf_flags &= ~BPF_READING;
 }



Home | Main Index | Thread Index | Old Index