Page MenuHomeFreeBSD

D23886.id69110.diff
No OneTemporary

D23886.id69110.diff

Index: head/sys/netinet6/ip6_output.c
===================================================================
--- head/sys/netinet6/ip6_output.c
+++ head/sys/netinet6/ip6_output.c
@@ -424,12 +424,12 @@
struct ifnet *ifp, *origifp;
struct mbuf *m = m0;
struct mbuf *mprev;
- int tlen, len;
- struct route_in6 ip6route;
- struct rtentry *rt = NULL;
- struct sockaddr_in6 *dst, src_sa, dst_sa;
+ struct route_in6 *ro_pmtu;
+ struct rtentry *rt;
+ struct sockaddr_in6 *dst, sin6, src_sa, dst_sa;
struct in6_addr odst;
u_char *nexthdrp;
+ int tlen, len;
int error = 0;
struct in6_ifaddr *ia = NULL;
u_long mtu;
@@ -438,7 +438,6 @@
struct ip6_exthdrs exthdrs;
struct in6_addr src0, dst0;
u_int32_t zone;
- struct route_in6 *ro_pmtu = NULL;
bool hdrsplit;
int sw_csum, tso;
int needfiblookup;
@@ -631,15 +630,15 @@
IP6STAT_INC(ip6s_localout);
/* Route packet. */
- if (ro == NULL) {
- ro = &ip6route;
- bzero((caddr_t)ro, sizeof(*ro));
- }
ro_pmtu = ro;
if (opt && opt->ip6po_rthdr)
ro = &opt->ip6po_route;
- dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ if (ro != NULL)
+ dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ else
+ dst = &sin6;
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
+
again:
/*
* If specified, try to fill in the traffic class field.
@@ -666,55 +665,127 @@
else
ip6->ip6_hlim = V_ip6_defmcasthlim;
}
+
+ if (ro == NULL || ro->ro_rt == NULL) {
+ bzero(dst, sizeof(*dst));
+ dst->sin6_family = AF_INET6;
+ dst->sin6_len = sizeof(*dst);
+ dst->sin6_addr = ip6->ip6_dst;
+ }
/*
- * Validate route against routing table additions;
- * a better/more specific route might have been added.
+ * Validate route against routing table changes.
* Make sure that the address family is set in route.
*/
- if (inp) {
- ro->ro_dst.sin6_family = AF_INET6;
- RT_VALIDATE((struct route *)ro, &inp->inp_rt_cookie, fibnum);
- }
- if (ro->ro_rt && fwd_tag == NULL && (ro->ro_rt->rt_flags & RTF_UP) &&
- ro->ro_dst.sin6_family == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) {
- rt = ro->ro_rt;
- ifp = ro->ro_rt->rt_ifp;
+ rt = NULL;
+ ifp = NULL;
+ mtu = 0;
+ if (ro != NULL) {
+ if (ro->ro_rt != NULL && inp != NULL) {
+ ro->ro_dst.sin6_family = AF_INET6; /* XXX KASSERT? */
+ RT_VALIDATE((struct route *)ro, &inp->inp_rt_cookie,
+ fibnum);
+ }
+ if (ro->ro_rt != NULL && fwd_tag == NULL &&
+ ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+ ro->ro_rt->rt_ifp == NULL ||
+ !RT_LINK_IS_UP(ro->ro_rt->rt_ifp) ||
+ ro->ro_dst.sin6_family != AF_INET6 ||
+ !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)))
+ RO_INVALIDATE_CACHE(ro);
+
+ if (ro->ro_rt != NULL && fwd_tag == NULL &&
+ (ro->ro_rt->rt_flags & RTF_UP) &&
+ ro->ro_dst.sin6_family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) {
+ rt = ro->ro_rt;
+ ifp = ro->ro_rt->rt_ifp;
+ } else {
+ if (ro->ro_lle)
+ LLE_FREE(ro->ro_lle); /* zeros ro_lle */
+ ro->ro_lle = NULL;
+ if (fwd_tag == NULL) {
+ 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;
+ }
+ error = in6_selectroute_fib(&dst_sa, opt, im6o, ro, &ifp,
+ &rt, fibnum);
+ if (error != 0) {
+ IP6STAT_INC(ip6s_noroute);
+ if (ifp != NULL)
+ in6_ifstat_inc(ifp, ifs6_out_discard);
+ goto bad;
+ }
+ if (ifp != NULL)
+ mtu = ifp->if_mtu;
+ }
+ if (rt == NULL) {
+ /*
+ * If in6_selectroute() does not return a route entry
+ * dst may not have been updated.
+ */
+ *dst = dst_sa; /* XXX */
+ } else {
+ if (rt->rt_flags & RTF_HOST)
+ mtu = rt->rt_mtu;
+ ia = (struct in6_ifaddr *)(rt->rt_ifa);
+ counter_u64_add(rt->rt_pksent, 1);
+ }
} else {
- if (ro->ro_lle)
- LLE_FREE(ro->ro_lle); /* zeros ro_lle */
- ro->ro_lle = NULL;
+ struct nhop6_extended nh6;
+ struct in6_addr kdst;
+ uint32_t scopeid;
+
if (fwd_tag == NULL) {
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;
}
- error = in6_selectroute_fib(&dst_sa, opt, im6o, ro, &ifp,
- &rt, fibnum);
+
+ if (IN6_IS_ADDR_MULTICAST(&dst_sa.sin6_addr) &&
+ im6o != NULL &&
+ (ifp = im6o->im6o_multicast_ifp) != NULL) {
+ /* We do not need a route lookup. */
+ *dst = dst_sa; /* XXX */
+ goto nonh6lookup;
+ }
+
+ in6_splitscope(&dst_sa.sin6_addr, &kdst, &scopeid);
+
+ if (IN6_IS_ADDR_MC_LINKLOCAL(&dst_sa.sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&dst_sa.sin6_addr)) {
+ if (scopeid > 0) {
+ ifp = in6_getlinkifnet(scopeid);
+ *dst = dst_sa; /* XXX */
+ goto nonh6lookup;
+ }
+ }
+
+ error = fib6_lookup_nh_ext(fibnum, &kdst, scopeid, NHR_REF, 0,
+ &nh6);
if (error != 0) {
- if (ifp != NULL)
- in6_ifstat_inc(ifp, ifs6_out_discard);
+ IP6STAT_INC(ip6s_noroute);
+ /* No ifp in6_ifstat_inc(ifp, ifs6_out_discard); */
+ error = EHOSTUNREACH;;
goto bad;
}
+
+ ifp = nh6.nh_ifp;
+ mtu = nh6.nh_mtu;
+ dst->sin6_addr = nh6.nh_addr;
+ ia = nh6.nh_ia;
+ fib6_free_nh_ext(fibnum, &nh6);
+nonh6lookup:
+ ;
}
- if (rt == NULL) {
- /*
- * If in6_selectroute() does not return a route entry
- * dst may not have been updated.
- */
- *dst = dst_sa; /* XXX */
- }
/* Then rt (for unicast) and ifp must be non-NULL valid values. */
if ((flags & IPV6_FORWARDING) == 0) {
/* XXX: the FORWARDING flag can be set for mrouting. */
in6_ifstat_inc(ifp, ifs6_out_request);
}
- if (rt != NULL) {
- ia = (struct in6_ifaddr *)(rt->rt_ifa);
- counter_u64_add(rt->rt_pksent, 1);
- }
/* Setup data structures for scope ID checks. */
src0 = ip6->ip6_src;
@@ -869,6 +940,9 @@
if ((error = ip6_getpmtu(ro_pmtu, ro != ro_pmtu, ifp, &ip6->ip6_dst,
&mtu, &alwaysfrag, fibnum, *nexthdrp)) != 0)
goto bad;
+ KASSERT(mtu > 0, ("%s:%d: mtu %ld, ro_pmtu %p ro %p ifp %p "
+ "alwaysfrag %d fibnum %u\n", __func__, __LINE__, mtu, ro_pmtu, ro,
+ ifp, alwaysfrag, fibnum));
/*
* The caller of this function may specify to use the minimum MTU
@@ -972,7 +1046,8 @@
error = netisr_queue(NETISR_IPV6, m);
goto done;
} else {
- RO_INVALIDATE_CACHE(ro);
+ if (ro != NULL)
+ RO_INVALIDATE_CACHE(ro);
needfiblookup = 1; /* Redo the routing table lookup. */
}
}
@@ -980,7 +1055,8 @@
if (fibnum != M_GETFIB(m)) {
m->m_flags |= M_SKIP_FIREWALL;
fibnum = M_GETFIB(m);
- RO_INVALIDATE_CACHE(ro);
+ if (ro != NULL)
+ RO_INVALIDATE_CACHE(ro);
needfiblookup = 1;
}
if (needfiblookup)
@@ -1005,7 +1081,10 @@
/* Or forward to some other address? */
if ((m->m_flags & M_IP6_NEXTHOP) &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
- dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ if (ro != NULL)
+ dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ else
+ dst = &sin6;
bcopy((fwd_tag+1), &dst_sa, sizeof(struct sockaddr_in6));
m->m_flags |= M_SKIP_FIREWALL;
m->m_flags &= ~M_IP6_NEXTHOP;
@@ -1188,8 +1267,6 @@
IP6STAT_INC(ip6s_fragmented);
done:
- if (ro == &ip6route)
- RO_RTFREE(ro);
return (error);
freehdrs:
@@ -1405,22 +1482,25 @@
struct nhop6_basic nh6;
struct in6_addr kdst;
uint32_t scopeid;
- struct sockaddr_in6 *sa6_dst;
+ struct sockaddr_in6 *sa6_dst, sin6;
u_long mtu;
mtu = 0;
- if (do_lookup) {
+ if (ro_pmtu == NULL || do_lookup) {
/*
* Here ro_pmtu has final destination address, while
* ro might represent immediate destination.
* Use ro_pmtu destination since mtu might differ.
*/
- sa6_dst = (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
- if (!IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))
- ro_pmtu->ro_mtu = 0;
+ if (ro_pmtu != NULL) {
+ sa6_dst = (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
+ if (!IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))
+ ro_pmtu->ro_mtu = 0;
+ } else
+ sa6_dst = &sin6;
- if (ro_pmtu->ro_mtu == 0) {
+ if (ro_pmtu == NULL || ro_pmtu->ro_mtu == 0) {
bzero(sa6_dst, sizeof(*sa6_dst));
sa6_dst->sin6_family = AF_INET6;
sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
@@ -1428,14 +1508,16 @@
in6_splitscope(dst, &kdst, &scopeid);
if (fib6_lookup_nh_basic(fibnum, &kdst, scopeid, 0, 0,
- &nh6) == 0)
- ro_pmtu->ro_mtu = nh6.nh_mtu;
- }
-
- mtu = ro_pmtu->ro_mtu;
+ &nh6) == 0) {
+ mtu = nh6.nh_mtu;
+ if (ro_pmtu != NULL)
+ ro_pmtu->ro_mtu = mtu;
+ }
+ } else
+ mtu = ro_pmtu->ro_mtu;
}
- if (ro_pmtu->ro_rt)
+ if (ro_pmtu != NULL && ro_pmtu->ro_rt != NULL)
mtu = ro_pmtu->ro_rt->rt_mtu;
return (ip6_calcmtu(ifp, dst, mtu, mtup, alwaysfragp, proto));

File Metadata

Mime Type
text/plain
Expires
Tue, Jun 23, 10:20 PM (13 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34260421
Default Alt Text
D23886.id69110.diff (8 KB)

Event Timeline