diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-07 17:27:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-07 17:27:38 -0500 |
commit | 4c8237cd76a0510677dc2e3dd0f8866ec8e0b1e5 (patch) | |
tree | 09f2b802b5f493bfd5345ec808f3b58300cab168 /net/ipv4/fib_semantics.c | |
parent | 256ee435b9a9ee9cca69602fe8046b27ca99fbee (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.c | 54 |
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 | } |