Module Name:    src
Committed By:   martin
Date:           Sun May  5 08:24:04 UTC 2019

Modified Files:
        src/external/bsd/dhcpcd/dist/src [netbsd-8]: bpf.c defs.h dhcp.c
            dhcp6.c dhcpcd.c dhcpcd.h if-bsd.c if-linux.c if-options.c if-sun.c
            if.c if.h

Log Message:
Sync to current, requested by roy in ticket #1256:

        external/bsd/dhcpcd/dist/src/bpf.c              up to 1.9
        external/bsd/dhcpcd/dist/src/defs.h             up to 1.1.1.21
        external/bsd/dhcpcd/dist/src/dhcp.c             up to 1.19
        external/bsd/dhcpcd/dist/src/dhcp6.c            up to 1.7
        external/bsd/dhcpcd/dist/src/dhcpcd.c           up to 1.19
        external/bsd/dhcpcd/dist/src/dhcpcd.h           up to 1.1.1.10
        external/bsd/dhcpcd/dist/src/if-bsd.c           up to 1.7
        external/bsd/dhcpcd/dist/src/if-linux.c         up to 1.1.1.13
        external/bsd/dhcpcd/dist/src/if-options.c       up to 1.14
        external/bsd/dhcpcd/dist/src/if-sun.c           up to 1.1.1.8
        external/bsd/dhcpcd/dist/src/if.c               up to 1.1.1.13
        external/bsd/dhcpcd/dist/src/if.h               up to 1.1.1.8

Import dhcpcd-7.2.2 with the following changes:
  *  DHCP: Ensure dhcp is running on the interface received from
  *  BSD: Link handling has been simplified, however it is expected
     that if an interface supports SIOCGIFMEDIA then it reports
     the correct link status via route(4) for reliable operations
  *  BPF: ARP filter is more robust
  *  BSD: Validate RTM message lengths

This security issue has been addressed:
  *  DHCPv6: Fix a potential read overflow with D6_OPTION_PD_EXCLUDE

Many thanks to Maxime Villard <m...@m00nbsd.net> for discovering this issue.


To generate a diff of this commit:
cvs rdiff -u -r1.3.8.3 -r1.3.8.4 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.1.1.4.2.7 -r1.1.1.4.2.8 \
    src/external/bsd/dhcpcd/dist/src/defs.h
cvs rdiff -u -r1.1.1.3.8.6 -r1.1.1.3.8.7 \
    src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.1.1.4.2.5 -r1.1.1.4.2.6 \
    src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.4.2.5 -r1.4.2.6 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.1.1.3.2.3 -r1.1.1.3.2.4 \
    src/external/bsd/dhcpcd/dist/src/dhcpcd.h
cvs rdiff -u -r1.1.1.3.2.5 -r1.1.1.3.2.6 \
    src/external/bsd/dhcpcd/dist/src/if-bsd.c \
    src/external/bsd/dhcpcd/dist/src/if-linux.c
cvs rdiff -u -r1.4.2.4 -r1.4.2.5 \
    src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.1.1.2.2.3 -r1.1.1.2.2.4 \
    src/external/bsd/dhcpcd/dist/src/if-sun.c \
    src/external/bsd/dhcpcd/dist/src/if.h
cvs rdiff -u -r1.1.1.3.2.4 -r1.1.1.3.2.5 \
    src/external/bsd/dhcpcd/dist/src/if.c

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.3.8.3 src/external/bsd/dhcpcd/dist/src/bpf.c:1.3.8.4
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.3.8.3	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Sun May  5 08:24:04 2019
@@ -301,6 +301,7 @@ bpf_close(struct interface *ifp, int fd)
 /* Normally this is needed by bootp.
  * Once that uses this again, the ARP guard here can be removed. */
 #ifdef ARP
+#define BPF_CMP_HWADDR_LEN	((((HWADDR_LEN / 4) + 2) * 2) + 1)
 static unsigned int
 bpf_cmp_hwaddr(struct bpf_insn *bpf, size_t bpf_len, size_t off,
     bool equal, uint8_t *hwaddr, size_t hwaddr_len)
@@ -414,7 +415,7 @@ static const struct bpf_insn bpf_arp_eth
 	         sizeof(((struct ether_arp *)0)->arp_sha), 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 };
-#define bpf_arp_ether_len	__arraycount(bpf_arp_ether)
+#define BPF_ARP_ETHER_LEN	__arraycount(bpf_arp_ether)
 
 static const struct bpf_insn bpf_arp_filter [] = {
 	/* Make sure this is for IP. */
@@ -425,21 +426,25 @@ static const struct bpf_insn bpf_arp_fil
 	BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct arphdr, ar_op)),
 	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0),
 	/* or ARP REPLY. */
-	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 1),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 	/* Make sure the protocol length matches. */
 	BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct arphdr, ar_pln)),
 	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(in_addr_t), 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 };
