Module Name:    src
Committed By:   ozaki-r
Date:           Thu Feb 23 07:57:10 UTC 2017

Modified Files:
        src/sys/net: if.c if.h
        src/sys/netinet6: in6.c in6_ifattach.c in6_var.h mld6.c
        src/sys/netipsec: key.c
        src/usr.bin/netstat: if.c
        src/usr.sbin/ifmcstat: ifmcstat.c

Log Message:
Remove mkludge stuffs

For unknown reasons, IPv6 multicast addresses are linked to a first
IPv6 address assigned to an interface. Due to the design, when removing
a first address having multicast addresses, we need to save them to
somewhere and later restore them once a new IPv6 address is activated.
mkludge stuffs support the operations.

This change links multicast addresses to an interface directly and
throws the kludge away.

Note that as usual some obsolete member variables remain for kvm(3)
users. And also sysctl net.inet6.multicast_kludge remains to avoid
breaking old ifmcstat.

TODO: currently ifnet has a list of in6_multi but obviously the list
should be protocol independent. Provide a common structure (if_multi
or something) to handle in6_multi and in_multi together as well as
ifaddr does for in_ifaddr and in6_ifaddr.


To generate a diff of this commit:
cvs rdiff -u -r1.380 -r1.381 src/sys/net/if.c
cvs rdiff -u -r1.234 -r1.235 src/sys/net/if.h
cvs rdiff -u -r1.237 -r1.238 src/sys/netinet6/in6.c
cvs rdiff -u -r1.111 -r1.112 src/sys/netinet6/in6_ifattach.c
cvs rdiff -u -r1.92 -r1.93 src/sys/netinet6/in6_var.h
cvs rdiff -u -r1.82 -r1.83 src/sys/netinet6/mld6.c
cvs rdiff -u -r1.102 -r1.103 src/sys/netipsec/key.c
cvs rdiff -u -r1.93 -r1.94 src/usr.bin/netstat/if.c
cvs rdiff -u -r1.20 -r1.21 src/usr.sbin/ifmcstat/ifmcstat.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/net/if.c
diff -u src/sys/net/if.c:1.380 src/sys/net/if.c:1.381
--- src/sys/net/if.c:1.380	Fri Feb 17 03:57:17 2017
+++ src/sys/net/if.c	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.380 2017/02/17 03:57:17 ozaki-r Exp $	*/
+/*	$NetBSD: if.c,v 1.381 2017/02/23 07:57:10 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.380 2017/02/17 03:57:17 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.381 2017/02/23 07:57:10 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -720,6 +720,7 @@ if_initialize(ifnet_t *ifp)
 	PSLIST_INIT(&ifp->if_addr_pslist);
 	psref_target_init(&ifp->if_psref, ifnet_psref_class);
 	ifp->if_ioctl_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
+	LIST_INIT(&ifp->if_multiaddrs);
 
 	IFNET_LOCK();
 	if_getindex(ifp);

Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.234 src/sys/net/if.h:1.235
--- src/sys/net/if.h:1.234	Fri Feb 17 03:57:17 2017
+++ src/sys/net/if.h	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.234 2017/02/17 03:57:17 ozaki-r Exp $	*/
+/*	$NetBSD: if.h,v 1.235 2017/02/23 07:57:10 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -231,6 +231,7 @@ struct callout;
 struct krwlock;
 struct if_percpuq;
 struct if_deferred_start;
+struct in6_multi;
 
 typedef unsigned short if_index_t;
 
@@ -344,6 +345,8 @@ typedef struct ifnet {
 	struct psref_target     if_psref;
 	struct pslist_head	if_addr_pslist;
 	struct if_deferred_start	*if_deferred_start;
+	/* XXX should be protocol independent */
+	LIST_HEAD(, in6_multi) if_multiaddrs;
 #endif
 } ifnet_t;
  

Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.237 src/sys/netinet6/in6.c:1.238
--- src/sys/netinet6/in6.c:1.237	Mon Jan 23 10:19:03 2017
+++ src/sys/netinet6/in6.c	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.c,v 1.237 2017/01/23 10:19:03 ozaki-r Exp $	*/
+/*	$NetBSD: in6.c,v 1.238 2017/02/23 07:57:10 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.237 2017/01/23 10:19:03 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.238 2017/02/23 07:57:10 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1370,23 +1370,6 @@ in6_unlink_ifa(struct in6_ifaddr *ia, st
 	mutex_exit(&in6_ifaddr_lock);
 
 	/*
-	 * XXX [email protected] -- if the interface is going
-	 * XXX away, don't save the multicast entries, delete them!
-	 */
-	if (LIST_EMPTY(&ia->ia6_multiaddrs))
-		;
-	else if (if_is_deactivated(ia->ia_ifa.ifa_ifp)) {
-		struct in6_multi *in6m, *next;
-
-		for (in6m = LIST_FIRST(&ia->ia6_multiaddrs); in6m != NULL;
-		     in6m = next) {
-			next = LIST_NEXT(in6m, in6m_entry);
-			in6_delmulti(in6m);
-		}
-	} else
-		in6_savemkludge(ia);
-
-	/*
 	 * Release the reference to the ND prefix.
 	 */
 	if (ia->ia6_ndpr != NULL) {
@@ -1754,9 +1737,6 @@ in6_ifinit(struct ifnet *ifp, struct in6
 		return error;
 	}
 
-	if (ifp->if_flags & IFF_MULTICAST)
-		in6_restoremkludge(ia, ifp);
-
 	return error;
 }
 

