Merge to Fedora kernel-2.6.7-1.492
[linux-2.6.git] / net / ipv4 / af_inet.c
index db0931a..e42418c 100644 (file)
@@ -158,6 +158,9 @@ void inet_sock_destruct(struct sock *sk)
 
        if (inet->opt)
                kfree(inet->opt);
+       
+       BUG_ON(sk->sk_nx_info);
+       BUG_ON(sk->sk_vx_info);
        dst_release(sk->sk_dst_cache);
 #ifdef INET_REFCNT_DEBUG
        atomic_dec(&inet_sock_nr);
@@ -166,79 +169,12 @@ void inet_sock_destruct(struct sock *sk)
 #endif
 }
 
-void inet_sock_release(struct sock *sk)
-{
-       if (sk->sk_prot->destroy)
-               sk->sk_prot->destroy(sk);
-
-       /* Observation: when inet_sock_release is called, processes have
-        * no access to socket. But net still has.
-        * Step one, detach it from networking:
-        *
-        * A. Remove from hash tables.
-        */
-
-       sk->sk_prot->unhash(sk);
-
-       /* In this point socket cannot receive new packets,
-        * but it is possible that some packets are in flight
-        * because some CPU runs receiver and did hash table lookup
-        * before we unhashed socket. They will achieve receive queue
-        * and will be purged by socket destructor.
-        *
-        * Also we still have packets pending on receive
-        * queue and probably, our own packets waiting in device queues.
-        * sock_destroy will drain receive queue, but transmitted
-        * packets will delay socket destruction until the last reference
-        * will be released.
-        */
-
-       sock_orphan(sk);
-
-       xfrm_sk_free_policy(sk);
-
-#ifdef INET_REFCNT_DEBUG
-       if (atomic_read(&sk->sk_refcnt) != 1)
-               printk(KERN_DEBUG "Destruction inet %p delayed, c=%d\n",
-                      sk, atomic_read(&sk->sk_refcnt));
-#endif
-       sock_put(sk);
-}
-
-
 /*
  *     The routines beyond this point handle the behaviour of an AF_INET
  *     socket object. Mostly it punts to the subprotocols of IP to do
  *     the work.
  */
 
-/*
- *     Set socket options on an inet socket.
- */
-int inet_setsockopt(struct socket *sock, int level, int optname,
-                   char __user *optval, int optlen)
-{
-       struct sock *sk = sock->sk;
-
-       return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
-}
-
-/*
- *     Get a socket option on an AF_INET socket.
- *
- *     FIX: POSIX 1003.1g is very ambiguous here. It states that
- *     asynchronous errors should be reported by getsockopt. We assume
- *     this means if you specify SO_ERROR (otherwise whats the point of it).
- */
-
-int inet_getsockopt(struct socket *sock, int level, int optname,
-                   char __user *optval, int __user *optlen)
-{
-       struct sock *sk = sock->sk;
-
-       return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);
-}
-
 /*
  *     Automatically bind an unbound socket.
  */
@@ -397,6 +333,11 @@ static int inet_create(struct socket *sock, int protocol)
        sk->sk_family      = PF_INET;
        sk->sk_protocol    = protocol;
        sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+       
+       set_vx_info(&sk->sk_vx_info, current->vx_info);
+       sk->sk_xid = vx_current_xid();
+       set_nx_info(&sk->sk_nx_info, current->nx_info);
+       sk->sk_nid = nx_current_nid();
 
        inet->uc_ttl    = -1;
        inet->mc_loop   = 1;
@@ -422,7 +363,7 @@ static int inet_create(struct socket *sock, int protocol)
        if (sk->sk_prot->init) {
                err = sk->sk_prot->init(sk);
                if (err)
-                       inet_sock_release(sk);
+                       sk_common_release(sk);
        }
 out:
        return err;
@@ -460,6 +401,8 @@ int inet_release(struct socket *sock)
                    !(current->flags & PF_EXITING))
                        timeout = sk->sk_lingertime;
                sock->sk = NULL;