-#define bpf_arp_filter_len	__arraycount(bpf_arp_filter)
-#define bpf_arp_extra		((((ARP_ADDRS_MAX + 1) * 2) * 2) + 2)
-#define bpf_arp_hw		((((HWADDR_LEN / 4) + 2) * 2) + 1)
+#define BPF_ARP_FILTER_LEN	__arraycount(bpf_arp_filter)
+
+#define BPF_ARP_ADDRS_LEN	1 + (ARP_ADDRS_MAX * 2) + 3 + \
+				(ARP_ADDRS_MAX * 2) + 1
+
+#define BPF_ARP_LEN		BPF_ARP_ETHER_LEN + BPF_ARP_FILTER_LEN + \
+				BPF_CMP_HWADDR_LEN + BPF_ARP_ADDRS_LEN
 
 int
 bpf_arp(struct interface *ifp, int fd)
 {
-	struct bpf_insn bpf[3+ bpf_arp_filter_len + bpf_arp_hw + bpf_arp_extra];
+	struct bpf_insn bpf[BPF_ARP_LEN];
 	struct bpf_insn *bp;
 	struct iarp_state *state;
 	uint16_t arp_len;
@@ -452,7 +457,7 @@ bpf_arp(struct interface *ifp, int fd)
 	switch(ifp->family) {
 	case ARPHRD_ETHER:
 		memcpy(bp, bpf_arp_ether, sizeof(bpf_arp_ether));
-		bp += bpf_arp_ether_len;
+		bp += BPF_ARP_ETHER_LEN;
 		arp_len = sizeof(struct ether_header)+sizeof(struct ether_arp);
 		break;
 	default:
@@ -462,10 +467,10 @@ bpf_arp(struct interface *ifp, int fd)
 
 	/* Copy in the main filter. */
 	memcpy(bp, bpf_arp_filter, sizeof(bpf_arp_filter));
-	bp += bpf_arp_filter_len;
+	bp += BPF_ARP_FILTER_LEN;
 
 	/* Ensure it's not from us. */
-	bp += bpf_cmp_hwaddr(bp, bpf_arp_hw, sizeof(struct arphdr),
+	bp += bpf_cmp_hwaddr(bp, BPF_CMP_HWADDR_LEN, sizeof(struct arphdr),
 	                     false, ifp->hwaddr, ifp->hwlen);
 
 	state = ARP_STATE(ifp);

Index: src/external/bsd/dhcpcd/dist/src/defs.h
diff -u src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.4.2.7 src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.4.2.8
--- src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.4.2.7	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/defs.h	Sun May  5 08:24:04 2019
@@ -28,7 +28,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"7.2.1"
+#define VERSION			"7.2.2"
 
 #ifndef CONFIG
 # define CONFIG			SYSCONFDIR "/" PACKAGE ".conf"

Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.1.1.3.8.6 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.1.1.3.8.7
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.1.1.3.8.6	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Sun May  5 08:24:04 2019
@@ -3499,9 +3499,14 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str
 			logerr(__func__);
 			return;
 		}
+		if (D_CSTATE(ifp) == NULL) {
+			logdebugx("%s: received BOOTP for inactive interface",
+			    ifp->name);
+			return;
+		}
 	}
 
-	dhcp_handlebootp(ifp, (struct bootp *)buf, (size_t)bytes,
+	dhcp_handlebootp(ifp, (struct bootp *)(void *)buf, (size_t)bytes,
 	    &from.sin_addr);
 #endif
 }

Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.1.1.4.2.5 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.1.1.4.2.6
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.1.1.4.2.5	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Sun May  5 08:24:04 2019
@@ -2166,40 +2166,38 @@ dhcp6_findpd(struct interface *ifp, cons
 			state->expire = a->prefix_vltime;
 		i++;
 
-		o = dhcp6_findoption(o, ol, D6_OPTION_PD_EXCLUDE, &ol);
 		a->prefix_exclude_len = 0;
 		memset(&a->prefix_exclude, 0, sizeof(a->prefix_exclude));
-#if 0
-		if (ex == NULL) {
-			struct dhcp6_option *w;
-			uint8_t *wp;
-
-			w = calloc(1, 128);
-			w->len = htons(2);
-			wp = D6_OPTION_DATA(w);
-			*wp++ = 64;
-			*wp++ = 0x78;
-			ex = w;
-		}
-#endif
+		o = dhcp6_findoption(o, ol, D6_OPTION_PD_EXCLUDE, &ol);
 		if (o == NULL)
 			continue;
-		if (ol < 2) {
-			logerrx("%s: truncated PD Exclude", ifp->name);
+
+		/* RFC 6603 4.2 says option length MUST be between 2 and 17.
+		 * This allows 1 octet for prefix length and 16 for the
+		 * subnet ID. */
+		if (ol < 2 || ol > 17) {
+			logerrx("%s: invalid PD Exclude option", ifp->name);
 			continue;
 		}
-		a->prefix_exclude_len = *o++;
+
+		/* RFC 6603 4.2 says prefix length MUST be between the
+		 * length of the IAPREFIX prefix length + 1 and 128. */
+		if (*o < a->prefix_len + 1 || *o > 128) {
+			logerrx("%s: invalid PD Exclude length", ifp->name);
+			continue;
+		}
+
 		ol--;
-		if (((a->prefix_exclude_len - a->prefix_len - 1) / NBBY) + 1
-		    != ol)
-		{
+		/* Check option length matches prefix length. */
+		if (((*o - a->prefix_len - 1) / NBBY) + 1 != ol) {
 			logerrx("%s: PD Exclude length mismatch", ifp->name);
-			a->prefix_exclude_len = 0;
 			continue;
 		}
-		nb = a->prefix_len % NBBY;
+		a->prefix_exclude_len = *o++;
+
 		memcpy(&a->prefix_exclude, &a->prefix,
 		    sizeof(a->prefix_exclude));
+		nb = a->prefix_len % NBBY;
 		if (nb)
 			ol--;
 		pw = a->prefix_exclude.s6_addr +

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4.2.5 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4.2.6
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.4.2.5	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Sun May  5 08:24:04 2019
@@ -84,6 +84,9 @@ const int dhcpcd_signals[] = {
 const size_t dhcpcd_signals_len = __arraycount(dhcpcd_signals);
 #endif
 
+#define IF_UPANDRUNNING(a) \
+	(((a)->flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
+
 static void
 usage(void)
 {
@@ -653,25 +656,6 @@ configure_interface(struct interface *if
 }
 
 static void
-dhcpcd_pollup(void *arg)
-{
-	struct interface *ifp = arg;
-	int carrier;
-
-	carrier = if_carrier(ifp); /* will set ifp->flags */
-	if (carrier == LINK_UP && !(ifp->flags & IFF_UP)) {
-		struct timespec tv;
-
-		tv.tv_sec = 0;
-		tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC;
-		eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcpcd_pollup, ifp);
-		return;
-	}
-
-	dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name);
-}
-
-static void
 dhcpcd_initstate2(struct interface *ifp, unsigned long long options)
 {
 	struct if_options *ifo;
@@ -724,35 +708,18 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
 	    !ifp->active)
 		return;
 
-	switch(carrier) {
-	case LINK_UNKNOWN:
-		carrier = if_carrier(ifp); /* will set ifp->flags */
-		break;
-	case LINK_UP:
-		/* we have a carrier! Still need to check for IFF_UP */
-		if (flags & IFF_UP)
+	if (carrier == LINK_UNKNOWN) {
+		if (ifp->wireless) {
+			carrier = LINK_DOWN;
 			ifp->flags = flags;
-		else {
-			/* So we need to poll for IFF_UP as there is no
-			 * kernel notification when it's set. */
-			dhcpcd_pollup(ifp);
-			return;
-		}
-		break;
-	default:
+		} else
+			carrier = if_carrier(ifp);
+	} else
 		ifp->flags = flags;
-	}
+	if (carrier == LINK_UNKNOWN)
+		carrier = IF_UPANDRUNNING(ifp) ? LINK_UP : LINK_DOWN;
 
-	/* If we here, we don't need to poll for IFF_UP any longer
-	 * if generated by a kernel event. */
-	eloop_timeout_delete(ifp->ctx->eloop, dhcpcd_pollup, ifp);
-
-	if (carrier == LINK_UNKNOWN) {
-		if (errno != ENOTTY && errno != ENXIO) {
-			/* Don't log an error if interface departed */
-			logerr("%s: %s", ifp->name, __func__);
-		}
-	} else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
+	if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
 		if (ifp->carrier != LINK_DOWN) {
 			if (ifp->carrier == LINK_UP)
 				loginfox("%s: carrier lost", ifp->name);
@@ -867,7 +834,6 @@ dhcpcd_startinterface(void *arg)
 	struct if_options *ifo = ifp->options;
 	char buf[DUID_LEN * 3];
 	int carrier;
-	struct timespec tv;
 
 	if (ifo->options & DHCPCD_LINK) {
 		switch (ifp->carrier) {
@@ -879,14 +845,22 @@ dhcpcd_startinterface(void *arg)
 		case LINK_UNKNOWN:
 			/* No media state available.
 			 * Loop until both IFF_UP and IFF_RUNNING are set */
-			if ((carrier = if_carrier(ifp)) == LINK_UNKNOWN) {
-				tv.tv_sec = 0;
-				tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC;
-				eloop_timeout_add_tv(ifp->ctx->eloop,
-				    &tv, dhcpcd_startinterface, ifp);
-			} else
-				dhcpcd_handlecarrier(ifp->ctx, carrier,
-				    ifp->flags, ifp->name);
+			carrier = if_carrier(ifp);
+			if (carrier == LINK_UNKNOWN) {
+				if (IF_UPANDRUNNING(ifp))
+					carrier = LINK_UP;
+				else {
+					struct timespec tv;
+
+					tv.tv_sec = 0;
+					tv.tv_nsec = IF_POLL_UP * NSEC_PER_MSEC;
+					eloop_timeout_add_tv(ifp->ctx->eloop,
+					    &tv, dhcpcd_startinterface, ifp);
+					return;
+				}
+			}
+			dhcpcd_handlecarrier(ifp->ctx, carrier,
+			    ifp->flags, ifp->name);
 			return;
 		}
 	}
@@ -987,20 +961,6 @@ dhcpcd_prestartinterface(void *arg)
 	    )
 		logerr("%s: %s", __func__, ifp->name);
 
-	if (ifp->options->options & DHCPCD_LINK &&
-	    ifp->carrier == LINK_UNKNOWN)
-	{
-		int carrier;
-
-		if ((carrier = if_carrier(ifp)) != LINK_UNKNOWN) {
-			dhcpcd_handlecarrier(ifp->ctx, carrier,
-			    ifp->flags, ifp->name);
-			return;
-		}
-		loginfox("%s: unknown carrier, waiting for interface flags",
-		    ifp->name);
-	}
-
 	dhcpcd_startinterface(ifp);
 }
 
@@ -1121,7 +1081,8 @@ dhcpcd_handlelink(void *arg)
 			dhcpcd_linkoverflow(ctx);
 			return;
 		}
-		logerr(__func__);
+		if (errno != ENOTSUP)
+			logerr(__func__);
 	}
 }
 

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.h
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.h:1.1.1.3.2.3 src/external/bsd/dhcpcd/dist/src/dhcpcd.h:1.1.1.3.2.4
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.h:1.1.1.3.2.3	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.h	Sun May  5 08:24:04 2019
@@ -85,7 +85,6 @@ struct interface {
 	unsigned short vlanid;
 	unsigned int metric;
 	int carrier;
-	bool media_valid;
 	bool wireless;
 	uint8_t ssid[IF_SSIDLEN];
 	unsigned int ssid_len;

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.1.1.3.2.5 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.1.1.3.2.6
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.1.1.3.2.5	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Sun May  5 08:24:04 2019
@@ -203,6 +203,19 @@ if_closesockets_os(struct dhcpcd_ctx *ct
 		close(priv->pf_inet6_fd);
 }
 
+int
+if_carrier(struct interface *ifp)
+{
+	struct ifmediareq ifmr = { .ifm_status = 0 };
+
+	strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
+	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 ||
+	    !(ifmr.ifm_status & IFM_AVALID))
+		return LINK_UNKNOWN;
+
+	return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
+}
+
 static void
 if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
 {
@@ -347,20 +360,28 @@ if_vlanid(const struct interface *ifp)
 #endif
 }
 
-static void
-get_addrs(int type, const void *data, const struct sockaddr **sa)
+static int
+get_addrs(int type, const void *data, size_t data_len,
+    const struct sockaddr **sa)
 {
-	const char *cp;
+	const char *cp, *ep;
 	int i;
 
 	cp = data;
+	ep = cp + data_len;
 	for (i = 0; i < RTAX_MAX; i++) {
 		if (type & (1 << i)) {
+			if (cp >= ep) {
+				errno = EINVAL;
+				return -1;
+			}
 			sa[i] = (const struct sockaddr *)cp;
 			RT_ADVANCE(cp, sa[i]);
 		} else
 			sa[i] = NULL;
 	}
+
+	return 0;
 }
 
 static struct interface *
@@ -634,7 +655,12 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	}
 #endif
 
-	get_addrs(rtm->rtm_addrs, rtm + 1, rti_info);
+	/* We have already checked that at least one address must be
+	 * present after the rtm structure. */
+	/* coverity[ptr_arith] */
+	if (get_addrs(rtm->rtm_addrs, rtm + 1,
+		      rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
+		return -1;
 	memset(rt, 0, sizeof(*rt));
 
 	rt->rt_flags = (unsigned int)rtm->rtm_flags;
@@ -700,13 +726,17 @@ if_initrt(struct dhcpcd_ctx *ctx, int af
 	end = buf + needed;
 	for (p = buf; p < end; p += rtm->rtm_msglen) {
 		rtm = (void *)p;
+		if (p + rtm->rtm_msglen >= end) {
+			errno = EINVAL;
+			break;
+		}
 		if (if_copyrt(ctx, &rt, rtm) == 0) {
 			rt.rt_dflags |= RTDF_INIT;
 			rt_recvrt(RTM_ADD, &rt, rtm->rtm_pid);
 		}
 	}
 	free(buf);
-	return 0;
+	return p == end ? 0 : -1;
 }
 
 #ifdef INET
@@ -968,40 +998,45 @@ if_getlifetime6(struct ipv6_addr *ia)
 }
 #endif
 
-static void
+static int
 if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan)
 {
 
+	if (ifan->ifan_msglen < sizeof(*ifan)) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	switch(ifan->ifan_what) {
 	case IFAN_ARRIVAL:
-		dhcpcd_handleinterface(ctx, 1, ifan->ifan_name);
-		break;
+		return dhcpcd_handleinterface(ctx, 1, ifan->ifan_name);
 	case IFAN_DEPARTURE:
-		dhcpcd_handleinterface(ctx, -1, ifan->ifan_name);
-		break;
+		return dhcpcd_handleinterface(ctx, -1, ifan->ifan_name);
 	}
+
+	return 0;
 }
 
-static void
+static int
 if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
 {
 	struct interface *ifp;
 	int link_state;
 
+	if (ifm->ifm_msglen < sizeof(*ifm)) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
-		return;
+		return 0;
 
 	switch (ifm->ifm_data.ifi_link_state) {
 	case LINK_STATE_UNKNOWN:
-		if (ifp->media_valid) {
-			link_state = LINK_DOWN;
-			break;
-		}
-		/* Interface does not report media state, so we have
-		 * to rely on IFF_UP. */
-		/* FALLTHROUGH */
+		link_state = LINK_UNKNOWN;
+		break;
 	case LINK_STATE_UP:
-		link_state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN;
+		link_state = LINK_UP;
 		break;
 	default:
 		link_state = LINK_DOWN;
@@ -1010,19 +1045,25 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const 
 
 	dhcpcd_handlecarrier(ctx, link_state,
 	    (unsigned int)ifm->ifm_flags, ifp->name);
+	return 0;
 }
 
-static void
+static int
 if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
 {
 	struct rt rt;
 
+	if (rtm->rtm_msglen < sizeof(*rtm)) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	/* Ignore errors. */
 	if (rtm->rtm_errno != 0)
-		return;
+		return 0;
 
 	if (if_copyrt(ctx, &rt, rtm) == -1)
-		return;
+		return -1;
 
 #ifdef INET6
 	/*
@@ -1046,9 +1087,10 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
 #endif
 
 	rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
+	return 0;
 }
 
-static void
+static int
 if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
 {
 	struct interface *ifp;
@@ -1056,11 +1098,21 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	int addrflags;
 	pid_t pid;
 
+	if (ifam->ifam_msglen < sizeof(*ifam)) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (~ifam->ifam_addrs & RTA_IFA)
+		return 0;
 	if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
-		return;
-	get_addrs(ifam->ifam_addrs, ifam + 1, rti_info);
-	if (rti_info[RTAX_IFA] == NULL)
-		return;
+		return 0;
+
+	/* We have already checked that at least one address must be
+	 * present after the ifam structure. */
+	/* coverity[ptr_arith] */
+	if (get_addrs(ifam->ifam_addrs, ifam + 1,
+		      ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
+		return -1;
 
 #ifdef HAVE_IFAM_PID
 	pid = ifam->ifam_pid;
@@ -1160,7 +1212,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 			}
 			freeifaddrs(ifaddrs);
 			if (ifa != NULL)
-				return;
+				return 0;
 #endif
 		}
 
@@ -1223,42 +1275,41 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	}
 #endif
 	}
+
+	return 0;
 }
 
