summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet6/ah_core.c6
-rw-r--r--sys/netinet6/icmp6.c63
-rw-r--r--sys/netinet6/in6.c20
-rw-r--r--sys/netinet6/in6.h11
-rw-r--r--sys/netinet6/in6_src.c19
-rw-r--r--sys/netinet6/in6_var.h2
-rw-r--r--sys/netinet6/ip6_forward.c6
-rw-r--r--sys/netinet6/ip6_input.c6
-rw-r--r--sys/netinet6/ip6_mroute.c33
-rw-r--r--sys/netinet6/ip6_output.c10
-rw-r--r--sys/netinet6/ipsec.c8
-rw-r--r--sys/netinet6/mld6.c2
-rw-r--r--sys/netinet6/nd6_nbr.c7
-rw-r--r--sys/netinet6/scope6.c78
14 files changed, 160 insertions, 111 deletions
diff --git a/sys/netinet6/ah_core.c b/sys/netinet6/ah_core.c
index 80270a0..4e7f594 100644
--- a/sys/netinet6/ah_core.c
+++ b/sys/netinet6/ah_core.c
@@ -1472,10 +1472,8 @@ ah6_calccksum(m, ahdat, len, algo, sav)
ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
ip6copy.ip6_vfc |= IPV6_VERSION;
ip6copy.ip6_hlim = 0;
- if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src))
- ip6copy.ip6_src.s6_addr16[1] = 0x0000;
- if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst))
- ip6copy.ip6_dst.s6_addr16[1] = 0x0000;
+ in6_clearscope(&ip6copy.ip6_src); /* XXX */
+ in6_clearscope(&ip6copy.ip6_dst); /* XXX */
(algo->update)(&algos, (u_int8_t *)&ip6copy,
sizeof(struct ip6_hdr));
} else {
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 642b7bd..389d7a2 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -358,10 +358,8 @@ icmp6_error(m, type, code, param)
nip6->ip6_src = oip6->ip6_src;
nip6->ip6_dst = oip6->ip6_dst;
- if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
- oip6->ip6_src.s6_addr16[1] = 0;
- if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
- oip6->ip6_dst.s6_addr16[1] = 0;
+ in6_clearscope(&oip6->ip6_src);
+ in6_clearscope(&oip6->ip6_dst);
icmp6 = (struct icmp6_hdr *)(nip6 + 1);
icmp6->icmp6_type = type;
@@ -1061,8 +1059,9 @@ icmp6_notify_error(m, off, icmp6len, code)
icmp6dst.sin6_addr = eip6->ip6_dst;
else
icmp6dst.sin6_addr = *finaldst;
- icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
- &icmp6dst.sin6_addr);
+ if (in6_addr2zoneid(m->m_pkthdr.rcvif, &icmp6dst.sin6_addr,
+ &icmp6dst.sin6_scope_id))
+ goto freeit;
if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst,
NULL, NULL)) {
/* should be impossbile */
@@ -1079,8 +1078,10 @@ icmp6_notify_error(m, off, icmp6len, code)
icmp6src.sin6_len = sizeof(struct sockaddr_in6);
icmp6src.sin6_family = AF_INET6;
icmp6src.sin6_addr = eip6->ip6_src;
- icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
- &icmp6src.sin6_addr);
+ if (in6_addr2zoneid(m->m_pkthdr.rcvif, &icmp6src.sin6_addr,
+ &icmp6src.sin6_scope_id)) {
+ goto freeit;
+ }
if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src,
NULL, NULL)) {
/* should be impossbile */
@@ -1284,15 +1285,19 @@ ni6_input(m, off)
/* m_pulldown instead of copy? */
m_copydata(m, off + sizeof(struct icmp6_nodeinfo),
subjlen, (caddr_t)&sin6.sin6_addr);
- sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
- &sin6.sin6_addr);
+ if (in6_addr2zoneid(m->m_pkthdr.rcvif,
+ &sin6.sin6_addr, &sin6.sin6_scope_id)) {
+ goto bad;
+ }
in6_embedscope(&sin6.sin6_addr, &sin6, NULL, NULL);
bzero(&sin6_d, sizeof(sin6_d));
sin6_d.sin6_family = AF_INET6; /* not used, actually */
sin6_d.sin6_len = sizeof(sin6_d); /* ditto */
sin6_d.sin6_addr = ip6->ip6_dst;
- sin6_d.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
- &ip6->ip6_dst);
+ if (in6_addr2zoneid(m->m_pkthdr.rcvif,
+ &ip6->ip6_dst, &sin6_d.sin6_scope_id)) {
+ goto bad;
+ }
in6_embedscope(&sin6_d.sin6_addr, &sin6_d, NULL, NULL);
subj = (char *)&sin6;
if (SA6_ARE_ADDR_EQUAL(&sin6, &sin6_d))
@@ -1863,9 +1868,7 @@ ni6_store_addrs(ni6, nni6, ifp0, resid)
/* copy the address itself */
bcopy(&ifa6->ia_addr.sin6_addr, cp,
sizeof(struct in6_addr));
- /* XXX: KAME link-local hack; remove ifindex */
- if (IN6_IS_ADDR_LINKLOCAL(&ifa6->ia_addr.sin6_addr))
- ((struct in6_addr *)cp)->s6_addr16[1] = 0;
+ in6_clearscope((struct in6_addr *)cp); /* XXX */
cp += sizeof(struct in6_addr);
resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
@@ -1899,7 +1902,7 @@ icmp6_rip6_input(mp, off)
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct in6pcb *in6p;
struct in6pcb *last = NULL;
- struct sockaddr_in6 rip6src;
+ struct sockaddr_in6 fromsa;
struct icmp6_hdr *icmp6;
struct mbuf *opts = NULL;
@@ -1914,11 +1917,11 @@ icmp6_rip6_input(mp, off)
}
#endif
- bzero(&rip6src, sizeof(rip6src));
- rip6src.sin6_len = sizeof(struct sockaddr_in6);
- rip6src.sin6_family = AF_INET6;
+ bzero(&fromsa, sizeof(fromsa));
+ fromsa.sin6_len = sizeof(struct sockaddr_in6);
+ fromsa.sin6_family = AF_INET6;
/* KAME hack: recover scopeid */
- (void)in6_recoverscope(&rip6src, &ip6->ip6_src, m->m_pkthdr.rcvif);
+ (void)in6_recoverscope(&fromsa, &ip6->ip6_src, m->m_pkthdr.rcvif);
LIST_FOREACH(in6p, &ripcb, inp_list) {
if ((in6p->inp_vflag & INP_IPV6) == 0)
@@ -1947,7 +1950,7 @@ icmp6_rip6_input(mp, off)
/* strip intermediate headers */
m_adj(n, off);
if (sbappendaddr(&last->in6p_socket->so_rcv,
- (struct sockaddr *)&rip6src, n, opts)
+ (struct sockaddr *)&fromsa, n, opts)
== 0) {
/* should notify about lost packet */
m_freem(n);
@@ -1967,7 +1970,7 @@ icmp6_rip6_input(mp, off)
/* strip intermediate headers */
m_adj(m, off);
if (sbappendaddr(&last->in6p_socket->so_rcv,
- (struct sockaddr *)&rip6src, m, opts) == 0) {
+ (struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
@@ -2447,7 +2450,8 @@ icmp6_redirect_output(m0, rt)
src_sa.sin6_len = sizeof(src_sa);
src_sa.sin6_addr = sip6->ip6_src;
/* we don't currently use sin6_scope_id, but eventually use it */
- src_sa.sin6_scope_id = in6_addr2scopeid(ifp, &sip6->ip6_src);
+ if (in6_addr2zoneid(ifp, &sip6->ip6_src, &src_sa.sin6_scope_id))
+ goto fail;
if (nd6_is_addr_neighbor(&src_sa, ifp) == 0)
goto fail;
if (IN6_IS_ADDR_MULTICAST(&sip6->ip6_dst))
@@ -2664,14 +2668,11 @@ noredhdropt:;
m0 = NULL;
}
- if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_src))
- sip6->ip6_src.s6_addr16[1] = 0;
- if (IN6_IS_ADDR_LINKLOCAL(&sip6->ip6_dst))
- sip6->ip6_dst.s6_addr16[1] = 0;
- if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_target))
- nd_rd->nd_rd_target.s6_addr16[1] = 0;
- if (IN6_IS_ADDR_LINKLOCAL(&nd_rd->nd_rd_dst))
- nd_rd->nd_rd_dst.s6_addr16[1] = 0;
+ /* XXX: clear embedded link IDs in the inner header */
+ in6_clearscope(&sip6->ip6_src);
+ in6_clearscope(&sip6->ip6_dst);
+ in6_clearscope(&nd_rd->nd_rd_target);
+ in6_clearscope(&nd_rd->nd_rd_dst);
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 83b5913..10f7473 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -786,7 +786,8 @@ in6_update_ifa(ifp, ifra, ia)
if ((error = in6_recoverscope(&dst6,
&ifra->ifra_dstaddr.sin6_addr, ifp)) != 0)
return (error);
- scopeid = in6_addr2scopeid(ifp, &dst6.sin6_addr);
+ if (in6_addr2zoneid(ifp, &dst6.sin6_addr, &scopeid))
+ return (EINVAL);
if (dst6.sin6_scope_id == 0) /* user omit to specify the ID. */
dst6.sin6_scope_id = scopeid;
else if (dst6.sin6_scope_id != scopeid)
@@ -1426,8 +1427,9 @@ in6_lifaddr_ioctl(so, cmd, data, ifp, td)
s6 = (struct sockaddr_in6 *)&iflr->addr;
if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {
s6->sin6_addr.s6_addr16[1] = 0;
- s6->sin6_scope_id =
- in6_addr2scopeid(ifp, &s6->sin6_addr);
+ if (in6_addr2zoneid(ifp, &s6->sin6_addr,
+ &s6->sin6_scope_id))
+ return (EINVAL);/* XXX */
}
if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
@@ -1435,9 +1437,9 @@ in6_lifaddr_ioctl(so, cmd, data, ifp, td)
s6 = (struct sockaddr_in6 *)&iflr->dstaddr;
if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) {
s6->sin6_addr.s6_addr16[1] = 0;
- s6->sin6_scope_id =
- in6_addr2scopeid(ifp,
- &s6->sin6_addr);
+ if (in6_addr2zoneid(ifp,
+ &s6->sin6_addr, &s6->sin6_scope_id))
+ return (EINVAL); /* EINVAL */
}
} else
bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
@@ -1865,11 +1867,15 @@ in6_ifawithscope(oifp, dst)
struct ifaddr *ifa;
struct ifnet *ifp;
struct in6_ifaddr *ifa_best = NULL;
+ u_int32_t dstzone, odstzone;
if (oifp == NULL) {
return (NULL);
}
+ if (in6_addr2zoneid(oifp, dst, &odstzone))
+ return (NULL);
+
/*
* We search for all addresses on all interfaces from the beginning.
* Comparing an interface with the outgoing interface will be done
@@ -1882,7 +1888,7 @@ in6_ifawithscope(oifp, dst)
* We can never take an address that breaks the scope zone
* of the destination.
*/
- if (in6_addr2scopeid(ifp, dst) != in6_addr2scopeid(oifp, dst))
+ if (in6_addr2zoneid(ifp, dst, &dstzone) || dstzone != odstzone)
continue;
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index dbaf4ba..e31e45a 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -218,15 +218,15 @@ extern const struct in6_addr in6mask128;
#define IN6ADDR_NODELOCAL_ALLNODES_INIT \
{{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_INTFACELOCAL_ALLNODES_INIT \
+ {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
-#define IN6ADDR_LINKLOCAL_ALLMDNS_INIT \
- {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }}}
#endif
extern const struct in6_addr in6addr_any;
@@ -303,12 +303,14 @@ extern const struct in6_addr in6addr_linklocal_allrouters;
#ifdef _KERNEL /* XXX nonstandard */
#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
+#define IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
#else
#define __IPV6_ADDR_SCOPE_NODELOCAL 0x01
+#define __IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
#define __IPV6_ADDR_SCOPE_LINKLOCAL 0x02
#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05
#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
@@ -342,6 +344,9 @@ extern const struct in6_addr in6addr_linklocal_allrouters;
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL))
+#define IN6_IS_ADDR_MC_INTFACELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) && \
+ (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_INTFACELOCAL))
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL))
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 6f81fe7..aa520b6 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -190,7 +190,7 @@ in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
if (IN6_IS_ADDR_MULTICAST(dst)) {
struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
- if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
+ if (ifp == NULL && IN6_IS_ADDR_MC_INTFACELOCAL(dst)) {
ifp = &loif[0];
}
@@ -498,7 +498,7 @@ in6_recoverscope(sin6, in6, ifp)
const struct in6_addr *in6;
struct ifnet *ifp;
{
- u_int32_t scopeid;
+ u_int32_t zoneid;
sin6->sin6_addr = *in6;
@@ -508,19 +508,19 @@ in6_recoverscope(sin6, in6, ifp)
*/
sin6->sin6_scope_id = 0;
- if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
+ if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
/*
* KAME assumption: link id == interface id
*/
- scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]);
- if (scopeid) {
+ zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
+ if (zoneid) {
/* sanity check */
- if (scopeid < 0 || if_index < scopeid)
+ if (zoneid < 0 || if_index < zoneid)
return ENXIO;
- if (ifp && ifp->if_index != scopeid)
+ if (ifp && ifp->if_index != zoneid)
return ENXIO;
sin6->sin6_addr.s6_addr16[1] = 0;
- sin6->sin6_scope_id = scopeid;
+ sin6->sin6_scope_id = zoneid;
}
}
@@ -529,12 +529,11 @@ in6_recoverscope(sin6, in6, ifp)
/*
* just clear the embedded scope identifier.
- * XXX: currently used for bsdi4 only as a supplement function.
*/
void
in6_clearscope(addr)
struct in6_addr *addr;
{
- if (IN6_IS_SCOPE_LINKLOCAL(addr))
+ if (IN6_IS_SCOPE_LINKLOCAL(addr) || IN6_IS_ADDR_MC_INTFACELOCAL(addr))
addr->s6_addr16[1] = 0;
}
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index b11b72c..5a520fa 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -584,7 +584,7 @@ void in6_purgemkludge __P((struct ifnet *));
struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int));
struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, struct in6_addr *));
char *ip6_sprintf __P((const struct in6_addr *));
-int in6_addr2scopeid __P((struct ifnet *, struct in6_addr *));
+int in6_addr2zoneid __P((struct ifnet *, struct in6_addr *, u_int32_t *));
int in6_matchlen __P((struct in6_addr *, struct in6_addr *));
int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int));
void in6_prefixlen2mask __P((struct in6_addr *, int));
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 3cc812e..7e847e9 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -114,6 +114,7 @@ ip6_forward(m, srcrt)
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
+ u_int32_t srczone, dstzone;
#ifdef IPSEC
struct secpolicy *sp = NULL;
#endif
@@ -360,8 +361,9 @@ ip6_forward(m, srcrt)
* unreachable error with Code 2 (beyond scope of source address).
* [draft-ietf-ipngwg-icmp-v3-02.txt, Section 3.1]
*/
- if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=
- in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) {
+ if (in6_addr2zoneid(m->m_pkthdr.rcvif, &ip6->ip6_src, &srczone) ||
+ in6_addr2zoneid(rt->rt_ifp, &ip6->ip6_src, &dstzone) ||
+ srczone != dstzone) {
ip6stat.ip6s_cantforward++;
ip6stat.ip6s_badscope++;
in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 8062ffe..54f252d 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -433,7 +433,8 @@ ip6_input(m)
ip6stat.ip6s_badscope++;
goto bad;
}
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
+ if ((IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
+ IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) &&
ip6->ip6_dst.s6_addr16[1]) {
ip6stat.ip6s_badscope++;
goto bad;
@@ -1106,8 +1107,7 @@ ip6_savecontrol(in6p, mp, ip6, m)
struct in6_pktinfo pi6;
bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
- if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
- pi6.ipi6_addr.s6_addr16[1] = 0;
+ in6_clearscope(&pi6.ipi6_addr); /* XXX */
pi6.ipi6_ifindex =
(m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index 607a2ea..a7a4884 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -971,7 +971,7 @@ ip6_mforward(ip6, ifp, m)
* Don't forward a packet with Hop limit of zero or one,
* or a packet destined to a local-only group.
*/
- if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_NODELOCAL(&ip6->ip6_dst) ||
+ if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
return (0);
ip6->ip6_hlim--;
@@ -1414,6 +1414,8 @@ ip6_mdq(m, ifp, rt)
* members downstream on the interface.
*/
for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
+ u_int32_t dscopein, sscopein, dscopeout, sscopeout;
+
if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
/*
* check if the outgoing packet is going to break
@@ -1421,17 +1423,24 @@ ip6_mdq(m, ifp, rt)
* XXX For packets through PIM register tunnel
* interface, we believe a routing daemon.
*/
- if ((mif6table[rt->mf6c_parent].m6_flags &
- MIFF_REGISTER) == 0 &&
- (mif6table[mifi].m6_flags & MIFF_REGISTER) == 0 &&
- (in6_addr2scopeid(ifp, &ip6->ip6_dst) !=
- in6_addr2scopeid(mif6table[mifi].m6_ifp,
- &ip6->ip6_dst) ||
- in6_addr2scopeid(ifp, &ip6->ip6_src) !=
- in6_addr2scopeid(mif6table[mifi].m6_ifp,
- &ip6->ip6_src))) {
- ip6stat.ip6s_badscope++;
- continue;
+ if (!(mif6table[rt->mf6c_parent].m6_flags &
+ MIFF_REGISTER) &&
+ !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
+ if (in6_addr2zoneid(mif6table[mifi].m6_ifp,
+ &ip6->ip6_dst,
+ &dscopeout) ||
+ in6_addr2zoneid(mif6table[mifi].m6_ifp,
+ &ip6->ip6_src,
+ &sscopeout) ||
+ in6_addr2zoneid(ifp, &ip6->ip6_dst,
+ &dscopein) ||
+ in6_addr2zoneid(ifp, &ip6->ip6_src,
+ &sscopein) ||
+ dscopein != dscopeout ||
+ sscopein != sscopeout) {
+ ip6stat.ip6s_badscope++;
+ continue;
+ }
}
mifp->m6_pkt_out++;
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 12dd282..51f5b7a 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -666,7 +666,7 @@ skip_ipsec2:;
* If the destination is a node-local scope multicast,
* the packet should be loop-backed only.
*/
- if (IN6_IS_ADDR_MC_NODELOCAL(&ip6->ip6_dst)) {
+ if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) {
/*
* If the outgoing interface is already specified,
* it should be a loopback interface.
@@ -1310,9 +1310,9 @@ ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup)
* route to match the interface MTU (as long as the
* field isn't locked).
*/
- mtu = ifmtu;
- if (!(ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU))
- ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu;
+ mtu = ifmtu;
+ if (!(ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU))
+ ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu;
}
} else if (ifp) {
mtu = IN6_LINKMTU(ifp);
@@ -2081,7 +2081,7 @@ ip6_setmoptions(optname, im6op, m)
* address, and choose the outgoing interface.
* XXX: is it a good approach?
*/
- if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
+ if (IN6_IS_ADDR_MC_INTFACELOCAL(&mreq->ipv6mr_multiaddr)) {
ifp = &loif[0];
} else {
ro.ro_rt = NULL;
diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c
index cdb4aa1..fbff11c 100644
--- a/sys/netinet6/ipsec.c
+++ b/sys/netinet6/ipsec.c
@@ -2134,11 +2134,9 @@ ipsec6_encapsulate(m, sav)
ip6 = mtod(m, struct ip6_hdr *);
ovbcopy((caddr_t)ip6, (caddr_t)oip6, sizeof(struct ip6_hdr));
- /* Fake link-local scope-class addresses */
- if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_src))
- oip6->ip6_src.s6_addr16[1] = 0;
- if (IN6_IS_SCOPE_LINKLOCAL(&oip6->ip6_dst))
- oip6->ip6_dst.s6_addr16[1] = 0;
+ /* XXX: Fake scoped addresses */
+ in6_clearscope(&oip6->ip6_src);
+ in6_clearscope(&oip6->ip6_dst);
/* construct new IPv6 header. see RFC 2401 5.1.2.2 */
/* ECN consideration. */
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 5f20cc5..15df24d 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -173,7 +173,7 @@ mld6_stop_listening(in6m)
if (in6m->in6m_state == MLD6_IREPORTEDLAST &&
(!IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal)) &&
- IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > IPV6_ADDR_SCOPE_NODELOCAL)
+ IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > IPV6_ADDR_SCOPE_INTFACELOCAL)
mld6_sendpkt(in6m, MLD_LISTENER_DONE,
&mld6_all_routers_linklocal);
}
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 0cac161..9598228 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -451,9 +451,7 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
nd_ns->nd_ns_code = 0;
nd_ns->nd_ns_reserved = 0;
nd_ns->nd_ns_target = *taddr6;
-
- if (IN6_IS_SCOPE_LINKLOCAL(&nd_ns->nd_ns_target))
- nd_ns->nd_ns_target.s6_addr16[1] = 0;
+ in6_clearscope(&nd_ns->nd_ns_target); /* XXX */
/*
* Add source link-layer address option.
@@ -882,8 +880,7 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
nd_na->nd_na_code = 0;
nd_na->nd_na_target = *taddr6;
- if (IN6_IS_SCOPE_LINKLOCAL(&nd_na->nd_na_target))
- nd_na->nd_na_target.s6_addr16[1] = 0;
+ in6_clearscope(&nd_na->nd_na_target); /* XXX */
/*
* "tlladdr" indicates NS's condition for adding tlladdr or not.
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