|
@@ -838,6 +838,23 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh)
|
|
|
return nh->nh_saddr;
|
|
|
}
|
|
|
|
|
|
+static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc)
|
|
|
+{
|
|
|
+ if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
|
|
|
+ fib_prefsrc != cfg->fc_dst) {
|
|
|
+ int tb_id = cfg->fc_table;
|
|
|
+
|
|
|
+ if (tb_id == RT_TABLE_MAIN)
|
|
|
+ tb_id = RT_TABLE_LOCAL;
|
|
|
+
|
|
|
+ if (inet_addr_type_table(cfg->fc_nlinfo.nl_net,
|
|
|
+ fib_prefsrc, tb_id) != RTN_LOCAL) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
struct fib_info *fib_create_info(struct fib_config *cfg)
|
|
|
{
|
|
|
int err;
|
|
@@ -1033,12 +1050,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
|
|
|
fi->fib_flags |= RTNH_F_LINKDOWN;
|
|
|
}
|
|
|
|
|
|
- if (fi->fib_prefsrc) {
|
|
|
- if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
|
|
|
- fi->fib_prefsrc != cfg->fc_dst)
|
|
|
- if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL)
|
|
|
- goto err_inval;
|
|
|
- }
|
|
|
+ if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc))
|
|
|
+ goto err_inval;
|
|
|
|
|
|
change_nexthops(fi) {
|
|
|
fib_info_update_nh_saddr(net, nexthop_nh);
|