Module Name:    src
Committed By:   ozaki-r
Date:           Tue Feb 28 04:07:11 UTC 2017

Modified Files:
        src/sys/netinet6: in6.c

Log Message:
Separate the code of joining multicast groups

No functional change.


To generate a diff of this commit:
cvs rdiff -u -r1.239 -r1.240 src/sys/netinet6/in6.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.239 src/sys/netinet6/in6.c:1.240
--- src/sys/netinet6/in6.c:1.239	Tue Feb 28 02:56:49 2017
+++ src/sys/netinet6/in6.c	Tue Feb 28 04:07:11 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.c,v 1.239 2017/02/28 02:56:49 ozaki-r Exp $	*/
+/*	$NetBSD: in6.c,v 1.240 2017/02/28 04:07:11 ozaki-r Exp $	*/
 /*	$KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.239 2017/02/28 02:56:49 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.240 2017/02/28 04:07:11 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -778,6 +778,204 @@ in6_control(struct socket *so, u_long cm
 	return error;
 }
 
+static int
+in6_join_mcastgroups(struct in6_aliasreq *ifra, struct in6_ifaddr *ia,
+    struct ifnet *ifp, struct in6_multi **in6m_sol, int flags)
+{
+	int error;
+	struct sockaddr_in6 mltaddr, mltmask;
+	struct in6_multi_mship *imm;
+	struct in6_addr llsol;
+	struct rtentry *rt;
+	int dad_delay;
+	char ip6buf[INET6_ADDRSTRLEN];
+
+	KASSERT(in6m_sol != NULL);
+
+	/* join solicited multicast addr for new host id */
+	memset(&llsol, 0, sizeof(struct in6_addr));
+	llsol.s6_addr16[0] = htons(0xff02);
+	llsol.s6_addr32[1] = 0;
+	llsol.s6_addr32[2] = htonl(1);
+	llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
+	llsol.s6_addr8[12] = 0xff;
+	if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
+		/* XXX: should not happen */
+		log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
+		goto out;
+	}
+	dad_delay = 0;
+	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
+		/*
+		 * We need a random delay for DAD on the address
+		 * being configured.  It also means delaying
+		 * transmission of the corresponding MLD report to
+		 * avoid report collision.
+		 * [draft-ietf-ipv6-rfc2462bis-02.txt]
+		 */
+		dad_delay = cprng_fast32() % (MAX_RTR_SOLICITATION_DELAY * hz);
+	}
+
+#define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
+	/* join solicited multicast addr for new host id */
+	imm = in6_joingroup(ifp, &llsol, &error, dad_delay);
+	if (!imm) {
+		nd6log(LOG_ERR,
+		    "addmulti failed for %s on %s (errno=%d)\n",
+		    IN6_PRINT(ip6buf, &llsol), if_name(ifp), error);
+		goto out;
+	}
+	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+	*in6m_sol = imm->i6mm_maddr;
+
+	sockaddr_in6_init(&mltmask, &in6mask32, 0, 0, 0);
+
+	/*
+	 * join link-local all-nodes address
+	 */
+	sockaddr_in6_init(&mltaddr, &in6addr_linklocal_allnodes,
+	    0, 0, 0);
+	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
+		goto out; /* XXX: should not fail */
+
+	/*
+	 * XXX: do we really need this automatic routes?
+	 * We should probably reconsider this stuff.  Most applications
+	 * actually do not need the routes, since they usually specify
+	 * the outgoing interface.
+	 */
+	rt = rtalloc1(sin6tosa(&mltaddr), 0);
+	if (rt) {
+		if (memcmp(&mltaddr.sin6_addr,
+		    &satocsin6(rt_getkey(rt))->sin6_addr,
+		    MLTMASK_LEN)) {
+			rt_unref(rt);
+			rt = NULL;
+		} else if (rt->rt_ifp != ifp) {
+			IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
+			    "network %04x:%04x::/32 = %04x:%04x::/32\n",
+			    __func__, rt->rt_ifp, ifp, ifp->if_xname,
+			    ntohs(mltaddr.sin6_addr.s6_addr16[0]),
+			    ntohs(mltaddr.sin6_addr.s6_addr16[1]),
+			    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0],
+			    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]);
+			rt_replace_ifa(rt, &ia->ia_ifa);
+			rt->rt_ifp = ifp;
+		}
+	}
+	if (!rt) {
+		struct rt_addrinfo info;
+
+		memset(&info, 0, sizeof(info));
+		info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
+		info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia->ia_addr);
+		info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
+		info.rti_info[RTAX_IFA] = sin6tosa(&ia->ia_addr);
+		/* XXX: we need RTF_CONNECTED to fake nd6_rtrequest */
+		info.rti_flags = RTF_UP | RTF_CONNECTED;
+		error = rtrequest1(RTM_ADD, &info, NULL);
+		if (error)
+			goto out;
+	} else {
+		rt_unref(rt);
+	}
+	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
+	if (!imm) {
+		nd6log(LOG_WARNING,
+		    "addmulti failed for %s on %s (errno=%d)\n",
+		    IN6_PRINT(ip6buf, &mltaddr.sin6_addr),
+		    if_name(ifp), error);
+		goto out;
+	}
+	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+
+	/*
+	 * join node information group address
+	 */
+	dad_delay = 0;
+	if ((flags & IN6_IFAUPDATE_DADDELAY)) {
+		/*
+		 * The spec doesn't say anything about delay for this
+		 * group, but the same logic should apply.
+		 */
+		dad_delay = cprng_fast32() % (MAX_RTR_SOLICITATION_DELAY * hz);
+	}
+	if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) != 0)
+		;
+	else if ((imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
+		  dad_delay)) == NULL) { /* XXX jinmei */
+		nd6log(LOG_WARNING,
+		    "addmulti failed for %s on %s (errno=%d)\n",
+		    IN6_PRINT(ip6buf, &mltaddr.sin6_addr),
+		    if_name(ifp), error);
+		/* XXX not very fatal, go on... */
+	} else {
+		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+	}
+
+
+	/*
+	 * join interface-local all-nodes address.
+	 * (ff01::1%ifN, and ff01::%ifN/32)
+	 */
+	mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
+	if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
+		goto out; /* XXX: should not fail */
+
+	/* XXX: again, do we really need the route? */
+	rt = rtalloc1(sin6tosa(&mltaddr), 0);
+	if (rt) {
+		/* 32bit came from "mltmask" */
+		if (memcmp(&mltaddr.sin6_addr,
+		    &satocsin6(rt_getkey(rt))->sin6_addr,
+		    32 / NBBY)) {
+			rt_unref(rt);
+			rt = NULL;
+		} else if (rt->rt_ifp != ifp) {
+			IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
+			    "network %04x:%04x::/32 = %04x:%04x::/32\n",
+			    __func__, rt->rt_ifp, ifp, ifp->if_xname,
+			    ntohs(mltaddr.sin6_addr.s6_addr16[0]),
+			    ntohs(mltaddr.sin6_addr.s6_addr16[1]),
+			    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0],
+			    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]);
+			rt_replace_ifa(rt, &ia->ia_ifa);
+			rt->rt_ifp = ifp;
+		}
+	}
+	if (!rt) {
+		struct rt_addrinfo info;
+
+		memset(&info, 0, sizeof(info));
+		info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
+		info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia->ia_addr);
+		info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
+		info.rti_info[RTAX_IFA] = sin6tosa(&ia->ia_addr);
+		info.rti_flags = RTF_UP | RTF_CONNECTED;
+		error = rtrequest1(RTM_ADD, &info, NULL);
+		if (error)
+			goto out;
+#undef	MLTMASK_LEN
+	} else {
+		rt_unref(rt);
+	}
+	imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
+	if (!imm) {
+		nd6log(LOG_WARNING,
+		    "addmulti failed for %s on %s (errno=%d)\n",
+		    IN6_PRINT(ip6buf, &mltaddr.sin6_addr),
+		    if_name(ifp), error);
+		goto out;
+	} else {
+		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+	}
+	return 0;
+
+out:
+	KASSERT(error != 0);
+	return error;
+}
+
 /*
  * Update parameters of an IPv6 interface address.
  * If necessary, a new entry is created and linked into address chains.
@@ -791,9 +989,7 @@ in6_update_ifa1(struct ifnet *ifp, struc
 	int error = 0, hostIsNew = 0, plen = -1;
 	struct sockaddr_in6 dst6;
 	struct in6_addrlifetime *lt;
-	struct in6_multi_mship *imm;
-	struct in6_multi *in6m_sol;
-	struct rtentry *rt;
+	struct in6_multi *in6m_sol = NULL;
 	int dad_delay, was_tentative;
 	struct in6_ifaddr *ia = iap ? *iap : NULL;
 	char ip6buf[INET6_ADDRSTRLEN];
@@ -801,8 +997,6 @@ in6_update_ifa1(struct ifnet *ifp, struc
 	KASSERT((iap == NULL && psref == NULL) ||
 	    (iap != NULL && psref != NULL));
 
-	in6m_sol = NULL;
-
 	/* Validate parameters */
 	if (ifp == NULL || ifra == NULL) /* this maybe redundant */
 		return EINVAL;
