patch-2.6.6-vs1.9.0
[linux-2.6.git] / net / ipv4 / af_inet.c
index edf4570..358b772 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);
@@ -397,6 +400,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;
@@ -421,8 +429,13 @@ 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);
+               if (err) {
+/*                     sk->sk_vx_info = NULL;
+                       put_vx_info(current->vx_info);
+                       sk->sk_nx_info = NULL;
+                       put_nx_info(current->nx_info);
+*/                     inet_sock_release(sk);
+               }
        }
 out:
        return err;
@@ -460,6 +473,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 +491,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 +505,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 +546,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 +571,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 */