Index: src/sys/netinet6/in6_ifattach.c
diff -u src/sys/netinet6/in6_ifattach.c:1.111 src/sys/netinet6/in6_ifattach.c:1.112
--- src/sys/netinet6/in6_ifattach.c:1.111	Thu Feb 16 08:12:44 2017
+++ src/sys/netinet6/in6_ifattach.c	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_ifattach.c,v 1.111 2017/02/16 08:12:44 knakahara Exp $	*/
+/*	$NetBSD: in6_ifattach.c,v 1.112 2017/02/23 07:57:10 ozaki-r Exp $	*/
 /*	$KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.111 2017/02/16 08:12:44 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.112 2017/02/23 07:57:10 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -735,9 +735,6 @@ in6_ifattach(struct ifnet *ifp, struct i
 		return;
 	}
 
-	/* create a multicast kludge storage (if we have not had one) */
-	in6_createmkludge(ifp);
-
 	/*
 	 * quirks based on interface type
 	 */
@@ -812,12 +809,11 @@ in6_ifdetach(struct ifnet *ifp)
 	/* nuke any of IPv6 addresses we have */
 	if_purgeaddrs(ifp, AF_INET6, in6_purgeaddr);
 
+	in6_purge_multi(ifp);
+
 	/* remove ip6_mrouter stuff */
 	ip6_mrouter_detach(ifp);
 
-	/* cleanup multicast address kludge table, if there is any */
-	in6_purgemkludge(ifp);
-
 	/* remove neighbor management table */
 	nd6_purge(ifp, NULL);
 

Index: src/sys/netinet6/in6_var.h
diff -u src/sys/netinet6/in6_var.h:1.92 src/sys/netinet6/in6_var.h:1.93
--- src/sys/netinet6/in6_var.h:1.92	Wed Feb 22 07:46:00 2017
+++ src/sys/netinet6/in6_var.h	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_var.h,v 1.92 2017/02/22 07:46:00 ozaki-r Exp $	*/
+/*	$NetBSD: in6_var.h,v 1.93 2017/02/23 07:57:10 ozaki-r Exp $	*/
 /*	$KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $	*/
 
 /*
@@ -113,7 +113,8 @@ struct	in6_ifaddr {
 	u_int32_t ia_plen;		/* prefix length */
 	/* DEPRECATED. Keep it to avoid breaking kvm(3) users */
 	struct	in6_ifaddr *ia_next;	/* next in6 list of IP6 addresses */
-	struct	in6_multihead ia6_multiaddrs;
+	/* DEPRECATED. Keep it to avoid breaking kvm(3) users */
+	struct	in6_multihead _ia6_multiaddrs;
 					/* list of multicast addresses */
 	int	ia6_flags;
 
