diff options
author | 2014-01-07 16:34:05 +0000 | |
---|---|---|
committer | 2014-01-07 16:34:05 +0000 | |
commit | c93b5f8a98fc0a4acee6dba25c8feea32417056e (patch) | |
tree | 9ddfb9dfbe2bfc42c99f3a2383cfc9da37f2a429 /sys/net/if_spppsubr.c | |
parent | use IF_NAMESIZE as size of buffer for interface name (diff) | |
download | wireguard-openbsd-c93b5f8a98fc0a4acee6dba25c8feea32417056e.tar.xz wireguard-openbsd-c93b5f8a98fc0a4acee6dba25c8feea32417056e.zip |
Some follow-up fixes for IFID collision handling in IPv6CP.
Really change the link-local address in the unlikely event of an IFID
collision, instead of going into an infinite conf-nak loop with the peer.
To make the netinet6 code use the IPv6CP IFID in a new link-local address,
in6_ifattach_linklocal() must accept a provided IFID. Replace the unused
'altifp' parameter with a new 'ifid' parameter for this purpose.
Always use the latest suggested address in IPv6CP replies, even if
the task to update the interface's address hasn't run yet.
Also, clear the ifindex (KAME hack) in addresses sent during IPv6CP.
ok mpi
Diffstat (limited to 'sys/net/if_spppsubr.c')
-rw-r--r-- | sys/net/if_spppsubr.c | 36 |
1 files changed, 33 insertions, 3 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*/ |