X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fipv4%2Ffib_frontend.c;h=86ff2711fc957977f179da841a0ffc3b698e75ac;hb=7fcb98d58cb4d18af6386f71025fc5192f25fbca;hp=15909a9fa9b2f855a0c95729f1119002dd6e7b9b;hpb=1bad118a330d494b23663fce94d4e9d9d5065fa7;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 15909a9..86ff271 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -47,19 +47,17 @@ #include #include -#define FFprint(a...) printk(KERN_DEBUG a) - #ifndef CONFIG_IP_MULTIPLE_TABLES static int __net_init fib4_rules_init(struct net *net) { struct fib_table *local_table, *main_table; - local_table = fib_hash_init(RT_TABLE_LOCAL); + local_table = fib_hash_table(RT_TABLE_LOCAL); if (local_table == NULL) return -ENOMEM; - main_table = fib_hash_init(RT_TABLE_MAIN); + main_table = fib_hash_table(RT_TABLE_MAIN); if (main_table == NULL) goto fail; @@ -85,7 +83,8 @@ struct fib_table *fib_new_table(struct net *net, u32 id) tb = fib_get_table(net, id); if (tb) return tb; - tb = fib_hash_init(id); + + tb = fib_hash_table(id); if (!tb) return NULL; h = id & (FIB_TABLE_HASHSZ - 1); @@ -117,6 +116,21 @@ struct fib_table *fib_get_table(struct net *net, u32 id) } #endif /* CONFIG_IP_MULTIPLE_TABLES */ +void fib_select_default(struct net *net, + const struct flowi *flp, struct fib_result *res) +{ + struct fib_table *tb; + int table = RT_TABLE_MAIN; +#ifdef CONFIG_IP_MULTIPLE_TABLES + if (res->r == NULL || res->r->action != FR_ACT_TO_TBL) + return; + table = res->r->table; +#endif + tb = fib_get_table(net, table); + if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) + tb->tb_select_default(tb, flp, res); +} + static void fib_flush(struct net *net) { int flushed = 0; @@ -139,7 +153,7 @@ static void fib_flush(struct net *net) * Find the first device with a given source address. */ -struct net_device * ip_dev_find(__be32 addr) +struct net_device * ip_dev_find(struct net *net, __be32 addr) { struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; struct fib_result res; @@ -150,7 +164,7 @@ struct net_device * ip_dev_find(__be32 addr) res.r = NULL; #endif - local_table = fib_get_table(&init_net, RT_TABLE_LOCAL); + local_table = fib_get_table(net, RT_TABLE_LOCAL); if (!local_table || local_table->tb_lookup(local_table, &fl, &res)) return NULL; if (res.type != RTN_LOCAL) @@ -177,7 +191,7 @@ static inline unsigned __inet_dev_addr_type(struct net *net, unsigned ret = RTN_BROADCAST; struct fib_table *local_table; - if (ipv4_is_zeronet(addr) || ipv4_is_badclass(addr)) + if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr)) return RTN_BROADCAST; if (ipv4_is_multicast(addr)) return RTN_MULTICAST; @@ -229,6 +243,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, struct fib_result res; int no_addr, rpf; int ret; + struct net *net; no_addr = rpf = 0; rcu_read_lock(); @@ -242,7 +257,8 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, if (in_dev == NULL) goto e_inval; - if (fib_lookup(&fl, &res)) + net = dev->nd_net; + if (fib_lookup(net, &fl, &res)) goto last_resort; if (res.type != RTN_UNICAST) goto e_inval_res; @@ -266,7 +282,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, fl.oif = dev->ifindex; ret = 0; - if (fib_lookup(&fl, &res) == 0) { + if (fib_lookup(net, &fl, &res) == 0) { if (res.type == RTN_UNICAST) { *spec_dst = FIB_RES_PREFSRC(res); ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; @@ -572,9 +588,6 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *ar struct fib_table *tb; int err; - if (net != &init_net) - return -EINVAL; - err = rtm_to_fib_config(net, skb, nlh, &cfg); if (err < 0) goto errout; @@ -597,14 +610,11 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *ar struct fib_table *tb; int err; - if (net != &init_net) - return -EINVAL; - err = rtm_to_fib_config(net, skb, nlh, &cfg); if (err < 0) goto errout; - tb = fib_new_table(&init_net, cfg.fc_table); + tb = fib_new_table(net, cfg.fc_table); if (tb == NULL) { err = -ENOBUFS; goto errout; @@ -625,9 +635,6 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) struct hlist_head *head; int dumped = 0; - if (net != &init_net) - return 0; - if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) return ip_rt_dump(skb, cb); @@ -715,7 +722,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) if (ifa->ifa_flags&IFA_F_SECONDARY) { prim = inet_ifa_byprefix(in_dev, prefix, mask); if (prim == NULL) { - printk(KERN_DEBUG "fib_add_ifaddr: bug: prim == NULL\n"); + printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL\n"); return; } } @@ -762,7 +769,7 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) else { prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); if (prim == NULL) { - printk(KERN_DEBUG "fib_del_ifaddr: bug: prim == NULL\n"); + printk(KERN_WARNING "fib_del_ifaddr: bug: prim == NULL\n"); return; } } @@ -794,15 +801,15 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim); /* Check, that this local address finally disappeared. */ - if (inet_addr_type(&init_net, ifa->ifa_local) != RTN_LOCAL) { + if (inet_addr_type(dev->nd_net, ifa->ifa_local) != RTN_LOCAL) { /* And the last, but not the least thing. We must flush stray FIB entries. 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, 0)) - fib_flush(&init_net); + if (fib_sync_down_addr(dev->nd_net, ifa->ifa_local)) + fib_flush(dev->nd_net); } } #undef LOCAL_OK @@ -879,25 +886,20 @@ static int nl_fib_lookup_init(struct net *net) nl_fib_input, NULL, THIS_MODULE); if (sk == NULL) return -EAFNOSUPPORT; - /* Don't hold an extra reference on the namespace */ - put_net(sk->sk_net); net->ipv4.fibnl = sk; return 0; } static void nl_fib_lookup_exit(struct net *net) { - /* At the last minute lie and say this is a socket for the - * initial network namespace. So the socket will be safe to free. - */ - net->ipv4.fibnl->sk_net = get_net(&init_net); - sock_put(net->ipv4.fibnl); + netlink_kernel_release(net->ipv4.fibnl); + net->ipv4.fibnl = NULL; } static void fib_disable_ip(struct net_device *dev, int force) { - if (fib_sync_down(0, dev, force)) - fib_flush(&init_net); + if (fib_sync_down_dev(dev, force)) + fib_flush(dev->nd_net); rt_cache_flush(0); arp_ifdown(dev); } @@ -934,9 +936,6 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo struct net_device *dev = ptr; struct in_device *in_dev = __in_dev_get_rtnl(dev); - if (dev->nd_net != &init_net) - return NOTIFY_DONE; - if (event == NETDEV_UNREGISTER) { fib_disable_ip(dev, 2); return NOTIFY_DONE; @@ -976,6 +975,7 @@ static struct notifier_block fib_netdev_notifier = { static int __net_init ip_fib_net_init(struct net *net) { + int err; unsigned int i; net->ipv4.fib_table_hash = kzalloc( @@ -986,7 +986,14 @@ static int __net_init ip_fib_net_init(struct net *net) for (i = 0; i < FIB_TABLE_HASHSZ; i++) INIT_HLIST_HEAD(&net->ipv4.fib_table_hash[i]); - return fib4_rules_init(net); + err = fib4_rules_init(net); + if (err < 0) + goto fail; + return 0; + +fail: + kfree(net->ipv4.fib_table_hash); + return err; } static void __net_exit ip_fib_net_exit(struct net *net) @@ -1016,10 +1023,6 @@ static int __net_init fib_net_init(struct net *net) { int error; - error = 0; - if (net != &init_net) - goto out; - error = ip_fib_net_init(net); if (error < 0) goto out; @@ -1060,6 +1063,8 @@ void __init ip_fib_init(void) register_pernet_subsys(&fib_net_ops); register_netdevice_notifier(&fib_netdev_notifier); register_inetaddr_notifier(&fib_inetaddr_notifier); + + fib_hash_init(); } EXPORT_SYMBOL(inet_addr_type);