]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv4/af_inet.c
[NET] NETNS: Omit net_device->nd_net without CONFIG_NET_NS.
[net-next-2.6.git] / net / ipv4 / af_inet.c
index e68103475cca2a76a349d270d1db72c62132b4c7..06cfb0bed631833aceeeb4b82ff00780f1b5626b 100644 (file)
@@ -126,6 +126,10 @@ extern void ip_mc_drop_socket(struct sock *sk);
 static struct list_head inetsw[SOCK_MAX];
 static DEFINE_SPINLOCK(inetsw_lock);
 
+struct ipv4_config ipv4_config;
+
+EXPORT_SYMBOL(ipv4_config);
+
 /* New destruction routine */
 
 void inet_sock_destruct(struct sock *sk)
@@ -135,6 +139,8 @@ void inet_sock_destruct(struct sock *sk)
        __skb_queue_purge(&sk->sk_receive_queue);
        __skb_queue_purge(&sk->sk_error_queue);
 
+       sk_mem_reclaim(sk);
+
        if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) {
                printk("Attempt to release TCP socket in state %d %p\n",
                       sk->sk_state, sk);
@@ -237,11 +243,28 @@ void build_ehash_secret(void)
 }
 EXPORT_SYMBOL(build_ehash_secret);
 
+static inline int inet_netns_ok(struct net *net, int protocol)
+{
+       int hash;
+       struct net_protocol *ipprot;
+
+       if (net == &init_net)
+               return 1;
+
+       hash = protocol & (MAX_INET_PROTOS - 1);
+       ipprot = rcu_dereference(inet_protos[hash]);
+
+       if (ipprot == NULL)
+               /* raw IP is OK */
+               return 1;
+       return ipprot->netns_ok;
+}
+
 /*
  *     Create an inet socket.
  */
 
