Lines 306-312
Link Here
|
306 |
struct route_in6 ip6route; |
306 |
struct route_in6 ip6route; |
307 |
struct rtentry *rt = NULL; |
307 |
struct rtentry *rt = NULL; |
308 |
struct sockaddr_in6 *dst, src_sa, dst_sa; |
308 |
struct sockaddr_in6 *dst, src_sa, dst_sa; |
309 |
struct in6_addr odst; |
309 |
struct in6_addr osrc, odst; |
310 |
int error = 0; |
310 |
int error = 0; |
311 |
struct in6_ifaddr *ia = NULL; |
311 |
struct in6_ifaddr *ia = NULL; |
312 |
u_long mtu; |
312 |
u_long mtu; |
Lines 322-327
Link Here
|
322 |
uint32_t fibnum; |
322 |
uint32_t fibnum; |
323 |
struct m_tag *fwd_tag = NULL; |
323 |
struct m_tag *fwd_tag = NULL; |
324 |
uint32_t id; |
324 |
uint32_t id; |
|
|
325 |
bool badsrcscope = false, baddstscope = false; |
325 |
|
326 |
|
326 |
if (inp != NULL) { |
327 |
if (inp != NULL) { |
327 |
INP_LOCK_ASSERT(inp); |
328 |
INP_LOCK_ASSERT(inp); |
Lines 593-617
Link Here
|
593 |
|
594 |
|
594 |
src0 = ip6->ip6_src; |
595 |
src0 = ip6->ip6_src; |
595 |
if (in6_setscope(&src0, origifp, &zone)) |
596 |
if (in6_setscope(&src0, origifp, &zone)) |
596 |
goto badscope; |
597 |
badsrcscope = true; |
597 |
bzero(&src_sa, sizeof(src_sa)); |
598 |
bzero(&src_sa, sizeof(src_sa)); |
598 |
src_sa.sin6_family = AF_INET6; |
599 |
src_sa.sin6_family = AF_INET6; |
599 |
src_sa.sin6_len = sizeof(src_sa); |
600 |
src_sa.sin6_len = sizeof(src_sa); |
600 |
src_sa.sin6_addr = ip6->ip6_src; |
601 |
src_sa.sin6_addr = ip6->ip6_src; |
601 |
if (sa6_recoverscope(&src_sa) || zone != src_sa.sin6_scope_id) |
602 |
if (sa6_recoverscope(&src_sa) || zone != src_sa.sin6_scope_id) |
602 |
goto badscope; |
603 |
badsrcscope = true; |
603 |
|
604 |
|
604 |
dst0 = ip6->ip6_dst; |
605 |
dst0 = ip6->ip6_dst; |
605 |
if (in6_setscope(&dst0, origifp, &zone)) |
606 |
if (in6_setscope(&dst0, origifp, &zone)) |
606 |
goto badscope; |
607 |
baddstscope = true; |
607 |
/* re-initialize to be sure */ |
608 |
/* re-initialize to be sure */ |
608 |
bzero(&dst_sa, sizeof(dst_sa)); |
609 |
bzero(&dst_sa, sizeof(dst_sa)); |
609 |
dst_sa.sin6_family = AF_INET6; |
610 |
dst_sa.sin6_family = AF_INET6; |
610 |
dst_sa.sin6_len = sizeof(dst_sa); |
611 |
dst_sa.sin6_len = sizeof(dst_sa); |
611 |
dst_sa.sin6_addr = ip6->ip6_dst; |
612 |
dst_sa.sin6_addr = ip6->ip6_dst; |
612 |
if (sa6_recoverscope(&dst_sa) || zone != dst_sa.sin6_scope_id) { |
613 |
if (sa6_recoverscope(&dst_sa) || zone != dst_sa.sin6_scope_id) |
613 |
goto badscope; |
614 |
baddstscope = true; |
614 |
} |
|
|
615 |
|
615 |
|
616 |
/* We should use ia_ifp to support the case of |
616 |
/* We should use ia_ifp to support the case of |
617 |
* sending packets to an address of our own. |
617 |
* sending packets to an address of our own. |
Lines 619-635
Link Here
|
619 |
if (ia != NULL && ia->ia_ifp) |
619 |
if (ia != NULL && ia->ia_ifp) |
620 |
ifp = ia->ia_ifp; |
620 |
ifp = ia->ia_ifp; |
621 |
|
621 |
|
622 |
/* scope check is done. */ |
|
|
623 |
goto routefound; |
624 |
|
625 |
badscope: |
626 |
IP6STAT_INC(ip6s_badscope); |
627 |
in6_ifstat_inc(origifp, ifs6_out_discard); |
628 |
if (error == 0) |
629 |
error = EHOSTUNREACH; /* XXX */ |
630 |
goto bad; |
631 |
|
632 |
routefound: |
633 |
if (rt && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
622 |
if (rt && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
634 |
if (opt && opt->ip6po_nextroute.ro_rt) { |
623 |
if (opt && opt->ip6po_nextroute.ro_rt) { |
635 |
/* |
624 |
/* |
Lines 665-670
Link Here
|
665 |
* the address; protocols will filter it later, |
654 |
* the address; protocols will filter it later, |
666 |
* thus deferring a hash lookup and lock acquisition |
655 |
* thus deferring a hash lookup and lock acquisition |
667 |
* at the expense of an m_copym(). |
656 |
* at the expense of an m_copym(). |
|
|
657 |
* |
658 |
* Note: ip6_mloopback clears the embedded scope IDs on |
659 |
* both src and dst |
668 |
*/ |
660 |
*/ |
669 |
ip6_mloopback(ifp, m); |
661 |
ip6_mloopback(ifp, m); |
670 |
} else { |
662 |
} else { |
Lines 788-793
Link Here
|
788 |
if (!PFIL_HOOKED(&V_inet6_pfil_hook)) |
780 |
if (!PFIL_HOOKED(&V_inet6_pfil_hook)) |
789 |
goto passout; |
781 |
goto passout; |
790 |
|
782 |
|
|
|
783 |
osrc = ip6->ip6_src; |
791 |
odst = ip6->ip6_dst; |
784 |
odst = ip6->ip6_dst; |
792 |
/* Run through list of hooks for output packets. */ |
785 |
/* Run through list of hooks for output packets. */ |
793 |
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, ifp, PFIL_OUT, inp); |
786 |
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, ifp, PFIL_OUT, inp); |
Lines 796-801
Link Here
|
796 |
/* adjust pointer */ |
789 |
/* adjust pointer */ |
797 |
ip6 = mtod(m, struct ip6_hdr *); |
790 |
ip6 = mtod(m, struct ip6_hdr *); |
798 |
|
791 |
|
|
|
792 |
/* Repeat the scope check if pfil changed addresses */ |
793 |
if (!IN6_ARE_ADDR_EQUAL(&osrc, &ip6->ip6_src)) { |
794 |
badsrcscope = false; |
795 |
src0 = ip6->ip6_src; |
796 |
if (in6_setscope(&src0, origifp, &zone)) |
797 |
badsrcscope = true; |
798 |
bzero(&src_sa, sizeof(src_sa)); |
799 |
src_sa.sin6_family = AF_INET6; |
800 |
src_sa.sin6_len = sizeof(src_sa); |
801 |
src_sa.sin6_addr = ip6->ip6_src; |
802 |
if (sa6_recoverscope(&src_sa) || zone != src_sa.sin6_scope_id) |
803 |
badsrcscope = true; |
804 |
} |
805 |
if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) { |
806 |
baddstscope = false; |
807 |
dst0 = ip6->ip6_dst; |
808 |
if (in6_setscope(&dst0, origifp, &zone)) |
809 |
baddstscope = true; |
810 |
/* re-initialize to be sure */ |
811 |
bzero(&dst_sa, sizeof(dst_sa)); |
812 |
dst_sa.sin6_family = AF_INET6; |
813 |
dst_sa.sin6_len = sizeof(dst_sa); |
814 |
dst_sa.sin6_addr = ip6->ip6_dst; |
815 |
if (sa6_recoverscope(&dst_sa) || zone != dst_sa.sin6_scope_id) |
816 |
baddstscope = true; |
817 |
} |
818 |
if (!badsrcscope && !baddstscope) |
819 |
goto goodscope; |
820 |
|
821 |
IP6STAT_INC(ip6s_badscope); |
822 |
in6_ifstat_inc(origifp, ifs6_out_discard); |
823 |
if (error == 0) |
824 |
error = EHOSTUNREACH; /* XXX */ |
825 |
goto bad; |
826 |
|
827 |
goodscope: |
828 |
|
829 |
/* |
830 |
* clear embedded scope identifiers if necessary. |
831 |
* in6_clearscope will touch the addresses only when necessary. |
832 |
*/ |
833 |
in6_clearscope(&ip6->ip6_src); |
834 |
in6_clearscope(&ip6->ip6_dst); |
835 |
|
799 |
needfiblookup = 0; |
836 |
needfiblookup = 0; |
800 |
/* See if destination IP address was changed by packet filter. */ |
837 |
/* See if destination IP address was changed by packet filter. */ |
801 |
if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) { |
838 |
if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) { |