lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Fri, 27 Jul 2012 21:18:27 -0700 (PDT)
From:	David Miller <davem@...emloft.net>
To:	alexander.duyck@...il.com
Cc:	eric.dumazet@...il.com, netdev@...r.kernel.org
Subject: [PATCH 3/7] ipv4: Store route type in fib_info.


This removes another value recorded in the fib_result return struct.

Signed-off-by: David S. Miller <davem@...emloft.net>
---
 include/net/ip_fib.h     |    3 ++-
 net/ipv4/devinet.c       |    2 +-
 net/ipv4/fib_frontend.c  |   10 +++++-----
 net/ipv4/fib_lookup.h    |    6 ++----
 net/ipv4/fib_semantics.c |   17 ++++++++++-------
 net/ipv4/fib_trie.c      |   20 ++++++++------------
 net/ipv4/route.c         |   36 ++++++++++++++++++++----------------
 7 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 847a46b..3cb9e45 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -100,6 +100,7 @@ struct fib_info {
 	unsigned char		fib_dead;
 	unsigned char		fib_protocol;
 	unsigned char		fib_scope;
+	unsigned char		fib_type;
 	__be32			fib_prefsrc;
 	u32			fib_priority;
 	u32			*fib_metrics;
@@ -125,8 +126,8 @@ struct fib_table;
 struct fib_result {
 	unsigned char		prefixlen;
 	unsigned char		__pad;
-	unsigned char		type;
 	unsigned char		__pad2;
+	unsigned char		__pad3;
 	u32			tclassid;
 	struct fib_nh		*nh;
 	struct fib_table	*table;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 1baaa53..1595a67d 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -163,7 +163,7 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
 		local = fib_get_table(net, RT_TABLE_LOCAL);
 		if (local &&
 		    !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) &&
-		    res.type == RTN_LOCAL)
+		    res.nh->nh_parent->fib_type == RTN_LOCAL)
 			result = res.nh->nh_dev;
 	}
 	if (result && devref)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index e02390d..495b540 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -175,7 +175,7 @@ static inline unsigned int __inet_dev_addr_type(struct net *net,
 		rcu_read_lock();
 		if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
 			if (!dev || dev == res.nh->nh_dev)
-				ret = res.type;
+				ret = res.nh->nh_parent->fib_type;
 		}
 		rcu_read_unlock();
 	}
@@ -267,8 +267,8 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 	net = dev_net(dev);
 	if (fib_lookup(net, &fl4, &res))
 		goto last_resort;
-	if (res.type != RTN_UNICAST) {
-		if (res.type != RTN_LOCAL || !accept_local)
+	if (res.nh->nh_parent->fib_type != RTN_UNICAST) {
+		if (res.nh->nh_parent->fib_type != RTN_LOCAL || !accept_local)
 			goto e_inval;
 	}
 	fib_combine_itag(itag, &res);
@@ -295,7 +295,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 
 	ret = 0;
 	if (fib_lookup(net, &fl4, &res) == 0) {
-		if (res.type == RTN_UNICAST)
+		if (res.nh->nh_parent->fib_type == RTN_UNICAST)
 			ret = res.nh->nh_scope >= RT_SCOPE_HOST;
 	}
 	return ret;
@@ -945,7 +945,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 
 			frn->prefixlen = res.prefixlen;
 			frn->nh_sel = nhsel;
-			frn->type = res.type;
+			frn->type = fi->fib_type;
 			frn->scope = fi->fib_scope;
 		}
 		rcu_read_unlock();
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index 5f110b6..3dd6b49 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -9,7 +9,6 @@ struct fib_alias {
 	struct list_head	fa_list;
 	struct fib_info		*fa_info;
 	u8			fa_tos;
-	u8			fa_type;
 	u8			fa_state;
 	struct rcu_head		rcu;
 };
@@ -28,9 +27,8 @@ extern void fib_release_info(struct fib_info *);
 extern struct fib_info *fib_create_info(struct fib_config *cfg);
 extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			 u32 tb_id, u8 type, __be32 dst,
