2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
6 * IPv4 Forwarding Information Base: FIB frontend.
8 * Version: $Id: fib_frontend.c,v 1.26 2001/10/31 21:55:54 davem Exp $
10 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
18 #include <linux/config.h>
19 #include <linux/module.h>
20 #include <asm/uaccess.h>
21 #include <asm/system.h>
22 #include <linux/bitops.h>
23 #include <linux/types.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
27 #include <linux/string.h>
28 #include <linux/socket.h>
29 #include <linux/sockios.h>
30 #include <linux/errno.h>
32 #include <linux/inet.h>
33 #include <linux/netdevice.h>
34 #include <linux/if_arp.h>
35 #include <linux/skbuff.h>
36 #include <linux/netlink.h>
37 #include <linux/init.h>
40 #include <net/protocol.h>
41 #include <net/route.h>
46 #include <net/ip_fib.h>
48 #define FFprint(a...) printk(KERN_DEBUG a)
50 #ifndef CONFIG_IP_MULTIPLE_TABLES
52 #define RT_TABLE_MIN RT_TABLE_MAIN
54 struct fib_table *ip_fib_local_table;
55 struct fib_table *ip_fib_main_table;
59 #define RT_TABLE_MIN 1
61 struct fib_table *fib_tables[RT_TABLE_MAX+1];
63 struct fib_table *__fib_new_table(int id)
67 tb = fib_hash_init(id);
75 #endif /* CONFIG_IP_MULTIPLE_TABLES */
78 static void fib_flush(void)
81 #ifdef CONFIG_IP_MULTIPLE_TABLES
85 for (id = RT_TABLE_MAX; id>0; id--) {
86 if ((tb = fib_get_table(id))==NULL)
88 flushed += tb->tb_flush(tb);
90 #else /* CONFIG_IP_MULTIPLE_TABLES */
91 flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
92 flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
93 #endif /* CONFIG_IP_MULTIPLE_TABLES */
100 * Find the first device with a given source address.
103 struct net_device * ip_dev_find(u32 addr)
105 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
106 struct fib_result res;
107 struct net_device *dev = NULL;
109 #ifdef CONFIG_IP_MULTIPLE_TABLES
113 if (!ip_fib_local_table ||
114 ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res))
116 if (res.type != RTN_LOCAL)
118 dev = FIB_RES_DEV(res);
127 unsigned inet_addr_type(u32 addr)
129 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
130 struct fib_result res;
131 unsigned ret = RTN_BROADCAST;
133 if (ZERONET(addr) || BADCLASS(addr))
134 return RTN_BROADCAST;
136 return RTN_MULTICAST;
138 #ifdef CONFIG_IP_MULTIPLE_TABLES
142 if (ip_fib_local_table) {
144 if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
153 /* Given (packet source, input interface) and optional (dst, oif, tos):
154 - (main) check, that source is valid i.e. not broadcast or our local
156 - figure out what "logical" interface this packet arrived
157 and calculate "specific destination" address.
158 - check, that packet arrived from expected physical interface.
161 int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
162 struct net_device *dev, u32 *spec_dst, u32 *itag)
164 struct in_device *in_dev;
165 struct flowi fl = { .nl_u = { .ip4_u =
170 struct fib_result res;
176 in_dev = __in_dev_get_rcu(dev);
178 no_addr = in_dev->ifa_list == NULL;
179 rpf = IN_DEV_RPFILTER(in_dev);
186 if (fib_lookup(&fl, &res))
188 if (res.type != RTN_UNICAST)
190 *spec_dst = FIB_RES_PREFSRC(res);
191 fib_combine_itag(itag, &res);
192 #ifdef CONFIG_IP_ROUTE_MULTIPATH
193 if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
195 if (FIB_RES_DEV(res) == dev)
198 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
207 fl.oif = dev->ifindex;
210 if (fib_lookup(&fl, &res) == 0) {
211 if (res.type == RTN_UNICAST) {
212 *spec_dst = FIB_RES_PREFSRC(res);
213 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
222 *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
232 #ifndef CONFIG_IP_NOSIOCRT
235 * Handle IP routing ioctl calls. These are used to manipulate the routing tables
238 int ip_rt_ioctl(unsigned int cmd, void __user *arg)
249 case SIOCADDRT: /* Add a route */
250 case SIOCDELRT: /* Delete a route */
251 if (!capable(CAP_NET_ADMIN))
253 if (copy_from_user(&r, arg, sizeof(struct rtentry)))
256 err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r);
258 if (cmd == SIOCDELRT) {
259 struct fib_table *tb = fib_get_table(req.rtm.rtm_table);
262 err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
264 struct fib_table *tb = fib_new_table(req.rtm.rtm_table);
267 err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
279 int ip_rt_ioctl(unsigned int cmd, void *arg)
286 static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
290 for (i=1; i<=RTA_MAX; i++) {
291 struct rtattr *attr = rta[i-1];
293 if (RTA_PAYLOAD(attr) < 4)
295 if (i != RTA_MULTIPATH && i != RTA_METRICS)
296 rta[i-1] = (struct rtattr*)RTA_DATA(attr);
302 int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
304 struct fib_table * tb;
305 struct rtattr **rta = arg;
306 struct rtmsg *r = NLMSG_DATA(nlh);
308 if (inet_check_attr(r, rta))
311 tb = fib_get_table(r->rtm_table);
313 return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
317 int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
319 struct fib_table * tb;
320 struct rtattr **rta = arg;
321 struct rtmsg *r = NLMSG_DATA(nlh);
323 if (inet_check_attr(r, rta))
326 tb = fib_new_table(r->rtm_table);
328 return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
332 int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
336 struct fib_table *tb;
338 if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
339 ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
340 return ip_rt_dump(skb, cb);
344 s_t = cb->args[0] = RT_TABLE_MIN;
346 for (t=s_t; t<=RT_TABLE_MAX; t++) {
347 if (t < s_t) continue;
349 memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
350 if ((tb = fib_get_table(t))==NULL)
352 if (tb->tb_dump(tb, skb, cb) < 0)
361 /* Prepare and feed intra-kernel routing request.
362 Really, it should be netlink message, but :-( netlink
363 can be not configured, so that we feed it directly
364 to fib engine. It is legal, because all events occur
365 only when netlink is already locked.
368 static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa)
370 struct fib_table * tb;
377 memset(&req.rtm, 0, sizeof(req.rtm));
378 memset(&rta, 0, sizeof(rta));
380 if (type == RTN_UNICAST)
381 tb = fib_new_table(RT_TABLE_MAIN);
383 tb = fib_new_table(RT_TABLE_LOCAL);
388 req.nlh.nlmsg_len = sizeof(req);
389 req.nlh.nlmsg_type = cmd;
390 req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
391 req.nlh.nlmsg_pid = 0;
392 req.nlh.nlmsg_seq = 0;
394 req.rtm.rtm_dst_len = dst_len;
395 req.rtm.rtm_table = tb->tb_id;
396 req.rtm.rtm_protocol = RTPROT_KERNEL;
397 req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
398 req.rtm.rtm_type = type;
401 rta.rta_prefsrc = &ifa->ifa_local;
402 rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
404 if (cmd == RTM_NEWROUTE)
405 tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
407 tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
410 void fib_add_ifaddr(struct in_ifaddr *ifa)
412 struct in_device *in_dev = ifa->ifa_dev;
413 struct net_device *dev = in_dev->dev;
414 struct in_ifaddr *prim = ifa;
415 u32 mask = ifa->ifa_mask;
416 u32 addr = ifa->ifa_local;
417 u32 prefix = ifa->ifa_address&mask;
419 if (ifa->ifa_flags&IFA_F_SECONDARY) {
420 prim = inet_ifa_byprefix(in_dev, prefix, mask);
422 printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n");
427 fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
429 if (!(dev->flags&IFF_UP))
432 /* Add broadcast address, if it is explicitly assigned. */
433 if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
434 fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
436 if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
437 (prefix != addr || ifa->ifa_prefixlen < 32)) {
438 fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
439 RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);
441 /* Add network specific broadcasts, when it takes a sense */
442 if (ifa->ifa_prefixlen < 31) {
443 fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
444 fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);
449 static void fib_del_ifaddr(struct in_ifaddr *ifa)
451 struct in_device *in_dev = ifa->ifa_dev;
452 struct net_device *dev = in_dev->dev;
453 struct in_ifaddr *ifa1;
454 struct in_ifaddr *prim = ifa;
455 u32 brd = ifa->ifa_address|~ifa->ifa_mask;
456 u32 any = ifa->ifa_address&ifa->ifa_mask;
463 if (!(ifa->ifa_flags&IFA_F_SECONDARY))
464 fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
465 RTN_UNICAST, any, ifa->ifa_prefixlen, prim);
467 prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
469 printk(KERN_DEBUG "fib_del_ifaddr: bug: prim == NULL\n");
474 /* Deletion is more complicated than add.
475 We should take care of not to delete too much :-)
477 Scan address list to be sure that addresses are really gone.
480 for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
481 if (ifa->ifa_local == ifa1->ifa_local)
483 if (ifa->ifa_broadcast == ifa1->ifa_broadcast)
485 if (brd == ifa1->ifa_broadcast)
487 if (any == ifa1->ifa_broadcast)
492 fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
494 fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
496 fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
497 if (!(ok&LOCAL_OK)) {
498 fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
500 /* Check, that this local address finally disappeared. */
501 if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
502 /* And the last, but not the least thing.
503 We must flush stray FIB entries.
505 First of all, we scan fib_info list searching
506 for stray nexthop entries, then ignite fib_flush.
508 if (fib_sync_down(ifa->ifa_local, NULL, 0))
518 static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
521 struct fib_result res;
522 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
523 .fwmark = frn->fl_fwmark,
525 .scope = frn->fl_scope } } };
529 frn->tb_id = tb->tb_id;
530 frn->err = tb->tb_lookup(tb, &fl, &res);
533 frn->prefixlen = res.prefixlen;
534 frn->nh_sel = res.nh_sel;
535 frn->type = res.type;
536 frn->scope = res.scope;
542 static void nl_fib_input(struct sock *sk, int len)
544 struct sk_buff *skb = NULL;
545 struct nlmsghdr *nlh = NULL;
546 struct fib_result_nl *frn;
549 struct fib_table *tb;
551 skb = skb_recv_datagram(sk, 0, 0, &err);
552 nlh = (struct nlmsghdr *)skb->data;
554 frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
555 tb = fib_get_table(frn->tb_id_in);
557 nl_fib_lookup(frn, tb);
559 pid = nlh->nlmsg_pid; /*pid of sending process */
560 NETLINK_CB(skb).pid = 0; /* from kernel */
561 NETLINK_CB(skb).dst_pid = pid;
562 NETLINK_CB(skb).dst_group = 0; /* unicast */
563 netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
566 static void nl_fib_lookup_init(void)
568 netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, THIS_MODULE);
571 static void fib_disable_ip(struct net_device *dev, int force)
573 if (fib_sync_down(0, dev, force))
579 static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
581 struct in_ifaddr *ifa = (struct in_ifaddr*)ptr;
586 #ifdef CONFIG_IP_ROUTE_MULTIPATH
587 fib_sync_up(ifa->ifa_dev->dev);
593 if (ifa->ifa_dev->ifa_list == NULL) {
594 /* Last address was deleted from this interface.
597 fib_disable_ip(ifa->ifa_dev->dev, 1);
606 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
608 struct net_device *dev = ptr;
609 struct in_device *in_dev = __in_dev_get_rtnl(dev);
611 if (event == NETDEV_UNREGISTER) {
612 fib_disable_ip(dev, 2);
623 } endfor_ifa(in_dev);
624 #ifdef CONFIG_IP_ROUTE_MULTIPATH
630 fib_disable_ip(dev, 0);
632 case NETDEV_CHANGEMTU:
640 static struct notifier_block fib_inetaddr_notifier = {
641 .notifier_call =fib_inetaddr_event,
644 static struct notifier_block fib_netdev_notifier = {
645 .notifier_call =fib_netdev_event,
648 void __init ip_fib_init(void)
650 #ifndef CONFIG_IP_MULTIPLE_TABLES
651 ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
652 ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
657 register_netdevice_notifier(&fib_netdev_notifier);
658 register_inetaddr_notifier(&fib_inetaddr_notifier);
659 nl_fib_lookup_init();
662 EXPORT_SYMBOL(inet_addr_type);
663 EXPORT_SYMBOL(ip_rt_ioctl);