summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_spppsubr.c36
-rw-r--r--sys/netinet6/in6.c4
-rw-r--r--sys/netinet6/in6_ifattach.c34
-rw-r--r--sys/netinet6/in6_ifattach.h6
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_ */