summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2016-01-09 16:34:37 +0000
committermelifaro <melifaro@FreeBSD.org>2016-01-09 16:34:37 +0000
commite4b451498bd9c31c5330b5eaae43284928764ed6 (patch)
tree579c8d1b294a8ca74c13716078c336d35c2125b0
parentb67974b0beac9df3e1c67251c921e86f82779f70 (diff)
downloadFreeBSD-src-e4b451498bd9c31c5330b5eaae43284928764ed6.zip
FreeBSD-src-e4b451498bd9c31c5330b5eaae43284928764ed6.tar.gz
Finish r275196: do not dereference rtentry in if_output() routines.
The only piece of information that is required is rt_flags subset. In particular, if_loop() requires RTF_REJECT and RTF_BLACKHOLE flags to check if this particular mbuf needs to be dropped (and what error should be returned). Note that if_loop() will always return EHOSTUNREACH for "reject" routes regardless of RTF_HOST flag existence. This is due to upcoming routing changes where RTF_HOST value won't be available as lookup result. All other functions require RTF_GATEWAY flag to check if they need to return EHOSTUNREACH instead of EHOSTDOWN error. There are 11 places where non-zero 'struct route' is passed to if_output(). For most of the callers (forwarding, bpf, arp) does not care about exact error value. In fact, the only place where this result is propagated is ip_output(). (ip6_output() passes NULL route to nd6_output_ifp()). Given that, add 3 new 'struct route' flags (RT_REJECT, RT_BLACKHOLE and RT_IS_GW) and inline function (rt_update_ro_flags()) to copy necessary rte flags to ro_flags. Call this function in ip_output() after looking up/ verifying rte. Reviewed by: ae
-rw-r--r--sys/net/if_arcsubr.c5
-rw-r--r--sys/net/if_ethersubr.c4
-rw-r--r--sys/net/if_fddisubr.c5
-rw-r--r--sys/net/if_fwsubr.c9
-rw-r--r--sys/net/if_iso88025subr.c8
-rw-r--r--sys/net/if_loop.c8
-rw-r--r--sys/net/route.h23
-rw-r--r--sys/netinet/ip_output.c1
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c8
9 files changed, 34 insertions, 37 deletions
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c
index 4944e97..16adba4 100644
--- a/sys/net/if_arcsubr.c
+++ b/sys/net/if_arcsubr.c
@@ -113,9 +113,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
error = 0;
#if defined(INET) || defined(INET6)
- if (ro != NULL && ro->ro_rt != NULL &&
- (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
- is_gw = 1;
+ if (ro != NULL)
+ is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#endif
switch (dst->sa_family) {
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 2b82ecc..2d652ad 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -202,7 +202,6 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
uint32_t *pflags)
{
struct ether_header *eh;
- struct rtentry *rt;
uint32_t lleflags = 0;
int error = 0;
#if defined(INET) || defined(INET6)
@@ -253,8 +252,7 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
}
if (error == EHOSTDOWN) {
- rt = (ro != NULL) ? ro->ro_rt : NULL;
- if (rt != NULL && (rt->rt_flags & RTF_GATEWAY) != 0)
+ if (ro != NULL && (ro->ro_flags & RT_HAS_GW) != 0)
error = EHOSTUNREACH;
}
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index 81b65a63..84ee669 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -119,9 +119,8 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
getmicrotime(&ifp->if_lastchange);
#if defined(INET) || defined(INET6)
- if (ro != NULL && ro->ro_rt != NULL &&
- (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
- is_gw = 1;
+ if (ro != NULL)
+ is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#endif
switch (dst->sa_family) {
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
index 626b1cb..a070f61 100644
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -106,9 +106,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
}
#if defined(INET) || defined(INET6)
- if (ro != NULL && ro->ro_rt != NULL &&
- (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
- is_gw = 1;
+ if (ro != NULL)
+ is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#endif
/*
* For unicast, we make a tag to store the lladdr of the
@@ -145,10 +144,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
* doesn't fit into the arp model.
*/
if (unicast) {
- is_gw = 0;
- if (ro != NULL && ro->ro_rt != NULL &&
- (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
- is_gw = 1;
error = arpresolve(ifp, is_gw, m, dst, (u_char *) destfw, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index 7192998..466784f 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -214,12 +214,8 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
struct rtentry *rt0 = NULL;
int is_gw = 0;
- if (ro != NULL) {
- rt0 = ro->ro_rt;
- if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
- is_gw = 1;
- }
-
+ if (ro != NULL)
+ is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error)
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index f4ac8b4..1291f7b 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -202,15 +202,12 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
struct route *ro)
{
u_int32_t af;
- struct rtentry *rt = NULL;
#ifdef MAC
int error;
#endif
M_ASSERTPKTHDR(m); /* check if we have the packet header */
- if (ro != NULL)
- rt = ro->ro_rt;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error) {
@@ -219,10 +216,9 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
}
#endif
- if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
+ if (ro != NULL && ro->ro_flags & (RT_REJECT|RT_BLACKHOLE)) {
m_freem(m);
- return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
- rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ return (ro->ro_flags & RT_BLACKHOLE ? 0 : EHOSTUNREACH);
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
diff --git a/sys/net/route.h b/sys/net/route.h
index 25d45f4..ae59efa 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -64,9 +64,13 @@ struct route {
#define RT_CACHING_CONTEXT 0x1 /* XXX: not used anywhere */
#define RT_NORTREF 0x2 /* doesn't hold reference on ro_rt */
-#define RT_L2_ME (1 << RT_L2_ME_BIT)
-#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT)
-#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT)
+#define RT_L2_ME (1 << RT_L2_ME_BIT) /* 0x0004 */
+#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT) /* 0x0008 */
+#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT) /* 0x0010 */
+
+#define RT_REJECT 0x0020 /* Destination is reject */
+#define RT_BLACKHOLE 0x0040 /* Destination is blackhole */
+#define RT_HAS_GW 0x0080 /* Destination has GW */
struct rt_metrics {
u_long rmx_locks; /* Kernel must leave these values alone */
@@ -215,6 +219,19 @@ fib_rte_to_nh_flags(int rt_flags)
return (res);
}
+/* rte<>ro_flags translation */
+static inline void
+rt_update_ro_flags(struct route *ro)
+{
+ int rt_flags = ro->ro_rt->rt_flags;
+
+ ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW);
+
+ ro->ro_flags = (rt_flags & RTF_REJECT) ? RT_REJECT : 0;
+ ro->ro_flags |= (rt_flags & RTF_BLACKHOLE) ? RT_BLACKHOLE : 0;
+ ro->ro_flags |= (rt_flags & RTF_GATEWAY) ? RT_HAS_GW : 0;
+}
+
/*
* Routing statistics.
*/
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 7ad43a2..fa225fc 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -376,6 +376,7 @@ again:
ia = ifatoia(rte->rt_ifa);
ifp = rte->rt_ifp;
counter_u64_add(rte->rt_pksent, 1);
+ rt_update_ro_flags(ro);
if (rte->rt_flags & RTF_GATEWAY)
gw = (struct sockaddr_in *)rte->rt_gateway;
if (rte->rt_flags & RTF_HOST)
diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e1f2dc0..6326bd2 100644
--- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1260,16 +1260,12 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
#if defined(INET) || defined(INET6)
struct llentry *lle = NULL;
#endif
- struct rtentry *rt0 = NULL;
struct ipoib_header *eh;
int error = 0, is_gw = 0;
short type;
- if (ro != NULL) {
- rt0 = ro->ro_rt;
- if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
- is_gw = 1;
- }
+ if (ro != NULL)
+ is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error)
OpenPOWER on IntegriCloud