summaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_frontend.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_frontend.c')
-rw-r--r--net/ipv4/fib_frontend.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 8775c43bf..409db8209 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -5,7 +5,7 @@
*
* IPv4 Forwarding Information Base: FIB frontend.
*
- * Version: $Id: fib_frontend.c,v 1.4 1997/11/09 20:05:23 kuznet Exp $
+ * Version: $Id: fib_frontend.c,v 1.6 1997/12/13 21:52:48 kuznet Exp $
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
@@ -93,7 +93,7 @@ void fib_flush(void)
#endif /* CONFIG_IP_MULTIPLE_TABLES */
if (flushed)
- rt_cache_flush(RT_FLUSH_DELAY);
+ rt_cache_flush(-1);
}
@@ -290,27 +290,51 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)
#ifdef CONFIG_RTNETLINK
+static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
+{
+ int i;
+
+ for (i=1; i<=RTA_MAX; i++) {
+ struct rtattr *attr = rta[i-1];
+ if (attr) {
+ if (RTA_PAYLOAD(attr) < 4)
+ return -EINVAL;
+#ifndef CONFIG_RTNL_OLD_IFINFO
+ if (i != RTA_MULTIPATH && i != RTA_METRICS)
+#endif
+ rta[i-1] = (struct rtattr*)RTA_DATA(attr);
+ }
+ }
+ return 0;
+}
+
int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib_table * tb;
- struct kern_rta *rta = arg;
+ struct rtattr **rta = arg;
struct rtmsg *r = NLMSG_DATA(nlh);
+ if (inet_check_attr(r, rta))
+ return -EINVAL;
+
tb = fib_get_table(r->rtm_table);
if (tb)
- return tb->tb_delete(tb, r, rta, nlh, &NETLINK_CB(skb));
+ return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
return -ESRCH;
}
int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib_table * tb;
- struct kern_rta *rta = arg;
+ struct rtattr **rta = arg;
struct rtmsg *r = NLMSG_DATA(nlh);
+ if (inet_check_attr(r, rta))
+ return -EINVAL;
+
tb = fib_new_table(r->rtm_table);
if (tb)
- return tb->tb_insert(tb, r, rta, nlh, &NETLINK_CB(skb));
+ return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
return -ENOBUFS;
}
@@ -370,7 +394,7 @@ static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr
req.nlh.nlmsg_len = sizeof(req);
req.nlh.nlmsg_type = cmd;
- req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
req.nlh.nlmsg_pid = 0;
req.nlh.nlmsg_seq = 0;
@@ -477,7 +501,7 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
First of all, we scan fib_info list searching
for stray nexthop entries, then ignite fib_flush.
*/
- if (fib_sync_down(ifa->ifa_local, NULL))
+ if (fib_sync_down(ifa->ifa_local, NULL, 0))
fib_flush();
}
}
@@ -494,11 +518,11 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
switch (event) {
case NETDEV_UP:
fib_add_ifaddr(ifa);
- rt_cache_flush(2*HZ);
+ rt_cache_flush(-1);
break;
case NETDEV_DOWN:
fib_del_ifaddr(ifa);
- rt_cache_flush(1*HZ);
+ rt_cache_flush(-1);
break;
}
return NOTIFY_DONE;
@@ -520,16 +544,24 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
#ifdef CONFIG_IP_ROUTE_MULTIPATH
fib_sync_up(dev);
#endif
- rt_cache_flush(2*HZ);
+ rt_cache_flush(-1);
break;
case NETDEV_DOWN:
- if (fib_sync_down(0, dev))
+ if (fib_sync_down(0, dev, 0))
fib_flush();
rt_cache_flush(0);
+ arp_ifdown(dev);
break;
case NETDEV_UNREGISTER:
if (in_dev->ifa_list)
printk("About to crash!\n");
+ if (fib_sync_down(0, dev, 1))
+ fib_flush();
+ rt_cache_flush(0);
+ arp_ifdown(dev);
+ break;
+ case NETDEV_CHANGEMTU:
+ case NETDEV_CHANGE:
rt_cache_flush(0);
break;
}