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.
This commit is contained in:
parent
7250944257
commit
00a9cf741d
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
@ -1369,23 +1369,6 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
|
||||
ifa_remove(ifp, &ia->ia_ifa);
|
||||
mutex_exit(&in6_ifaddr_lock);
|
||||
|
||||
/*
|
||||
* XXX thorpej@NetBSD.org -- 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.
|
||||
*/
|
||||
@ -1754,9 +1737,6 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
|
||||
return error;
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_MULTICAST)
|
||||
in6_restoremkludge(ia, ifp);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -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 ifnet *altifp)
|
||||
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);
|
||||
|
||||
|
@ -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, void *, struct ifnet *);
|
||||
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 *
|
||||
|
@ -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"
|
||||
@ -135,19 +135,6 @@ __KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.82 2017/02/22 07:46:00 ozaki-r Exp $");
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
|
||||
/*
|
||||
* 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, struct ifnet *ifp,
|
||||
*/
|
||||
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, struct ifnet *ifp,
|
||||
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, struct ifnet *ifp,
|
||||
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 *imm)
|
||||
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:
|
||||
|
@ -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 *sin6)
|
||||
* 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;
|
||||
|
@ -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 sockaddr *sa,
|
||||
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);
|
||||
|
@ -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 char *ifname)
|
||||
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 char *ifname)
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user