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:
parent
8ffdadcf4a
commit
9a4f9608ad
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121315
@ -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 {
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user