@@ -630,7 +631,8 @@ struct	in6_multi {
 	LIST_ENTRY(in6_multi) in6m_entry; /* list glue */
 	struct	in6_addr in6m_addr;	/* IP6 multicast address */
 	struct	ifnet *in6m_ifp;	/* back pointer to ifnet */
-	struct	in6_ifaddr *in6m_ia;	/* back pointer to in6_ifaddr */
+	/* DEPRECATED. Keep it to avoid breaking kvm(3) users */
+	struct	in6_ifaddr *_in6m_ia;	/* back pointer to in6_ifaddr */
 	u_int	in6m_refcount;		/* # membership claims by sockets */
 	u_int	in6m_state;		/* state of the membership */
 	int	in6m_timer;		/* delay to send the 1st report */
@@ -645,79 +647,6 @@ struct	in6_multi {
 /* flags to in6_update_ifa */
 #define IN6_IFAUPDATE_DADDELAY	0x1 /* first time to configure an address */
 
-/*
- * Structure used by macros below to remember position when stepping through
- * all of the in6_multi records.
- */
-struct	in6_multistep {
-	struct	in6_ifaddr *i_ia;
-	struct	in6_multi *i_in6m;
-};
-
-/*
- * Macros for looking up the in6_multi record for a given IP6 multicast
- * address on a given interface. If no matching record is found, "in6m"
- * returns NULL.
- */
-
-static inline struct in6_multi *
-in6_lookup_multi(struct in6_addr *addr, struct ifnet *ifp)
-{
-	struct in6_multi *in6m;
-	struct in6_ifaddr *ia;
-	int s;
-
-	s = pserialize_read_enter();
-	if ((ia = in6_get_ia_from_ifp(ifp)) == NULL) {
-		pserialize_read_exit(s);
-	  	return NULL;
-	}
-	LIST_FOREACH(in6m, &ia->ia6_multiaddrs, in6m_entry) {
-		if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, addr))
-			break;
-	}
-	pserialize_read_exit(s);
-	return in6m;
-}
-
-/*
- * Macro to step through all of the in6_multi records, one at a time.
- * The current position is remembered in "step", which the caller must
- * provide.  IN6_FIRST_MULTI(), below, must be called to initialize "step"
- * and get the first record.  Both macros return a NULL "in6m" when there
- * are no remaining records.
- */
-static inline struct in6_multi *
-in6_next_multi(struct in6_multistep *step)
-{
-	struct in6_multi *in6m;
-
-	if ((in6m = step->i_in6m) != NULL) {
-		step->i_in6m = LIST_NEXT(in6m, in6m_entry);
-		return in6m;
-	}
-	while (step->i_ia != NULL) {
-		in6m = LIST_FIRST(&step->i_ia->ia6_multiaddrs);
-		/* FIXME NOMPSAFE */
-		step->i_ia = IN6_ADDRLIST_READER_NEXT(step->i_ia);
-		if (in6m != NULL) {
-			step->i_in6m = LIST_NEXT(in6m, in6m_entry);
-			break;
-		}
-	}
-	return in6m;
-}
-
-static inline struct in6_multi *
-in6_first_multi(struct in6_multistep *step)
-{						
-
-	/* FIXME NOMPSAFE */
-	step->i_ia = IN6_ADDRLIST_READER_FIRST();
-	step->i_in6m = NULL;			
-	return in6_next_multi(step);		
-}
-
 #if 0
 /*
  * Macros for looking up the in6_multi_mship record for a given IP6 multicast
@@ -752,6 +681,9 @@ do {									\
 
 void	in6_init(void);
 
+struct in6_multi *
+	in6_lookup_multi(const struct in6_addr *, const struct ifnet *);
+void	in6_purge_multi(struct ifnet *);
 struct	in6_multi *in6_addmulti(struct in6_addr *, struct ifnet *,
 	int *, int);
 void	in6_delmulti(struct in6_multi *);
@@ -763,16 +695,12 @@ int	in6_control(struct socket *, u_long,
 int	in6_update_ifa(struct ifnet *, struct in6_aliasreq *, int);
 void	in6_purgeaddr(struct ifaddr *);
 void	in6_purgeif(struct ifnet *);
-void	in6_savemkludge(struct in6_ifaddr *);
 void	in6_setmaxmtu  (void);
 int	in6_if2idlen  (struct ifnet *);
 void	*in6_domifattach(struct ifnet *);
 void	in6_domifdetach(struct ifnet *, void *);
-void	in6_restoremkludge(struct in6_ifaddr *, struct ifnet *);
 void	in6_ifremlocal(struct ifaddr *);
 void	in6_ifaddlocal(struct ifaddr *);
-void	in6_createmkludge(struct ifnet *);
-void	in6_purgemkludge(struct ifnet *);
 struct in6_ifaddr *
 	in6ifa_ifpforlinklocal(const struct ifnet *, int);
 struct in6_ifaddr *

Index: src/sys/netinet6/mld6.c
diff -u src/sys/netinet6/mld6.c:1.82 src/sys/netinet6/mld6.c:1.83
--- src/sys/netinet6/mld6.c:1.82	Wed Feb 22 07:46:00 2017
+++ src/sys/netinet6/mld6.c	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mld6.c,v 1.82 2017/02/22 07:46:00 ozaki-r Exp $	*/
+/*	$NetBSD: mld6.c,v 1.83 2017/02/23 07:57:10 ozaki-r Exp $	*/
 /*	$KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $	*/
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.82 2017/02/22 07:46:00 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.83 2017/02/23 07:57:10 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -136,19 +136,6 @@ __KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.8
 
 
 /*
- * This structure is used to keep track of in6_multi chains which belong to
- * deleted interface addresses.
- */
-static LIST_HEAD(, multi6_kludge) in6_mk = LIST_HEAD_INITIALIZER(in6_mk);
-
-struct multi6_kludge {
-	LIST_ENTRY(multi6_kludge) mk_entry;
-	struct ifnet *mk_ifp;
-	struct in6_multihead mk_head;
-};
-
-
-/*
  * Protocol constants
  */
 
