Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146520090
D18769.id52622.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D18769.id52622.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D18769: Fix broken IPv6 scope ID checks in outgoing direction
Attached
Detach File
Event Timeline
Log In to Comment