aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-07 17:27:38 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-07 17:27:38 -0500
commit4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5 (patch)
tree09f2b802b5f493bfd5345ec808f3b58300cab168 /net/ipv4/fib_semantics.c
parent256ee435b9a9ee9cca69602fe8046b27ca99fbee (diff)
ipv4: Validate route entry type at insert instead of every lookup.
fib_semantic_match() requires that if the type doesn't signal an automatic error, it must be of type RTN_UNICAST, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, or RTN_MULTICAST. Checking this every route lookup is pointless work. Instead validate it during route insertion, via fib_create_info(). Also, there was nothing making sure the type value was less than RTN_MAX, so add that missing check while we're here. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 562f34cd9303..c29291b21009 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -707,6 +707,9 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
707 int nhs = 1; 707 int nhs = 1;
708 struct net *net = cfg->fc_nlinfo.nl_net; 708 struct net *net = cfg->fc_nlinfo.nl_net;
709 709
710 if (cfg->fc_type > RTN_MAX)
711 goto err_inval;
712
710 /* Fast check to catch the most weird cases */ 713 /* Fast check to catch the most weird cases */
711 if (fib_props[cfg->fc_type].scope > cfg->fc_scope) 714 if (fib_props[cfg->fc_type].scope > cfg->fc_scope)
712 goto err_inval; 715 goto err_inval;
@@ -812,6 +815,17 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
812 if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) 815 if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
813 goto err_inval; 816 goto err_inval;
814 goto link_it; 817 goto link_it;
818 } else {
819 switch (cfg->fc_type) {
820 case RTN_UNICAST:
821 case RTN_LOCAL:
822 case RTN_BROADCAST:
823 case RTN_ANYCAST:
824 case RTN_MULTICAST:
825 break;
826 default:
827 goto err_inval;
828 }
815 } 829 }
816 830
817 if (cfg->fc_scope > RT_SCOPE_HOST) 831 if (cfg->fc_scope > RT_SCOPE_HOST)
@@ -915,35 +929,23 @@ int fib_semantic_match(struct fib_table *tb, struct list_head *head,
915 if (fi->fib_flags & RTNH_F_DEAD) 929 if (fi->fib_flags & RTNH_F_DEAD)
916 continue; 930 continue;
917 931
918 switch (fa->fa_type) { 932 for_nexthops(fi) {
919 case RTN_UNICAST: 933 if (nh->nh_flags & RTNH_F_DEAD)
920 case RTN_LOCAL: 934 continue;
921 case RTN_BROADCAST: 935 if (!flp->oif || flp->oif == nh->nh_oif)
922 case RTN_ANYCAST: 936 break;
923 case RTN_MULTICAST: 937 }
924 for_nexthops(fi) {
925 if (nh->nh_flags & RTNH_F_DEAD)
926 continue;
927 if (!flp->oif || flp->oif == nh->nh_oif)
928 break;
929 }
930#ifdef CONFIG_IP_ROUTE_MULTIPATH 938#ifdef CONFIG_IP_ROUTE_MULTIPATH
931 if (nhsel < fi->fib_nhs) { 939 if (nhsel < fi->fib_nhs) {
932 nh_sel = nhsel; 940 nh_sel = nhsel;
933 goto out_fill_res; 941 goto out_fill_res;
934 } 942 }
935#else 943#else
936 if (nhsel < 1) 944 if (nhsel < 1)
937 goto out_fill_res; 945 goto out_fill_res;
938#endif 946#endif
939 endfor_nexthops(fi); 947 endfor_nexthops(fi);
940 continue; 948 continue;
941
942 default:
943 pr_warning("fib_semantic_match bad type %#x\n",
944 fa->fa_type);
945 return -EINVAL;
946 }
947 } 949 }
948 return err; 950 return err;
949 } 951 }