1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-10 14:02:43 +00:00

- change scope to zone.

- change node-local to interface-local.
- better error handling of address-to-scope mapping.
- use in6_clearscope().

Obtained from:	KAME
This commit is contained in:
Hajimu UMEMOTO 2003-10-21 20:05:32 +00:00
parent 8ffdadcf4a
commit 9a4f9608ad
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121315
14 changed files with 160 additions and 111 deletions

View File

@ -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 {

View File

@ -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));

View File

@ -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)

View File

@ -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))

View File

@ -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;
}

View File

@ -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));

View File

@ -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);

View File

@ -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;

View File

@ -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++;

View File

@ -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;

View File

@ -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. */

View File

@ -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);
}

View File

@ -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.

View File

@ -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;
}
}