|
@@ -125,6 +125,39 @@ static void inet_hash_remove(struct in_ifaddr *ifa)
|
|
spin_unlock(&inet_addr_hash_lock);
|
|
spin_unlock(&inet_addr_hash_lock);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * __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, or RTNL
|
|
|
|
+ */
|
|
|
|
+struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
|
|
|
|
+{
|
|
|
|
+ unsigned int hash = inet_addr_hash(net, addr);
|
|
|
|
+ struct net_device *result = NULL;
|
|
|
|
+ struct in_ifaddr *ifa;
|
|
|
|
+ struct hlist_node *node;
|
|
|
|
+
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+ hlist_for_each_entry_rcu(ifa, node, &inet_addr_lst[hash], hash) {
|
|
|
|
+ struct net_device *dev = ifa->ifa_dev->dev;
|
|
|
|
+
|
|
|
|
+ if (!net_eq(dev_net(dev), net))
|
|
|
|
+ continue;
|
|
|
|
+ if (ifa->ifa_address == addr) {
|
|
|
|
+ result = dev;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (result && devref)
|
|
|
|
+ dev_hold(result);
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(__ip_dev_find);
|
|
|
|
+
|
|
static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
|
|
static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
|
|
|
|
|
|
static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
|
|
static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
|