summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/ifconfig/ifconfig.833
-rw-r--r--sbin/ifconfig/ifconfig.c12
-rw-r--r--sys/net/if.h7
-rw-r--r--sys/netinet6/in6.h3
-rw-r--r--sys/netinet6/in6_ifattach.c28
-rw-r--r--sys/netinet6/in6_var.h3
-rw-r--r--sys/netinet6/nd6.h7
-rw-r--r--sys/netinet6/nd6_rtr.c67
8 files changed, 135 insertions, 25 deletions
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index 52efd5a2038..003fb9ba4ac 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ifconfig.8,v 1.193 2010/04/02 21:16:24 deraadt Exp $
+.\" $OpenBSD: ifconfig.8,v 1.194 2010/04/06 14:12:10 stsp Exp $
.\" $NetBSD: ifconfig.8,v 1.11 1996/01/04 21:27:29 pk Exp $
.\" $FreeBSD: ifconfig.8,v 1.16 1998/02/01 07:03:29 steve Exp $
.\"
@@ -31,7 +31,7 @@
.\"
.\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94
.\"
-.Dd $Mdocdate: April 2 2010 $
+.Dd $Mdocdate: April 6 2010 $
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -1103,6 +1103,7 @@ authentication.
.Bk -words
.Ar inet6-interface
.Op Oo Fl Oc Cm anycast
+.Op Oo Fl Oc Cm autoconfprivacy
.Op Cm eui64
.Op Cm pltime Ar n
.Op Oo Fl Oc Cm tentative
@@ -1115,6 +1116,34 @@ The options are as follows:
Set the IPv6 anycast address bit.
.It Fl anycast
Clear the IPv6 anycast address bit.
+.It Cm autoconfprivacy
+Enable privacy extensions for stateless IPv6 address autoconfiguration
+(RFC 4941) on the interface.
+The purpose of these extensions is to prevent tracking of individual
+devices which connect to the IPv6 internet from different networks
+using stateless autoconfiguration.
+The interface identifier often remains constant and provides the lower
+64 bits of an autoconfigured IPv6 address, facilitating tracking of
+individual devices (and hence, potentially, users of these devices)
+over long periods of time (weeks to months to years).
+When these extensions are active, random interface identifiers are used
+for autoconfigured addresses.
+Autoconfigured addresses are also made temporary, which means that they
+will automatically be replaced regularly.
+Temporary addresses are deprecated after 24 hours.
+Once a temporary address has been deprecated, a new temporary address
+will be configured upon reception of a router advertisement indicating
+that the prefix is still valid.
+Deprecated addresses will not be used for new connections as long as a
+non-deprecated address remains available.
+Temporary addresses become invalid after one week, at which time they
+will be removed from the interface.
+Address lifetime extension through router advertisements is ignored
+for temporary addresses.
+.It Fl autoconfprivacy
+Disable IPv6 autoconf privacy extensions on the interface.
+Currently configured addresses will not be removed until they become
+invalid.
.It Cm eui64
Fill the interface index
.Pq the lowermost 64th bit of an IPv6 address
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 7dcc488e362..b3ba114f908 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifconfig.c,v 1.230 2010/04/03 03:13:01 deraadt Exp $ */
+/* $OpenBSD: ifconfig.c,v 1.231 2010/04/06 14:12:10 stsp Exp $ */
/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
/*
@@ -338,6 +338,8 @@ const struct cmd {
{ "pltime", NEXTARG, 0, setia6pltime },
{ "vltime", NEXTARG, 0, setia6vltime },
{ "eui64", 0, 0, setia6eui64 },
+ { "autoconfprivacy", IFXF_INET6_PRIVACY, 0, setifxflags },
+ { "-autoconfprivacy", -IFXF_INET6_PRIVACY, 0, setifxflags },
#endif /*INET6*/
#ifndef SMALL
{ "rtlabel", NEXTARG, 0, setifrtlabel },
@@ -1189,6 +1191,12 @@ setifxflags(const char *vname, int value)
{
struct ifreq my_ifr;
+ if ((value == IFXF_INET6_PRIVACY || value == -IFXF_INET6_PRIVACY)
+ && afp->af_af != AF_INET6) {
+ errx(1, "autoconfprivacy needs AF inet6, current AF is `%s'",
+ afp->af_name);
+ }
+
bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
if (ioctl(s, SIOCGIFXFLAGS, (caddr_t)&my_ifr) < 0)
@@ -2981,6 +2989,8 @@ in6_alias(struct in6_ifreq *creq)
printf(" deprecated");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF)
printf(" autoconf");
+ if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_PRIVACY)
+ printf(" autoconfprivacy");
}
if (scopeid)
diff --git a/sys/net/if.h b/sys/net/if.h
index 8425dc0fd80..d467bbaa20e 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.113 2010/01/13 02:26:49 henning Exp $ */
+/* $OpenBSD: if.h,v 1.114 2010/04/06 14:12:10 stsp Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -323,8 +323,9 @@ struct ifnet { /* and the entries */
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
-#define IFXF_TXREADY 0x1 /* interface is ready to tx */
-#define IFXF_NOINET6 0x2 /* don't do inet6 */
+#define IFXF_TXREADY 0x1 /* interface is ready to tx */
+#define IFXF_NOINET6 0x2 /* don't do inet6 */
+#define IFXF_INET6_PRIVACY 0x4 /* autoconf privacy extension */
#define IFXF_CANTCHANGE \
(IFXF_TXREADY)
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index c50b86e0547..336bf2e1d49 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.h,v 1.48 2009/11/05 20:50:14 michele Exp $ */
+/* $OpenBSD: in6.h,v 1.49 2010/04/06 14:12:10 stsp Exp $ */
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
/*
@@ -784,6 +784,7 @@ int in6_addrscope(struct in6_addr *);
struct in6_ifaddr *in6_ifawithscope(struct ifnet *, struct in6_addr *);
struct in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *);
extern void in6_if_up(struct ifnet *);
+void in6_get_rand_ifid(struct ifnet *, struct in6_addr *);
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index c24a1bb9c0f..be61bddc831 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_ifattach.c,v 1.50 2010/02/08 12:04:35 jsing Exp $ */
+/* $OpenBSD: in6_ifattach.c,v 1.51 2010/04/06 14:12:10 stsp Exp $ */
/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
/*
@@ -58,11 +58,13 @@
#include <netinet6/ip6_mroute.h>
#endif
+#include <dev/rndvar.h>
+
unsigned long in6_maxmtu = 0;
int ip6_auto_linklocal = 1; /* enable by default */
-int get_rand_ifid(struct ifnet *, struct in6_addr *);
+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 in6_ifattach_loopback(struct ifnet *);
@@ -88,7 +90,7 @@ int in6_ifattach_loopback(struct ifnet *);
* in6 - upper 64bits are preserved
*/
int
-get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
+get_last_resort_ifid(struct ifnet *ifp, struct in6_addr *in6)
{
MD5_CTX ctxt;
u_int8_t digest[16];
@@ -119,6 +121,24 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
}
/*
+ * Generate a random interface identifier.
+ *
+ * in6 - upper 64bits are preserved
+ */
+void
+in6_get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
+{
+ arc4random_buf(&in6->s6_addr32[2], 8);
+
+ /* make sure to set "u" bit to local, and "g" bit to individual. */
+ in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
+ in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
+
+ /* convert EUI64 into IPv6 interface identifier */
+ EUI64_TO_IFID(in6);
+}
+
+/*
* Get interface identifier for the specified interface.
* XXX assumes single sockaddr_dl (AF_LINK address) per an interface
*
@@ -280,7 +300,7 @@ get_ifid(struct ifnet *ifp0, struct ifnet *altifp, struct in6_addr *in6)
}
/* last resort: get from random number source */
- if (get_rand_ifid(ifp, in6) == 0) {
+ if (get_last_resort_ifid(ifp, in6) == 0) {
nd6log((LOG_DEBUG,
"%s: interface identifier generated by random number\n",
ifp0->if_xname));
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index b55993a1d35..82df23171d4 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_var.h,v 1.30 2008/10/01 21:17:06 claudio Exp $ */
+/* $OpenBSD: in6_var.h,v 1.31 2010/04/06 14:12:10 stsp Exp $ */
/* $KAME: in6_var.h,v 1.55 2001/02/16 12:49:45 itojun Exp $ */
/*
@@ -438,6 +438,7 @@ struct in6_rrenumreq {
* (used only at first SIOC* call)
*/
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
+#define IN6_IFF_PRIVACY 0x80 /* RFC 4941 temporary address */
/* do not input/output */
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 45d45054784..6eed9551610 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.h,v 1.26 2008/06/11 06:30:36 mcbride Exp $ */
+/* $OpenBSD: nd6.h,v 1.27 2010/04/06 14:12:10 stsp Exp $ */
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
/*
@@ -222,6 +222,11 @@ struct in6_ndifreq {
#define ND6_INFINITE_LIFETIME 0xffffffff
+/* contants for RFC 4941 autoconf privacy extension */
+#define ND6_PRIV_MAX_DESYNC_FACTOR 600 /* 10 minutes */
+#define ND6_PRIV_VALID_LIFETIME 604800 /* 1 week */
+#define ND6_PRIV_PREFERRED_LIFETIME 86400 /* 1 day */
+
#ifdef _KERNEL
/* node constants */
#define MAX_REACHABLE_TIME 3600000 /* msec */
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index d706afa184c..c882331c078 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6_rtr.c,v 1.51 2010/02/08 11:56:09 jsing Exp $ */
+/* $OpenBSD: nd6_rtr.c,v 1.52 2010/04/06 14:12:10 stsp Exp $ */
/* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */
/*
@@ -57,6 +57,8 @@
#include <netinet6/nd6.h>
#include <netinet/icmp6.h>
+#include <dev/rndvar.h>
+
#define SDL(s) ((struct sockaddr_dl *)s)
int rtpref(struct nd_defrouter *);
@@ -1044,6 +1046,7 @@ prelist_update(struct nd_prefix *new, struct nd_defrouter *dr, struct mbuf *m)
struct nd_prefix *pr;
int s = splsoftnet();
int error = 0;
+ int tempaddr_preferred = 0;
int auth;
struct in6_addrlifetime lt6_tmp;
@@ -1210,6 +1213,18 @@ prelist_update(struct nd_prefix *new, struct nd_defrouter *dr, struct mbuf *m)
* with the Subject "StoredLifetime in RFC 2462".
*/
lt6_tmp = ifa6->ia6_lifetime;
+
+ /* RFC 4941 temporary addresses (privacy extension). */
+ if (ifa6->ia6_flags & IN6_IFF_PRIVACY) {
+ /* Do we still have a non-deprecated address? */
+ if ((ifa6->ia6_flags & IN6_IFF_DEPRECATED) == 0)
+ tempaddr_preferred = 1;
+ /* Don't extend lifetime for temporary addresses. */
+ if (new->ndpr_vltime >= lt6_tmp.ia6t_vltime)
+ continue;
+ if (new->ndpr_pltime >= lt6_tmp.ia6t_pltime)
+ continue;
+ }
if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
storedlifetime = ND6_INFINITE_LIFETIME;
else if (time_second - ifa6->ia6_updatetime >
@@ -1254,9 +1269,14 @@ prelist_update(struct nd_prefix *new, struct nd_defrouter *dr, struct mbuf *m)
ifa6->ia6_lifetime = lt6_tmp;
ifa6->ia6_updatetime = time_second;
}
- if (ia6_match == NULL && new->ndpr_vltime) {
+
+ if ((ia6_match == NULL ||
+ (((ia6_match->ia6_flags & IN6_IFF_PRIVACY) ||
+ (ifp->if_xflags & IFXF_INET6_PRIVACY)) && !tempaddr_preferred)) &&
+ new->ndpr_vltime) {
/*
- * No address matched and the valid lifetime is non-zero.
+ * No address matched, or there is no preferred RFC 4941
+ * temporary address. And the valid prefix lifetime is non-zero.
* Create a new address.
*/
if ((ia6 = in6_ifadd(new)) != NULL) {
@@ -1683,7 +1703,7 @@ in6_ifadd(struct nd_prefix *pr)
struct in6_aliasreq ifra;
struct in6_ifaddr *ia, *ib;
int error, s, plen0;
- struct in6_addr mask;
+ struct in6_addr mask, rand_ifid;
int prefixlen = pr->ndpr_plen;
in6_prefixlen2mask(&mask, prefixlen);
@@ -1750,14 +1770,29 @@ in6_ifadd(struct nd_prefix *pr)
ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
/* interface ID */
- ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
- (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
- ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
- (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
- ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
- (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
- ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
- (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
+ if (ifp->if_xflags & IFXF_INET6_PRIVACY) {
+ ifra.ifra_flags |= IN6_IFF_PRIVACY;
+ bcopy(&pr->ndpr_prefix.sin6_addr, &rand_ifid,
+ sizeof(rand_ifid));
+ in6_get_rand_ifid(ifp, &rand_ifid);
+ ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
+ (rand_ifid.s6_addr32[0] & ~mask.s6_addr32[0]);
+ ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
+ (rand_ifid.s6_addr32[1] & ~mask.s6_addr32[1]);
+ ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
+ (rand_ifid.s6_addr32[2] & ~mask.s6_addr32[2]);
+ ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
+ (rand_ifid.s6_addr32[3] & ~mask.s6_addr32[3]);
+ } else {
+ ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
+ (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
+ ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
+ (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
+ ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
+ (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
+ ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
+ (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
+ }
/* new prefix mask. */
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
@@ -1773,6 +1808,14 @@ in6_ifadd(struct nd_prefix *pr)
ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime;
ifra.ifra_lifetime.ia6t_pltime = pr->ndpr_pltime;
+ if (ifp->if_xflags & IFXF_INET6_PRIVACY) {
+ if (ifra.ifra_lifetime.ia6t_vltime > ND6_PRIV_VALID_LIFETIME)
+ ifra.ifra_lifetime.ia6t_vltime = ND6_PRIV_VALID_LIFETIME;
+ if (ifra.ifra_lifetime.ia6t_pltime > ND6_PRIV_PREFERRED_LIFETIME)
+ ifra.ifra_lifetime.ia6t_pltime = ND6_PRIV_PREFERRED_LIFETIME
+ - (arc4random() % ND6_PRIV_MAX_DESYNC_FACTOR);
+ }
+
/* XXX: scope zone ID? */
ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */