|
@@ -147,34 +147,40 @@ static void fib_flush(struct net *net)
|
|
rt_cache_flush(net, -1);
|
|
rt_cache_flush(net, -1);
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Find the first device with a given source address.
|
|
|
|
|
|
+/**
|
|
|
|
+ * __ip_dev_find - find the first device with a given source address.
|
|
|
|
+ * @net: the net namespace
|
|
|
|
+ * @addr: the source address
|
|
|
|
+ * @devref: if true, take a reference on the found device
|
|
|
|
+ *
|
|
|
|
+ * If a caller uses devref=false, it should be protected by RCU
|
|
*/
|
|
*/
|
|
-
|
|
|
|
-struct net_device * ip_dev_find(struct net *net, __be32 addr)
|
|
|
|
|
|
+struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
|
|
{
|
|
{
|
|
- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } },
|
|
|
|
- .flags = FLOWI_FLAG_MATCH_ANY_IIF };
|
|
|
|
- struct fib_result res;
|
|
|
|
|
|
+ struct flowi fl = {
|
|
|
|
+ .nl_u = {
|
|
|
|
+ .ip4_u = {
|
|
|
|
+ .daddr = addr
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ .flags = FLOWI_FLAG_MATCH_ANY_IIF
|
|
|
|
+ };
|
|
|
|
+ struct fib_result res = { 0 };
|
|
struct net_device *dev = NULL;
|
|
struct net_device *dev = NULL;
|
|
|
|
|
|
-#ifdef CONFIG_IP_MULTIPLE_TABLES
|
|
|
|
- res.r = NULL;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
if (fib_lookup(net, &fl, &res))
|
|
if (fib_lookup(net, &fl, &res))
|
|
return NULL;
|
|
return NULL;
|
|
if (res.type != RTN_LOCAL)
|
|
if (res.type != RTN_LOCAL)
|
|
goto out;
|
|
goto out;
|
|
dev = FIB_RES_DEV(res);
|
|
dev = FIB_RES_DEV(res);
|
|
|
|
|
|
- if (dev)
|
|
|
|
|
|
+ if (dev && devref)
|
|
dev_hold(dev);
|
|
dev_hold(dev);
|
|
out:
|
|
out:
|
|
fib_res_put(&res);
|
|
fib_res_put(&res);
|
|
return dev;
|
|
return dev;
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL(ip_dev_find);
|
|
|
|
|
|
+EXPORT_SYMBOL(__ip_dev_find);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Find address type as if only "dev" was present in the system. If
|
|
* Find address type as if only "dev" was present in the system. If
|