summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/scope6.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/scope6.c')
-rw-r--r--sys/netinet6/scope6.c78
1 files changed, 56 insertions, 22 deletions
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index fbb681a..39531d4 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -70,7 +70,7 @@ scope6_ifattach(ifp)
* XXX: IPV6_ADDR_SCOPE_xxx macros are not standard.
* Should we rather hardcode here?
*/
- sid->s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = ifp->if_index;
+ sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] = ifp->if_index;
sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index;
#ifdef MULTI_SCOPE
/* by default, we don't care about scope boundary for these scopes. */
@@ -117,6 +117,16 @@ scope6_set(ifp, idlist)
for (i = 0; i < 16; i++) {
if (idlist->s6id_list[i] &&
idlist->s6id_list[i] != sid->s6id_list[i]) {
+ /*
+ * An interface zone ID must be the corresponding
+ * interface index by definition.
+ */
+ if (i == IPV6_ADDR_SCOPE_INTFACELOCAL &&
+ idlist->s6id_list[i] != ifp->if_index) {
+ splx(s);
+ return (EINVAL);
+ }
+
if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
idlist->s6id_list[i] > if_index) {
/*
@@ -167,8 +177,8 @@ in6_addrscope(addr)
{
int scope;
- if (addr->s6_addr8[0] == 0xfe) {
- scope = addr->s6_addr8[1] & 0xc0;
+ if (addr->s6_addr[0] == 0xfe) {
+ scope = addr->s6_addr[1] & 0xc0;
switch (scope) {
case 0x80:
@@ -184,16 +194,16 @@ in6_addrscope(addr)
}
- if (addr->s6_addr8[0] == 0xff) {
- scope = addr->s6_addr8[1] & 0x0f;
+ if (addr->s6_addr[0] == 0xff) {
+ scope = addr->s6_addr[1] & 0x0f;
/*
* due to other scope such as reserved,
* return scope doesn't work.
*/
switch (scope) {
- case IPV6_ADDR_SCOPE_NODELOCAL:
- return IPV6_ADDR_SCOPE_NODELOCAL;
+ case IPV6_ADDR_SCOPE_INTFACELOCAL:
+ return IPV6_ADDR_SCOPE_INTFACELOCAL;
break;
case IPV6_ADDR_SCOPE_LINKLOCAL:
return IPV6_ADDR_SCOPE_LINKLOCAL;
@@ -207,22 +217,33 @@ in6_addrscope(addr)
}
}
+ /*
+ * Regard loopback and unspecified addresses as global, since
+ * they have no ambiguity.
+ */
if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
- if (addr->s6_addr8[15] == 1) /* loopback */
- return IPV6_ADDR_SCOPE_NODELOCAL;
- if (addr->s6_addr8[15] == 0) /* unspecified */
+ if (addr->s6_addr[15] == 1) /* loopback */
return IPV6_ADDR_SCOPE_LINKLOCAL;
+ if (addr->s6_addr[15] == 0) /* unspecified */
+ return IPV6_ADDR_SCOPE_GLOBAL; /* XXX: correct? */
}
return IPV6_ADDR_SCOPE_GLOBAL;
}
+/*
+ * When we introduce the "4+28" split semantics in sin6_scope_id,
+ * a 32bit integer is not enough to tell a large ID from an error (-1).
+ * So, we intentionally use a large type as the return value.
+ */
int
-in6_addr2scopeid(ifp, addr)
+in6_addr2zoneid(ifp, addr, ret_id)
struct ifnet *ifp; /* must not be NULL */
struct in6_addr *addr; /* must not be NULL */
+ u_int32_t *ret_id; /* must not be NULL */
{
int scope;
+ u_int32_t zoneid = 0;
struct scope6_id *sid = SID(ifp);
#ifdef DIAGNOSTIC
@@ -230,6 +251,10 @@ in6_addr2scopeid(ifp, addr)
panic("in6_addr2zoneid: scope array is NULL");
/* NOTREACHED */
}
+ if (ret_id == NULL) {
+ panic("in6_addr2zoneid: return ID is null");
+ /* NOTREACHED */
+ }
#endif
/*
@@ -239,28 +264,37 @@ in6_addr2scopeid(ifp, addr)
if (IN6_IS_ADDR_LOOPBACK(addr)) {
if (!(ifp->if_flags & IFF_LOOPBACK))
return (-1);
- else
- return (0); /* there's no ambiguity */
+ else {
+ *ret_id = 0; /* there's no ambiguity */
+ return (0);
+ }
}
scope = in6_addrscope(addr);
- switch(scope) {
- case IPV6_ADDR_SCOPE_NODELOCAL:
- return (-1); /* XXX: is this an appropriate value? */
+ switch (scope) {
+ case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
+ zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
+ break;
case IPV6_ADDR_SCOPE_LINKLOCAL:
- return (sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]);
+ zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
+ break;
case IPV6_ADDR_SCOPE_SITELOCAL:
- return (sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]);
+ zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
+ break;
case IPV6_ADDR_SCOPE_ORGLOCAL:
- return (sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]);
+ zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
+ break;
default:
- return (0); /* XXX: treat as global. */
+ zoneid = 0; /* XXX: treat as global. */
+ break;
}
+ *ret_id = zoneid;
+ return (0);
}
void
@@ -274,12 +308,12 @@ scope6_setdefault(ifp)
* "interface" and provide a user interface to set the default.
*/
if (ifp) {
- sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] =
+ sid_default.s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] =
ifp->if_index;
sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
ifp->if_index;
} else {
- sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = 0;
+ sid_default.s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] = 0;
sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
}
}
OpenPOWER on IntegriCloud