-static void
+static int
 if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
 {
 
 	if (rtm->rtm_version != RTM_VERSION)
-		return;
+		return 0;
 
 	switch(rtm->rtm_type) {
 #ifdef RTM_IFANNOUNCE
 	case RTM_IFANNOUNCE:
-		if_announce(ctx, (const void *)rtm);
-		break;
+		return if_announce(ctx, (const void *)rtm);
 #endif
 	case RTM_IFINFO:
-		if_ifinfo(ctx, (const void *)rtm);
-		break;
+		return if_ifinfo(ctx, (const void *)rtm);
 	case RTM_ADD:		/* FALLTHROUGH */
 	case RTM_CHANGE:	/* FALLTHROUGH */
 	case RTM_DELETE:
-		if_rtm(ctx, (const void *)rtm);
-		break;
+		return if_rtm(ctx, (const void *)rtm);
 #ifdef RTM_CHGADDR
 	case RTM_CHGADDR:	/* FALLTHROUGH */
 #endif
 	case RTM_DELADDR:	/* FALLTHROUGH */
 	case RTM_NEWADDR:
-		if_ifa(ctx, (const void *)rtm);
-		break;
+		return if_ifa(ctx, (const void *)rtm);
 #ifdef RTM_DESYNC
 	case RTM_DESYNC:
-		dhcpcd_linkoverflow(ctx);
-		break;
+		return dhcpcd_linkoverflow(ctx);
 #endif
 	}
+
+	return 0;
 }
 
 int
