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.c472
1 files changed, 366 insertions, 106 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index ba2a70745a63..cfb527c060e4 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -32,10 +32,12 @@
32#include <linux/inet.h> 32#include <linux/inet.h>
33#include <linux/inetdevice.h> 33#include <linux/inetdevice.h>
34#include <linux/netdevice.h> 34#include <linux/netdevice.h>
35#include <linux/if_addr.h>
35#include <linux/if_arp.h> 36#include <linux/if_arp.h>
36#include <linux/skbuff.h> 37#include <linux/skbuff.h>
37#include <linux/netlink.h> 38#include <linux/netlink.h>
38#include <linux/init.h> 39#include <linux/init.h>
40#include <linux/list.h>
39 41
40#include <net/ip.h> 42#include <net/ip.h>
41#include <net/protocol.h> 43#include <net/protocol.h>
@@ -50,48 +52,67 @@
50 52
51#ifndef CONFIG_IP_MULTIPLE_TABLES 53#ifndef CONFIG_IP_MULTIPLE_TABLES
52 54
53#define RT_TABLE_MIN RT_TABLE_MAIN
54
55struct fib_table *ip_fib_local_table; 55struct fib_table *ip_fib_local_table;
56struct fib_table *ip_fib_main_table; 56struct fib_table *ip_fib_main_table;
57 57
58#else 58#define FIB_TABLE_HASHSZ 1
59static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
59 60
60#define RT_TABLE_MIN 1 61#else
61 62
62struct fib_table *fib_tables[RT_TABLE_MAX+1]; 63#define FIB_TABLE_HASHSZ 256
64static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
63 65
64struct fib_table *__fib_new_table(int id) 66struct fib_table *fib_new_table(u32 id)
65{ 67{
66 struct fib_table *tb; 68 struct fib_table *tb;
69 unsigned int h;
67 70
71 if (id == 0)
72 id = RT_TABLE_MAIN;
73 tb = fib_get_table(id);
74 if (tb)
75 return tb;
68 tb = fib_hash_init(id); 76 tb = fib_hash_init(id);
69 if (!tb) 77 if (!tb)
70 return NULL; 78 return NULL;
71 fib_tables[id] = tb; 79 h = id & (FIB_TABLE_HASHSZ - 1);
80 hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]);
72 return tb; 81 return tb;
73} 82}
74 83
84struct fib_table *fib_get_table(u32 id)
85{
86 struct fib_table *tb;
87 struct hlist_node *node;
88 unsigned int h;
75 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}
76#endif /* CONFIG_IP_MULTIPLE_TABLES */ 103#endif /* CONFIG_IP_MULTIPLE_TABLES */
77 104
78
79static void fib_flush(void) 105static void fib_flush(void)
80{ 106{
81 int flushed = 0; 107 int flushed = 0;
82#ifdef CONFIG_IP_MULTIPLE_TABLES
83 struct fib_table *tb; 108 struct fib_table *tb;
84 int id; 109 struct hlist_node *node;
110 unsigned int h;
85 111
86 for (id = RT_TABLE_MAX; id>0; id--) { 112 for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
87 if ((tb = fib_get_table(id))==NULL) 113 hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist)
88 continue; 114 flushed += tb->tb_flush(tb);
89 flushed += tb->tb_flush(tb);
90 } 115 }
91#else /* CONFIG_IP_MULTIPLE_TABLES */
92 flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
93 flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
94#endif /* CONFIG_IP_MULTIPLE_TABLES */
95 116
96 if (flushed) 117 if (flushed)
97 rt_cache_flush(-1); 118 rt_cache_flush(-1);
@@ -232,42 +253,190 @@ e_inval:
232 253
233#ifndef CONFIG_IP_NOSIOCRT 254#ifndef CONFIG_IP_NOSIOCRT
234 255
256static inline u32 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 u32 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 u32 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
235/* 400/*
236 * 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
237 */ 402 */
238 403
239int ip_rt_ioctl(unsigned int cmd, void __user *arg) 404int ip_rt_ioctl(unsigned int cmd, void __user *arg)
240{ 405{
406 struct fib_config cfg;
407 struct rtentry rt;
241 int err; 408 int err;
242 struct kern_rta rta;
243 struct rtentry r;
244 struct {
245 struct nlmsghdr nlh;
246 struct rtmsg rtm;
247 } req;
248 409
249 switch (cmd) { 410 switch (cmd) {
250 case SIOCADDRT: /* Add a route */ 411 case SIOCADDRT: /* Add a route */
251 case SIOCDELRT: /* Delete a route */ 412 case SIOCDELRT: /* Delete a route */
252 if (!capable(CAP_NET_ADMIN)) 413 if (!capable(CAP_NET_ADMIN))
253 return -EPERM; 414 return -EPERM;
254 if (copy_from_user(&r, arg, sizeof(struct rtentry))) 415
416 if (copy_from_user(&rt, arg, sizeof(rt)))
255 return -EFAULT; 417 return -EFAULT;
418
256 rtnl_lock(); 419 rtnl_lock();
257 err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r); 420 err = rtentry_to_fib_config(cmd, &rt, &cfg);
258 if (err == 0) { 421 if (err == 0) {
422 struct fib_table *tb;
423
259 if (cmd == SIOCDELRT) { 424 if (cmd == SIOCDELRT) {
260 struct fib_table *tb = fib_get_table(req.rtm.rtm_table); 425 tb = fib_get_table(cfg.fc_table);
261 err = -ESRCH;
262 if (tb) 426 if (tb)
263 err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); 427 err = tb->tb_delete(tb, &cfg);
428 else
429 err = -ESRCH;
264 } else { 430 } else {
265 struct fib_table *tb = fib_new_table(req.rtm.rtm_table); 431 tb = fib_new_table(cfg.fc_table);
266 err = -ENOBUFS;
267 if (tb) 432 if (tb)
268 err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); 433 err = tb->tb_insert(tb, &cfg);
434 else
435 err = -ENOBUFS;
269 } 436 }
270 kfree(rta.rta_mx); 437
438 /* allocated by rtentry_to_fib_config() */
439 kfree(cfg.fc_mx);
271 } 440 }
272 rtnl_unlock(); 441 rtnl_unlock();
273 return err; 442 return err;
@@ -284,77 +453,169 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)
284 453
285#endif 454#endif
286 455
287static 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)
288{ 473{
289 int i; 474 struct nlattr *attr;
290 475 int err, remaining;
291 for (i=1; i<=RTA_MAX; i++, rta++) { 476 struct rtmsg *rtm;
292 struct rtattr *attr = *rta; 477
293 if (attr) { 478 err = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipv4_policy);
294 if (RTA_PAYLOAD(attr) < 4) 479 if (err < 0)
295 return -EINVAL; 480 goto errout;
296 if (i != RTA_MULTIPATH && i != RTA_METRICS) 481
297 *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_u32(attr);
503 break;
504 case RTA_SRC:
505 cfg->fc_src = nla_get_u32(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_u32(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_u32(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;
298 } 536 }
299 } 537 }
538
300 return 0; 539 return 0;
540errout:
541 return err;
301} 542}
302 543
303int 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)
304{ 545{
305 struct fib_table * tb; 546 struct fib_config cfg;
306 struct rtattr **rta = arg; 547 struct fib_table *tb;
307 struct rtmsg *r = NLMSG_DATA(nlh); 548 int err;
308 549
309 if (inet_check_attr(r, rta)) 550 err = rtm_to_fib_config(skb, nlh, &cfg);
310 return -EINVAL; 551 if (err < 0)
552 goto errout;
311 553
312 tb = fib_get_table(r->rtm_table); 554 tb = fib_get_table(cfg.fc_table);
313 if (tb) 555 if (tb == NULL) {
314 return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); 556 err = -ESRCH;
315 return -ESRCH; 557 goto errout;
558 }
559
560 err = tb->tb_delete(tb, &cfg);
561errout:
562 return err;
316} 563}
317 564
318int 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)
319{ 566{
320 struct fib_table * tb; 567 struct fib_config cfg;
321 struct rtattr **rta = arg; 568 struct fib_table *tb;
322 struct rtmsg *r = NLMSG_DATA(nlh); 569 int err;
323 570
324 if (inet_check_attr(r, rta)) 571 err = rtm_to_fib_config(skb, nlh, &cfg);
325 return -EINVAL; 572 if (err < 0)
573 goto errout;
326 574
327 tb = fib_new_table(r->rtm_table); 575 tb = fib_new_table(cfg.fc_table);
328 if (tb) 576 if (tb == NULL) {
329 return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); 577 err = -ENOBUFS;
330 return -ENOBUFS; 578 goto errout;
579 }
580
581 err = tb->tb_insert(tb, &cfg);
582errout:
583 return err;
331} 584}
332 585
333int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) 586int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
334{ 587{
335 int t; 588 unsigned int h, s_h;
336 int s_t; 589 unsigned int e = 0, s_e;
337 struct fib_table *tb; 590 struct fib_table *tb;
591 struct hlist_node *node;
592 int dumped = 0;
338 593
339 if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && 594 if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
340 ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED) 595 ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
341 return ip_rt_dump(skb, cb); 596 return ip_rt_dump(skb, cb);
342 597
343 s_t = cb->args[0]; 598 s_h = cb->args[0];
344 if (s_t == 0) 599 s_e = cb->args[1];
345 s_t = cb->args[0] = RT_TABLE_MIN; 600
346 601 for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
347 for (t=s_t; t<=RT_TABLE_MAX; t++) { 602 e = 0;
348 if (t < s_t) continue; 603 hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
349 if (t > s_t) 604 if (e < s_e)
350 memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); 605 goto next;
351 if ((tb = fib_get_table(t))==NULL) 606 if (dumped)
352 continue; 607 memset(&cb->args[2], 0, sizeof(cb->args) -
353 if (tb->tb_dump(tb, skb, cb) < 0) 608 2 * sizeof(cb->args[0]));
354 break; 609 if (tb->tb_dump(tb, skb, cb) < 0)
610 goto out;
611 dumped = 1;
612next:
613 e++;
614 }
355 } 615 }
356 616out:
357 cb->args[0] = t; 617 cb->args[1] = e;
618 cb->args[0] = h;
358 619
359 return skb->len; 620 return skb->len;
360} 621}
@@ -366,17 +627,19 @@ int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
366 only when netlink is already locked. 627 only when netlink is already locked.
367 */ 628 */
368 629
369static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa) 630static void fib_magic(int cmd, int type, u32 dst, int dst_len,
631 struct in_ifaddr *ifa)
370{ 632{
371 struct fib_table * tb; 633 struct fib_table *tb;
372 struct { 634 struct fib_config cfg = {
373 struct nlmsghdr nlh; 635 .fc_protocol = RTPROT_KERNEL,
374 struct rtmsg rtm; 636 .fc_type = type,
375 } req; 637 .fc_dst = dst,
376 struct kern_rta rta; 638 .fc_dst_len = dst_len,
377 639 .fc_prefsrc = ifa->ifa_local,
378 memset(&req.rtm, 0, sizeof(req.rtm)); 640 .fc_oif = ifa->ifa_dev->dev->ifindex,
379 memset(&rta, 0, sizeof(rta)); 641 .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
642 };
380 643
381 if (type == RTN_UNICAST) 644 if (type == RTN_UNICAST)
382 tb = fib_new_table(RT_TABLE_MAIN); 645 tb = fib_new_table(RT_TABLE_MAIN);
@@ -386,26 +649,17 @@ static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr
386 if (tb == NULL) 649 if (tb == NULL)
387 return; 650 return;
388 651
389 req.nlh.nlmsg_len = sizeof(req); 652 cfg.fc_table = tb->tb_id;
390 req.nlh.nlmsg_type = cmd;
391 req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
392 req.nlh.nlmsg_pid = 0;
393 req.nlh.nlmsg_seq = 0;
394 653
395 req.rtm.rtm_dst_len = dst_len; 654 if (type != RTN_LOCAL)
396 req.rtm.rtm_table = tb->tb_id; 655 cfg.fc_scope = RT_SCOPE_LINK;
397 req.rtm.rtm_protocol = RTPROT_KERNEL; 656 else
398 req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST); 657 cfg.fc_scope = RT_SCOPE_HOST;
399 req.rtm.rtm_type = type;
400
401 rta.rta_dst = &dst;
402 rta.rta_prefsrc = &ifa->ifa_local;
403 rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
404 658
405 if (cmd == RTM_NEWROUTE) 659 if (cmd == RTM_NEWROUTE)
406 tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); 660 tb->tb_insert(tb, &cfg);
407 else 661 else
408 tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); 662 tb->tb_delete(tb, &cfg);
409} 663}
410 664
411void fib_add_ifaddr(struct in_ifaddr *ifa) 665void fib_add_ifaddr(struct in_ifaddr *ifa)
@@ -652,11 +906,17 @@ static struct notifier_block fib_netdev_notifier = {
652 906
653void __init ip_fib_init(void) 907void __init ip_fib_init(void)
654{ 908{
909 unsigned int i;
910
911 for (i = 0; i < FIB_TABLE_HASHSZ; i++)
912 INIT_HLIST_HEAD(&fib_table_hash[i]);
655#ifndef CONFIG_IP_MULTIPLE_TABLES 913#ifndef CONFIG_IP_MULTIPLE_TABLES
656 ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); 914 ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
915 hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
657 ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN); 916 ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
917 hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
658#else 918#else
659 fib_rules_init(); 919 fib4_rules_init();
660#endif 920#endif
661 921
662 register_netdevice_notifier(&fib_netdev_notifier); 922 register_netdevice_notifier(&fib_netdev_notifier);