+               clr_vx_info(&sk->sk_vx_info);
+               clr_nx_info(&sk->sk_nx_info);
                sk->sk_prot->close(sk, timeout);
        }
        return 0;
@@ -476,6 +419,10 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        unsigned short snum;
        int chk_addr_ret;
        int err;
+       __u32 s_addr;   /* Address used for validation */
+       __u32 s_addr1;
+       __u32 s_addr2 = 0xffffffffl;    /* Optional address of the socket */
+       struct nx_info *nxi = sk->sk_nx_info;
 
        /* If the socket has its own bind function then use it. (RAW) */
        if (sk->sk_prot->bind) {
@@ -486,7 +433,36 @@ 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);
+       s_addr = s_addr1 = addr->sin_addr.s_addr;
+       nxdprintk("inet_bind(%p) %p,%p;%lx\n",
+               sk, nx_info, sk->sk_socket,
+               (sk->sk_socket?sk->sk_socket->flags:0));
+       if (nxi) {
+               __u32 v4_bcast = nxi->v4_bcast;
+               __u32 ipv4root = nxi->ipv4[0];
+               int nbipv4 = nxi->nbipv4;
+               if (s_addr == 0) {
+                       s_addr = ipv4root;
+                       if (nbipv4 > 1)
+                               s_addr1 = 0;
+                       else {
+                               s_addr1 = ipv4root;
+                       }
+                       s_addr2 = v4_bcast;
+               } else if (s_addr == 0x0100007f) {
+                       s_addr = s_addr1 = ipv4root;
+               } else if (s_addr != v4_bcast) {
+                       int i;
+                       for (i=0; i<nbipv4; i++) {
+                               if (s_addr == nxi->ipv4[i])
+                                       break;
+                       }
+                       if (i == nbipv4) {
+                               return -EADDRNOTAVAIL;
+                       }
+               }
+       }
+       chk_addr_ret = inet_addr_type(s_addr);
 
        /* Not specified by any standard per-se, however it breaks too
         * many applications when removed.  It is unfortunate since
@@ -498,7 +474,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 &&
+           s_addr != INADDR_ANY &&
            chk_addr_ret != RTN_LOCAL &&
            chk_addr_ret != RTN_MULTICAST &&
            chk_addr_ret != RTN_BROADCAST)
@@ -523,7 +499,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (sk->sk_state != TCP_CLOSE || inet->num)
                goto out_release_sock;
 
-       inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
+       inet->rcv_saddr = inet->saddr = s_addr1;
+       inet->rcv_saddr2 = s_addr2;
        if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
                inet->saddr = 0;  /* Use device */
 
@@ -729,22 +706,6 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
        return 0;
 }
 
-
-int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
-                size_t size, int flags)
-{
-       struct sock *sk = sock->sk;
-       int addr_len = 0;
-       int err;
-
-       err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
-                                  flags & ~MSG_DONTWAIT, &addr_len);
-       if (err >= 0)
-               msg->msg_namelen = addr_len;
-       return err;
-}
-
-
 int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
                 size_t size)
 {
@@ -848,7 +809,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCADDRT:
                case SIOCDELRT:
                case SIOCRTMSG:
-                       err = ip_rt_ioctl(cmd, (void *)arg);
+                       err = ip_rt_ioctl(cmd, (void __user *)arg);
                        break;
                case SIOCDARP:
                case SIOCGARP:
@@ -891,10 +852,10 @@ struct proto_ops inet_stream_ops = {
        .ioctl =        inet_ioctl,
        .listen =       inet_listen,
        .shutdown =     inet_shutdown,
-       .setsockopt =   inet_setsockopt,
-       .getsockopt =   inet_getsockopt,
+       .setsockopt =   sock_common_setsockopt,
+       .getsockopt =   sock_common_getsockopt,
        .sendmsg =      inet_sendmsg,
-       .recvmsg =      inet_recvmsg,
+       .recvmsg =      sock_common_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     tcp_sendpage
 };
@@ -912,10 +873,10 @@ struct proto_ops inet_dgram_ops = {
        .ioctl =        inet_ioctl,
        .listen =       sock_no_listen,
        .shutdown =     inet_shutdown,
-       .setsockopt =   inet_setsockopt,
-       .getsockopt =   inet_getsockopt,
+       .setsockopt =   sock_common_setsockopt,
+       .getsockopt =   sock_common_getsockopt,
        .sendmsg =      inet_sendmsg,
-       .recvmsg =      inet_recvmsg,
+       .recvmsg =      sock_common_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     inet_sendpage,
 };
@@ -1041,24 +1002,24 @@ void inet_unregister_protosw(struct inet_protosw *p)
 }
 
 #ifdef CONFIG_IP_MULTICAST
