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
- Lines: 169
- Date:
Mon Aug 23 10:01:02 1999
- Orig file:
v2.3.14/linux/net/ipv4/fib_frontend.c
- Orig date:
Wed Aug 18 11:38:49 1999
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)