[NETNS]: Add namespace parameter to ip_dev_find.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv4 / fib_frontend.c
index 15909a9fa9b2f855a0c95729f1119002dd6e7b9b..d28261826bc2b35b775946a378cef1959fa99077 100644 (file)
 #include <net/ip_fib.h>
 #include <net/rtnetlink.h>
 
-#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,7 +801,7 @@ 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.
 
@@ -802,7 +809,7 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
                           for stray nexthop entries, then ignite fib_flush.
                        */
                        if (fib_sync_down(ifa->ifa_local, NULL, 0))
-                               fib_flush(&init_net);
+                               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);
+               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;
@@ -1016,10 +1015,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 +1055,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);