changeset 4469:246f6cfa2f6b draft

sun: Fix numerous issues handling route messages Fix extracting the sockaddr's. Fix finding the correct alias for new addresses. Fix finding the correct alias for deleted addresses. Fix finding the correct flags for the alias.
author Roy Marples <roy@marples.name>
date Sun, 21 Apr 2019 23:56:48 +0000
parents 714f593946d5
children 974677be560f
files src/if-sun.c
diffstat 1 files changed, 88 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/if-sun.c	Sun Apr 21 20:17:49 2019 +0000
+++ b/src/if-sun.c	Sun Apr 21 23:56:48 2019 +0000
@@ -74,9 +74,8 @@
 #endif
 
 #ifndef RT_ROUNDUP
-#define RT_ROUNDUP(a)							      \
-	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-#define RT_ADVANCE(x, n) (x += RT_ROUNDUP(salen(n)))
+#define RT_ROUNDUP(a)                                                        \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
 #endif
 
 #define COPYOUT(sin, sa) do {						      \
@@ -427,14 +426,16 @@
 {
 	const char *cp;
 	int i;
+	const struct sockaddr **sap;
 
 	cp = data;
 	for (i = 0; i < RTAX_MAX; i++) {
+		sap = &sa[i];
 		if (type & (1 << i)) {
-			sa[i] = (const struct sockaddr *)cp;
-			RT_ADVANCE(cp, sa[i]);
+			*sap = (const struct sockaddr *)cp;
+			cp += salen(*sap);
 		} else
-			sa[i] = NULL;
+			*sap = NULL;
 	}
 	return 0;
 }
@@ -751,15 +752,19 @@
 		rt->rt_mtu = 0;
 }
 
-static int
-if_addrflags0(int fd, const char *ifname)
+static uint64_t
+if_addrflags0(int fd, const char *ifname, const struct sockaddr *sa)
 {
 	struct lifreq		lifr;
 
 	memset(&lifr, 0, sizeof(lifr));
 	strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
 	if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1)
-		return -1;
+		return 0;
+	if (ioctl(fd, SIOCGLIFADDR, &lifr) == -1)
+		return 0;
+	if (sa_cmp(sa, (struct sockaddr *)&lifr.lifr_addr) != 0)
+		return 0;
 
 	return lifr.lifr_flags;
 }
@@ -808,13 +813,41 @@
 	}
 }
 