@@ -1272,9 +1323,13 @@ if_handlelink(struct dhcpcd_ctx *ctx)
 	len = recvmsg(ctx->link_fd, &msg, 0);
 	if (len == -1)
 		return -1;
-	if (len != 0)
-		if_dispatch(ctx, &rtm.hdr);
-	return 0;
+	if (len == 0)
+		return 0;
+	if (len < rtm.hdr.rtm_msglen) {
+		errno = EINVAL;
+		return -1;
+	}
+	return if_dispatch(ctx, &rtm.hdr);
 }
 
 #ifndef SYS_NMLN	/* OSX */
Index: src/external/bsd/dhcpcd/dist/src/if-linux.c
diff -u src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.3.2.5 src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.3.2.6
--- src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.3.2.5	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/if-linux.c	Sun May  5 08:24:04 2019
@@ -349,6 +349,15 @@ if_closesockets_os(struct dhcpcd_ctx *ct
 	}
 }
 
+int
+if_carrier(struct interface *ifp)
+{
+
+	if (if_getflags(ifp) == -1)
+		return LINK_UNKNOWN;
+	return ifp->flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
+}
+
 static int
 get_netlink(struct dhcpcd_ctx *ctx, struct iovec *iov,
     struct interface *ifp, int fd, int flags,

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.4.2.4 src/external/bsd/dhcpcd/dist/src/if-options.c:1.4.2.5
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.4.2.4	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Sun May  5 08:24:04 2019
@@ -1320,7 +1320,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			return -1;
 #else
 			if (ifname == NULL) {
-				logerr("IA PD must belong in an "
+				logerrx("IA PD must belong in an "
 				    "interface block");
 				return -1;
 			}

Index: src/external/bsd/dhcpcd/dist/src/if-sun.c
diff -u src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.2.2.3 src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.2.2.4
--- src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.2.2.3	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/if-sun.c	Sun May  5 08:24:04 2019
@@ -171,13 +171,16 @@ if_closesockets_os(struct dhcpcd_ctx *ct
 }
 
 int
-if_carrier_os(struct interface *ifp)
+if_carrier(struct interface *ifp)
 {
 	kstat_ctl_t		*kcp;
 	kstat_t			*ksp;
 	kstat_named_t		*knp;
 	link_state_t		linkstate;
 
+	if (if_getflags(ifp) == -1)
+		return LINK_UNKNOWN;
+
 	kcp = kstat_open();
 	if (kcp == NULL)
 		goto err;
@@ -423,21 +426,26 @@ if_linkaddr(struct sockaddr_dl *sdl, con
 }
 
 static int
-get_addrs(int type, const void *data, const struct sockaddr **sa)
+get_addrs(int type, const void *data, size_t data_len,
+    const struct sockaddr **sa)
 {
-	const char *cp;
+	const char *cp, *ep;
 	int i;
-	const struct sockaddr **sap;
 
 	cp = data;
+	ep = cp + data_len;
 	for (i = 0; i < RTAX_MAX; i++) {
-		sap = &sa[i];
 		if (type & (1 << i)) {
-			*sap = (const struct sockaddr *)cp;
-			RT_ADVANCE(cp, *sap);
+			if (cp >= ep) {
+				errno = EINVAL;
+				return -1;
+			}
+			sa[i] = (const struct sockaddr *)cp;
+			RT_ADVANCE(cp, sa[i]);
 		} else
-			*sap = NULL;
+			sa[i] = NULL;
 	}
+
 	return 0;
 }
 
@@ -629,10 +637,16 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 {
 	const struct sockaddr *rti_info[RTAX_MAX];
 
-	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
+	if (~rtm->rtm_addrs & RTA_DST)
+		return -1;
+
+	/* We have already checked that at least one address must be
+	 * present after the rtm structure. */
+	/* coverity[ptr_arith] */
+	if (get_addrs(rtm->rtm_addrs, rtm + 1,
+		      rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
 		return -1;
 
-	get_addrs(rtm->rtm_addrs, rtm + 1, rti_info);
 	memset(rt, 0, sizeof(*rt));
 
 	rt->rt_flags = (unsigned int)rtm->rtm_flags;
@@ -640,7 +654,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	if (rtm->rtm_addrs & RTA_NETMASK)
 		COPYSA(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
 	/* dhcpcd likes an unspecified gateway to indicate via the link. */
-	if (rt->rt_flags & RTF_GATEWAY &&
+	if (rtm->rtm_addrs & RTA_GATEWAY &&
 	    rti_info[RTAX_GATEWAY]->sa_family != AF_LINK)
 		COPYSA(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
 	if (rtm->rtm_addrs & RTA_SRC)
@@ -696,7 +710,7 @@ out:
 	return rt;
 }
 
-static void
+static int
 if_finishrt(struct dhcpcd_ctx *ctx, struct rt *rt)
 {
 	int mtu;
@@ -740,10 +754,8 @@ if_finishrt(struct dhcpcd_ctx *ctx, stru
 	if (rt->rt_ifp == NULL) {
 		if (if_route_get(ctx, rt) == NULL) {
 			rt->rt_ifp = if_loopback(ctx);
-			if (rt->rt_ifp == NULL) {
-				logerr(__func__);
-				return;
-			}
+			if (rt->rt_ifp == NULL)
+				return - 1;
 		}
 	}
 
@@ -752,8 +764,12 @@ if_finishrt(struct dhcpcd_ctx *ctx, stru
 	 * This confuses dhcpcd as it expects MTU to be 0
 	 * when no explicit MTU has been set. */
 	mtu = if_getmtu(rt->rt_ifp);
+	if (mtu == -1)
+		return -1;
 	if (rt->rt_mtu == (unsigned int)mtu)
 		rt->rt_mtu = 0;
+
+	return 0;
 }
 
 static uint64_t
@@ -773,12 +789,17 @@ if_addrflags0(int fd, const char *ifname
 	return lifr.lifr_flags;
 }
 
-static void
+static int
 if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
 {
 	const struct sockaddr *sa;
 	struct rt rt;
 
+	if (rtm->rtm_msglen < sizeof(*rtm) + sizeof(*sa)) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	sa = (const void *)(rtm + 1);
 	switch (sa->sa_family) {
 #ifdef INET6
@@ -796,7 +817,9 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
 			struct in6_addr dst6;
 			struct sockaddr_dl sdl;
 
-			get_addrs(rtm->rtm_addrs, sa, rti_info);
+			if (get_addrs(rtm->rtm_addrs, sa,
+			    rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
+				return -1;
 			COPYOUT6(dst6, rti_info[RTAX_DST]);
 			if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)
 				memcpy(&sdl, rti_info[RTAX_GATEWAY],
@@ -811,10 +834,12 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
 	}
 #endif
 
-	if (if_copyrt(ctx, &rt, rtm) == 0) {
-		if_finishrt(ctx, &rt);
-		rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
-	}
+	if (if_copyrt(ctx, &rt, rtm) == -1 && errno != ESRCH)
+		return -1;
+	if (if_finishrt(ctx, &rt) == -1)
+		return -1;
+	rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
+	return 0;
 }
 
 static bool
@@ -860,7 +885,7 @@ if_getbrdaddr(struct dhcpcd_ctx *ctx, co
 	return r;
 }
 
-static void
+static int
 if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
 {
 	struct interface	*ifp;
@@ -868,16 +893,26 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	int			flags;
 	char			ifalias[IF_NAMESIZE];
 
+	if (ifam->ifam_msglen < sizeof(*ifam)) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (~ifam->ifam_addrs & RTA_IFA)
+		return 0;
+
+	/* We have already checked that at least one address must be
+	 * present after the ifam structure. */
+	/* coverity[ptr_arith] */
+	if (get_addrs(ifam->ifam_addrs, ifam + 1,
+		      ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
+		return -1;
+	sa = rti_info[RTAX_IFA];
+
 	/* XXX We have no way of knowing who generated these
 	 * messages wich truely sucks because we want to
 	 * avoid listening to our own delete messages. */
 	if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
-		return;
-	sa = (const void *)(ifam + 1);
-	get_addrs(ifam->ifam_addrs, sa, rti_info);
-
-	if ((sa = rti_info[RTAX_IFA]) == NULL)
-		return;
+		return 0;
 
 	/*
 	 * ifa_msghdr does not supply the alias, just the interface index.
@@ -893,7 +928,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	 *   ifam_pid
 	 */
 	if (ifam->ifam_type != RTM_DELADDR && !if_getalias(ifp, sa, ifalias))
-		return;
+		return 0;
 
 	switch (sa->sa_family) {
 	case AF_LINK:
@@ -921,20 +956,20 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 
 			ia = ipv4_iffindaddr(ifp, &addr, &mask);
 			if (ia == NULL)
-				return;
+				return 0;
 			strlcpy(ifalias, ia->alias, sizeof(ifalias));
 		} else if (bcast.s_addr == INADDR_ANY) {
 			/* Work around a bug where broadcast
 			 * address is not correctly reported. */
 			if (if_getbrdaddr(ctx, ifalias, &bcast) == -1)
-				return;
+				return 0;
 		}
 		flags = if_addrflags(ifp, &addr, ifalias);
 		if (ifam->ifam_type == RTM_DELADDR) {
 			if (flags != -1)
-				return;
+				return 0;
 		} else if (flags == -1)
-			return;
+			return 0;
 
 		ipv4_handleifa(ctx,
 		    ifam->ifam_type == RTM_CHGADDR ?
@@ -959,15 +994,15 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 
 			ia = ipv6_iffindaddr(ifp, &addr6, 0);
 			if (ia == NULL)
-				return;
+				return 0;
 			strlcpy(ifalias, ia->alias, sizeof(ifalias));
 		}
 		flags = if_addrflags6(ifp, &addr6, ifalias);
 		if (ifam->ifam_type == RTM_DELADDR) {
 			if (flags != -1)
-				return;
+				return 0;
 		} else if (flags == -1)
-			return;
+			return 0;
 
 		ipv6_handleifa(ctx,
 		    ifam->ifam_type == RTM_CHGADDR ?
@@ -977,17 +1012,24 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	}
 #endif
 	}
+
+	return 0;
 }
 
-static void
+static int
 if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
 {
 	struct interface *ifp;
 	int state;
 	unsigned int flags;
 
+	if (ifm->ifm_msglen < sizeof(*ifm)) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
-		return;
+		return 0;
 	flags = (unsigned int)ifm->ifm_flags;
 	if (ifm->ifm_flags & IFF_OFFLINE)
 		state = LINK_DOWN;
@@ -996,30 +1038,30 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const 
 		flags |= IFF_UP;
 	}
 	dhcpcd_handlecarrier(ctx, state, flags, ifp->name);
+	return 0;
 }
 
-static void
+static int
 if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
 {
 
 	if (rtm->rtm_version != RTM_VERSION)
-		return;
+		return 0;
 
 	switch(rtm->rtm_type) {
 	case RTM_IFINFO:
-		if_ifinfo(ctx, (const void *)rtm);
-		break;
+		return if_ifinfo(ctx, (const void *)rtm);
 	case RTM_ADD:		/* FALLTHROUGH */
 	case RTM_CHANGE:	/* FALLTHROUGH */
 	case RTM_DELETE:
-		if_rtm(ctx, (const void *)rtm);
-		break;
+		return if_rtm(ctx, (const void *)rtm);
 	case RTM_CHGADDR:	/* FALLTHROUGH */
 	case RTM_DELADDR:	/* FALLTHROUGH */
 	case RTM_NEWADDR:
-		if_ifa(ctx, (const void *)rtm);
-		break;
+		return if_ifa(ctx, (const void *)rtm);
 	}
+
+	return 0;
 }
 
 int
@@ -1032,9 +1074,15 @@ if_handlelink(struct dhcpcd_ctx *ctx)
 
 	if ((len = recvmsg(ctx->link_fd, &msg, 0)) == -1)
 		return -1;
-	if (len != 0)
-		if_dispatch(ctx, &rtm.hdr);
-	return 0;
+	if (len == -1)
+		return -1;
+	if (len == 0)
+		return 0;
+	if (len < rtm.hdr.rtm_msglen) {
+		errno = EINVAL;
+		return -1;
+	}
+	return if_dispatch(ctx, &rtm.hdr);
 }
 
 static void
@@ -1320,8 +1368,10 @@ if_walkrt(struct dhcpcd_ctx *ctx, char *
 		rt.rt_mtu = re->ipRouteInfo.re_max_frag;
 		if_octetstr(ifname, &re->ipRouteIfIndex, sizeof(ifname));
 		rt.rt_ifp = if_find(ctx->ifaces, ifname);
-		if_finishrt(ctx, &rt);
-		rt_recvrt(RTM_ADD, &rt, 0);
+		if (if_finishrt(ctx, &rt) == -1)
+			logerr(__func__);
+		else
+			rt_recvrt(RTM_ADD, &rt, 0);
 	} while (++re < e);
 	return 0;
 }
@@ -1367,8 +1417,10 @@ if_walkrt6(struct dhcpcd_ctx *ctx, char 
 		rt.rt_mtu = re->ipv6RouteInfo.re_max_frag;
 		if_octetstr(ifname, &re->ipv6RouteIfIndex, sizeof(ifname));
 		rt.rt_ifp = if_find(ctx->ifaces, ifname);
-		if_finishrt(ctx, &rt);
-		rt_recvrt(RTM_ADD, &rt, 0);
+		if (if_finishrt(ctx, &rt) == -1)
+			logerr(__func__);
+		else
+			rt_recvrt(RTM_ADD, &rt, 0);
 	} while (++re < e);
 	return 0;
 }
Index: src/external/bsd/dhcpcd/dist/src/if.h
diff -u src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.2.2.3 src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.2.2.4
--- src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.2.2.3	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/if.h	Sun May  5 08:24:04 2019
@@ -111,6 +111,7 @@ int if_getifaddrs(struct ifaddrs **);
 #define	getifaddrs	if_getifaddrs
 #endif
 
+int if_getflags(struct interface *ifp);
 int if_setflag(struct interface *ifp, short flag);
 #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING))
 bool if_valid_hwaddr(const uint8_t *, size_t);
@@ -133,7 +134,6 @@ int if_carrier(struct interface *);
 int if_makealias(char *, size_t, const char *, int);
 #endif
 
-int if_carrier_os(struct interface *);
 int if_mtu_os(const struct interface *);
 
 /*

Index: src/external/bsd/dhcpcd/dist/src/if.c
diff -u src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.3.2.4 src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.3.2.5
--- src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.3.2.4	Fri Apr 26 19:18:22 2019
+++ src/external/bsd/dhcpcd/dist/src/if.c	Sun May  5 08:24:04 2019
@@ -126,65 +126,37 @@ if_closesockets(struct dhcpcd_ctx *ctx)
 }
 
 int
-if_carrier(struct interface *ifp)
+if_getflags(struct interface *ifp)
 {
-	int r;
-	struct ifreq ifr;
-#ifdef SIOCGIFMEDIA
-	struct ifmediareq ifmr;
-#endif
+	struct ifreq ifr = { .ifr_flags = 0 };
 
-	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
-	r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr);
-	if (r != -1)
-		ifp->flags = (unsigned int)ifr.ifr_flags;
-
-#ifdef __sun
-	return if_carrier_os(ifp);
-#else
-	if (r == -1)
-		return LINK_UNKNOWN;
-
-#ifdef SIOCGIFMEDIA
-	memset(&ifmr, 0, sizeof(ifmr));
-	strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
-	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) != -1 &&
-	    ifmr.ifm_status & IFM_AVALID)
-	{
-		ifp->media_valid = true;
-		r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
-	} else {
-		ifp->media_valid = false;
-		r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN;
-	}
-#else
-	r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
-#endif
-#endif /* __sun */
-	return r;
+	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
+		return -1;
+	ifp->flags = (unsigned int)ifr.ifr_flags;
+	return 0;
 }
 
 int
 if_setflag(struct interface *ifp, short flag)
 {
-	struct ifreq ifr;
-	int r;
+	struct ifreq ifr = { .ifr_flags = 0 };
+	short f;
+
+	if (if_getflags(ifp) == -1)
+		return -1;
+
+	f = (short)ifp->flags;
+	if ((f & flag) == flag)
+		return 0;
 
-	memset(&ifr, 0, sizeof(ifr));
 	strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
-	r = -1;
-	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == 0) {
-		if (flag == 0 || (ifr.ifr_flags & flag) == flag)
-			r = 0;
-		else {
-			ifr.ifr_flags |= flag;
-			if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0)
-				r = 0;
-		}
-		ifp->flags = (unsigned int)ifr.ifr_flags;
-	}
-	return r;
+	ifr.ifr_flags = f | flag;
+	if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) == -1)
+		return -1;
+
+	ifp->flags = (unsigned int)ifr.ifr_flags;
+	return 0;
 }
 
 static int

Reply via email to