diff options
-rw-r--r-- | sys/net/if_spppsubr.c | 36 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 4 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 34 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.h | 6 |
4 files changed, 53 insertions, 27 deletions
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index 59de883e42f..b080aa4a975 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_spppsubr.c,v 1.114 2013/12/11 18:27:23 jca Exp $ */ +/* $OpenBSD: if_spppsubr.c,v 1.115 2014/01/07 16:34:05 stsp Exp $ */ /* * Synchronous PPP/Cisco link level subroutines. * Keepalive protocol implemented in both Cisco and PPP modes. @@ -69,6 +69,10 @@ #include <netinet/if_ether.h> #endif +#ifdef INET6 +#include <netinet6/in6_ifattach.h> +#endif + #include <net/if_sppp.h> # define UNTIMEOUT(fun, arg, handle) \ @@ -3222,7 +3226,10 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len) addlog("\n"); /* pass 2: parse option values */ - sppp_get_ip6_addrs(sp, &myaddr, NULL, NULL); + if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) + myaddr = sp->ipv6cp.req_ifid.ifra_addr.sin6_addr; + else + sppp_get_ip6_addrs(sp, &myaddr, NULL, NULL); if (debug) log(LOG_DEBUG, "%s: ipv6cp parse opt values: ", SPP_ARGS(ifp)); @@ -3455,7 +3462,10 @@ sppp_ipv6cp_scr(struct sppp *sp) int i = 0; if (sp->ipv6cp.opts & (1 << IPV6CP_OPT_IFID)) { - sppp_get_ip6_addrs(sp, &ouraddr, NULL, NULL); + if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) + ouraddr = sp->ipv6cp.req_ifid.ifra_addr.sin6_addr; + else + sppp_get_ip6_addrs(sp, &ouraddr, NULL, NULL); opt[i++] = IPV6CP_OPT_IFID; opt[i++] = 10; bcopy(&ouraddr.s6_addr[8], &opt[i], 8); @@ -4768,6 +4778,25 @@ sppp_update_ip6_addr(void *arg1, void *arg2) return; } + /* + * Changing the link-local address requires purging all + * existing addresses and routes for the interface first. + */ + if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) { + in6_ifdetach(ifp); + error = in6_ifattach_linklocal(ifp, &ifra->ifra_addr.sin6_addr); + if (error) + log(LOG_ERR, SPP_FMT + "could not update IPv6 address (error %d)\n", + SPP_ARGS(ifp), error); + splx(s); + return; + } + + /* + * Code below changes address parameters only, not the address itself. + */ + /* Destination address can only be set for /128. */ if (!in6_are_prefix_equal(&ia->ia_prefixmask.sin6_addr, &mask, 128)) { ifra->ifra_dstaddr.sin6_len = 0; @@ -4843,6 +4872,7 @@ sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest) myaddr.s6_addr[14] ^= (random & 0xff); myaddr.s6_addr[15] ^= ((random & 0xff00) >> 8); } + myaddr.s6_addr16[1] = 0; /* KAME hack: clear ifindex */ bcopy(&myaddr, suggest, sizeof(myaddr)); } #endif /*INET6*/ diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index d9a472f8466..80c357124f8 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.c,v 1.126 2013/11/28 10:16:44 mpi Exp $ */ +/* $OpenBSD: in6.c,v 1.127 2014/01/07 16:34:05 stsp Exp $ */ /* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */ /* @@ -2220,7 +2220,7 @@ in6_if_up(struct ifnet *ifp) /* * special cases, like 6to4, are handled in in6_ifattach */ - in6_ifattach(ifp, NULL); + in6_ifattach(ifp); dad_delay = 0; TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 4a558bdc47b..26369b05230 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_ifattach.c,v 1.65 2014/01/06 13:01:20 stsp Exp $ */ +/* $OpenBSD: in6_ifattach.c,v 1.66 2014/01/07 16:34:05 stsp Exp $ */ /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */ /* @@ -67,7 +67,7 @@ int ip6_auto_linklocal = 1; /* enable by default */ int get_last_resort_ifid(struct ifnet *, struct in6_addr *); int get_hw_ifid(struct ifnet *, struct in6_addr *); -int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *); +int get_ifid(struct ifnet *, struct in6_addr *); int in6_ifattach_loopback(struct ifnet *); #define EUI64_GBIT 0x01 @@ -257,11 +257,9 @@ found: * Get interface identifier for the specified interface. If it is not * available on ifp0, borrow interface identifier from other information * sources. - * - * altifp - secondary EUI64 source */ int -get_ifid(struct ifnet *ifp0, struct ifnet *altifp, struct in6_addr *in6) +get_ifid(struct ifnet *ifp0, struct in6_addr *in6) { struct ifnet *ifp; @@ -272,13 +270,6 @@ get_ifid(struct ifnet *ifp0, struct ifnet *altifp, struct in6_addr *in6) goto success; } - /* try secondary EUI64 source. this basically is for ATM PVC */ - if (altifp && get_hw_ifid(altifp, in6) == 0) { - nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n", - ifp0->if_xname, altifp->if_xname)); - goto success; - } - /* next, try to get it from some other hardware interface */ TAILQ_FOREACH(ifp, &ifnet, if_list) { if (ifp == ifp0) @@ -318,11 +309,11 @@ success: } /* - * altifp - secondary EUI64 source + * ifid - used as EUI64 if not NULL, overrides other EUI64 sources */ int -in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) +in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid) { struct in6_ifaddr *ia; struct in6_aliasreq ifra; @@ -348,8 +339,15 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) if ((ifp->if_flags & IFF_LOOPBACK) != 0) { ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1); + } else if (ifid) { + ifra.ifra_addr.sin6_addr = *ifid; + ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80); + ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); + ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; + ifra.ifra_addr.sin6_addr.s6_addr[8] &= ~EUI64_GBIT; + ifra.ifra_addr.sin6_addr.s6_addr[8] |= EUI64_UBIT; } else { - if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) { + if (get_ifid(ifp, &ifra.ifra_addr.sin6_addr) != 0) { nd6log((LOG_ERR, "%s: no ifid available\n", ifp->if_xname)); return (-1); @@ -565,11 +563,9 @@ in6_nigroup(struct ifnet *ifp, const char *name, int namelen, * XXX multiple loopback interface needs more care. for instance, * nodelocal address needs to be configured onto only one of them. * XXX multiple link-local address case - * - * altifp - secondary EUI64 source */ void -in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) +in6_ifattach(struct ifnet *ifp) { struct in6_ifaddr *ia; struct in6_addr in6; @@ -634,7 +630,7 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) if (ip6_auto_linklocal) { ia = in6ifa_ifpforlinklocal(ifp, 0); if (ia == NULL) { - if (in6_ifattach_linklocal(ifp, altifp) == 0) { + if (in6_ifattach_linklocal(ifp, NULL) == 0) { /* linklocal address assigned */ } else { /* failed to assign linklocal address. bark? */ diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h index 44bea78d569..6f574d6e1be 100644 --- a/sys/netinet6/in6_ifattach.h +++ b/sys/netinet6/in6_ifattach.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_ifattach.h,v 1.5 2006/08/31 12:37:31 mcbride Exp $ */ +/* $OpenBSD: in6_ifattach.h,v 1.6 2014/01/07 16:34:05 stsp Exp $ */ /* $KAME: in6_ifattach.h,v 1.9 2000/04/12 05:35:48 itojun Exp $ */ /* @@ -34,10 +34,10 @@ #define _NETINET6_IN6_IFATTACH_H_ #ifdef _KERNEL -void in6_ifattach(struct ifnet *, struct ifnet *); +void in6_ifattach(struct ifnet *); void in6_ifdetach(struct ifnet *); int in6_nigroup(struct ifnet *, const char *, int, struct sockaddr_in6 *); -int in6_ifattach_linklocal(struct ifnet *, struct ifnet *); +int in6_ifattach_linklocal(struct ifnet *, struct in6_addr *); #endif /* _KERNEL */ #endif /* _NETINET6_IN6_IFATTACH_H_ */ |