Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet6 Separate the code of joining multicast groups
details: https://anonhg.NetBSD.org/src/rev/76d8d0944fbc
branches: trunk
changeset: 351821:76d8d0944fbc
user: ozaki-r <ozaki-r%NetBSD.org@localhost>
date: Tue Feb 28 04:07:11 2017 +0000
description:
Separate the code of joining multicast groups
No functional change.
diffstat:
sys/netinet6/in6.c | 391 +++++++++++++++++++++++++++-------------------------
1 files changed, 203 insertions(+), 188 deletions(-)
diffs (truncated from 434 to 300 lines):
diff -r f5d813b084bf -r 76d8d0944fbc sys/netinet6/in6.c
--- a/sys/netinet6/in6.c Tue Feb 28 03:32:11 2017 +0000
+++ b/sys/netinet6/in6.c Tue Feb 28 04:07:11 2017 +0000
@@ -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 @@
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 @@
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 @@
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 @@
/* 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);
+ error = in6_join_mcastgroups(ifra, ia, ifp, &in6m_sol, flags);
+ if (error != 0)
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 */
-
- /*
Home |
Main Index |
Thread Index |
Old Index