aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_frontend.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r--net/ipv4/fib_frontend.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index b05c23b05a9f..919f2ad19b49 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -168,8 +168,11 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
168 struct fib_result res = { 0 }; 168 struct fib_result res = { 0 };
169 struct net_device *dev = NULL; 169 struct net_device *dev = NULL;
170 170
171 if (fib_lookup(net, &fl, &res)) 171 rcu_read_lock();
172 if (fib_lookup(net, &fl, &res)) {
173 rcu_read_unlock();
172 return NULL; 174 return NULL;
175 }
173 if (res.type != RTN_LOCAL) 176 if (res.type != RTN_LOCAL)
174 goto out; 177 goto out;
175 dev = FIB_RES_DEV(res); 178 dev = FIB_RES_DEV(res);
@@ -177,7 +180,7 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
177 if (dev && devref) 180 if (dev && devref)
178 dev_hold(dev); 181 dev_hold(dev);
179out: 182out:
180 fib_res_put(&res); 183 rcu_read_unlock();
181 return dev; 184 return dev;
182} 185}
183EXPORT_SYMBOL(__ip_dev_find); 186EXPORT_SYMBOL(__ip_dev_find);
@@ -207,11 +210,12 @@ static inline unsigned __inet_dev_addr_type(struct net *net,
207 local_table = fib_get_table(net, RT_TABLE_LOCAL); 210 local_table = fib_get_table(net, RT_TABLE_LOCAL);
208 if (local_table) { 211 if (local_table) {
209 ret = RTN_UNICAST; 212 ret = RTN_UNICAST;
210 if (!fib_table_lookup(local_table, &fl, &res)) { 213 rcu_read_lock();
214 if (!fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {
211 if (!dev || dev == res.fi->fib_dev) 215 if (!dev || dev == res.fi->fib_dev)
212 ret = res.type; 216 ret = res.type;
213 fib_res_put(&res);
214 } 217 }
218 rcu_read_unlock();
215 } 219 }
216 return ret; 220 return ret;
217} 221}
@@ -235,6 +239,7 @@ EXPORT_SYMBOL(inet_dev_addr_type);
235 * - figure out what "logical" interface this packet arrived 239 * - figure out what "logical" interface this packet arrived
236 * and calculate "specific destination" address. 240 * and calculate "specific destination" address.
237 * - check, that packet arrived from expected physical interface. 241 * - check, that packet arrived from expected physical interface.
242 * called with rcu_read_lock()
238 */ 243 */
239int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, 244int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
240 struct net_device *dev, __be32 *spec_dst, 245 struct net_device *dev, __be32 *spec_dst,
@@ -259,7 +264,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
259 struct net *net; 264 struct net *net;
260 265
261 no_addr = rpf = accept_local = 0; 266 no_addr = rpf = accept_local = 0;
262 rcu_read_lock();
263 in_dev = __in_dev_get_rcu(dev); 267 in_dev = __in_dev_get_rcu(dev);
264 if (in_dev) { 268 if (in_dev) {
265 no_addr = in_dev->ifa_list == NULL; 269 no_addr = in_dev->ifa_list == NULL;
@@ -268,7 +272,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
268 if (mark && !IN_DEV_SRC_VMARK(in_dev)) 272 if (mark && !IN_DEV_SRC_VMARK(in_dev))
269 fl.mark = 0; 273 fl.mark = 0;
270 } 274 }
271 rcu_read_unlock();
272 275
273 if (in_dev == NULL) 276 if (in_dev == NULL)
274 goto e_inval; 277 goto e_inval;
@@ -278,7 +281,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
278 goto last_resort; 281 goto last_resort;
279 if (res.type != RTN_UNICAST) { 282 if (res.type != RTN_UNICAST) {
280 if (res.type != RTN_LOCAL || !accept_local) 283 if (res.type != RTN_LOCAL || !accept_local)
281 goto e_inval_res; 284 goto e_inval;
282 } 285 }
283 *spec_dst = FIB_RES_PREFSRC(res); 286 *spec_dst = FIB_RES_PREFSRC(res);
284 fib_combine_itag(itag, &res); 287 fib_combine_itag(itag, &res);
@@ -299,10 +302,8 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
299#endif 302#endif
300 if (dev_match) { 303 if (dev_match) {
301 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; 304 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
302 fib_res_put(&res);
303 return ret; 305 return ret;
304 } 306 }
305 fib_res_put(&res);
306 if (no_addr) 307 if (no_addr)
307 goto last_resort; 308 goto last_resort;
308 if (rpf == 1) 309 if (rpf == 1)
@@ -315,7 +316,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
315 *spec_dst = FIB_RES_PREFSRC(res); 316 *spec_dst = FIB_RES_PREFSRC(res);
316 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; 317 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
317 } 318 }
318 fib_res_put(&res);
319 } 319 }
320 return ret; 320 return ret;
321 321
@@ -326,8 +326,6 @@ last_resort:
326 *itag = 0; 326 *itag = 0;
327 return 0; 327 return 0;
328 328
329e_inval_res:
330 fib_res_put(&res);
331e_inval: 329e_inval:
332 return -EINVAL; 330 return -EINVAL;
333e_rpf: 331e_rpf:
@@ -873,15 +871,16 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
873 local_bh_disable(); 871 local_bh_disable();
874 872
875 frn->tb_id = tb->tb_id; 873 frn->tb_id = tb->tb_id;
876 frn->err = fib_table_lookup(tb, &fl, &res); 874 rcu_read_lock();
875 frn->err = fib_table_lookup(tb, &fl, &res, FIB_LOOKUP_NOREF);
877 876
878 if (!frn->err) { 877 if (!frn->err) {
879 frn->prefixlen = res.prefixlen; 878 frn->prefixlen = res.prefixlen;
880 frn->nh_sel = res.nh_sel; 879 frn->nh_sel = res.nh_sel;
881 frn->type = res.type; 880 frn->type = res.type;
882 frn->scope = res.scope; 881 frn->scope = res.scope;
883 fib_res_put(&res);
884 } 882 }
883 rcu_read_unlock();
885 local_bh_enable(); 884 local_bh_enable();
886 } 885 }
887} 886}