aboutsummaryrefslogtreecommitdiffstats
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.c492
1 files changed, 375 insertions, 117 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 31387abf53a2..9c399a70dd5d 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -15,7 +15,6 @@
15 * 2 of the License, or (at your option) any later version. 15 * 2 of the License, or (at your option) any later version.
16 */ 16 */
17 17
18#include <linux/config.h>
19#include <linux/module.h> 18#include <linux/module.h>
20#include <asm/uaccess.h> 19#include <asm/uaccess.h>
21#include <asm/system.h> 20#include <asm/system.h>
@@ -33,10 +32,12 @@
33#include <linux/inet.h> 32#include <linux/inet.h>
34#include <linux/inetdevice.h> 33#include <linux/inetdevice.h>
35#include <linux/netdevice.h> 34#include <linux/netdevice.h>
35#include <linux/if_addr.h>
36#include <linux/if_arp.h> 36#include <linux/if_arp.h>
37#include <linux/skbuff.h> 37#include <linux/skbuff.h>
38#include <linux/netlink.h> 38#include <linux/netlink.h>
39#include <linux/init.h> 39#include <linux/init.h>
40#include <linux/list.h>
40 41
41#include <net/ip.h> 42#include <net/ip.h>
42#include <net/protocol.h> 43#include <net/protocol.h>
@@ -51,48 +52,67 @@
51 52
52#ifndef CONFIG_IP_MULTIPLE_TABLES 53#ifndef CONFIG_IP_MULTIPLE_TABLES
53 54
54#define RT_TABLE_MIN RT_TABLE_MAIN
55
56struct fib_table *ip_fib_local_table; 55struct fib_table *ip_fib_local_table;
57struct fib_table *ip_fib_main_table; 56struct fib_table *ip_fib_main_table;
58 57
59#else 58#define FIB_TABLE_HASHSZ 1
59static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
60 60
61#define RT_TABLE_MIN 1 61#else
62 62
63struct fib_table *fib_tables[RT_TABLE_MAX+1]; 63#define FIB_TABLE_HASHSZ 256
64static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
64 65
65struct fib_table *__fib_new_table(int id) 66struct fib_table *fib_new_table(u32 id)
66{ 67{
67 struct fib_table *tb; 68 struct fib_table *tb;
69 unsigned int h;
68 70
71 if (id == 0)
72 id = RT_TABLE_MAIN;
73 tb = fib_get_table(id);
74 if (tb)
75 return tb;
69 tb = fib_hash_init(id); 76 tb = fib_hash_init(id);
70 if (!tb) 77 if (!tb)
71 return NULL; 78 return NULL;
72 fib_tables[id] = tb; 79 h = id & (FIB_TABLE_HASHSZ - 1);
80 hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]);
73 return tb; 81 return tb;
74} 82}
75 83
84struct fib_table *fib_get_table(u32 id)
85{
86 struct fib_table *tb;
87 struct hlist_node *node;
88 unsigned int h;
76 89
90 if (id == 0)
91 id = RT_TABLE_MAIN;
92 h = id & (FIB_TABLE_HASHSZ - 1);
93 rcu_read_lock();
94 hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb_hlist) {
95 if (tb->tb_id == id) {
96 rcu_read_unlock();
97 return tb;
98 }
99 }
100 rcu_read_unlock();
101 return NULL;
102}
77#endif /* CONFIG_IP_MULTIPLE_TABLES */ 103#endif /* CONFIG_IP_MULTIPLE_TABLES */
78 104
79
80static void fib_flush(void) 105static void fib_flush(void)
81{ 106{
82 int flushed = 0; 107 int flushed = 0;
83#ifdef CONFIG_IP_MULTIPLE_TABLES
84 struct fib_table *tb; 108 struct fib_table *tb;
85 int id; 109 struct hlist_node *node;
110 unsigned int h;
86 111
87 for (id = RT_TABLE_MAX; id>0; id--) { 112 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
88 if ((tb = fib_get_table(id))==NULL) 113 hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist)
89 continue; 114 flushed += tb->tb_flush(tb);
90 flushed += tb->tb_flush(tb);
91 } 115 }
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 116
97 if (flushed) 117 if (flushed)
98 rt_cache_flush(-1); 118 rt_cache_flush(-1);
@@ -102,7 +122,7 @@ static void fib_flush(void)
102 * Find the first device with a given source address. 122 * Find the first device with a given source address.
103 */ 123 */
104 124
105struct net_device * ip_dev_find(u32 addr) 125struct net_device * ip_dev_find(__be32 addr)
106{ 126{
107 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; 127 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
108 struct fib_result res; 128 struct fib_result res;
@@ -126,7 +146,7 @@ out:
126 return dev; 146 return dev;
127} 147}
128 148
129unsigned inet_addr_type(u32 addr) 149unsigned inet_addr_type(__be32 addr)
130{ 150{
131 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; 151 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
132 struct fib_result res; 152 struct fib_result res;
@@ -160,8 +180,8 @@ unsigned inet_addr_type(u32 addr)
160 - check, that packet arrived from expected physical interface. 180 - check, that packet arrived from expected physical interface.
161 */ 181 */
162 182
163int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, 183int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
164 struct net_device *dev, u32 *spec_dst, u32 *itag) 184 struct net_device *dev, __be32 *spec_dst, u32 *itag)
165{ 185{
166 struct in_device *in_dev; 186 struct in_device *in_dev;
167 struct flowi fl = { .nl_u = { .ip4_u = 187 struct flowi fl = { .nl_u = { .ip4_u =
@@ -233,42 +253,190 @@ e_inval:
233 253
234#ifndef CONFIG_IP_NOSIOCRT 254#ifndef CONFIG_IP_NOSIOCRT
235 255
256static inline __be32 sk_extract_addr(struct sockaddr *addr)
257{
258 return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
259}
260
261static int put_rtax(struct nlattr *mx, int len, int type, u32 value)
262{
263 struct nlattr *nla;
264
265 nla = (struct nlattr *) ((char *) mx + len);
266 nla->nla_type = type;
267 nla->nla_len = nla_attr_size(4);
268 *(u32 *) nla_data(nla) = value;
269
270 return len + nla_total_size(4);
271}
272
273static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
274 struct fib_config *cfg)
275{
276 __be32 addr;
277 int plen;
278
279 memset(cfg, 0, sizeof(*cfg));
280
281 if (rt->rt_dst.sa_family != AF_INET)
282 return -EAFNOSUPPORT;
283
284 /*
285 * Check mask for validity:
286 * a) it must be contiguous.
287 * b) destination must have all host bits clear.
288 * c) if application forgot to set correct family (AF_INET),
289 * reject request unless it is absolutely clear i.e.
290 * both family and mask are zero.
291 */
292 plen = 32;
293 addr = sk_extract_addr(&rt->rt_dst);
294 if (!(rt->rt_flags & RTF_HOST)) {
295 __be32 mask = sk_extract_addr(&rt->rt_genmask);
296
297 if (rt->rt_genmask.sa_family != AF_INET) {
298 if (mask || rt->rt_genmask.sa_family)
299 return -EAFNOSUPPORT;
300 }
301
302 if (bad_mask(mask, addr))
303 return -EINVAL;
304
305 plen = inet_mask_len(mask);
306 }
307
308 cfg->fc_dst_len = plen;
309 cfg->fc_dst = addr;
310
311 if (cmd != SIOCDELRT) {
312 cfg->fc_nlflags = NLM_F_CREATE;
313 cfg->fc_protocol = RTPROT_BOOT;
314 }
315
316 if (rt->rt_metric)
317 cfg->fc_priority = rt->rt_metric - 1;
318
319 if (rt->rt_flags & RTF_REJECT) {
320 cfg->fc_scope = RT_SCOPE_HOST;
321 cfg->fc_type = RTN_UNREACHABLE;
322 return 0;
323 }
324
325 cfg->fc_scope = RT_SCOPE_NOWHERE;
326 cfg->fc_type = RTN_UNICAST;
327
328 if (rt->rt_dev) {
329 char *colon;
330 struct net_device *dev;
331 char devname[IFNAMSIZ];
332
333 if (copy_from_user(devname, rt->rt_dev, IFNAMSIZ-1))
334 return -EFAULT;
335
336 devname[IFNAMSIZ-1] = 0;
337 colon = strchr(devname, ':');
338 if (colon)
339 *colon = 0;
340 dev = __dev_get_by_name(devname);
341 if (!dev)
342 return -ENODEV;
343 cfg->fc_oif = dev->ifindex;
344 if (colon) {
345 struct in_ifaddr *ifa;
346 struct in_device *in_dev = __in_dev_get_rtnl(dev);
347 if (!in_dev)
348 return -ENODEV;
349 *colon = ':';
350 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
351 if (strcmp(ifa->ifa_label, devname) == 0)
352 break;
353 if (ifa == NULL)
354 return -ENODEV;
355 cfg->fc_prefsrc = ifa->ifa_local;
356 }
357 }
358
359 addr = sk_extract_addr(&rt->rt_gateway);
360 if (rt->rt_gateway.sa_family == AF_INET && addr) {
361 cfg->fc_gw = addr;
362 if (rt->rt_flags & RTF_GATEWAY &&
363 inet_addr_type(addr) == RTN_UNICAST)
364 cfg->fc_scope = RT_SCOPE_UNIVERSE;
365 }
366
367 if (cmd == SIOCDELRT)
368 return 0;
369
370 if (rt->rt_flags & RTF_GATEWAY && !cfg->fc_gw)
371 return -EINVAL;
372
373 if (cfg->fc_scope == RT_SCOPE_NOWHERE)
374 cfg->fc_scope = RT_SCOPE_LINK;
375
376 if (rt->rt_flags & (RTF_MTU | RTF_WINDOW | RTF_IRTT)) {
377 struct nlattr *mx;
378 int len = 0;
379
380 mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL);
381 if (mx == NULL)
382 return -ENOMEM;
383
384 if (rt->rt_flags & RTF_MTU)
385 len = put_rtax(mx, len, RTAX_ADVMSS, rt->rt_mtu - 40);
386
387 if (rt->rt_flags & RTF_WINDOW)
388 len = put_rtax(mx, len, RTAX_WINDOW, rt->rt_window);
389
390 if (rt->rt_flags & RTF_IRTT)
391 len = put_rtax(mx, len, RTAX_RTT, rt->rt_irtt << 3);
392
393 cfg->fc_mx = mx;
394 cfg->fc_mx_len = len;
395 }
396
397 return 0;
398}
399
236/* 400/*
237 * Handle IP routing ioctl calls. These are used to manipulate the routing tables 401 * Handle IP routing ioctl calls. These are used to manipulate the routing tables
238 */ 402 */
239 403
240int ip_rt_ioctl(unsigned int cmd, void __user *arg) 404int ip_rt_ioctl(unsigned int cmd, void __user *arg)
241{ 405{
406 struct fib_config cfg;
407 struct rtentry rt;
242 int err; 408 int err;
243 struct kern_rta rta;
244 struct rtentry r;
245 struct {
246 struct nlmsghdr nlh;
247 struct rtmsg rtm;
248 } req;
249 409
250 switch (cmd) { 410 switch (cmd) {
251 case SIOCADDRT: /* Add a route */ 411 case SIOCADDRT: /* Add a route */
252 case SIOCDELRT: /* Delete a route */ 412 case SIOCDELRT: /* Delete a route */
253 if (!capable(CAP_NET_ADMIN)) 413 if (!capable(CAP_NET_ADMIN))
254 return -EPERM; 414 return -EPERM;
255 if (copy_from_user(&r, arg, sizeof(struct rtentry))) 415
416 if (copy_from_user(&rt, arg, sizeof(rt)))
256 return -EFAULT; 417 return -EFAULT;
418
257 rtnl_lock(); 419 rtnl_lock();
258 err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r); 420 err = rtentry_to_fib_config(cmd, &rt, &cfg);
259 if (err == 0) { 421 if (err == 0) {
422 struct fib_table *tb;
423
260 if (cmd == SIOCDELRT) { 424 if (cmd == SIOCDELRT) {
261 struct fib_table *tb = fib_get_table(req.rtm.rtm_table); 425 tb = fib_get_table(cfg.fc_table);
262 err = -ESRCH;
263 if (tb) 426 if (tb)
264 err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); 427 err = tb->tb_delete(tb, &cfg);
428 else
429 err = -ESRCH;
265 } else { 430 } else {
266 struct fib_table *tb = fib_new_table(req.rtm.rtm_table); 431 tb = fib_new_table(cfg.fc_table);
267 err = -ENOBUFS;
268 if (tb) 432 if (tb)
269 err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); 433 err = tb->tb_insert(tb, &cfg);
434 else
435 err = -ENOBUFS;
270 } 436 }
271 kfree(rta.rta_mx); 437
438 /* allocated by rtentry_to_fib_config() */
439 kfree(cfg.fc_mx);
272 } 440 }
273 rtnl_unlock(); 441 rtnl_unlock();
274 return err; 442 return err;
@@ -285,77 +453,169 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)
285 453
286#endif 454#endif
287 455
288static int inet_check_attr(struct rtmsg *r, struct rtattr **rta) 456struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
457 [RTA_DST] = { .type = NLA_U32 },
458 [RTA_SRC] = { .type = NLA_U32 },
459 [RTA_IIF] = { .type = NLA_U32 },
460 [RTA_OIF] = { .type = NLA_U32 },
461 [RTA_GATEWAY] = { .type = NLA_U32 },
462 [RTA_PRIORITY] = { .type = NLA_U32 },
463 [RTA_PREFSRC] = { .type = NLA_U32 },
464 [RTA_METRICS] = { .type = NLA_NESTED },
465 [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
466 [RTA_PROTOINFO] = { .type = NLA_U32 },
467 [RTA_FLOW] = { .type = NLA_U32 },
468 [RTA_MP_ALGO] = { .type = NLA_U32 },
469};
470
471static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
472 struct fib_config *cfg)
289{ 473{
290 int i; 474 struct nlattr *attr;
291 475 int err, remaining;
292 for (i=1; i<=RTA_MAX; i++, rta++) { 476 struct rtmsg *rtm;
293 struct rtattr *attr = *rta; 477
294 if (attr) { 478 err = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipv4_policy);
295 if (RTA_PAYLOAD(attr) < 4) 479 if (err < 0)
296 return -EINVAL; 480 goto errout;
297 if (i != RTA_MULTIPATH && i != RTA_METRICS) 481
298 *rta = (struct rtattr*)RTA_DATA(attr); 482 memset(cfg, 0, sizeof(*cfg));
483
484 rtm = nlmsg_data(nlh);
485 cfg->fc_family = rtm->rtm_family;
486 cfg->fc_dst_len = rtm->rtm_dst_len;
487 cfg->fc_src_len = rtm->rtm_src_len;
488 cfg->fc_tos = rtm->rtm_tos;
489 cfg->fc_table = rtm->rtm_table;
490 cfg->fc_protocol = rtm->rtm_protocol;
491 cfg->fc_scope = rtm->rtm_scope;
492 cfg->fc_type = rtm->rtm_type;
493 cfg->fc_flags = rtm->rtm_flags;
494 cfg->fc_nlflags = nlh->nlmsg_flags;
495
496 cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
497 cfg->fc_nlinfo.nlh = nlh;
498
499 nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
500 switch (attr->nla_type) {
501 case RTA_DST:
502 cfg->fc_dst = nla_get_be32(attr);
503 break;
504 case RTA_SRC:
505 cfg->fc_src = nla_get_be32(attr);
506 break;
507 case RTA_OIF:
508 cfg->fc_oif = nla_get_u32(attr);
509 break;
510 case RTA_GATEWAY:
511 cfg->fc_gw = nla_get_be32(attr);
512 break;
513 case RTA_PRIORITY:
514 cfg->fc_priority = nla_get_u32(attr);
515 break;
516 case RTA_PREFSRC:
517 cfg->fc_prefsrc = nla_get_be32(attr);
518 break;
519 case RTA_METRICS:
520 cfg->fc_mx = nla_data(attr);
521 cfg->fc_mx_len = nla_len(attr);
522 break;
523 case RTA_MULTIPATH:
524 cfg->fc_mp = nla_data(attr);
525 cfg->fc_mp_len = nla_len(attr);
526 break;
527 case RTA_FLOW:
528 cfg->fc_flow = nla_get_u32(attr);
529 break;
530 case RTA_MP_ALGO:
531 cfg->fc_mp_alg = nla_get_u32(attr);
532 break;
533 case RTA_TABLE:
534 cfg->fc_table = nla_get_u32(attr);
535 break;
299 } 536 }
300 } 537 }
538
301 return 0; 539 return 0;
540errout:
541 return err;
302} 542}
303 543
304int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 544int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
305{ 545{
306 struct fib_table * tb; 546 struct fib_config cfg;
307 struct rtattr **rta = arg; 547 struct fib_table *tb;
308 struct rtmsg *r = NLMSG_DATA(nlh); 548 int err;
309 549
310 if (inet_check_attr(r, rta)) 550 err = rtm_to_fib_config(skb, nlh, &cfg);
311 return -EINVAL; 551 if (err < 0)
552 goto errout;
312 553
313 tb = fib_get_table(r->rtm_table); 554 tb = fib_get_table(cfg.fc_table);
314 if (tb) 555 if (tb == NULL) {
315 return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); 556 err = -ESRCH;
316 return -ESRCH; 557 goto errout;
558 }
559
560 err = tb->tb_delete(tb, &cfg);
561errout:
562 return err;
317} 563}
318 564
319int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 565int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
320{ 566{
321 struct fib_table * tb; 567 struct fib_config cfg;
322 struct rtattr **rta = arg; 568 struct fib_table *tb;
323 struct rtmsg *r = NLMSG_DATA(nlh); 569 int err;
324 570
325 if (inet_check_attr(r, rta)) 571 err = rtm_to_fib_config(skb, nlh, &cfg);
326 return -EINVAL; 572 if (err < 0)
573 goto errout;
327 574
328 tb = fib_new_table(r->rtm_table); 575 tb = fib_new_table(cfg.fc_table);
329 if (tb) 576 if (tb == NULL) {
330 return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); 577 err = -ENOBUFS;
331 return -ENOBUFS; 578 goto errout;
579 }
580
581 err = tb->tb_insert(tb, &cfg);
582errout:
583 return err;
332} 584}
333 585
334int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) 586int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
335{ 587{
336 int t; 588 unsigned int h, s_h;
337 int s_t; 589 unsigned int e = 0, s_e;
338 struct fib_table *tb; 590 struct fib_table *tb;
591 struct hlist_node *node;
592 int dumped = 0;
339 593
340 if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && 594 if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
341 ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED) 595 ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
342 return ip_rt_dump(skb, cb); 596 return ip_rt_dump(skb, cb);
343 597
344 s_t = cb->args[0]; 598 s_h = cb->args[0];
345 if (s_t == 0) 599 s_e = cb->args[1];
346 s_t = cb->args[0] = RT_TABLE_MIN; 600
347 601 for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
348 for (t=s_t; t<=RT_TABLE_MAX; t++) { 602 e = 0;
349 if (t < s_t) continue; 603 hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
350 if (t > s_t) 604 if (e < s_e)
351 memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); 605 goto next;
352 if ((tb = fib_get_table(t))==NULL) 606 if (dumped)
353 continue; 607 memset(&cb->args[2], 0, sizeof(cb->args) -
354 if (tb->tb_dump(tb, skb, cb) < 0) 608 2 * sizeof(cb->args[0]));
355 break; 609 if (tb->tb_dump(tb, skb, cb) < 0)
610 goto out;
611 dumped = 1;
612next:
613 e++;
614 }
356 } 615 }
357 616out:
358 cb->args[0] = t; 617 cb->args[1] = e;
618 cb->args[0] = h;
359 619
360 return skb->len; 620 return skb->len;
361} 621}
@@ -367,17 +627,18 @@ int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
367 only when netlink is already locked. 627 only when netlink is already locked.
368 */ 628 */
369 629
370static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa) 630static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
371{ 631{
372 struct fib_table * tb; 632 struct fib_table *tb;
373 struct { 633 struct fib_config cfg = {
374 struct nlmsghdr nlh; 634 .fc_protocol = RTPROT_KERNEL,
375 struct rtmsg rtm; 635 .fc_type = type,
376 } req; 636 .fc_dst = dst,
377 struct kern_rta rta; 637 .fc_dst_len = dst_len,
378 638 .fc_prefsrc = ifa->ifa_local,
379 memset(&req.rtm, 0, sizeof(req.rtm)); 639 .fc_oif = ifa->ifa_dev->dev->ifindex,
380 memset(&rta, 0, sizeof(rta)); 640 .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
641 };
381 642
382 if (type == RTN_UNICAST) 643 if (type == RTN_UNICAST)
383 tb = fib_new_table(RT_TABLE_MAIN); 644 tb = fib_new_table(RT_TABLE_MAIN);
@@ -387,26 +648,17 @@ static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr
387 if (tb == NULL) 648 if (tb == NULL)
388 return; 649 return;
389 650
390 req.nlh.nlmsg_len = sizeof(req); 651 cfg.fc_table = tb->tb_id;
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 652
396 req.rtm.rtm_dst_len = dst_len; 653 if (type != RTN_LOCAL)
397 req.rtm.rtm_table = tb->tb_id; 654 cfg.fc_scope = RT_SCOPE_LINK;
398 req.rtm.rtm_protocol = RTPROT_KERNEL; 655 else
399 req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST); 656 cfg.fc_scope = 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 657
406 if (cmd == RTM_NEWROUTE) 658 if (cmd == RTM_NEWROUTE)
407 tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); 659 tb->tb_insert(tb, &cfg);
408 else 660 else
409 tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); 661 tb->tb_delete(tb, &cfg);
410} 662}
411 663
412void fib_add_ifaddr(struct in_ifaddr *ifa) 664void fib_add_ifaddr(struct in_ifaddr *ifa)
@@ -414,9 +666,9 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
414 struct in_device *in_dev = ifa->ifa_dev; 666 struct in_device *in_dev = ifa->ifa_dev;
415 struct net_device *dev = in_dev->dev; 667 struct net_device *dev = in_dev->dev;
416 struct in_ifaddr *prim = ifa; 668 struct in_ifaddr *prim = ifa;
417 u32 mask = ifa->ifa_mask; 669 __be32 mask = ifa->ifa_mask;
418 u32 addr = ifa->ifa_local; 670 __be32 addr = ifa->ifa_local;
419 u32 prefix = ifa->ifa_address&mask; 671 __be32 prefix = ifa->ifa_address&mask;
420 672
421 if (ifa->ifa_flags&IFA_F_SECONDARY) { 673 if (ifa->ifa_flags&IFA_F_SECONDARY) {
422 prim = inet_ifa_byprefix(in_dev, prefix, mask); 674 prim = inet_ifa_byprefix(in_dev, prefix, mask);
@@ -432,7 +684,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
432 return; 684 return;
433 685
434 /* Add broadcast address, if it is explicitly assigned. */ 686 /* Add broadcast address, if it is explicitly assigned. */
435 if (ifa->ifa_broadcast && ifa->ifa_broadcast != 0xFFFFFFFF) 687 if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
436 fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); 688 fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
437 689
438 if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) && 690 if (!ZERONET(prefix) && !(ifa->ifa_flags&IFA_F_SECONDARY) &&
@@ -454,8 +706,8 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
454 struct net_device *dev = in_dev->dev; 706 struct net_device *dev = in_dev->dev;
455 struct in_ifaddr *ifa1; 707 struct in_ifaddr *ifa1;
456 struct in_ifaddr *prim = ifa; 708 struct in_ifaddr *prim = ifa;
457 u32 brd = ifa->ifa_address|~ifa->ifa_mask; 709 __be32 brd = ifa->ifa_address|~ifa->ifa_mask;
458 u32 any = ifa->ifa_address&ifa->ifa_mask; 710 __be32 any = ifa->ifa_address&ifa->ifa_mask;
459#define LOCAL_OK 1 711#define LOCAL_OK 1
460#define BRD_OK 2 712#define BRD_OK 2
461#define BRD0_OK 4 713#define BRD0_OK 4
@@ -653,11 +905,17 @@ static struct notifier_block fib_netdev_notifier = {
653 905
654void __init ip_fib_init(void) 906void __init ip_fib_init(void)
655{ 907{
908 unsigned int i;
909
910 for (i = 0; i < FIB_TABLE_HASHSZ; i++)
911 INIT_HLIST_HEAD(&fib_table_hash[i]);
656#ifndef CONFIG_IP_MULTIPLE_TABLES 912#ifndef CONFIG_IP_MULTIPLE_TABLES
657 ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); 913 ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
914 hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
658 ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN); 915 ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
916 hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
659#else 917#else
660 fib_rules_init(); 918 fib4_rules_init();
661#endif 919#endif
662 920
663 register_netdevice_notifier(&fib_netdev_notifier); 921 register_netdevice_notifier(&fib_netdev_notifier);