This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / net / ipv4 / af_inet.c
index edf4570..8d450fb 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);
@@ -216,7 +219,7 @@ void inet_sock_release(struct sock *sk)
  *     Set socket options on an inet socket.
  */
 int inet_setsockopt(struct socket *sock, int level, int optname,
-                   char *optval, int optlen)
+                   char __user *optval, int optlen)
 {
        struct sock *sk = sock->sk;
 
@@ -232,7 +235,7 @@ int inet_setsockopt(struct socket *sock, int level, int optname,
  */
 
 int inet_getsockopt(struct socket *sock, int level, int optname,
-                   char *optval, int *optlen)
+                   char __user *optval, int __user *optlen)
 {
        struct sock *sk = sock->sk;
 
@@ -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 */
 
@@ -843,7 +892,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
                case SIOCGSTAMP:
-                       err = sock_get_timestamp(sk, (struct timeval *)arg);
+                       err = sock_get_timestamp(sk, (struct timeval __user *)arg);
                        break;
                case SIOCADDRT:
                case SIOCDELRT:
@@ -853,7 +902,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCDARP:
                case SIOCGARP:
                case SIOCSARP:
-                       err = arp_ioctl(cmd, (void *)arg);
+                       err = arp_ioctl(cmd, (void __user *)arg);
                        break;
                case SIOCGIFADDR:
                case SIOCSIFADDR:
@@ -866,13 +915,13 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCSIFPFLAGS:
                case SIOCGIFPFLAGS:
                case SIOCSIFFLAGS:
-                       err = devinet_ioctl(cmd, (void *)arg);
+                       err = devinet_ioctl(cmd, (void __user *)arg);
                        break;
                default:
                        if (!sk->sk_prot->ioctl ||
                            (err = sk->sk_prot->ioctl(sk, cmd, arg)) ==
                                                                -ENOIOCTLCMD)
-                               err = dev_ioctl(cmd, (void *)arg);
+                               err = dev_ioctl(cmd, (void __user *)arg);
                        break;
        }
        return err;
@@ -978,7 +1027,7 @@ void inet_register_protosw(struct inet_protosw *p)
 
        spin_lock_bh(&inetsw_lock);
 
-       if (p->type > SOCK_MAX)
+       if (p->type >= SOCK_MAX)
                goto out_illegal;
 
        /* If we are trying to override a permanent protocol, bail. */