@@ -340,11 +327,10 @@ mld_input(struct mbuf *m, int off)
 	struct ifnet *ifp;
 	struct in6_multi *in6m = NULL;
 	struct in6_addr mld_addr, all_in6;
-	struct in6_ifaddr *ia;
 	u_long timer = 0;	/* timer value in the MLD query header */
-	int s;
+	struct psref psref;
 
-	ifp = m_get_rcvif(m, &s);
+	ifp = m_get_rcvif_psref(m, &psref);
 	if (__predict_false(ifp == NULL))
 		goto out;
 	IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh));
@@ -409,8 +395,6 @@ mld_input(struct mbuf *m, int off)
 	 */
 	switch (mldh->mld_type) {
 	case MLD_LISTENER_QUERY: {
-		struct psref psref;
-
 		if (ifp->if_flags & IFF_LOOPBACK)
 			break;
 
@@ -436,15 +420,7 @@ mld_input(struct mbuf *m, int off)
 		 */
 		timer = ntohs(mldh->mld_maxdelay);
 
-		ia = in6_get_ia_from_ifp_psref(ifp, &psref);
-		if (ia == NULL)
-			break;
-
-		/* The following operations may sleep */
-		m_put_rcvif(ifp, &s);
-		ifp = NULL;
-
-		LIST_FOREACH(in6m, &ia->ia6_multiaddrs, in6m_entry) {
+		LIST_FOREACH(in6m, &ifp->if_multiaddrs, in6m_entry) {
 			if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_in6) ||
 			    IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) <
 			    IPV6_ADDR_SCOPE_LINKLOCAL)
@@ -469,7 +445,6 @@ mld_input(struct mbuf *m, int off)
 				mld_starttimer(in6m);
 			}
 		}
-		ia6_release(ia, &psref);
 		break;
 	    }
 
@@ -514,7 +489,7 @@ mld_input(struct mbuf *m, int off)
 out:
 	m_freem(m);
 out_nodrop:
-	m_put_rcvif(ifp, &s);
+	m_put_rcvif_psref(ifp, &psref);
 }
 
 static void