-			 int dst_len, u8 tos, struct fib_info *fi,
-			 unsigned int);
+			 u32 tb_id, __be32 dst, int dst_len, u8 tos,
+			 struct fib_info *fi, unsigned int);
 extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 		      int dst_len, u32 tb_id, struct nl_info *info,
 		      unsigned int nlm_flags);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 6f73403..13b801a 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -252,7 +252,8 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
 	unsigned int mask = (fib_info_hash_size - 1);
 	unsigned int val = fi->fib_nhs;
 
-	val ^= (fi->fib_protocol << 8) | fi->fib_scope;
+	val ^= ((fi->fib_protocol << 16) | (fi->fib_scope << 8) |
+		fi->fib_type);
 	val ^= (__force u32)fi->fib_prefsrc;
 	val ^= fi->fib_priority;
 	for_nexthops(fi) {
@@ -279,6 +280,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
 			continue;
 		if (nfi->fib_protocol == fi->fib_protocol &&
 		    nfi->fib_scope == fi->fib_scope &&
+		    nfi->fib_type == fi->fib_type &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
 		    nfi->fib_priority == fi->fib_priority &&
 		    memcmp(nfi->fib_metrics, fi->fib_metrics,
@@ -359,8 +361,7 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 		goto errout;
 
 	err = fib_dump_info(skb, info->pid, seq, event, tb_id,
-			    fa->fa_type, key, dst_len,
-			    fa->fa_tos, fa->fa_info, nlm_flags);
+			    key, dst_len, fa->fa_tos, fa->fa_info, nlm_flags);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in fib_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
@@ -610,7 +611,8 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 			}
 		}
 		err = -EINVAL;
-		if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+		if (res.nh->nh_parent->fib_type != RTN_UNICAST &&
+		    res.nh->nh_parent->fib_type != RTN_LOCAL)
 			goto out;
 		nh->nh_scope = res.nh->nh_parent->fib_scope;
 		nh->nh_oif = res.nh->nh_oif;
@@ -798,6 +800,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 	fi->fib_net = hold_net(net);
 	fi->fib_protocol = cfg->fc_protocol;
 	fi->fib_scope = cfg->fc_scope;
+	fi->fib_type = cfg->fc_type;
 	fi->fib_flags = cfg->fc_flags;
 	fi->fib_priority = cfg->fc_priority;
 	fi->fib_prefsrc = cfg->fc_prefsrc;
@@ -957,7 +960,7 @@ failure:
 }
 
 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-		  u32 tb_id, u8 type, __be32 dst, int dst_len, u8 tos,