-static int inet_create(struct socket *sock, int protocol)
+static int inet_create(struct net *net, struct socket *sock, int protocol)
 {
        struct sock *sk;
        struct list_head *p;
@@ -311,6 +334,10 @@ lookup_protocol:
        if (answer->capability > 0 && !capable(answer->capability))
                goto out_rcu_unlock;
 
+       err = -EAFNOSUPPORT;
+       if (!inet_netns_ok(net, protocol))
+               goto out_rcu_unlock;
+
        sock->ops = answer->ops;
        answer_prot = answer->prot;
        answer_no_check = answer->no_check;
@@ -320,7 +347,7 @@ lookup_protocol:
        BUG_TRAP(answer_prot->slab != NULL);
 
        err = -ENOBUFS;
-       sk = sk_alloc(PF_INET, GFP_KERNEL, answer_prot, 1);
+       sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
        if (sk == NULL)
                goto out;
 
@@ -437,7 +464,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (addr_len < sizeof(struct sockaddr_in))
                goto out;
 
-       chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
+       chk_addr_ret = inet_addr_type(sk->sk_net, addr->sin_addr.s_addr);
 
        /* Not specified by any standard per-se, however it breaks too
         * many applications when removed.  It is unfortunate since
@@ -449,7 +476,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        err = -EADDRNOTAVAIL;
        if (!sysctl_ip_nonlocal_bind &&
            !inet->freebind &&
-           addr->sin_addr.s_addr != INADDR_ANY &&
+           addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
            chk_addr_ret != RTN_LOCAL &&
            chk_addr_ret != RTN_MULTICAST &&
            chk_addr_ret != RTN_BROADCAST)
@@ -775,6 +802,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        struct sock *sk = sock->sk;
        int err = 0;
+       struct net *net = sk->sk_net;
 
        switch (cmd) {
                case SIOCGSTAMP:
@@ -786,12 +814,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCADDRT:
                case SIOCDELRT:
                case SIOCRTMSG:
-                       err = ip_rt_ioctl(cmd, (void __user *)arg);
+                       err = ip_rt_ioctl(net, cmd, (void __user *)arg);
                        break;
                case SIOCDARP:
                case SIOCGARP:
                case SIOCSARP:
-                       err = arp_ioctl(cmd, (void __user *)arg);
+                       err = arp_ioctl(net, cmd, (void __user *)arg);
                        break;
                case SIOCGIFADDR:
                case SIOCSIFADDR:
@@ -804,7 +832,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCSIFPFLAGS:
                case SIOCGIFPFLAGS:
                case SIOCSIFFLAGS:
-                       err = devinet_ioctl(cmd, (void __user *)arg);
+                       err = devinet_ioctl(net, cmd, (void __user *)arg);
                        break;
                default:
                        if (sk->sk_prot->ioctl)
@@ -835,6 +863,7 @@ const struct proto_ops inet_stream_ops = {
        .recvmsg           = sock_common_recvmsg,
        .mmap              = sock_no_mmap,
        .sendpage          = tcp_sendpage,
+       .splice_read       = tcp_splice_read,
 #ifdef CONFIG_COMPAT
        .compat_setsockopt = compat_sock_common_setsockopt,
        .compat_getsockopt = compat_sock_common_getsockopt,
@@ -939,7 +968,7 @@ static struct inet_protosw inetsw_array[] =
        }
 };
 
-#define INETSW_ARRAY_LEN (sizeof(inetsw_array) / sizeof(struct inet_protosw))
+#define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)
 
 void inet_register_protosw(struct inet_protosw *p)
 {
@@ -1049,7 +1078,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
        if (sysctl_ip_dynaddr > 1) {
                printk(KERN_INFO "%s(): shifting inet->"
                                 "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
-                      __FUNCTION__,
+                      __func__,
                       NIPQUAD(old_saddr),
                       NIPQUAD(new_saddr));
        }
@@ -1103,7 +1132,7 @@ int inet_sk_rebuild_header(struct sock *sk)
        };
 
        security_sk_classify_flow(sk, &fl);
-       err = ip_route_output_flow(&rt, &fl, sk, 0);
+       err = ip_route_output_flow(sk->sk_net, &rt, &fl, sk, 0);
 }
        if (!err)
                sk_setup_caps(sk, &rt->u.dst);
@@ -1234,7 +1263,7 @@ unsigned long snmp_fold_field(void *mib[], int offt)
 }
 EXPORT_SYMBOL_GPL(snmp_fold_field);
 
-int snmp_mib_init(void *ptr[2], size_t mibsize, size_t mibalign)
+int snmp_mib_init(void *ptr[2], size_t mibsize)
 {
        BUG_ON(ptr == NULL);
        ptr[0] = __alloc_percpu(mibsize);
@@ -1273,43 +1302,44 @@ static struct net_protocol tcp_protocol = {
        .gso_send_check = tcp_v4_gso_send_check,
        .gso_segment =  tcp_tso_segment,
        .no_policy =    1,
+       .netns_ok =     1,
 };
 
 static struct net_protocol udp_protocol = {
        .handler =      udp_rcv,
        .err_handler =  udp_err,
        .no_policy =    1,
+       .netns_ok =     1,
 };
 
 static struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
+       .no_policy =    1,
+       .netns_ok =     1,
 };
 
 static int __init init_ipv4_mibs(void)
 {
        if (snmp_mib_init((void **)net_statistics,
-                         sizeof(struct linux_mib),
-                         __alignof__(struct linux_mib)) < 0)
+                         sizeof(struct linux_mib)) < 0)
                goto err_net_mib;
        if (snmp_mib_init((void **)ip_statistics,
-                         sizeof(struct ipstats_mib),
-                         __alignof__(struct ipstats_mib)) < 0)
+                         sizeof(struct ipstats_mib)) < 0)
                goto err_ip_mib;
        if (snmp_mib_init((void **)icmp_statistics,
-                         sizeof(struct icmp_mib),
-                         __alignof__(struct icmp_mib)) < 0)
+                         sizeof(struct icmp_mib)) < 0)
                goto err_icmp_mib;
+       if (snmp_mib_init((void **)icmpmsg_statistics,
+                         sizeof(struct icmpmsg_mib)) < 0)
+               goto err_icmpmsg_mib;
        if (snmp_mib_init((void **)tcp_statistics,
-                         sizeof(struct tcp_mib),
-                         __alignof__(struct tcp_mib)) < 0)
+                         sizeof(struct tcp_mib)) < 0)
                goto err_tcp_mib;
        if (snmp_mib_init((void **)udp_statistics,
-                         sizeof(struct udp_mib),
-                         __alignof__(struct udp_mib)) < 0)
+                         sizeof(struct udp_mib)) < 0)
                goto err_udp_mib;
        if (snmp_mib_init((void **)udplite_statistics,
-                         sizeof(struct udp_mib),
-                         __alignof__(struct udp_mib)) < 0)
+                         sizeof(struct udp_mib)) < 0)
                goto err_udplite_mib;
 
        tcp_mib_init();
@@ -1321,6 +1351,8 @@ err_udplite_mib:
 err_udp_mib:
        snmp_mib_free((void **)tcp_statistics);
 err_tcp_mib:
+       snmp_mib_free((void **)icmpmsg_statistics);
+err_icmpmsg_mib:
        snmp_mib_free((void **)icmp_statistics);
 err_icmp_mib:
        snmp_mib_free((void **)ip_statistics);
@@ -1404,11 +1436,14 @@ static int __init inet_init(void)
 
        ip_init();
 
-       tcp_v4_init(&inet_family_ops);
+       tcp_v4_init();
 
        /* Setup TCP slab cache for open requests. */
        tcp_init();
 
+       /* Setup UDP memory threshold */
+       udp_init();
+
        /* Add UDP-Lite (RFC 3828) */
        udplite4_register();
 
@@ -1416,7 +1451,8 @@ static int __init inet_init(void)
         *      Set the ICMP layer up
         */
 
-       icmp_init(&inet_family_ops);
+       if (icmp_init() < 0)
+               panic("Failed to create the ICMP control socket.\n");
 
        /*
         *      Initialise the multicast router
@@ -1462,15 +1498,11 @@ static int __init ipv4_proc_init(void)
                goto out_tcp;
        if (udp4_proc_init())
                goto out_udp;
-       if (fib_proc_init())
-               goto out_fib;
        if (ip_misc_proc_init())
                goto out_misc;
 out:
        return rc;
 out_misc:
-       fib_proc_exit();
-out_fib:
        udp4_proc_exit();
 out_udp:
        tcp4_proc_exit();