patch-2.3.15 linux/net/ipv4/fib_frontend.c

Next file: linux/net/ipv4/fib_hash.c
Previous file: linux/net/ipv4/devinet.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.14/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: FIB frontend.
  *
- * Version:	$Id: fib_frontend.c,v 1.16 1999/06/09 10:10:42 davem Exp $
+ * Version:	$Id: fib_frontend.c,v 1.18 1999/08/20 11:04:59 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -146,21 +146,33 @@
 {
 	struct rt_key key;
 	struct fib_result res;
+	struct net_device *dev = NULL;
 
 	memset(&key, 0, sizeof(key));
 	key.dst = addr;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+	res.r = NULL;
+#endif
 
-	if (!local_table || local_table->tb_lookup(local_table, &key, &res)
-	    || res.type != RTN_LOCAL)
+	if (!local_table || local_table->tb_lookup(local_table, &key, &res)) {
 		return NULL;
-
-	return FIB_RES_DEV(res);
+	}
+	if (res.type != RTN_LOCAL)
+		goto out;
+	dev = FIB_RES_DEV(res);
+	if (dev)
+		atomic_inc(&dev->refcnt);
+
+out:
+	fib_res_put(&res);
+	return dev;
 }
 
 unsigned inet_addr_type(u32 addr)
 {
 	struct rt_key		key;
 	struct fib_result	res;
+	unsigned ret = RTN_BROADCAST;
 
 	if (ZERONET(addr) || BADCLASS(addr))
 		return RTN_BROADCAST;
@@ -169,13 +181,18 @@
 
 	memset(&key, 0, sizeof(key));
 	key.dst = addr;
-
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+	res.r = NULL;
+#endif
+	
 	if (local_table) {
-		if (local_table->tb_lookup(local_table, &key, &res) == 0)
-			return res.type;
-		return RTN_UNICAST;
+		ret = RTN_UNICAST;
+		if (local_table->tb_lookup(local_table, &key, &res) == 0) {
+			ret = res.type;
+			fib_res_put(&res);
+		}
 	}
-	return RTN_BROADCAST;
+	return ret;
 }
 
 /* Given (packet source, input interface) and optional (dst, oif, tos):
@@ -189,9 +206,11 @@
 int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
 			struct net_device *dev, u32 *spec_dst, u32 *itag)
 {
-	struct in_device *in_dev = dev->ip_ptr;
+	struct in_device *in_dev;
 	struct rt_key key;
 	struct fib_result res;
+	int no_addr, rpf;
+	int ret;
 
 	key.dst = src;
 	key.src = dst;
@@ -200,12 +219,22 @@
 	key.iif = oif;
 	key.scope = RT_SCOPE_UNIVERSE;
 
+	no_addr = rpf = 0;
+	read_lock(&inetdev_lock);
+	in_dev = __in_dev_get(dev);
+	if (in_dev) {
+		no_addr = in_dev->ifa_list == NULL;
+		rpf = IN_DEV_RPFILTER(in_dev);
+	}
+	read_unlock(&inetdev_lock);
+
 	if (in_dev == NULL)
-		return -EINVAL;
+		goto e_inval;
+
 	if (fib_lookup(&key, &res))
 		goto last_resort;
 	if (res.type != RTN_UNICAST)
-		return -EINVAL;
+		goto e_inval_res;
 	*spec_dst = FIB_RES_PREFSRC(res);
 	if (itag)
 		fib_combine_itag(itag, &res);
@@ -214,25 +243,39 @@
 #else
 	if (FIB_RES_DEV(res) == dev)
 #endif
-		return FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
-
-	if (in_dev->ifa_list == NULL)
+	{
+		ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+		fib_res_put(&res);
+		return ret;
+	}
+	fib_res_put(&res);
+	if (no_addr)
 		goto last_resort;
-	if (IN_DEV_RPFILTER(in_dev))
-		return -EINVAL;
+	if (rpf)
+		goto e_inval;
 	key.oif = dev->ifindex;
-	if (fib_lookup(&key, &res) == 0 && res.type == RTN_UNICAST) {
-		*spec_dst = FIB_RES_PREFSRC(res);
-		return FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+
+	ret = 0;
+	if (fib_lookup(&key, &res) == 0) {
+		if (res.type == RTN_UNICAST) {
+			*spec_dst = FIB_RES_PREFSRC(res);
+			ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+		}
+		fib_res_put(&res);
 	}
-	return 0;
+	return ret;
 
 last_resort:
-	if (IN_DEV_RPFILTER(in_dev))
-		return -EINVAL;
+	if (rpf)
+		goto e_inval;
 	*spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
 	*itag = 0;
 	return 0;
+
+e_inval_res:
+	fib_res_put(&res);
+e_inval:
+	return -EINVAL;
 }
 
 #ifndef CONFIG_IP_NOSIOCRT
@@ -561,7 +604,7 @@
 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
 	struct net_device *dev = ptr;
-	struct in_device *in_dev = dev->ip_ptr;
+	struct in_device *in_dev = __in_dev_get(dev);
 
 	if (!in_dev)
 		return NOTIFY_DONE;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)