+static bool
+if_getalias(struct interface *ifp, const struct sockaddr *sa, char *alias)
+{
+	struct ifaddrs		*ifaddrs, *ifa;
+	struct interface	*ifpx;
+	bool			found;
+
+	ifaddrs = NULL;
+	if (getallifaddrs(sa->sa_family, &ifaddrs, 0) == -1)
+		return false;
+	found = false;
+	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+		if (ifa->ifa_addr == NULL)
+			continue;
+		if (sa_cmp(sa, ifa->ifa_addr) != 0)
+			continue;
+		/* Check it's for the right interace. */
+		ifpx = if_find(ifp->ctx->ifaces, ifa->ifa_name);
+		if (ifp == ifpx) {
+			strlcpy(alias, ifa->ifa_name, IF_NAMESIZE);
+			found = true;
+			break;
+		}
+	}
+	freeifaddrs(ifaddrs);
+	return found;
+}
+
 static void
 if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
 {
 	struct interface	*ifp;
 	const struct sockaddr	*sa, *rti_info[RTAX_MAX];
 	int			flags;
-	const char		*ifalias;
+	char			ifalias[IF_NAMESIZE];
 
 	/* XXX We have no way of knowing who generated these
 	 * messages wich truely sucks because we want to
@@ -823,6 +856,7 @@
 		return;
 	sa = (const void *)(ifam + 1);
 	get_addrs(ifam->ifam_addrs, sa, rti_info);
+
 	if ((sa = rti_info[RTAX_IFA]) == NULL)
 		return;
 
@@ -839,31 +873,8 @@
 	 *   ifam_alias
 	 *   ifam_pid
 	 */
-
-	ifalias = ifp->name;
-	if (ifam->ifam_type != RTM_DELADDR && sa->sa_family != AF_LINK) {
-		struct ifaddrs	*ifaddrs, *ifa;
-
-		ifaddrs = NULL;
-		if (getallifaddrs(sa->sa_family, &ifaddrs, 0) == -1)
-			return;
-		for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
-			if (ifa->ifa_addr != NULL) {
-				if (sa_cmp(sa, ifa->ifa_addr) == 0) {
-					/* Check it's for the right interace. */
-					struct interface	*ifpx;
-
-					ifpx = if_find(ctx->ifaces,
-					    ifa->ifa_name);
-					if (ifp == ifpx) {
-						ifalias = ifa->ifa_name;
-						break;
-					}
-				}
-			}
-		}
-		freeifaddrs(ifaddrs);
-	}
+	if (ifam->ifam_type != RTM_DELADDR && !if_getalias(ifp, sa, ifalias))
+		return;
 
 	switch (sa->sa_family) {
 	case AF_LINK:
@@ -886,12 +897,20 @@
 		COPYOUT(mask, rti_info[RTAX_NETMASK]);
 		COPYOUT(bcast, rti_info[RTAX_BRD]);
 
-		if (ifam->ifam_type != RTM_DELADDR) {
-			flags = if_addrflags0(ctx->pf_inet_fd, ifalias);
-			if (flags == -1)
-				break;
-		} else
-			flags = 0;
+		if (ifam->ifam_type == RTM_DELADDR) {
+			struct ipv4_addr *ia;
+
+			ia = ipv4_iffindaddr(ifp, &addr, &mask);
+			if (ia == NULL)
+				return;
+			strlcpy(ifalias, ia->alias, sizeof(ifalias));
+		}
+		flags = if_addrflags(ifp, &addr, ifalias);
+		if (ifam->ifam_type == RTM_DELADDR) {
+			if (flags != -1)
+				return;
+		} else if (flags == -1)
+			return;
 
 		ipv4_handleifa(ctx,
 		    ifam->ifam_type == RTM_CHGADDR ?
@@ -911,15 +930,20 @@
 		sin6 = (const void *)rti_info[RTAX_NETMASK];
 		mask6 = sin6->sin6_addr;
 
-		if (ifam->ifam_type != RTM_DELADDR) {
-			const struct priv	 *priv;
+		if (ifam->ifam_type == RTM_DELADDR) {
+			struct ipv6_addr	*ia;
 
-			priv = (struct priv *)ctx->priv;
-			flags = if_addrflags0(priv->pf_inet6_fd, ifalias);
-			if (flags == -1)
-				break;
-		} else
-			flags = 0;
+			ia = ipv6_iffindaddr(ifp, &addr6, 0);
+			if (ia == NULL)
+				return;
+			strlcpy(ifalias, ia->alias, sizeof(ifalias));
+		}
+		flags = if_addrflags6(ifp, &addr6, ifalias);
+		if (ifam->ifam_type == RTM_DELADDR) {
+			if (flags != -1)
+				return;
+		} else if (flags == -1)
+			return;
 
 		ipv6_handleifa(ctx,
 		    ifam->ifam_type == RTM_CHGADDR ?
@@ -1490,13 +1514,16 @@
 }
 
 int
-if_addrflags(const struct interface *ifp, __unused const struct in_addr *addr,
+if_addrflags(const struct interface *ifp, const struct in_addr *addr,
     const char *alias)
 {
-	int		flags, aflags;
+	union sa_ss	ss;
+	uint64_t	aflags;
+	int		flags;
 
-	aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias);
-	if (aflags == -1)
+	sa_in_init(&ss.sa, addr);
+	aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias, &ss.sa);
+	if (aflags == 0)
 		return -1;
 	flags = 0;
 	if (aflags & IFF_DUPLICATE)
@@ -1542,14 +1569,19 @@
 }
 
 int
-if_addrflags6(const struct interface *ifp, __unused const struct in6_addr *addr,
+if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
     const char *alias)
 {
 	struct priv		*priv;
-	int			aflags, flags;
+	union sa_ss		ss;
+	uint64_t		aflags;
+	int			flags;
 
 	priv = (struct priv *)ifp->ctx->priv;
-	aflags = if_addrflags0(priv->pf_inet6_fd, alias);
+	sa_in6_init(&ss.sa, addr);
+	aflags = if_addrflags0(priv->pf_inet6_fd, alias, &ss.sa);
+	if (aflags == 0)
+		return -1;
 	flags = 0;
 	if (aflags & IFF_DUPLICATE)
 		flags |= IN6_IFF_DUPLICATED;