From f6d1124f7c014acbbe714776114c070ec6ee6b7a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 30 Sep 2010 03:31:56 +0000 Subject: [PATCH] --- yaml --- r: 214821 b: refs/heads/master c: 82efee1499a27c06f5afb11b07db384fdb3f7004 h: refs/heads/master i: 214819: 59ac957327e7b2831229c5de75745b56ce51a1f3 v: v3 --- [refs] | 2 +- trunk/include/linux/inetdevice.h | 7 ++++++- trunk/net/ipv4/fib_frontend.c | 32 +++++++++++++++++++------------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/[refs] b/[refs] index a7a251059365..997f1893202b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 828bac87bb074f3366621724fdfbe314f98ccc7e +refs/heads/master: 82efee1499a27c06f5afb11b07db384fdb3f7004 diff --git a/trunk/include/linux/inetdevice.h b/trunk/include/linux/inetdevice.h index 1ec09bb4a3ab..ccd5b07d678d 100644 --- a/trunk/include/linux/inetdevice.h +++ b/trunk/include/linux/inetdevice.h @@ -159,7 +159,12 @@ struct in_ifaddr { extern int register_inetaddr_notifier(struct notifier_block *nb); extern int unregister_inetaddr_notifier(struct notifier_block *nb); -extern struct net_device *ip_dev_find(struct net *net, __be32 addr); +extern struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref); +static inline struct net_device *ip_dev_find(struct net *net, __be32 addr) +{ + return __ip_dev_find(net, addr, true); +} + extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b); extern int devinet_ioctl(struct net *net, unsigned int cmd, void __user *); extern void devinet_init(void); diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 981f3c59b334..4a69a957872b 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -147,34 +147,40 @@ static void fib_flush(struct net *net) 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; -#ifdef CONFIG_IP_MULTIPLE_TABLES - res.r = NULL; -#endif - if (fib_lookup(net, &fl, &res)) return NULL; if (res.type != RTN_LOCAL) goto out; dev = FIB_RES_DEV(res); - if (dev) + if (dev && devref) dev_hold(dev); out: fib_res_put(&res); 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