[NET]: Use u32 for routing table IDs
[linux-2.6] / net / ipv4 / fib_frontend.c
1 /*
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.
5  *
6  *              IPv4 Forwarding Information Base: FIB frontend.
7  *
8  * Version:     $Id: fib_frontend.c,v 1.26 2001/10/31 21:55:54 davem Exp $
9  *
10  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11  *
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.
16  */
17
18 #include <linux/module.h>
19 #include <asm/uaccess.h>
20 #include <asm/system.h>
21 #include <linux/bitops.h>
22 #include <linux/capability.h>
23 #include <linux/types.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/mm.h>
27 #include <linux/string.h>
28 #include <linux/socket.h>
29 #include <linux/sockios.h>
30 #include <linux/errno.h>
31 #include <linux/in.h>
32 #include <linux/inet.h>
33 #include <linux/inetdevice.h>
34 #include <linux/netdevice.h>
35 #include <linux/if_addr.h>
36 #include <linux/if_arp.h>
37 #include <linux/skbuff.h>
38 #include <linux/netlink.h>
39 #include <linux/init.h>
40
41 #include <net/ip.h>
42 #include <net/protocol.h>
43 #include <net/route.h>
44 #include <net/tcp.h>
45 #include <net/sock.h>
46 #include <net/icmp.h>
47 #include <net/arp.h>
48 #include <net/ip_fib.h>
49
50 #define FFprint(a...) printk(KERN_DEBUG a)
51
52 #ifndef CONFIG_IP_MULTIPLE_TABLES
53
54 #define RT_TABLE_MIN RT_TABLE_MAIN
55
56 struct fib_table *ip_fib_local_table;
57 struct fib_table *ip_fib_main_table;
58
59 #else
60
61 #define RT_TABLE_MIN 1
62
63 struct fib_table *fib_tables[RT_TABLE_MAX+1];
64
65 struct fib_table *__fib_new_table(u32 id)
66 {
67         struct fib_table *tb;
68
69         tb = fib_hash_init(id);
70         if (!tb)
71                 return NULL;
72         fib_tables[id] = tb;
73         return tb;
74 }
75
76
77 #endif /* CONFIG_IP_MULTIPLE_TABLES */
78
79
80 static void fib_flush(void)
81 {
82         int flushed = 0;
83 #ifdef CONFIG_IP_MULTIPLE_TABLES
84         struct fib_table *tb;
85         u32 id;
86
87         for (id = RT_TABLE_MAX; id>0; id--) {
88                 if ((tb = fib_get_table(id))==NULL)
89                         continue;
90                 flushed += tb->tb_flush(tb);
91         }
92 #else /* CONFIG_IP_MULTIPLE_TABLES */
93         flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
94         flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
95 #endif /* CONFIG_IP_MULTIPLE_TABLES */
96
97         if (flushed)
98                 rt_cache_flush(-1);
99 }
100
101 /*
102  *      Find the first device with a given source address.
103  */
104
105 struct net_device * ip_dev_find(u32 addr)
106 {
107         struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
108         struct fib_result res;
109         struct net_device *dev = NULL;
110
111 #ifdef CONFIG_IP_MULTIPLE_TABLES
112         res.r = NULL;
113 #endif
114
115         if (!ip_fib_local_table ||
116             ip_fib_local_table->tb_lookup(ip_fib_local_table, &fl, &res))
117                 return NULL;
118         if (res.type != RTN_LOCAL)
119                 goto out;
120         dev = FIB_RES_DEV(res);
121
122         if (dev)
123                 dev_hold(dev);
124 out:
125         fib_res_put(&res);
126         return dev;
127 }
128
129 unsigned inet_addr_type(u32 addr)
130 {
131         struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
132         struct fib_result       res;
133         unsigned ret = RTN_BROADCAST;
134
135         if (ZERONET(addr) || BADCLASS(addr))
136                 return RTN_BROADCAST;
137         if (MULTICAST(addr))
138                 return RTN_MULTICAST;
139
140 #ifdef CONFIG_IP_MULTIPLE_TABLES
141         res.r = NULL;
142 #endif
143         
144         if (ip_fib_local_table) {
145                 ret = RTN_UNICAST;
146                 if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
147                                                    &fl, &res)) {
148                         ret = res.type;
149                         fib_res_put(&res);
150                 }
151         }
152         return ret;
153 }
154
155 /* Given (packet source, input interface) and optional (dst, oif, tos):
156    - (main) check, that source is valid i.e. not broadcast or our local
157      address.
158    - figure out what "logical" interface this packet arrived
159      and calculate "specific destination" address.
160    - check, that packet arrived from expected physical interface.
161  */
162
163 int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
164                         struct net_device *dev, u32 *spec_dst, u32 *itag)
165 {
166         struct in_device *in_dev;
167         struct flowi fl = { .nl_u = { .ip4_u =
168                                       { .daddr = src,
169                                         .saddr = dst,
170                                         .tos = tos } },
171                             .iif = oif };
172         struct fib_result res;
173         int no_addr, rpf;
174         int ret;
175
176         no_addr = rpf = 0;
177         rcu_read_lock();
178         in_dev = __in_dev_get_rcu(dev);
179         if (in_dev) {
180                 no_addr = in_dev->ifa_list == NULL;
181                 rpf = IN_DEV_RPFILTER(in_dev);
182         }
183         rcu_read_unlock();
184
185         if (in_dev == NULL)
186                 goto e_inval;
187
188         if (fib_lookup(&fl, &res))
189                 goto last_resort;
190         if (res.type != RTN_UNICAST)
191                 goto e_inval_res;
192         *spec_dst = FIB_RES_PREFSRC(res);
193         fib_combine_itag(itag, &res);
194 #ifdef CONFIG_IP_ROUTE_MULTIPATH
195         if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
196 #else
197         if (FIB_RES_DEV(res) == dev)
198 #endif
199         {
200                 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
201                 fib_res_put(&res);
202                 return ret;
203         }
204         fib_res_put(&res);
205         if (no_addr)
206                 goto last_resort;
207         if (rpf)
208                 goto e_inval;
209         fl.oif = dev->ifindex;
210
211         ret = 0;
212         if (fib_lookup(&fl, &res) == 0) {
213                 if (res.type == RTN_UNICAST) {
214                         *spec_dst = FIB_RES_PREFSRC(res);
215                         ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
216                 }
217                 fib_res_put(&res);
218         }
219         return ret;
220
221 last_resort:
222         if (rpf)
223                 goto e_inval;
224         *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
225         *itag = 0;
226         return 0;
227
228 e_inval_res:
229         fib_res_put(&res);
230 e_inval:
231         return -EINVAL;
232 }
233
234 #ifndef CONFIG_IP_NOSIOCRT
235
236 /*
237  *      Handle IP routing ioctl calls. These are used to manipulate the routing tables
238  */
239  
240 int ip_rt_ioctl(unsigned int cmd, void __user *arg)
241 {
242         int err;
243         struct kern_rta rta;
244         struct rtentry  r;
245         struct {
246                 struct nlmsghdr nlh;
247                 struct rtmsg    rtm;
248         } req;
249
250         switch (cmd) {
251         case SIOCADDRT:         /* Add a route */
252         case SIOCDELRT:         /* Delete a route */
253                 if (!capable(CAP_NET_ADMIN))
254                         return -EPERM;
255                 if (copy_from_user(&r, arg, sizeof(struct rtentry)))
256                         return -EFAULT;
257                 rtnl_lock();
258                 err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r);
259                 if (err == 0) {
260                         if (cmd == SIOCDELRT) {
261                                 struct fib_table *tb = fib_get_table(req.rtm.rtm_table);
262                                 err = -ESRCH;
263                                 if (tb)
264                                         err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
265                         } else {
266                                 struct fib_table *tb = fib_new_table(req.rtm.rtm_table);
267                                 err = -ENOBUFS;
268                                 if (tb)
269                                         err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
270                         }
271                         kfree(rta.rta_mx);
272                 }
273                 rtnl_unlock();
274                 return err;
275         }
276         return -EINVAL;
277 }
278
279 #else
280
281 int ip_rt_ioctl(unsigned int cmd, void *arg)
282 {
283         return -EINVAL;
284 }
285
286 #endif
287
288 static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
289 {
290         int i;
291
292         for (i=1; i<=RTA_MAX; i++, rta++) {
293                 struct rtattr *attr = *rta;
294                 if (attr) {
295                         if (RTA_PAYLOAD(attr) < 4)
296                                 return -EINVAL;
297                         if (i != RTA_MULTIPATH && i != RTA_METRICS)
298                                 *rta = (struct rtattr*)RTA_DATA(attr);
299                 }
300         }
301         return 0;
302 }
303
304 int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
305 {
306         struct fib_table * tb;
307         struct rtattr **rta = arg;
308         struct rtmsg *r = NLMSG_DATA(nlh);
309
310         if (inet_check_attr(r, rta))
311                 return -EINVAL;
312
313         tb = fib_get_table(r->rtm_table);
314         if (tb)
315                 return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
316         return -ESRCH;
317 }
318
319 int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
320 {
321         struct fib_table * tb;
322         struct rtattr **rta = arg;
323         struct rtmsg *r = NLMSG_DATA(nlh);
324
325         if (inet_check_attr(r, rta))
326                 return -EINVAL;
327
328         tb = fib_new_table(r->rtm_table);
329         if (tb)
330                 return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
331         return -ENOBUFS;
332 }
333
334 int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
335 {
336         u32 t;
337         u32 s_t;
338         struct fib_table *tb;
339
340         if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
341             ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
342                 return ip_rt_dump(skb, cb);
343
344         s_t = cb->args[0];
345         if (s_t == 0)
346                 s_t = cb->args[0] = RT_TABLE_MIN;
347
348         for (t=s_t; t<=RT_TABLE_MAX; t++) {
349                 if (t < s_t) continue;
350                 if (t > s_t)
351                         memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
352                 if ((tb = fib_get_table(t))==NULL)
353                         continue;
354                 if (tb->tb_dump(tb, skb, cb) < 0) 
355                         break;
356         }
357
358         cb->args[0] = t;
359
360         return skb->len;
361 }
362
363 /* Prepare and feed intra-kernel routing request.
364    Really, it should be netlink message, but :-( netlink
365    can be not configured, so that we feed it directly
366    to fib engine. It is legal, because all events occur
367    only when netlink is already locked.
368  */
369
370 static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa)
371 {
372         struct fib_table * tb;
373         struct {
374                 struct nlmsghdr nlh;
375                 struct rtmsg    rtm;
376         } req;
377         struct kern_rta rta;
378
379         memset(&req.rtm, 0, sizeof(req.rtm));
380         memset(&rta, 0, sizeof(rta));
381
382         if (type == RTN_UNICAST)
383                 tb = fib_new_table(RT_TABLE_MAIN);
384         else
385                 tb = fib_new_table(RT_TABLE_LOCAL);
386
387         if (tb == NULL)
388                 return;
389
390         req.nlh.nlmsg_len = sizeof(req);
391         req.nlh.nlmsg_type = cmd;
392         req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
393         req.nlh.nlmsg_pid = 0;
394         req.nlh.nlmsg_seq = 0;
395
396         req.rtm.rtm_dst_len = dst_len;
397         req.rtm.rtm_table = tb->tb_id;
398         req.rtm.rtm_protocol = RTPROT_KERNEL;
399         req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
400         req.rtm.rtm_type = type;
401
402         rta.rta_dst = &dst;
403         rta.rta_prefsrc = &ifa->ifa_local;
404         rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
405
406         if (cmd == RTM_NEWROUTE)
407                 tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
408         else
409                 tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
410 }
411
412 void fib_add_ifaddr(struct in_ifaddr *ifa)
413 {
414         struct in_device *in_dev = ifa->ifa_dev;
415         struct net_device *dev = in_dev->dev;
416         struct in_ifaddr *prim = ifa;
417         u32 mask = ifa->ifa_mask;
418         u32 addr = ifa->ifa_local;
419         u32 prefix = ifa->ifa_address&mask;
420
421         if (ifa->ifa_flags&IFA_F_SECONDARY) {
422                 prim = inet_ifa_byprefix(in_dev, prefix, mask);
423                 if (prim == NULL) {
424                         printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n");
425                         return;
426                 }
427         }
428
429         fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
430
431         if (!(dev->flags&IFF_UP))
432                 return;
433
434         /* Add broadcast address, if it is explicitly assigned. */
435         if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF)
436                 fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
437
438         if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
439             (prefix != addr || ifa->ifa_prefixlen < 32)) {
440                 fib_magic(RTM_NEWROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
441                           RTN_UNICAST, prefix, ifa->ifa_prefixlen, prim);
442
443                 /* Add network specific broadcasts, when it takes a sense */
444                 if (ifa->ifa_prefixlen < 31) {
445                         fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
446                         fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix|~mask, 32, prim);
447                 }
448         }
449 }
450
451 static void fib_del_ifaddr(struct in_ifaddr *ifa)
452 {
453         struct in_device *in_dev = ifa->ifa_dev;
454         struct net_device *dev = in_dev->dev;
455         struct in_ifaddr *ifa1;
456         struct in_ifaddr *prim = ifa;
457         u32 brd = ifa->ifa_address|~ifa->ifa_mask;
458         u32 any = ifa->ifa_address&ifa->ifa_mask;
459 #define LOCAL_OK        1
460 #define BRD_OK          2
461 #define BRD0_OK         4
462 #define BRD1_OK         8
463         unsigned ok = 0;
464
465         if (!(ifa->ifa_flags&IFA_F_SECONDARY))
466                 fib_magic(RTM_DELROUTE, dev->flags&IFF_LOOPBACK ? RTN_LOCAL :
467                           RTN_UNICAST, any, ifa->ifa_prefixlen, prim);
468         else {
469                 prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
470                 if (prim == NULL) {
471                         printk(KERN_DEBUG "fib_del_ifaddr: bug: prim == NULL\n");
472                         return;
473                 }
474         }
475
476         /* Deletion is more complicated than add.
477            We should take care of not to delete too much :-)
478
479            Scan address list to be sure that addresses are really gone.
480          */
481
482         for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
483                 if (ifa->ifa_local == ifa1->ifa_local)
484                         ok |= LOCAL_OK;
485                 if (ifa->ifa_broadcast == ifa1->ifa_broadcast)
486                         ok |= BRD_OK;
487                 if (brd == ifa1->ifa_broadcast)
488                         ok |= BRD1_OK;
489                 if (any == ifa1->ifa_broadcast)
490                         ok |= BRD0_OK;
491         }
492
493         if (!(ok&BRD_OK))
494                 fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
495         if (!(ok&BRD1_OK))
496                 fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
497         if (!(ok&BRD0_OK))
498                 fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
499         if (!(ok&LOCAL_OK)) {
500                 fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
501
502                 /* Check, that this local address finally disappeared. */
503                 if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
504                         /* And the last, but not the least thing.
505                            We must flush stray FIB entries.
506
507                            First of all, we scan fib_info list searching
508                            for stray nexthop entries, then ignite fib_flush.
509                         */
510                         if (fib_sync_down(ifa->ifa_local, NULL, 0))
511                                 fib_flush();
512                 }
513         }
514 #undef LOCAL_OK
515 #undef BRD_OK
516 #undef BRD0_OK
517 #undef BRD1_OK
518 }
519
520 static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
521 {
522         
523         struct fib_result       res;
524         struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, 
525                                                             .fwmark = frn->fl_fwmark,
526                                                             .tos = frn->fl_tos,
527                                                             .scope = frn->fl_scope } } };
528         if (tb) {
529                 local_bh_disable();
530
531                 frn->tb_id = tb->tb_id;
532                 frn->err = tb->tb_lookup(tb, &fl, &res);
533
534                 if (!frn->err) {
535                         frn->prefixlen = res.prefixlen;
536                         frn->nh_sel = res.nh_sel;
537                         frn->type = res.type;
538                         frn->scope = res.scope;
539                 }
540                 local_bh_enable();
541         }
542 }
543
544 static void nl_fib_input(struct sock *sk, int len)
545 {
546         struct sk_buff *skb = NULL;
547         struct nlmsghdr *nlh = NULL;
548         struct fib_result_nl *frn;
549         u32 pid;     
550         struct fib_table *tb;
551         
552         skb = skb_dequeue(&sk->sk_receive_queue);
553         nlh = (struct nlmsghdr *)skb->data;
554         if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
555             nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) {
556                 kfree_skb(skb);
557                 return;
558         }
559         
560         frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
561         tb = fib_get_table(frn->tb_id_in);
562
563         nl_fib_lookup(frn, tb);
564         
565         pid = nlh->nlmsg_pid;           /*pid of sending process */
566         NETLINK_CB(skb).pid = 0;         /* from kernel */
567         NETLINK_CB(skb).dst_pid = pid;
568         NETLINK_CB(skb).dst_group = 0;  /* unicast */
569         netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
570 }    
571
572 static void nl_fib_lookup_init(void)
573 {
574       netlink_kernel_create(NETLINK_FIB_LOOKUP, 0, nl_fib_input, THIS_MODULE);
575 }
576
577 static void fib_disable_ip(struct net_device *dev, int force)
578 {
579         if (fib_sync_down(0, dev, force))
580                 fib_flush();
581         rt_cache_flush(0);
582         arp_ifdown(dev);
583 }
584
585 static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
586 {
587         struct in_ifaddr *ifa = (struct in_ifaddr*)ptr;
588
589         switch (event) {
590         case NETDEV_UP:
591                 fib_add_ifaddr(ifa);
592 #ifdef CONFIG_IP_ROUTE_MULTIPATH
593                 fib_sync_up(ifa->ifa_dev->dev);
594 #endif
595                 rt_cache_flush(-1);
596                 break;
597         case NETDEV_DOWN:
598                 fib_del_ifaddr(ifa);
599                 if (ifa->ifa_dev->ifa_list == NULL) {
600                         /* Last address was deleted from this interface.
601                            Disable IP.
602                          */
603                         fib_disable_ip(ifa->ifa_dev->dev, 1);
604                 } else {
605                         rt_cache_flush(-1);
606                 }
607                 break;
608         }
609         return NOTIFY_DONE;
610 }
611
612 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
613 {
614         struct net_device *dev = ptr;
615         struct in_device *in_dev = __in_dev_get_rtnl(dev);
616
617         if (event == NETDEV_UNREGISTER) {
618                 fib_disable_ip(dev, 2);
619                 return NOTIFY_DONE;
620         }
621
622         if (!in_dev)
623                 return NOTIFY_DONE;
624
625         switch (event) {
626         case NETDEV_UP:
627                 for_ifa(in_dev) {
628                         fib_add_ifaddr(ifa);
629                 } endfor_ifa(in_dev);
630 #ifdef CONFIG_IP_ROUTE_MULTIPATH
631                 fib_sync_up(dev);
632 #endif
633                 rt_cache_flush(-1);
634                 break;
635         case NETDEV_DOWN:
636                 fib_disable_ip(dev, 0);
637                 break;
638         case NETDEV_CHANGEMTU:
639         case NETDEV_CHANGE:
640                 rt_cache_flush(0);
641                 break;
642         }
643         return NOTIFY_DONE;
644 }
645
646 static struct notifier_block fib_inetaddr_notifier = {
647         .notifier_call =fib_inetaddr_event,
648 };
649
650 static struct notifier_block fib_netdev_notifier = {
651         .notifier_call =fib_netdev_event,
652 };
653
654 void __init ip_fib_init(void)
655 {
656 #ifndef CONFIG_IP_MULTIPLE_TABLES
657         ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
658         ip_fib_main_table  = fib_hash_init(RT_TABLE_MAIN);
659 #else
660         fib4_rules_init();
661 #endif
662
663         register_netdevice_notifier(&fib_netdev_notifier);
664         register_inetaddr_notifier(&fib_inetaddr_notifier);
665         nl_fib_lookup_init();
666 }
667
668 EXPORT_SYMBOL(inet_addr_type);
669 EXPORT_SYMBOL(ip_dev_find);