+		  u32 tb_id, __be32 dst, int dst_len, u8 tos,
 		  struct fib_info *fi, unsigned int flags)
 {
 	struct nlmsghdr *nlh;
@@ -978,7 +981,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 		rtm->rtm_table = RT_TABLE_COMPAT;
 	if (nla_put_u32(skb, RTA_TABLE, tb_id))
 		goto nla_put_failure;
-	rtm->rtm_type = type;
+	rtm->rtm_type = fi->fib_type;
 	rtm->rtm_flags = fi->fib_flags;
 	rtm->rtm_scope = fi->fib_scope;
 	rtm->rtm_protocol = fi->fib_protocol;
@@ -1142,7 +1145,7 @@ void fib_select_default(struct fib_result *res)
 
 		if ((next_nh->nh_parent->fib_scope !=
 		     res->nh->nh_parent->fib_scope) ||
-		    fa->fa_type != RTN_UNICAST)
+		    next_nh->nh_parent->fib_type != RTN_UNICAST)
 			continue;
 
 		if (next_nh->nh_parent->fib_priority >
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 83cf215..f812f06 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1253,8 +1253,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 				break;
 			if (fa->fa_info->fib_priority != fi->fib_priority)
 				break;
-			if (fa->fa_type == cfg->fc_type &&
-			    fa->fa_info == fi) {
+			if (fa->fa_info == fi) {
 				fa_match = fa;
 				break;
 			}
@@ -1278,7 +1277,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 			fi_drop = fa->fa_info;
 			new_fa->fa_tos = fa->fa_tos;
 			new_fa->fa_info = fi;
-			new_fa->fa_type = cfg->fc_type;
 			state = fa->fa_state;
 			new_fa->fa_state = state & ~FA_S_ACCESSED;
 
@@ -1314,7 +1312,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 
 	new_fa->fa_info = fi;
 	new_fa->fa_tos = tos;
-	new_fa->fa_type = cfg->fc_type;
 	new_fa->fa_state = 0;
 	/*
 	 * Insert new entry to the list.
@@ -1374,7 +1371,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 			if (fa->fa_info->fib_scope < flp->flowi4_scope)
 				continue;
 			fib_alias_accessed(fa);
-			err = fib_props[fa->fa_type].error;
+			err = fib_props[fi->fib_type].error;
 			if (err) {
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 				t->stats.semantic_match_passed++;
@@ -1395,7 +1392,6 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 				t->stats.semantic_match_passed++;
 #endif
 				res->prefixlen = li->plen;
-				res->type = fa->fa_type;
 				res->nh = nh;
 				res->table = tb;
 				res->fa_head = &li->falh;
@@ -1670,7 +1666,8 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
 		if (fa->fa_tos != tos)
 			break;
 
-		if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
+		if ((!cfg->fc_type ||
+		     fa->fa_info->fib_type == cfg->fc_type) &&
 		    (cfg->fc_scope == RT_SCOPE_NOWHERE ||
 		     fa->fa_info->fib_scope == cfg->fc_scope) &&
 		    (!cfg->fc_prefsrc ||
@@ -1873,7 +1870,6 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
 				  cb->nlh->nlmsg_seq,
 				  RTM_NEWROUTE,
 				  tb->tb_id,
-				  fa->fa_type,
 				  xkey,
 				  plen,
 				  fa->fa_tos,
@@ -2394,7 +2390,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
 					   rtn_scope(buf1, sizeof(buf1),
 						     fa->fa_info->fib_scope),
 					   rtn_type(buf2, sizeof(buf2),
-						    fa->fa_type));
+						    fa->fa_info->fib_type));
 				if (fa->fa_tos)
 					seq_printf(seq, " tos=%d", fa->fa_tos);
 				seq_putc(seq, '\n');
@@ -2546,11 +2542,11 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
 			const struct fib_info *fi = fa->fa_info;
-			unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
+			unsigned int flags = fib_flag_trans(fi->fib_type, mask, fi);
 			int len;
 
-			if (fa->fa_type == RTN_BROADCAST
-			    || fa->fa_type == RTN_MULTICAST)
+			if (fi->fib_type == RTN_BROADCAST ||
+			    fi->fib_type == RTN_MULTICAST)
 				continue;
 
 			if (fi)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 0b3277c..6d4353b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1436,7 +1436,7 @@ static int __mkroute_input(struct sk_buff *skb,
 
 	rth->rt_genid = rt_genid(dev_net(rth->dst.dev));
 	rth->rt_flags = flags;
-	rth->rt_type = res->type;
+	rth->rt_type = res->nh->nh_parent->fib_type;
 	rth->rt_is_input = 1;
 	rth->rt_iif 	= 0;
 	rth->rt_pmtu	= 0;
@@ -1445,7 +1445,7 @@ static int __mkroute_input(struct sk_buff *skb,
 	rth->dst.input = ip_forward;
 	rth->dst.output = ip_output;
 
-	rt_set_nexthop(rth, daddr, res, NULL, nh, res->type, itag);
+	rt_set_nexthop(rth, daddr, res, NULL, nh, rth->rt_type, itag);
 	skb_dst_set(skb, &rth->dst);
 out:
 	err = 0;
@@ -1491,6 +1491,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	int		err = -EINVAL;
 	struct net    *net = dev_net(dev);
 	bool do_cache;
+	u8 type;
 
 	/* IP on this device is disabled. */
 
@@ -1541,10 +1542,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 	RT_CACHE_STAT_INC(in_slow_tot);
 
-	if (res.type == RTN_BROADCAST)
+	type = res.nh->nh_parent->fib_type;
+	if (type == RTN_BROADCAST)
 		goto brd_input;
 
-	if (res.type == RTN_LOCAL) {
+	if (type == RTN_LOCAL) {
 		err = fib_validate_source(skb, saddr, daddr, tos,
 					  net->loopback_dev->ifindex,
 					  dev, in_dev, &itag);
@@ -1555,7 +1557,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 	if (!IN_DEV_FORWARD(in_dev))
 		goto no_route;
-	if (res.type != RTN_UNICAST)
+	if (type != RTN_UNICAST)
 		goto martian_destination;
 
 	err = ip_mkroute_input(skb, &res, &fl4, in_dev, daddr, saddr, tos);
@@ -1572,7 +1574,7 @@ brd_input:
 			goto martian_source_keep_err;
 	}
 	flags |= RTCF_BROADCAST;
-	res.type = RTN_BROADCAST;
+	type = RTN_BROADCAST;
 	RT_CACHE_STAT_INC(in_brd);
 
 local_input:
@@ -1602,12 +1604,12 @@ local_input:
 
 	rth->rt_genid = rt_genid(net);
 	rth->rt_flags 	= flags|RTCF_LOCAL;
-	rth->rt_type	= res.type;
+	rth->rt_type	= type;
 	rth->rt_is_input = 1;
 	rth->rt_iif	= 0;
 	rth->rt_pmtu	= 0;
 	rth->rt_gateway	= 0;
-	if (res.type == RTN_UNREACHABLE) {
+	if (type == RTN_UNREACHABLE) {
 		rth->dst.input= ip_error;
 		rth->dst.error= -err;
 		rth->rt_flags 	&= ~RTCF_LOCAL;
@@ -1620,7 +1622,7 @@ local_input:
 
 no_route:
 	RT_CACHE_STAT_INC(in_no_route);
-	res.type = RTN_UNREACHABLE;
+	type = RTN_UNREACHABLE;
 	if (err == -ESRCH)
 		err = -ENETUNREACH;
 	goto local_input;
@@ -1700,13 +1702,12 @@ EXPORT_SYMBOL(ip_route_input_noref);
 /* called with rcu_read_lock() */
 static struct rtable *__mkroute_output(const struct fib_result *res,
 				       const struct flowi4 *fl4, int orig_oif,
-				       struct net_device *dev_out,
+				       struct net_device *dev_out, u8 type,
 				       unsigned int flags)
 {
 	struct fib_nh_exception *fnhe;
 	struct fib_nh *nh = res->nh;
 	struct in_device *in_dev;
-	u16 type = res->type;
 	struct rtable *rth;
 
 	in_dev = __in_dev_get_rcu(dev_out);
@@ -1809,6 +1810,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	struct fib_result res;
 	struct rtable *rth;
 	int orig_oif;
+	u8 type;
 
 	res.tclassid	= 0;
 	res.nh		= NULL;
@@ -1822,6 +1824,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 			 RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
 
 	rcu_read_lock();
+	type = 0;
 	if (fl4->saddr) {
 		rth = ERR_PTR(-EINVAL);
 		if (ipv4_is_multicast(fl4->saddr) ||
@@ -1906,7 +1909,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 			fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
 		dev_out = net->loopback_dev;
 		fl4->flowi4_oif = net->loopback_dev->ifindex;
-		res.type = RTN_LOCAL;
+		type = RTN_LOCAL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
 	}
@@ -1936,14 +1939,15 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 			if (fl4->saddr == 0)
 				fl4->saddr = inet_select_addr(dev_out, 0,
 							      RT_SCOPE_LINK);
-			res.type = RTN_UNICAST;
+			type = RTN_UNICAST;
 			goto make_route;
 		}
 		rth = ERR_PTR(-ENETUNREACH);
 		goto out;
 	}
+	type = res.nh->nh_parent->fib_type;
 
-	if (res.type == RTN_LOCAL) {
+	if (type == RTN_LOCAL) {
 		if (!fl4->saddr) {
 			struct fib_info *fi = res.nh->nh_parent;
 			if (fi->fib_prefsrc)
@@ -1965,7 +1969,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 #endif
 	if (!res.prefixlen &&
 	    res.table->tb_num_default > 1 &&
-	    res.type == RTN_UNICAST && !fl4->flowi4_oif)
+	    type == RTN_UNICAST && !fl4->flowi4_oif)
 		fib_select_default(&res);
 
 	if (!fl4->saddr)
@@ -1976,7 +1980,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 
 make_route:
-	rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
+	rth = __mkroute_output(&res, fl4, orig_oif, dev_out, type, flags);
 
 out:
 	rcu_read_unlock();
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