diff options
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6.c | 21 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 7 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.h | 1 | ||||
-rw-r--r-- | sys/netinet6/nd6_rtr.c | 54 | ||||
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 2 |
5 files changed, 60 insertions, 25 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index ce0655408a28..4f756a75fac7 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1235,11 +1235,20 @@ in6_addifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *i int carp_attached = 0; int error; - /* Check if this interface is a bridge member */ - if (ifp->if_bridge && bridge_member_ifaddrs_p && - !bridge_member_ifaddrs_p()) { - error = EINVAL; - goto out; + /* + * Check if bridge wants to allow adding addrs to member interfaces. + */ + if (ifp->if_bridge != NULL && ifp->if_type != IFT_GIF && + bridge_member_ifaddrs_p != NULL) { + if (bridge_member_ifaddrs_p()) { + if_printf(ifp, "WARNING: Assigning an IP address to " + "an interface which is also a bridge member is " + "deprecated and will be unsupported in a future " + "release.\n"); + } else { + error = EINVAL; + goto out; + } } /* @@ -2618,6 +2627,8 @@ in6_domifdetach(struct ifnet *ifp, void *aux) { struct in6_ifextra *ext = (struct in6_ifextra *)aux; + MPASS(ifp->if_afdata[AF_INET6] == NULL); + mld_domifdetach(ifp); scope6_ifdetach(ext->scope6_id); nd6_ifdetach(ifp, ext->nd_ifinfo); diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index f284f7fa5ffc..cc149616006e 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -83,7 +83,6 @@ VNET_DECLARE(struct inpcbinfo, ripcbinfo); #define V_ripcbinfo VNET(ripcbinfo) static int get_rand_ifid(struct ifnet *, struct in6_addr *); -static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *); static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *); static int in6_ifattach_loopback(struct ifnet *); static void in6_purgemaddrs(struct ifnet *); @@ -271,8 +270,8 @@ found: * * altifp - secondary EUI64 source */ -static int -get_ifid(struct ifnet *ifp0, struct ifnet *altifp, +int +in6_get_ifid(struct ifnet *ifp0, struct ifnet *altifp, struct in6_addr *in6) { struct ifnet *ifp; @@ -356,7 +355,7 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); } else { NET_EPOCH_ENTER(et); - error = get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr); + error = in6_get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr); NET_EPOCH_EXIT(et); if (error != 0) { nd6log((LOG_ERR, diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h index 897926e90078..fd52422b10be 100644 --- a/sys/netinet6/in6_ifattach.h +++ b/sys/netinet6/in6_ifattach.h @@ -41,6 +41,7 @@ void in6_ifdetach(struct ifnet *); void in6_ifdetach_destroy(struct ifnet *); void in6_tmpaddrtimer(void *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); +int in6_get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *); int in6_nigroup(struct ifnet *, const char *, int, struct in6_addr *); int in6_nigroup_oldmcprefix(struct ifnet *, const char *, int, struct in6_addr *); #endif /* _KERNEL */ diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index b9af0a78a584..6fe78083df23 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1182,9 +1182,9 @@ in6_ifadd(struct nd_prefixctl *pr, int mcast) struct ifnet *ifp = pr->ndpr_ifp; struct ifaddr *ifa; struct in6_aliasreq ifra; - struct in6_ifaddr *ia, *ib; + struct in6_ifaddr *ia = NULL, *ib = NULL; int error, plen0; - struct in6_addr mask; + struct in6_addr *ifid_addr = NULL, mask; int prefixlen = pr->ndpr_plen; int updateflags; char ip6buf[INET6_ADDRSTRLEN]; @@ -1212,18 +1212,42 @@ in6_ifadd(struct nd_prefixctl *pr, int mcast) * with different interface identifiers. */ ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */ - if (ifa) + if (ifa) { ib = (struct in6_ifaddr *)ifa; - else - return NULL; + ifid_addr = &ib->ia_addr.sin6_addr; + + /* prefixlen + ifidlen must be equal to 128 */ + plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL); + if (prefixlen != plen0) { + ifa_free(ifa); + ifid_addr = NULL; + nd6log((LOG_DEBUG, + "%s: wrong prefixlen for %s (prefix=%d ifid=%d)\n", + __func__, if_name(ifp), prefixlen, 128 - plen0)); + } + } - /* prefixlen + ifidlen must be equal to 128 */ - plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL); - if (prefixlen != plen0) { - ifa_free(ifa); + /* No suitable LL address, get the ifid directly */ + if (ifid_addr == NULL) { + struct in6_addr taddr; + ifa = ifa_alloc(sizeof(taddr), M_WAITOK); + if (ifa) { + ib = (struct in6_ifaddr *)ifa; + ifid_addr = &ib->ia_addr.sin6_addr; + if(in6_get_ifid(ifp, NULL, ifid_addr) != 0) { + nd6log((LOG_DEBUG, + "%s: failed to get ifid for %s\n", + __func__, if_name(ifp))); + ifa_free(ifa); + ifid_addr = NULL; + } + } + } + + if (ifid_addr == NULL) { nd6log((LOG_INFO, - "%s: wrong prefixlen for %s (prefix=%d ifid=%d)\n", - __func__, if_name(ifp), prefixlen, 128 - plen0)); + "%s: could not determine ifid for %s\n", + __func__, if_name(ifp))); return NULL; } @@ -1233,13 +1257,13 @@ in6_ifadd(struct nd_prefixctl *pr, int mcast) IN6_MASK_ADDR(&ifra.ifra_addr.sin6_addr, &mask); /* interface ID */ ifra.ifra_addr.sin6_addr.s6_addr32[0] |= - (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]); + (ifid_addr->s6_addr32[0] & ~mask.s6_addr32[0]); ifra.ifra_addr.sin6_addr.s6_addr32[1] |= - (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]); + (ifid_addr->s6_addr32[1] & ~mask.s6_addr32[1]); ifra.ifra_addr.sin6_addr.s6_addr32[2] |= - (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]); + (ifid_addr->s6_addr32[2] & ~mask.s6_addr32[2]); ifra.ifra_addr.sin6_addr.s6_addr32[3] |= - (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]); + (ifid_addr->s6_addr32[3] & ~mask.s6_addr32[3]); ifa_free(ifa); /* lifetimes. */ diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 0027cf3bd230..1a32365f5d1d 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -341,7 +341,7 @@ udp6_multi_input(struct mbuf *m, int off, int proto, /* * No matching pcb found; discard datagram. (No need * to send an ICMP Port Unreachable for a broadcast - * or multicast datgram.) + * or multicast datagram.) */ UDPSTAT_INC(udps_noport); UDPSTAT_INC(udps_noportmcast); |