@@ -655,7 +630,6 @@ struct	in6_multi *
 in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp, 
 	int *errorp, int timer)
 {
-	struct	in6_ifaddr *ia;
 	struct	sockaddr_in6 sin6;
 	struct	in6_multi *in6m;
 	int	s = splsoftnet();
@@ -672,7 +646,6 @@ in6_addmulti(struct in6_addr *maddr6, st
 		 */
 		in6m->in6m_refcount++;
 	} else {
-		int _s;
 		/*
 		 * New address; allocate a new multicast record
 		 * and link it into the interface's multicast list.
@@ -692,21 +665,8 @@ in6_addmulti(struct in6_addr *maddr6, st
 		callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE);
 		callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m);
 
-		_s = pserialize_read_enter();
-		ia = in6_get_ia_from_ifp(ifp);
-		if (ia == NULL) {
-			pserialize_read_exit(_s);
-			callout_destroy(&in6m->in6m_timer_ch);
-			free(in6m, M_IPMADDR);
-			splx(s);
-			*errorp = EADDRNOTAVAIL; /* appropriate? */
-			return (NULL);
-		}
-		in6m->in6m_ia = ia;
-		ifaref(&ia->ia_ifa); /* gain a reference */
 		/* FIXME NOMPSAFE: need to lock */
-		LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
-		pserialize_read_exit(_s);
+		LIST_INSERT_HEAD(&ifp->if_multiaddrs, in6m, in6m_entry);
 
 		/*
 		 * Ask the network driver to update its multicast reception
@@ -718,7 +678,6 @@ in6_addmulti(struct in6_addr *maddr6, st
 			callout_destroy(&in6m->in6m_timer_ch);
 			LIST_REMOVE(in6m, in6m_entry);
 			free(in6m, M_IPMADDR);
-			ifafree(&ia->ia_ifa);
 			splx(s);
 			return (NULL);
 		}
@@ -766,11 +725,8 @@ in6_delmulti(struct in6_multi *in6m)
 		/*
 		 * Unlink from list.
 		 */
+		/* FIXME NOMPSAFE: need to lock */
 		LIST_REMOVE(in6m, in6m_entry);
-		if (in6m->in6m_ia != NULL) {
-			ifafree(&in6m->in6m_ia->ia_ifa); /* release reference */
-			in6m->in6m_ia = NULL;
-		}
 
 		/*
 		 * Delete all references of this multicasting group from
@@ -806,6 +762,37 @@ in6_delmulti(struct in6_multi *in6m)
 	splx(s);
 }
 
+/*
+ * Look up the in6_multi record for a given IP6 multicast address
+ * on a given interface. If no matching record is found, "in6m"
+ * returns NULL.
+ */
+struct in6_multi *
+in6_lookup_multi(const struct in6_addr *addr, const struct ifnet *ifp)
+{
+	struct in6_multi *in6m;
+
+	/* XXX NOMPSAFE */
+	LIST_FOREACH(in6m, &ifp->if_multiaddrs, in6m_entry) {
+		if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, addr))
+			break;
+	}
+	return in6m;
+}
+
+/*
+ * Purge in6_multi records associated to the interface.
+ */
+void
+in6_purge_multi(struct ifnet *ifp)
+{
+	struct in6_multi *in6m, *next;
+
+	/* XXX NOMPSAFE */
+	LIST_FOREACH_SAFE(in6m, &ifp->if_multiaddrs, in6m_entry, next) {
+		in6_delmulti(in6m);
+	}
+}
 
 struct in6_multi_mship *
 in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, 
@@ -839,180 +826,17 @@ in6_leavegroup(struct in6_multi_mship *i
 	return 0;
 }
 
-
 /*
- * Multicast address kludge:
- * If there were any multicast addresses attached to this interface address,
- * either move them to another address on this interface, or save them until
- * such time as this interface is reconfigured for IPv6.
+ * DEPRECATED: keep it just to avoid breaking old sysctl users.
  */
