diff options
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r-- | net/ipv4/fib_frontend.c | 27 |
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); |
179 | out: | 182 | out: |
180 | fib_res_put(&res); | 183 | rcu_read_unlock(); |
181 | return dev; | 184 | return dev; |
182 | } | 185 | } |
183 | EXPORT_SYMBOL(__ip_dev_find); | 186 | EXPORT_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 | */ |
239 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | 244 | int 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 | ||
329 | e_inval_res: | ||
330 | fib_res_put(&res); | ||
331 | e_inval: | 329 | e_inval: |
332 | return -EINVAL; | 330 | return -EINVAL; |
333 | e_rpf: | 331 | e_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 | } |