-static struct inet_protocol igmp_protocol = {
+static struct net_protocol igmp_protocol = {
        .handler =      igmp_rcv,
 };
 #endif
 
-static struct inet_protocol tcp_protocol = {
+static struct net_protocol tcp_protocol = {
        .handler =      tcp_v4_rcv,
        .err_handler =  tcp_v4_err,
        .no_policy =    1,
 };
 
-static struct inet_protocol udp_protocol = {
+static struct net_protocol udp_protocol = {
        .handler =      udp_rcv,
        .err_handler =  udp_err,
        .no_policy =    1,
 };
 
-static struct inet_protocol icmp_protocol = {
+static struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
 };
 
@@ -1066,8 +1027,8 @@ static int __init init_ipv4_mibs(void)
 {
        net_statistics[0] = alloc_percpu(struct linux_mib);
        net_statistics[1] = alloc_percpu(struct linux_mib);
-       ip_statistics[0] = alloc_percpu(struct ip_mib);
-       ip_statistics[1] = alloc_percpu(struct ip_mib);
+       ip_statistics[0] = alloc_percpu(struct ipstats_mib);
+       ip_statistics[1] = alloc_percpu(struct ipstats_mib);
        icmp_statistics[0] = alloc_percpu(struct icmp_mib);
        icmp_statistics[1] = alloc_percpu(struct icmp_mib);
        tcp_statistics[0] = alloc_percpu(struct tcp_mib);
@@ -1101,13 +1062,13 @@ static int __init inet_init(void)
 
        tcp_sk_cachep = kmem_cache_create("tcp_sock",
                                          sizeof(struct tcp_sock), 0,
-                                         SLAB_HWCACHE_ALIGN, 0, 0);
+                                         SLAB_HWCACHE_ALIGN, NULL, NULL);
        udp_sk_cachep = kmem_cache_create("udp_sock",
                                          sizeof(struct udp_sock), 0,
-                                         SLAB_HWCACHE_ALIGN, 0, 0);
+                                         SLAB_HWCACHE_ALIGN, NULL, NULL);
        raw4_sk_cachep = kmem_cache_create("raw4_sock",
                                           sizeof(struct raw_sock), 0,
-                                          SLAB_HWCACHE_ALIGN, 0, 0);
+                                          SLAB_HWCACHE_ALIGN, NULL, NULL);
        if (!tcp_sk_cachep || !udp_sk_cachep || !raw4_sk_cachep)
                printk(KERN_CRIT
                       "inet_init: Can't create protocol sock SLAB caches!\n");
@@ -1242,17 +1203,13 @@ EXPORT_SYMBOL(inet_dgram_connect);
 EXPORT_SYMBOL(inet_dgram_ops);
 EXPORT_SYMBOL(inet_family_ops);
 EXPORT_SYMBOL(inet_getname);
-EXPORT_SYMBOL(inet_getsockopt);
 EXPORT_SYMBOL(inet_ioctl);
 EXPORT_SYMBOL(inet_listen);
-EXPORT_SYMBOL(inet_recvmsg);
 EXPORT_SYMBOL(inet_register_protosw);
 EXPORT_SYMBOL(inet_release);
 EXPORT_SYMBOL(inet_sendmsg);
-EXPORT_SYMBOL(inet_setsockopt);
 EXPORT_SYMBOL(inet_shutdown);
 EXPORT_SYMBOL(inet_sock_destruct);
-EXPORT_SYMBOL(inet_sock_release);
 EXPORT_SYMBOL(inet_stream_connect);
 EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_unregister_protosw);