sync with KAME regarding the following clarification in RFC3542:
- disable IPv6 operation if DAD fails for some EUI-64 link-local addresses. - export get_hw_ifid() (and rename it) as a subroutine for this process. Obtained from: KAME Reviewd by: ume, gnn MFC after: 2 week
This commit is contained in:
parent
6b6c96661e
commit
d28bde669a
sys/netinet6
@ -75,7 +75,6 @@ extern struct inpcbinfo ripcbinfo;
|
||||
|
||||
static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
|
||||
static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
|
||||
static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
|
||||
static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
|
||||
static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
|
||||
static int in6_ifattach_loopback __P((struct ifnet *));
|
||||
@ -217,8 +216,8 @@ generate_tmp_ifid(seed0, seed1, ret)
|
||||
* Get interface identifier for the specified interface.
|
||||
* XXX assumes single sockaddr_dl (AF_LINK address) per an interface
|
||||
*/
|
||||
static int
|
||||
get_hw_ifid(ifp, in6)
|
||||
int
|
||||
in6_get_hw_ifid(ifp, in6)
|
||||
struct ifnet *ifp;
|
||||
struct in6_addr *in6; /* upper 64bits are preserved */
|
||||
{
|
||||
@ -359,14 +358,14 @@ get_ifid(ifp0, altifp, in6)
|
||||
struct ifnet *ifp;
|
||||
|
||||
/* first, try to get it from the interface itself */
|
||||
if (get_hw_ifid(ifp0, in6) == 0) {
|
||||
if (in6_get_hw_ifid(ifp0, in6) == 0) {
|
||||
nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
|
||||
if_name(ifp0)));
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* try secondary EUI64 source. this basically is for ATM PVC */
|
||||
if (altifp && get_hw_ifid(altifp, in6) == 0) {
|
||||
if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
|
||||
nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
|
||||
if_name(ifp0), if_name(altifp)));
|
||||
goto success;
|
||||
@ -377,7 +376,7 @@ get_ifid(ifp0, altifp, in6)
|
||||
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
|
||||
if (ifp == ifp0)
|
||||
continue;
|
||||
if (get_hw_ifid(ifp, in6) != 0)
|
||||
if (in6_get_hw_ifid(ifp, in6) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
@ -38,6 +38,7 @@ void in6_ifattach __P((struct ifnet *, struct ifnet *));
|
||||
void in6_ifdetach __P((struct ifnet *));
|
||||
void in6_get_tmpifid __P((struct ifnet *, u_int8_t *, const u_int8_t *, int));
|
||||
void in6_tmpaddrtimer __P((void *));
|
||||
int in6_get_hw_ifid __P((struct ifnet *, struct in6_addr *));
|
||||
int in6_nigroup __P((struct ifnet *, const char *, int, struct in6_addr *));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/in6_ifattach.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
@ -1306,6 +1307,7 @@ nd6_dad_duplicated(ifa)
|
||||
struct ifaddr *ifa;
|
||||
{
|
||||
struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
|
||||
struct ifnet *ifp;
|
||||
struct dadq *dp;
|
||||
|
||||
dp = nd6_dad_find(ifa);
|
||||
@ -1325,10 +1327,45 @@ nd6_dad_duplicated(ifa)
|
||||
/* We are done with DAD, with duplicate address found. (failure) */
|
||||
nd6_dad_stoptimer(dp);
|
||||
|
||||
ifp = ifa->ifa_ifp;
|
||||
log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
|
||||
if_name(ifa->ifa_ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
|
||||
if_name(ifp), ip6_sprintf(&ia->ia_addr.sin6_addr));
|
||||
log(LOG_ERR, "%s: manual intervention required\n",
|
||||
if_name(ifa->ifa_ifp));
|
||||
if_name(ifp));
|
||||
|
||||
/*
|
||||
* If the address is a link-local address formed from an interface
|
||||
* identifier based on the hardware address which is supposed to be
|
||||
* uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP
|
||||
* operation on the interface SHOULD be disabled.
|
||||
* [rfc2462bis-03 Section 5.4.5]
|
||||
*/
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
|
||||
struct in6_addr in6;
|
||||
|
||||
/*
|
||||
* To avoid over-reaction, we only apply this logic when we are
|
||||
* very sure that hardware addresses are supposed to be unique.
|
||||
*/
|
||||
switch (ifp->if_type) {
|
||||
case IFT_ETHER:
|
||||
case IFT_FDDI:
|
||||
case IFT_ATM:
|
||||
case IFT_IEEE1394:
|
||||
#ifdef IFT_IEEE80211
|
||||
case IFT_IEEE80211:
|
||||
#endif
|
||||
in6 = ia->ia_addr.sin6_addr;
|
||||
if (in6_get_hw_ifid(ifp, &in6) == 0 &&
|
||||
IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
|
||||
ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
|
||||
log(LOG_ERR, "%s: possible hardware address "
|
||||
"duplication detected, disable IPv6\n",
|
||||
if_name(ifp));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
|
||||
free(dp, M_IP6NDP);
|
||||
|
Loading…
x
Reference in New Issue
Block a user