-void
-in6_savemkludge(struct in6_ifaddr *oia)
-{
-	struct in6_ifaddr *ia;
-	struct in6_multi *in6m;
-	int s;
-
-	s = pserialize_read_enter();
-	ia = in6_get_ia_from_ifp(oia->ia_ifp);
-	if (ia) {	/* there is another address */
-		KASSERT(ia != oia);
-		while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) {
-			LIST_REMOVE(in6m, in6m_entry);
-			ifaref(&ia->ia_ifa);
-			ifafree(&in6m->in6m_ia->ia_ifa);
-			in6m->in6m_ia = ia;
-			/* FIXME NOMPSAFE: need to lock */
-			LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
-		}
-	} else {	/* last address on this if deleted, save */
-		struct multi6_kludge *mk;
-
-		LIST_FOREACH(mk, &in6_mk, mk_entry) {
-			if (mk->mk_ifp == oia->ia_ifp)
-				break;
-		}
-		if (mk == NULL) /* this should not happen! */
-			panic("in6_savemkludge: no kludge space");
-
-		while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) {
-			LIST_REMOVE(in6m, in6m_entry);
-			ifafree(&in6m->in6m_ia->ia_ifa); /* release reference */
-			in6m->in6m_ia = NULL;
-			LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
-		}
-	}
-	pserialize_read_exit(s);
-}
-
-/*
- * Continuation of multicast address hack:
- * If there was a multicast group list previously saved for this interface,
- * then we re-attach it to the first address configured on the i/f.
- */
-void
-in6_restoremkludge(struct in6_ifaddr *ia, struct ifnet *ifp)
-{
-	struct multi6_kludge *mk;
-	struct in6_multi *in6m;
-
-	LIST_FOREACH(mk, &in6_mk, mk_entry) {
-		if (mk->mk_ifp == ifp)
-			break;
-	}
-	if (mk == NULL)
-		return;
-	while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL) {
-		LIST_REMOVE(in6m, in6m_entry);
-		in6m->in6m_ia = ia;
-		ifaref(&ia->ia_ifa);
-		LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
-	}
-}
-
-/*
- * Allocate space for the kludge at interface initialization time.
- * Formerly, we dynamically allocated the space in in6_savemkludge() with
- * malloc(M_WAITOK).  However, it was wrong since the function could be called
- * under an interrupt context (software timer on address lifetime expiration).
- * Also, we cannot just give up allocating the strucutre, since the group
- * membership structure is very complex and we need to keep it anyway.
- * Of course, this function MUST NOT be called under an interrupt context.
- * Specifically, it is expected to be called only from in6_ifattach(), though
- * it is a global function.
- */
-void
-in6_createmkludge(struct ifnet *ifp)
-{
-	struct multi6_kludge *mk;
-
-	LIST_FOREACH(mk, &in6_mk, mk_entry) {
-		/* If we've already had one, do not allocate. */
-		if (mk->mk_ifp == ifp)
-			return;
-	}
-
-	mk = malloc(sizeof(*mk), M_IPMADDR, M_ZERO|M_WAITOK);
-
-	LIST_INIT(&mk->mk_head);
-	mk->mk_ifp = ifp;
-	LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
-}
-
-void
-in6_purgemkludge(struct ifnet *ifp)
-{
-	struct multi6_kludge *mk;
-	struct in6_multi *in6m, *next;
-
-	LIST_FOREACH(mk, &in6_mk, mk_entry) {
-		if (mk->mk_ifp == ifp)
-			break;
-	}
-	if (mk == NULL)
-		return;
-
-	/* leave from all multicast groups joined */
-	for (in6m = LIST_FIRST(&mk->mk_head); in6m != NULL; in6m = next) {
-		next = LIST_NEXT(in6m, in6m_entry);
-		in6_delmulti(in6m);
-	}
-	LIST_REMOVE(mk, mk_entry);
-	free(mk, M_IPMADDR);
-}
-
 static int
 in6_mkludge_sysctl(SYSCTLFN_ARGS)
 {
-	struct multi6_kludge *mk;
-	struct in6_multi *in6m;
-	int error;
-	uint32_t tmp;
-	size_t written;
 
 	if (namelen != 1)
 		return EINVAL;
-
-	if (oldp == NULL) {
-		*oldlenp = 0;
-		LIST_FOREACH(mk, &in6_mk, mk_entry) {
-			if (mk->mk_ifp->if_index == name[0])
-				continue;
-			LIST_FOREACH(in6m, &mk->mk_head, in6m_entry) {
-				*oldlenp += sizeof(struct in6_addr) +
-				    sizeof(uint32_t);
-			}
-		}
-		return 0;
-	}
-
-	error = 0;
-	written = 0;
-	LIST_FOREACH(mk, &in6_mk, mk_entry) {
-		if (mk->mk_ifp->if_index == name[0])
-			continue;
-		LIST_FOREACH(in6m, &mk->mk_head, in6m_entry) {
-			if (written + sizeof(struct in6_addr) +
-			    sizeof(uint32_t) > *oldlenp)
-				goto done;
-			error = sysctl_copyout(l, &in6m->in6m_addr,
-			    oldp, sizeof(struct in6_addr));
-			if (error)
-				goto done;
-			oldp = (char *)oldp + sizeof(struct in6_addr);
-			written += sizeof(struct in6_addr);
-			tmp = in6m->in6m_refcount;
-			error = sysctl_copyout(l, &tmp, oldp, sizeof(tmp));
-			if (error)
-				goto done;
-			oldp = (char *)oldp + sizeof(tmp);
-			written += sizeof(tmp);
-		}
-	}
-
-done:
-	*oldlenp = written;
-	return error;
+	*oldlenp = 0;
+	return 0;
 }
 
 static int