@@ -1081,188 +1275,9 @@ in6_update_ifa1(struct ifnet *ifp, struc
 
 	/* join necessary multicast groups */
 	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
-		struct sockaddr_in6 mltaddr, mltmask;
-		struct in6_addr llsol;
-
-		/* join solicited multicast addr for new host id */
-		memset(&llsol, 0, sizeof(struct in6_addr));
-		llsol.s6_addr16[0] = htons(0xff02);
-		llsol.s6_addr32[1] = 0;
-		llsol.s6_addr32[2] = htonl(1);
-		llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
-		llsol.s6_addr8[12] = 0xff;
-		if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
-			/* XXX: should not happen */
-			log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
-			goto cleanup;
-		}
-		dad_delay = 0;
-		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
-			/*
-			 * We need a random delay for DAD on the address
-			 * being configured.  It also means delaying
-			 * transmission of the corresponding MLD report to
-			 * avoid report collision.
-			 * [draft-ietf-ipv6-rfc2462bis-02.txt]
-			 */
-			dad_delay = cprng_fast32() %
-			    (MAX_RTR_SOLICITATION_DELAY * hz);
-		}
-
-#define	MLTMASK_LEN  4	/* mltmask's masklen (=32bit=4octet) */
-		/* join solicited multicast addr for new host id */
-		imm = in6_joingroup(ifp, &llsol, &error, dad_delay);
-		if (!imm) {
-			nd6log(LOG_ERR,
-			    "addmulti failed for %s on %s (errno=%d)\n",
-			    IN6_PRINT(ip6buf, &llsol), if_name(ifp), error);
-			goto cleanup;
-		}
-		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
-		in6m_sol = imm->i6mm_maddr;
-
-		sockaddr_in6_init(&mltmask, &in6mask32, 0, 0, 0);
-
-		/*
-		 * join link-local all-nodes address
-		 */
-		sockaddr_in6_init(&mltaddr, &in6addr_linklocal_allnodes,
-		    0, 0, 0);
-		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
-			goto cleanup; /* XXX: should not fail */
-
-		/*
-		 * XXX: do we really need this automatic routes?
-		 * We should probably reconsider this stuff.  Most applications
-		 * actually do not need the routes, since they usually specify
-		 * the outgoing interface.
-		 */
-		rt = rtalloc1(sin6tosa(&mltaddr), 0);
-		if (rt) {
-			if (memcmp(&mltaddr.sin6_addr,
-			    &satocsin6(rt_getkey(rt))->sin6_addr,
-			    MLTMASK_LEN)) {
-				rt_unref(rt);
-				rt = NULL;
-			} else if (rt->rt_ifp != ifp) {
-				IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
-				    "network %04x:%04x::/32 = %04x:%04x::/32\n",
-				    __func__, rt->rt_ifp, ifp, ifp->if_xname,
-				    ntohs(mltaddr.sin6_addr.s6_addr16[0]),
-				    ntohs(mltaddr.sin6_addr.s6_addr16[1]),
-				    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0],
-				    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]);
-				rt_replace_ifa(rt, &ia->ia_ifa);
-				rt->rt_ifp = ifp;
-			}
-		}
-		if (!rt) {
-			struct rt_addrinfo info;
-
-			memset(&info, 0, sizeof(info));
-			info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
-			info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia->ia_addr);
-			info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
-			info.rti_info[RTAX_IFA] = sin6tosa(&ia->ia_addr);
-			/* XXX: we need RTF_CONNECTED to fake nd6_rtrequest */
-			info.rti_flags = RTF_UP | RTF_CONNECTED;
-			error = rtrequest1(RTM_ADD, &info, NULL);
-			if (error)
-				goto cleanup;
-		} else {
-			rt_unref(rt);
-		}
-		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
-		if (!imm) {
-			nd6log(LOG_WARNING,
-			    "addmulti failed for %s on %s (errno=%d)\n",
-			    IN6_PRINT(ip6buf, &mltaddr.sin6_addr),
-			    if_name(ifp), error);
-			goto cleanup;
-		}
-		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
-
-		/*
-		 * join node information group address
-		 */
-		dad_delay = 0;
-		if ((flags & IN6_IFAUPDATE_DADDELAY)) {
-			/*
-			 * The spec doesn't say anything about delay for this
-			 * group, but the same logic should apply.
-			 */
-			dad_delay = cprng_fast32() %
-			    (MAX_RTR_SOLICITATION_DELAY * hz);
-		}
-		if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) != 0)
-			;
-		else if ((imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
-		          dad_delay)) == NULL) { /* XXX jinmei */
-			nd6log(LOG_WARNING,
-			    "addmulti failed for %s on %s (errno=%d)\n",
-			    IN6_PRINT(ip6buf, &mltaddr.sin6_addr),
-			    if_name(ifp), error);
-			/* XXX not very fatal, go on... */
-		} else {
-			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
-		}
-
-
-		/*
-		 * join interface-local all-nodes address.
-		 * (ff01::1%ifN, and ff01::%ifN/32)
-		 */
-		mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
-		if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0) 
-			goto cleanup; /* XXX: should not fail */
-
-		/* XXX: again, do we really need the route? */
-		rt = rtalloc1(sin6tosa(&mltaddr), 0);
-		if (rt) {
-			/* 32bit came from "mltmask" */
-			if (memcmp(&mltaddr.sin6_addr,
-			    &satocsin6(rt_getkey(rt))->sin6_addr,
-			    32 / NBBY)) {
-				rt_unref(rt);
-				rt = NULL;
-			} else if (rt->rt_ifp != ifp) {
-				IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
-				    "network %04x:%04x::/32 = %04x:%04x::/32\n",
-				    __func__, rt->rt_ifp, ifp, ifp->if_xname,
-				    ntohs(mltaddr.sin6_addr.s6_addr16[0]),
-				    ntohs(mltaddr.sin6_addr.s6_addr16[1]),
-				    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0],
-				    satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]);
-				rt_replace_ifa(rt, &ia->ia_ifa);
-				rt->rt_ifp = ifp;
-			}
-		}
-		if (!rt) {
-			struct rt_addrinfo info;
-
-			memset(&info, 0, sizeof(info));
-			info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
-			info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia->ia_addr);
-			info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
-			info.rti_info[RTAX_IFA] = sin6tosa(&ia->ia_addr);
-			info.rti_flags = RTF_UP | RTF_CONNECTED;
-			error = rtrequest1(RTM_ADD, &info, NULL);
-			if (error)
-				goto cleanup;
-#undef	MLTMASK_LEN
-		} else {
-			rt_unref(rt);
-		}
-		imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
-		if (!imm) {
-			nd6log(LOG_WARNING,
-			    "addmulti failed for %s on %s (errno=%d)\n",
-			    IN6_PRINT(ip6buf, &mltaddr.sin6_addr),
-			    if_name(ifp), error);
+		error = in6_join_mcastgroups(ifra, ia, ifp, &in6m_sol, flags);
+		if (error != 0)
 			goto cleanup;
-		} else {
-			LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
-		}
 	}
 
 	/* Add local address to lltable, if necessary (ex. on p2p link). */

Reply via email to