Page MenuHomeFreeBSD

D18769.id52622.diff
No OneTemporary

D18769.id52622.diff

Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -571,52 +571,79 @@
counter_u64_add(rt->rt_pksent, 1);
}
-
/*
- * The outgoing interface must be in the zone of source and
- * destination addresses.
+ * setup data structures for scope ID checks
*/
- origifp = ifp;
-
src0 = ip6->ip6_src;
- if (in6_setscope(&src0, origifp, &zone))
- goto badscope;
bzero(&src_sa, sizeof(src_sa));
src_sa.sin6_family = AF_INET6;
src_sa.sin6_len = sizeof(src_sa);
src_sa.sin6_addr = ip6->ip6_src;
- if (sa6_recoverscope(&src_sa) || zone != src_sa.sin6_scope_id)
- goto badscope;
dst0 = ip6->ip6_dst;
- if (in6_setscope(&dst0, origifp, &zone))
- goto badscope;
/* re-initialize to be sure */
bzero(&dst_sa, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
- if (sa6_recoverscope(&dst_sa) || zone != dst_sa.sin6_scope_id) {
- goto badscope;
- }
- /* We should use ia_ifp to support the case of
- * sending packets to an address of our own.
- */
- if (ia != NULL && ia->ia_ifp)
- ifp = ia->ia_ifp;
+ /* check for valid scope ID */
+ if (in6_setscope(&src0, ifp, &zone) == 0 &&
+ sa6_recoverscope(&src_sa) == 0 && zone == src_sa.sin6_scope_id &&
+ in6_setscope(&dst0, ifp, &zone) == 0 &&
+ sa6_recoverscope(&dst_sa) == 0 && zone == dst_sa.sin6_scope_id) {
+ /*
+ * The outgoing interface is in the zone of the source
+ * and destination addresses.
+ */
+ origifp = ifp;
+
+ /*
+ * We should use ia_ifp to support the case of sending
+ * packets to an address of our own.
+ */
+ if (ia != NULL && ia->ia_ifp)
+ ifp = ia->ia_ifp;
- /* scope check is done. */
- goto routefound;
+ } else if ((ifp->if_flags & IFF_LOOPBACK) &&
+ sa6_recoverscope(&src_sa) == 0 &&
+ sa6_recoverscope(&dst_sa) == 0 &&
+ dst_sa.sin6_scope_id != 0 &&
+ (src_sa.sin6_scope_id == 0 ||
+ src_sa.sin6_scope_id == dst_sa.sin6_scope_id) &&
+ (origifp = ifnet_byindex(dst_sa.sin6_scope_id)) != NULL) {
+ /*
+ * If the destination network interface is a loopback
+ * interface and the destination network address has a
+ * scope ID, the scope check above will fail, because
+ * the zone is lo0, while "sin6_scope_id" is a network
+ * interface.
+ *
+ * Because the default loopback network interface
+ * knows nothing about scope ID values, which are
+ * cleared by ip6_input(), the trick is to pretend the
+ * outgoing packet was received by the real network
+ * interface, by setting "origifp" different from
+ * "ifp". This is only allowed when "ifp" is a
+ * loopback network interface.
+ *
+ * The code below will recover the scope ID from the
+ * source and destination address and verify there is
+ * a valid destination scope ID. If there is a source
+ * scope ID, verify it belongs to the same scope as
+ * the destination address.
+ *
+ * If all the checks succeed use the network interface
+ * pointed to by the scope ID.
+ */
+ } else {
+ IP6STAT_INC(ip6s_badscope);
+ in6_ifstat_inc(ifp, ifs6_out_discard);
+ if (error == 0)
+ error = EHOSTUNREACH; /* XXX */
+ goto bad;
+ }
- badscope:
- IP6STAT_INC(ip6s_badscope);
- in6_ifstat_inc(origifp, ifs6_out_discard);
- if (error == 0)
- error = EHOSTUNREACH; /* XXX */
- goto bad;
-
- routefound:
if (rt && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
if (opt && opt->ip6po_nextroute.ro_rt) {
/*

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 4, 8:26 AM (2 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29234984
Default Alt Text
D18769.id52622.diff (3 KB)

Event Timeline