Module Name: src Committed By: roy Date: Tue Jul 30 10:25:03 UTC 2019
Modified Files: src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcp6.c dhcpcd.c if-bsd.c if-options.c ipv6.c ipv6.h ipv6nd.c Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/src/bpf.c \ src/external/bsd/dhcpcd/dist/src/dhcp6.c cvs rdiff -u -r1.22 -r1.23 src/external/bsd/dhcpcd/dist/src/dhcp.c \ src/external/bsd/dhcpcd/dist/src/dhcpcd.c cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/src/if-bsd.c \ src/external/bsd/dhcpcd/dist/src/ipv6nd.c cvs rdiff -u -r1.15 -r1.16 src/external/bsd/dhcpcd/dist/src/if-options.c cvs rdiff -u -r1.2 -r1.3 src/external/bsd/dhcpcd/dist/src/ipv6.c \ src/external/bsd/dhcpcd/dist/src/ipv6.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/dhcpcd/dist/src/bpf.c diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.10 src/external/bsd/dhcpcd/dist/src/bpf.c:1.11 --- src/external/bsd/dhcpcd/dist/src/bpf.c:1.10 Wed Jul 24 09:57:43 2019 +++ src/external/bsd/dhcpcd/dist/src/bpf.c Tue Jul 30 10:25:03 2019 @@ -93,7 +93,7 @@ bpf_frame_header_len(const struct interf } } -static const uint8_t etherbroadcastaddr[] = +static const uint8_t etherbcastaddr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int @@ -104,7 +104,7 @@ bpf_frame_bcast(const struct interface * case ARPHRD_ETHER: return memcmp(frame + offsetof(struct ether_header, ether_dhost), - etherbroadcastaddr, sizeof(etherbroadcastaddr)); + etherbcastaddr, sizeof(etherbcastaddr)); default: return -1; } @@ -552,6 +552,12 @@ bpf_arp(struct interface *ifp, int fd) } #endif +#define BPF_M_FHLEN 0 +#define BPF_M_IPHLEN 1 +#define BPF_M_IPLEN 2 +#define BPF_M_UDP 3 +#define BPF_M_UDPLEN 4 + static const struct bpf_insn bpf_bootp_ether[] = { /* Make sure this is an IP packet. */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, @@ -561,16 +567,26 @@ static const struct bpf_insn bpf_bootp_e /* Load frame header length into X. */ BPF_STMT(BPF_LDX + BPF_W + BPF_IMM, sizeof(struct ether_header)), - /* Copy to M0. */ - BPF_STMT(BPF_STX, 0), + /* Copy frame header length to memory */ + BPF_STMT(BPF_STX, BPF_M_FHLEN), }; #define BPF_BOOTP_ETHER_LEN __arraycount(bpf_bootp_ether) static const struct bpf_insn bpf_bootp_filter[] = { - /* Make sure it's an optionless IPv4 packet. */ + /* Make sure it's an IPv4 packet. */ + BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0), + BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0xf0), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x40, 1, 0), + BPF_STMT(BPF_RET + BPF_K, 0), + + /* Ensure IP header length is big enough and + * store the IP header length in memory. */ BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x45, 1, 0), + BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x0f), + BPF_STMT(BPF_ALU + BPF_MUL + BPF_K, 4), + BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ip), 1, 0), BPF_STMT(BPF_RET + BPF_K, 0), + BPF_STMT(BPF_ST, BPF_M_IPHLEN), /* Make sure it's a UDP packet. */ BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct ip, ip_p)), @@ -582,39 +598,42 @@ static const struct bpf_insn bpf_bootp_f BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 0, 1), BPF_STMT(BPF_RET + BPF_K, 0), - /* Store IP location in M1. */ + /* Store IP length. */ BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct ip, ip_len)), - BPF_STMT(BPF_ST, 1), - - /* Store IP length in M2. */ - BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct ip, ip_len)), - BPF_STMT(BPF_ST, 2), + BPF_STMT(BPF_ST, BPF_M_IPLEN), /* Advance to the UDP header. */ - BPF_STMT(BPF_MISC + BPF_TXA, 0), - BPF_STMT(BPF_ALU + BPF_ADD + BPF_K, sizeof(struct ip)), + BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPHLEN), + BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0), BPF_STMT(BPF_MISC + BPF_TAX, 0), - /* Store X in M3. */ - BPF_STMT(BPF_STX, 3), + /* Store UDP location */ + BPF_STMT(BPF_STX, BPF_M_UDP), /* Make sure it's from and to the right port. */ BPF_STMT(BPF_LD + BPF_W + BPF_IND, 0), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (BOOTPS << 16) + BOOTPC, 1, 0), BPF_STMT(BPF_RET + BPF_K, 0), - /* Store UDP length in X. */ + /* Store UDP length. */ BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct udphdr, uh_ulen)), + BPF_STMT(BPF_ST, BPF_M_UDPLEN), + + /* Ensure that UDP length + IP header length == IP length */ + /* Copy IP header length to X. */ + BPF_STMT(BPF_LDX + BPF_MEM, BPF_M_IPHLEN), + /* Add UDP length (A) to IP header length (X). */ + BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0), + /* Store result in X. */ BPF_STMT(BPF_MISC + BPF_TAX, 0), - /* Copy IP length in M2 to A. */ - BPF_STMT(BPF_LD + BPF_MEM, 2), - /* Ensure IP length - IP header size == UDP length. */ - BPF_STMT(BPF_ALU + BPF_SUB + BPF_K, sizeof(struct ip)), + /* Copy IP length to A. */ + BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPLEN), + /* Ensure X == A. */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), BPF_STMT(BPF_RET + BPF_K, 0), - /* Advance to the BOOTP packet (UDP X is in M3). */ - BPF_STMT(BPF_LD + BPF_MEM, 3), + /* Advance to the BOOTP packet. */ + BPF_STMT(BPF_LD + BPF_MEM, BPF_M_UDP), BPF_STMT(BPF_ALU + BPF_ADD + BPF_K, sizeof(struct udphdr)), BPF_STMT(BPF_MISC + BPF_TAX, 0), @@ -695,11 +714,10 @@ bpf_bootp(struct interface *ifp, int fd) } #endif - /* All passed, return the packet - * (Frame length in M0, IP length in M2). */ - BPF_SET_STMT(bp, BPF_LD + BPF_MEM, 0); + /* All passed, return the packet - frame length + ip length */ + BPF_SET_STMT(bp, BPF_LD + BPF_MEM, BPF_M_FHLEN); bp++; - BPF_SET_STMT(bp, BPF_LDX + BPF_MEM, 2); + BPF_SET_STMT(bp, BPF_LDX + BPF_MEM, BPF_M_IPLEN); bp++; BPF_SET_STMT(bp, BPF_ALU + BPF_ADD + BPF_X, 0); bp++; Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.10 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11 --- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.10 Fri Jul 26 10:53:45 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Tue Jul 30 10:25:03 2019 @@ -1938,6 +1938,7 @@ dhcp6_checkstatusok(const struct interfa if ((opt = f(farg, len, D6_OPTION_STATUS_CODE, &opt_len)) == NULL) { //logdebugx("%s: no status", ifp->name); state->lerror = 0; + errno = ESRCH; return 0; } @@ -1949,7 +1950,8 @@ dhcp6_checkstatusok(const struct interfa code = ntohs(code); if (code == D6_STATUS_OK) { state->lerror = 0; - return 1; + errno = 0; + return 0; } /* Anything after the code is a message. */ @@ -1980,7 +1982,8 @@ dhcp6_checkstatusok(const struct interfa logfunc("%s: DHCPv6 REPLY: %s", ifp->name, status); free(sbuf); state->lerror = code; - return -1; + errno = 0; + return (int)code; } const struct ipv6_addr * @@ -2227,7 +2230,7 @@ dhcp6_findia(struct interface *ifp, stru struct dhcp6_option o; uint8_t *d, *p; struct dhcp6_ia_na ia; - int i, e; + int i, e, error; size_t j; uint16_t nl; uint8_t iaid[4]; @@ -2316,7 +2319,9 @@ dhcp6_findia(struct interface *ifp, stru } } else ia.t1 = ia.t2 = 0; /* appease gcc */ - if (dhcp6_checkstatusok(ifp, NULL, p, o.len) == -1) { + if ((error = dhcp6_checkstatusok(ifp, NULL, p, o.len)) != 0) { + if (error == D6_STATUS_NOBINDING) + state->has_no_binding = true; e = 1; continue; } @@ -2417,7 +2422,7 @@ dhcp6_validatelease(struct interface *if const char *sfrom, const struct timespec *acquired) { struct dhcp6_state *state; - int ok, nia; + int nia, ok_errno; struct timespec aq; if (len <= sizeof(*m)) { @@ -2426,8 +2431,10 @@ dhcp6_validatelease(struct interface *if } state = D6_STATE(ifp); - if ((ok = dhcp6_checkstatusok(ifp, m, NULL, len) == -1)) + errno = 0; + if (dhcp6_checkstatusok(ifp, m, NULL, len) != 0) return -1; + ok_errno = errno; state->renew = state->rebind = state->expire = 0; state->lowpl = ND6_INFINITE_LIFETIME; @@ -2435,9 +2442,10 @@ dhcp6_validatelease(struct interface *if clock_gettime(CLOCK_MONOTONIC, &aq); acquired = &aq; } + state->has_no_binding = false; nia = dhcp6_findia(ifp, m, len, sfrom, acquired); if (nia == 0) { - if (state->state != DH6S_CONFIRM && ok != 1) { + if (state->state != DH6S_CONFIRM && ok_errno != 0) { logerrx("%s: no useable IA found in lease", ifp->name); return -1; } @@ -2447,6 +2455,7 @@ dhcp6_validatelease(struct interface *if * IA's must have existed here otherwise we would * have rejected it earlier. */ assert(state->new != NULL && state->new_len != 0); + state->has_no_binding = false; nia = dhcp6_findia(ifp, state->new, state->new_len, sfrom, acquired); } @@ -3269,7 +3278,7 @@ dhcp6_recvif(struct interface *ifp, cons case DHCP6_REPLY: switch(state->state) { case DH6S_INFORM: - if (dhcp6_checkstatusok(ifp, r, NULL, len) == -1) + if (dhcp6_checkstatusok(ifp, r, NULL, len) != 0) return; break; case DH6S_CONFIRM: @@ -3317,6 +3326,14 @@ dhcp6_recvif(struct interface *ifp, cons dhcp6_startdiscover(ifp); return; } + /* RFC8415 18.2.10.1 */ + if ((state->state == DH6S_RENEW || + state->state == DH6S_REBIND) && + state->has_no_binding) + { + dhcp6_startrequest(ifp); + return; + } if (state->state == DH6S_DISCOVER) state->state = DH6S_REQUEST; break; Index: src/external/bsd/dhcpcd/dist/src/dhcp.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.22 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23 --- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.22 Fri Jul 26 10:47:29 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcp.c Tue Jul 30 10:25:03 2019 @@ -3220,70 +3220,80 @@ rapidcommit: } static void * -get_udp_data(void *udp, size_t *len) +get_udp_data(void *packet, size_t *len) { - struct bootp_pkt *p; - - p = (struct bootp_pkt *)udp; - *len = (size_t)ntohs(p->ip.ip_len) - sizeof(p->ip) - sizeof(p->udp); - return (char *)udp + offsetof(struct bootp_pkt, bootp); + const struct ip *ip = packet; + size_t ip_hl = (size_t)ip->ip_hl * 4; + char *p = packet; + + p += ip_hl + sizeof(struct udphdr); + *len = (size_t)ntohs(ip->ip_len) - sizeof(struct udphdr) - ip_hl; + return p; } static int -valid_udp_packet(void *data, size_t data_len, struct in_addr *from, - int noudpcsum) +valid_udp_packet(void *packet, size_t plen, struct in_addr *from, + unsigned int flags) { - struct bootp_pkt *p; - uint16_t bytes; + struct ip *ip = packet; + char ip_hlv = *(char *)ip; + size_t ip_hlen; + uint16_t ip_len, uh_sum; + struct udphdr *udp; - if (data_len < sizeof(p->ip)) { - if (from) + if (plen < sizeof(*ip)) { + if (from != NULL) from->s_addr = INADDR_ANY; errno = ERANGE; return -1; } - p = (struct bootp_pkt *)data; - if (from) - from->s_addr = p->ip.ip_src.s_addr; - if (checksum(&p->ip, sizeof(p->ip)) != 0) { + + if (from != NULL) + from->s_addr = ip->ip_src.s_addr; + + ip_hlen = (size_t)ip->ip_hl * 4; + if (checksum(ip, ip_hlen) != 0) { errno = EINVAL; return -1; } - bytes = ntohs(p->ip.ip_len); + ip_len = ntohs(ip->ip_len); /* Check we have a payload */ - if (bytes <= sizeof(p->ip) + sizeof(p->udp)) { + if (ip_len <= ip_hlen + sizeof(*udp)) { errno = ERANGE; return -1; } /* Check we don't go beyond the payload */ - if (bytes > data_len) { + if (ip_len > plen) { errno = ENOBUFS; return -1; } - if (noudpcsum == 0) { - uint16_t udpsum, iplen; + if (flags & BPF_PARTIALCSUM) + return 0; + + udp = (struct udphdr *)((char *)ip + ip_hlen); + if (udp->uh_sum == 0) + return 0; + uh_sum = udp->uh_sum; - /* This does scribble on the packet, but at this point - * we don't care to keep it. */ - iplen = p->ip.ip_len; - udpsum = p->udp.uh_sum; - p->udp.uh_sum = 0; - p->ip.ip_hl = 0; - p->ip.ip_v = 0; - p->ip.ip_tos = 0; - p->ip.ip_len = p->udp.uh_ulen; - p->ip.ip_id = 0; - p->ip.ip_off = 0; - p->ip.ip_ttl = 0; - p->ip.ip_sum = 0; - if (udpsum && checksum(p, bytes) != udpsum) { - errno = EINVAL; - return -1; - } - p->ip.ip_len = iplen; + /* This does scribble on the packet, but at this point + * we don't care to keep it. */ + udp->uh_sum = 0; + ip->ip_hl = 0; + ip->ip_v = 0; + ip->ip_tos = 0; + ip->ip_len = udp->uh_ulen; + ip->ip_id = 0; + ip->ip_off = 0; + ip->ip_ttl = 0; + ip->ip_sum = 0; + if (checksum(packet, ip_len) != uh_sum) { + errno = EINVAL; + return -1; } + *(char *)ip = ip_hlv; + ip->ip_len = htons(ip_len); return 0; } @@ -3320,9 +3330,7 @@ dhcp_handlepacket(struct interface *ifp, size_t udp_len; const struct dhcp_state *state = D_CSTATE(ifp); - if (valid_udp_packet(data, len, &from, - state->bpf_flags & RAW_PARTIALCSUM) == -1) - { + if (valid_udp_packet(data, len, &from, state->bpf_flags) == -1) { if (errno == EINVAL) logerrx("%s: checksum failure from %s", ifp->name, inet_ntoa(from)); @@ -3384,6 +3392,7 @@ dhcp_readpacket(void *arg) static void dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp) { + const struct dhcp_state *state; struct sockaddr_in from; unsigned char buf[10 * 1024]; /* Maximum MTU */ struct iovec iov = { @@ -3405,8 +3414,7 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str ssize_t bytes; if (ifp != NULL) { - const struct dhcp_state *state = D_CSTATE(ifp); - + state = D_CSTATE(ifp); s = state->udp_fd; } else s = ctx->udp_fd; @@ -3426,13 +3434,19 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str logerr(__func__); return; } - if (D_CSTATE(ifp) == NULL) { + 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 Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.22 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.22 Thu Jul 25 08:55:18 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Tue Jul 30 10:25:03 2019 @@ -2125,13 +2125,13 @@ exit1: } free(ctx.ifaces); } + free_options(&ctx, ifo); #ifdef HAVE_OPEN_MEMSTREAM if (ctx.script_fp) fclose(ctx.script_fp); #endif free(ctx.script_buf); free(ctx.script_env); - free_options(&ctx, ifo); rt_dispose(&ctx); free(ctx.duid); if (ctx.link_fd != -1) { Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.9 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10 --- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.9 Wed Jul 24 09:57:43 2019 +++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Tue Jul 30 10:25:03 2019 @@ -51,6 +51,8 @@ #include <netinet6/nd6.h> #ifdef __NetBSD__ #include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */ +#elif defined(__DragonFly__) +#include <net/vlan/if_vlan_var.h> #else #include <net/if_vlan_var.h> #endif @@ -541,7 +543,7 @@ if_route(unsigned char cmd, const struct * try to encourage someone to fix that by logging a waring during compile. */ #if defined(__FreeBSD__) || defined(__OpenBSD__) -#warning OS does not allow IPv6 address sharing +#warning kernel does not allow IPv6 address sharing if (!gateway_unspec || rt->rt_dest.sa_family!=AF_INET6) #endif rtm->rtm_addrs |= RTA_IFP; Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.9 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10 --- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.9 Fri Jul 26 10:53:45 2019 +++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c Tue Jul 30 10:25:03 2019 @@ -434,13 +434,7 @@ ipv6nd_sendadvertisement(void *arg) s = ctx->nd_fd; #endif if (sendmsg(s, &msg, 0) == -1) -#ifdef __OpenBSD__ -/* This isn't too critical as they don't support IPv6 address sharing */ -#warning Cannot send NA messages on OpenBSD - logdebug(__func__); -#else logerr(__func__); -#endif if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) { eloop_timeout_add_sec(ctx->eloop, @@ -527,6 +521,8 @@ ipv6nd_advertise(struct ipv6_addr *ia) eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf); ipv6nd_sendadvertisement(iaf); } +#elif !defined(SMALL) +#warning kernel does not support userland sending ND6 advertisements #endif /* ND6_ADVERTISE */ static void Index: src/external/bsd/dhcpcd/dist/src/if-options.c diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.15 src/external/bsd/dhcpcd/dist/src/if-options.c:1.16 --- src/external/bsd/dhcpcd/dist/src/if-options.c:1.15 Wed Jul 24 09:57:43 2019 +++ src/external/bsd/dhcpcd/dist/src/if-options.c Tue Jul 30 10:25:03 2019 @@ -2611,73 +2611,92 @@ void free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo) { size_t i; +#ifdef RT_FREE_ROUTE_TABLE + struct interface *ifp; + struct rt *rt; +#endif struct dhcp_opt *opt; struct vivco *vo; #ifdef AUTH struct token *token; #endif - if (ifo) { - if (ifo->environ) { - i = 0; - while (ifo->environ[i]) - free(ifo->environ[i++]); - free(ifo->environ); - } - if (ifo->config) { - i = 0; - while (ifo->config[i]) - free(ifo->config[i++]); - free(ifo->config); + if (ifo == NULL) + return; + + if (ifo->environ) { + i = 0; + while (ifo->environ[i]) + free(ifo->environ[i++]); + free(ifo->environ); + } + if (ifo->config) { + i = 0; + while (ifo->config[i]) + free(ifo->config[i++]); + free(ifo->config); + } + +#ifdef RT_FREE_ROUTE_TABLE + /* Stupidly, we don't know the interface when creating the options. + * As such, make sure each route has one so they can goto the + * free list. */ + ifp = ctx->ifaces != NULL ? TAILQ_FIRST(ctx->ifaces) : NULL; + if (ifp != NULL) { + RB_TREE_FOREACH(rt, &ifo->routes) { + if (rt->rt_ifp == NULL) + rt->rt_ifp = ifp; } - rt_headclear0(ctx, &ifo->routes, AF_UNSPEC); - if (ifo->script != default_script) - free(ifo->script); - free(ifo->arping); - free(ifo->blacklist); - free(ifo->fallback); - - for (opt = ifo->dhcp_override; - ifo->dhcp_override_len > 0; - opt++, ifo->dhcp_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->dhcp_override); - for (opt = ifo->nd_override; - ifo->nd_override_len > 0; - opt++, ifo->nd_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->nd_override); - for (opt = ifo->dhcp6_override; - ifo->dhcp6_override_len > 0; - opt++, ifo->dhcp6_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->dhcp6_override); - for (vo = ifo->vivco; - ifo->vivco_len > 0; - vo++, ifo->vivco_len--) - free(vo->data); - free(ifo->vivco); - for (opt = ifo->vivso_override; - ifo->vivso_override_len > 0; - opt++, ifo->vivso_override_len--) - free_dhcp_opt_embenc(opt); - free(ifo->vivso_override); + } +#endif + rt_headclear0(ctx, &ifo->routes, AF_UNSPEC); + + if (ifo->script != default_script) + free(ifo->script); + free(ifo->arping); + free(ifo->blacklist); + free(ifo->fallback); + + for (opt = ifo->dhcp_override; + ifo->dhcp_override_len > 0; + opt++, ifo->dhcp_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->dhcp_override); + for (opt = ifo->nd_override; + ifo->nd_override_len > 0; + opt++, ifo->nd_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->nd_override); + for (opt = ifo->dhcp6_override; + ifo->dhcp6_override_len > 0; + opt++, ifo->dhcp6_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->dhcp6_override); + for (vo = ifo->vivco; + ifo->vivco_len > 0; + vo++, ifo->vivco_len--) + free(vo->data); + free(ifo->vivco); + for (opt = ifo->vivso_override; + ifo->vivso_override_len > 0; + opt++, ifo->vivso_override_len--) + free_dhcp_opt_embenc(opt); + free(ifo->vivso_override); #if defined(INET6) && !defined(SMALL) - for (; ifo->ia_len > 0; ifo->ia_len--) - free(ifo->ia[ifo->ia_len - 1].sla); + for (; ifo->ia_len > 0; ifo->ia_len--) + free(ifo->ia[ifo->ia_len - 1].sla); #endif - free(ifo->ia); + free(ifo->ia); #ifdef AUTH - while ((token = TAILQ_FIRST(&ifo->auth.tokens))) { - TAILQ_REMOVE(&ifo->auth.tokens, token, next); - if (token->realm_len) - free(token->realm); - free(token->key); - free(token); - } -#endif - free(ifo); + while ((token = TAILQ_FIRST(&ifo->auth.tokens))) { + TAILQ_REMOVE(&ifo->auth.tokens, token, next); + if (token->realm_len) + free(token->realm); + free(token->key); + free(token); } +#endif + free(ifo); } Index: src/external/bsd/dhcpcd/dist/src/ipv6.c diff -u src/external/bsd/dhcpcd/dist/src/ipv6.c:1.2 src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3 --- src/external/bsd/dhcpcd/dist/src/ipv6.c:1.2 Fri Jul 26 10:53:45 2019 +++ src/external/bsd/dhcpcd/dist/src/ipv6.c Tue Jul 30 10:25:03 2019 @@ -634,6 +634,15 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons #ifdef __sun struct ipv6_state *state; struct ipv6_addr *ia2; + + /* If we re-add then address on Solaris then the prefix + * route will be scrubbed and re-added. Something might + * be using it, so let's avoid it. */ + if (ia->flags & IPV6_AF_DADCOMPLETED) { + logdebugx("%s: IP address %s already exists", + ia->iface->name, ia->saddr); + return 0; + } #endif /* Remember the interface of the address. */ @@ -1187,6 +1196,8 @@ out: /* Done with the ia now, so free it. */ if (cmd == RTM_DELADDR) ipv6_freeaddr(ia); + else if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE)) + ia->flags |= IPV6_AF_DADCOMPLETED; } int @@ -1465,8 +1476,10 @@ ipv6_newaddr(struct interface *ifp, cons goto err; ia->iface = ifp; - ia->flags = IPV6_AF_NEW | flags; ia->addr_flags = addr_flags; + ia->flags = IPV6_AF_NEW | flags; + if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE)) + ia->flags |= IPV6_AF_DADCOMPLETED; ia->prefix_len = prefix_len; ia->dhcp6_fd = -1; Index: src/external/bsd/dhcpcd/dist/src/ipv6.h diff -u src/external/bsd/dhcpcd/dist/src/ipv6.h:1.2 src/external/bsd/dhcpcd/dist/src/ipv6.h:1.3 --- src/external/bsd/dhcpcd/dist/src/ipv6.h:1.2 Fri Jul 26 10:53:45 2019 +++ src/external/bsd/dhcpcd/dist/src/ipv6.h Tue Jul 30 10:25:03 2019 @@ -149,7 +149,13 @@ # define IN6_IFF_DETACHED 0 #endif -#ifndef SMALL +/* + * ND6 Advertising is only used for IP address sharing to prefer + * the address on a specific interface. + * This just fails to work on OpenBSD and causes erroneous duplicate + * address messages on BSD's other then NetBSD. + */ +#if !defined(SMALL) && (defined(__NetBSD__) || defined(__linux__)) # define ND6_ADVERTISE #endif