diff options
author | ume <ume@FreeBSD.org> | 2003-10-21 20:05:32 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2003-10-21 20:05:32 +0000 |
commit | 5199c863f8f9e7f134710595dee582ad037bffb6 (patch) | |
tree | 56bbb38b63af457fee9d7a7dcb4dabbee7fdf438 /sys/netinet6 | |
parent | cf8253f2389748ecf024ef70a17807c7d6d733ee (diff) | |
download | FreeBSD-src-5199c863f8f9e7f134710595dee582ad037bffb6.zip FreeBSD-src-5199c863f8f9e7f134710595dee582ad037bffb6.tar.gz |
- change scope to zone.
- change node-local to interface-local.
- better error handling of address-to-scope mapping.
- use in6_clearscope().
Obtained from: KAME
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/ah_core.c | 6 | ||||
-rw-r--r-- | sys/netinet6/icmp6.c | 63 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 20 | ||||
-rw-r--r-- | sys/netinet6/in6.h | 11 | ||||
-rw-r--r-- | sys/netinet6/in6_src.c | 19 | ||||
-rw-r--r-- | sys/netinet6/in6_var.h | 2 | ||||
-rw-r--r-- | sys/netinet6/ip6_forward.c | 6 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 6 | ||||
-rw-r--r-- | sys/netinet6/ip6_mroute.c | 33 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 10 | ||||
-rw-r--r-- | sys/netinet6/ipsec.c | 8 | ||||
-rw-r--r-- | sys/netinet6/mld6.c | 2 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 7 | ||||
-rw-r--r-- | sys/netinet6/scope6.c | 78 |
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; } } |