diff options
author | hrs <hrs@FreeBSD.org> | 2013-07-02 16:58:15 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2013-07-02 16:58:15 +0000 |
commit | 50e0add9e4de4d5547753f15e5df2059b5ee1f11 (patch) | |
tree | 8775244886e162bc495c5bb160eb522c8ecc72c6 /sys/netinet6 | |
parent | b3bce89084554d40481243aa35610916fd7cf077 (diff) | |
download | FreeBSD-src-50e0add9e4de4d5547753f15e5df2059b5ee1f11.zip FreeBSD-src-50e0add9e4de4d5547753f15e5df2059b5ee1f11.tar.gz |
- Allow ND6_IFF_AUTO_LINKLOCAL for IFT_BRIDGE. An interface with IFT_BRIDGE
is initialized with !ND6_IFF_AUTO_LINKLOCAL && !ND6_IFF_ACCEPT_RTADV
regardless of net.inet6.ip6.accept_rtadv and net.inet6.ip6.auto_linklocal.
To configure an autoconfigured link-local address (RFC 4862), the
following rc.conf(5) configuration can be used:
ifconfig_bridge0_ipv6="inet6 auto_linklocal"
- if_bridge(4) now removes IPv6 addresses on a member interface to be
added when the parent interface or one of the existing member
interfaces has an IPv6 address. if_bridge(4) merges each link-local
scope zone which the member interfaces form respectively, so it causes
address scope violation. Removal of the IPv6 addresses prevents it.
- if_lagg(4) now removes IPv6 addresses on a member interfaces
unconditionally.
- Set reasonable flags to non-IPv6-capable interfaces. [*]
Submitted by: rpaulo [*]
MFC after: 1 week
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/in6.c | 26 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 15 | ||||
-rw-r--r-- | sys/netinet6/in6_var.h | 1 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 24 |
4 files changed, 51 insertions, 15 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 80359c1..9e005c5 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1987,6 +1987,32 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr) } /* + * Find a link-local scoped address on ifp and return it if any. + */ +struct in6_ifaddr * +in6ifa_llaonifp(struct ifnet *ifp) +{ + struct sockaddr_in6 *sin6; + struct ifaddr *ifa; + + if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) + return (NULL); + if_addr_rlock(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) || + IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr) || + IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr)) + break; + } + if_addr_runlock(ifp); + + return ((struct in6_ifaddr *)ifa); +} + +/* * Convert IP6 address to printable (loggable) representation. Caller * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long. */ diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 85890ab..674356a 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -266,6 +266,7 @@ found: /* get EUI64 */ switch (ifp->if_type) { + case IFT_BRIDGE: case IFT_ETHER: case IFT_L2VLAN: case IFT_FDDI: @@ -727,6 +728,8 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) switch (ifp->if_type) { case IFT_PFLOG: case IFT_PFSYNC: + ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; + ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED; return; } @@ -734,7 +737,6 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) * quirks based on interface type */ switch (ifp->if_type) { -#ifdef IFT_STF case IFT_STF: /* * 6to4 interface is a very special kind of beast. @@ -742,8 +744,8 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) * linklocals for 6to4 interface, but there's no use and * it is rather harmful to have one. */ - goto statinit; -#endif + ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; + break; default: break; } @@ -777,8 +779,7 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) /* * assign a link-local address, if there's none. */ - if (ifp->if_type != IFT_BRIDGE && - !(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && + if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) { int error; @@ -795,10 +796,6 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) ifa_free(&ia->ia_ifa); } -#ifdef IFT_STF /* XXX */ -statinit: -#endif - /* update dynamically. */ if (V_in6_maxmtu < ifp->if_mtu) V_in6_maxmtu = ifp->if_mtu; diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index 3b4e89e..b3f7218 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -800,6 +800,7 @@ void in6_setmaxmtu(void); int in6_if2idlen(struct ifnet *); struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, struct in6_addr *); +struct in6_ifaddr *in6ifa_llaonifp(struct ifnet *); char *ip6_sprintf(char *, const struct in6_addr *); int in6_addr2zoneid(struct ifnet *, struct in6_addr *, u_int32_t *); int in6_matchlen(struct in6_addr *, struct in6_addr *); diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 0e30825..0a67a8a 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -176,13 +176,25 @@ nd6_ifattach(struct ifnet *ifp) nd->flags = ND6_IFF_PERFORMNUD; - /* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL. */ - if (V_ip6_auto_linklocal || (ifp->if_flags & IFF_LOOPBACK)) + /* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL. + * XXXHRS: Clear ND6_IFF_AUTO_LINKLOCAL on an IFT_BRIDGE interface by + * default regardless of the V_ip6_auto_linklocal configuration to + * give a reasonable default behavior. + */ + if ((V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) || + (ifp->if_flags & IFF_LOOPBACK)) nd->flags |= ND6_IFF_AUTO_LINKLOCAL; - - /* A loopback interface does not need to accept RTADV. */ - if (V_ip6_accept_rtadv && !(ifp->if_flags & IFF_LOOPBACK)) - nd->flags |= ND6_IFF_ACCEPT_RTADV; + /* + * A loopback interface does not need to accept RTADV. + * XXXHRS: Clear ND6_IFF_ACCEPT_RTADV on an IFT_BRIDGE interface by + * default regardless of the V_ip6_accept_rtadv configuration to + * prevent the interface from accepting RA messages arrived + * on one of the member interfaces with ND6_IFF_ACCEPT_RTADV. + */ + if (V_ip6_accept_rtadv && + !(ifp->if_flags & IFF_LOOPBACK) && + (ifp->if_type != IFT_BRIDGE)) + nd->flags |= ND6_IFF_ACCEPT_RTADV; if (V_ip6_no_radr && !(ifp->if_flags & IFF_LOOPBACK)) nd->flags |= ND6_IFF_NO_RADR; |