@@ -1020,7 +844,7 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
 {
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
-	struct in6_ifaddr *ifa6;
+	struct in6_ifaddr *ia6;
 	struct in6_multi *in6m;
 	uint32_t tmp;
 	int error;
@@ -1042,10 +866,7 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
 		*oldlenp = 0;
 		s = pserialize_read_enter();
 		IFADDR_READER_FOREACH(ifa, ifp) {
-			if (ifa->ifa_addr->sa_family != AF_INET6)
-				continue;
-			ifa6 = (struct in6_ifaddr *)ifa;
-			LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) {
+			LIST_FOREACH(in6m, &ifp->if_multiaddrs, in6m_entry) {
 				*oldlenp += 2 * sizeof(struct in6_addr) +
 				    sizeof(uint32_t);
 			}
@@ -1066,12 +887,18 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
 		ifa_acquire(ifa, &psref_ia);
 		pserialize_read_exit(s);
 
-		ifa6 = (struct in6_ifaddr *)ifa;
-		LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) {
+		ia6 = ifatoia6(ifa);
+		LIST_FOREACH(in6m, &ifp->if_multiaddrs, in6m_entry) {
 			if (written + 2 * sizeof(struct in6_addr) +
 			    sizeof(uint32_t) > *oldlenp)
 				goto done;
-			error = sysctl_copyout(l, &ifa6->ia_addr.sin6_addr,
+			/*
+			 * XXX return the first IPv6 address to keep backward
+			 * compatibility, however now multicast addresses
+			 * don't belong to any IPv6 addresses so it should be
+			 * unnecessary.
+			 */
+			error = sysctl_copyout(l, &ia6->ia_addr.sin6_addr,
 			    oldp, sizeof(struct in6_addr));
 			if (error)
 				goto done;
@@ -1093,6 +920,8 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
 
 		s = pserialize_read_enter();
 		ifa_release(ifa, &psref_ia);
+
+		break;
 	}
 	pserialize_read_exit(s);
 done:

Index: src/sys/netipsec/key.c
diff -u src/sys/netipsec/key.c:1.102 src/sys/netipsec/key.c:1.103
--- src/sys/netipsec/key.c:1.102	Wed Feb 22 07:46:00 2017
+++ src/sys/netipsec/key.c	Thu Feb 23 07:57:09 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.102 2017/02/22 07:46:00 ozaki-r Exp $	*/
+/*	$NetBSD: key.c,v 1.103 2017/02/23 07:57:09 ozaki-r Exp $	*/
 /*	$FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $	*/
 /*	$KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $	*/
 
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.102 2017/02/22 07:46:00 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.103 2017/02/23 07:57:09 ozaki-r Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -4180,16 +4180,7 @@ key_ismyaddr6(const struct sockaddr_in6 
 		 * about IPv4 multicast??
 		 * XXX scope
 		 */
-		in6m = NULL;
-#ifdef __FreeBSD__
 		in6m = in6_lookup_multi(&sin6->sin6_addr, ia->ia_ifp);
-#else
-		for ((in6m) = ia->ia6_multiaddrs.lh_first;
-		     (in6m) != NULL &&
-		     !IN6_ARE_ADDR_EQUAL(&(in6m)->in6m_addr, &sin6->sin6_addr);
-		     (in6m) = in6m->in6m_entry.le_next)
-			continue;
-#endif
 		if (in6m) {
 			pserialize_read_exit(s);
 			return 1;

Index: src/usr.bin/netstat/if.c
diff -u src/usr.bin/netstat/if.c:1.93 src/usr.bin/netstat/if.c:1.94
--- src/usr.bin/netstat/if.c:1.93	Sun Jan 22 04:52:04 2017
+++ src/usr.bin/netstat/if.c	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.93 2017/01/22 04:52:04 mrg Exp $	*/
+/*	$NetBSD: if.c,v 1.94 2017/02/23 07:57:10 ozaki-r Exp $	*/
 
 /*
  * Copyright (c) 1983, 1988, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "from: @(#)if.c	8.2 (Berkeley) 2/21/94";
 #else
-__RCSID("$NetBSD: if.c,v 1.93 2017/01/22 04:52:04 mrg Exp $");
+__RCSID("$NetBSD: if.c,v 1.94 2017/02/23 07:57:10 ozaki-r Exp $");
 #endif
 #endif /* not lint */
 
@@ -553,7 +553,7 @@ print_addr(const int ifindex, struct soc
 			struct in6_multi inm;
 			union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo;
 		
-			multiaddr = (u_long)ifaddr->in6.ia6_multiaddrs.lh_first;
+			multiaddr = (u_long)ifaddr->in6._ia6_multiaddrs.lh_first;
 			while (multiaddr != 0) {
 				kread(multiaddr, (char *)&inm, sizeof inm);
 				ia6_print(&inm.in6m_addr);

Index: src/usr.sbin/ifmcstat/ifmcstat.c
diff -u src/usr.sbin/ifmcstat/ifmcstat.c:1.20 src/usr.sbin/ifmcstat/ifmcstat.c:1.21
--- src/usr.sbin/ifmcstat/ifmcstat.c:1.20	Tue Jan 10 05:43:27 2017
+++ src/usr.sbin/ifmcstat/ifmcstat.c	Thu Feb 23 07:57:10 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ifmcstat.c,v 1.20 2017/01/10 05:43:27 ozaki-r Exp $	*/
+/*	$NetBSD: ifmcstat.c,v 1.21 2017/02/23 07:57:10 ozaki-r Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -29,7 +29,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: ifmcstat.c,v 1.20 2017/01/10 05:43:27 ozaki-r Exp $");
+__RCSID("$NetBSD: ifmcstat.c,v 1.21 2017/02/23 07:57:10 ozaki-r Exp $");
 
 #include <err.h>
 #include <errno.h>
@@ -179,9 +179,9 @@ print_ether_mcast(u_short ifindex)
 static void
 print_inet6_mcast(u_short ifindex, const char *ifname)
 {
-	static int mcast_oids[4], kludge_oids[4];
+	static int mcast_oids[4];
 	const char *addr;
-	uint8_t *mcast_addrs, *kludge_addrs, *p, *last_p;
+	uint8_t *mcast_addrs, *p, *last_p;
 	uint32_t refcnt;
 	size_t len;
 
@@ -194,17 +194,7 @@ print_inet6_mcast(u_short ifindex, const
 			errx(1, "Wrong OID path for net.inet6.multicast");
 	}
 
-	if (kludge_oids[0] == 0) {
-		size_t oidlen = __arraycount(kludge_oids);
-		if (sysctlnametomib("net.inet6.multicast_kludge", kludge_oids,
-		    &oidlen) == -1)
-			errx(1, "net.inet6.multicast_kludge not found");
-		if (oidlen != 3)
-			errx(1, "Wrong OID path for net.inet6.multicast_kludge");
-	}
-
 	mcast_oids[3] = ifindex;
-	kludge_oids[3] = ifindex;
 
 	mcast_addrs = asysctl(mcast_oids, 4, &len);
 	if (mcast_addrs == NULL && len != 0) {
@@ -230,24 +220,4 @@ print_inet6_mcast(u_short ifindex, const
 		}
 	}
 	free(mcast_addrs);
-
-	kludge_addrs = asysctl(kludge_oids, 4, &len);
-	if (kludge_addrs == NULL && len != 0) {
-		warn("failed to read net.inet6.multicast_kludge");
-		return;
-	}
-	if (len) {
-		printf("\t(on kludge entry for %s)\n", ifname);
-		p = kludge_addrs;
-		while (len >= sizeof(struct in6_addr) + sizeof(uint32_t)) {
-			addr = inet6_n2a(p);
-			p += sizeof(struct in6_addr);
-			memcpy(&refcnt, p, sizeof(refcnt));
-			p += sizeof(refcnt);
-			printf("\t\tgroup %s refcount %" PRIu32 "\n", addr,
-			    refcnt);
-			len -= sizeof(struct in6_addr) + sizeof(uint32_t);
-		}
-	}
-	free(kludge_addrs);
 }

Reply via email to