]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/socket.c
istallion: Use helpers
[linux-2.6-omap-h63xx.git] / net / socket.c
index 74784dfe8e5b2b6d304c68e34e9ba4c8194123e3..1ba57d88898184160c8fd3c918eba73f3cd77d00 100644 (file)
@@ -90,6 +90,7 @@
 #include <asm/unistd.h>
 
 #include <net/compat.h>
+#include <net/wext.h>
 
 #include <net/sock.h>
 #include <linux/netfilter.h>
@@ -112,6 +113,9 @@ static long compat_sock_ioctl(struct file *file,
 static int sock_fasync(int fd, struct file *filp, int on);
 static ssize_t sock_sendpage(struct file *file, struct page *page,
                             int offset, size_t size, loff_t *ppos, int more);
+static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
+                               struct pipe_inode_info *pipe, size_t len,
+                               unsigned int flags);
 
 /*
  *     Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
@@ -134,6 +138,7 @@ static const struct file_operations socket_file_ops = {
        .fasync =       sock_fasync,
        .sendpage =     sock_sendpage,
        .splice_write = generic_splice_sendpage,
+       .splice_read =  sock_splice_read,
 };
 
 /*
@@ -175,9 +180,9 @@ static DEFINE_PER_CPU(int, sockets_in_use) = 0;
  *     invalid addresses -EFAULT is returned. On a success 0 is returned.
  */
 
-int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
+int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
 {
-       if (ulen < 0 || ulen > MAX_SOCK_ADDR)
+       if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
                return -EINVAL;
        if (ulen == 0)
                return 0;
@@ -203,7 +208,7 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
  *     specified. Zero is returned for a success.
  */
 
-int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
+int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr,
                      int __user *ulen)
 {
        int err;
@@ -214,7 +219,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
                return err;
        if (len > klen)
                len = klen;
-       if (len < 0 || len > MAX_SOCK_ADDR)
+       if (len < 0 || len > sizeof(struct sockaddr_storage))
                return -EINVAL;
        if (len) {
                if (audit_sockaddr(klen, kaddr))
@@ -691,6 +696,18 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
        return sock->ops->sendpage(sock, page, offset, size, flags);
 }
 
+static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
+                               struct pipe_inode_info *pipe, size_t len,
+                               unsigned int flags)
+{
+       struct socket *sock = file->private_data;
+
+       if (unlikely(!sock->ops->splice_read))
+               return -EINVAL;
+
+       return sock->ops->splice_read(sock, ppos, pipe, len, flags);
+}
+
 static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
                                         struct sock_iocb *siocb)
 {
@@ -841,7 +858,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 
        sock = file->private_data;
        sk = sock->sk;
-       net = sk->sk_net;
+       net = sock_net(sk);
        if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
                err = dev_ioctl(net, cmd, argp);
        } else
@@ -893,11 +910,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                        if (!dlci_ioctl_hook)
                                request_module("dlci");
 
-                       if (dlci_ioctl_hook) {
-                               mutex_lock(&dlci_ioctl_mutex);
+                       mutex_lock(&dlci_ioctl_mutex);
+                       if (dlci_ioctl_hook)
                                err = dlci_ioctl_hook(cmd, argp);
-                               mutex_unlock(&dlci_ioctl_mutex);
-                       }
+                       mutex_unlock(&dlci_ioctl_mutex);
                        break;
                default:
                        err = sock->ops->ioctl(sock, cmd, arg);
@@ -1057,20 +1073,19 @@ int sock_wake_async(struct socket *sock, int how, int band)
        if (!sock || !sock->fasync_list)
                return -1;
        switch (how) {
-       case 1:
-
+       case SOCK_WAKE_WAITD:
                if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
                        break;
                goto call_kill;
-       case 2:
+       case SOCK_WAKE_SPACE:
                if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
                        break;
                /* fall through */
-       case 0:
+       case SOCK_WAKE_IO:
 call_kill:
                __kill_fasync(sock->fasync_list, SIGIO, band);
                break;
-       case 3:
+       case SOCK_WAKE_URG:
                __kill_fasync(sock->fasync_list, SIGURG, band);
        }
        return 0;
@@ -1327,20 +1342,20 @@ out_fd:
 asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
 {
        struct socket *sock;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        int err, fput_needed;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
-               err = move_addr_to_kernel(umyaddr, addrlen, address);
+               err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
                if (err >= 0) {
                        err = security_socket_bind(sock,
-                                                  (struct sockaddr *)address,
+                                                  (struct sockaddr *)&address,
                                                   addrlen);
                        if (!err)
                                err = sock->ops->bind(sock,
                                                      (struct sockaddr *)
-                                                     address, addrlen);
+                                                     &address, addrlen);
                }
                fput_light(sock->file, fput_needed);
        }
@@ -1353,17 +1368,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
  *     ready for listening.
  */
 
-int sysctl_somaxconn __read_mostly = SOMAXCONN;
-
 asmlinkage long sys_listen(int fd, int backlog)
 {
        struct socket *sock;
        int err, fput_needed;
+       int somaxconn;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
-               if ((unsigned)backlog > sysctl_somaxconn)
-                       backlog = sysctl_somaxconn;
+               somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
+               if ((unsigned)backlog > somaxconn)
+                       backlog = somaxconn;
 
                err = security_socket_listen(sock, backlog);
                if (!err)
@@ -1392,7 +1407,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
        struct socket *sock, *newsock;
        struct file *newfile;
        int err, len, newfd, fput_needed;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
@@ -1431,13 +1446,13 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
                goto out_fd;
 
        if (upeer_sockaddr) {
-               if (newsock->ops->getname(newsock, (struct sockaddr *)address,
+               if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
                                          &len, 2) < 0) {
                        err = -ECONNABORTED;
                        goto out_fd;
                }
-               err = move_addr_to_user(address, len, upeer_sockaddr,
-                                       upeer_addrlen);
+               err = move_addr_to_user((struct sockaddr *)&address,
+                                       len, upeer_sockaddr, upeer_addrlen);
                if (err < 0)
                        goto out_fd;
        }
@@ -1480,22 +1495,22 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
                            int addrlen)
 {
        struct socket *sock;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        int err, fput_needed;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
-       err = move_addr_to_kernel(uservaddr, addrlen, address);
+       err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
        if (err < 0)
                goto out_put;
 
        err =
-           security_socket_connect(sock, (struct sockaddr *)address, addrlen);
+           security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
        if (err)
                goto out_put;
 
-       err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
+       err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
                                 sock->file->f_flags);
 out_put:
        fput_light(sock->file, fput_needed);
@@ -1512,7 +1527,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
                                int __user *usockaddr_len)
 {
        struct socket *sock;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        int len, err, fput_needed;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
@@ -1523,10 +1538,10 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
        if (err)
                goto out_put;
 
-       err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
+       err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
        if (err)
                goto out_put;
-       err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
+       err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
 
 out_put:
        fput_light(sock->file, fput_needed);
@@ -1543,7 +1558,7 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
                                int __user *usockaddr_len)
 {
        struct socket *sock;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        int len, err, fput_needed;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
@@ -1555,10 +1570,10 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
                }
 
                err =
-                   sock->ops->getname(sock, (struct sockaddr *)address, &len,
+                   sock->ops->getname(sock, (struct sockaddr *)&address, &len,
                                       1);
                if (!err)
-                       err = move_addr_to_user(address, len, usockaddr,
+                       err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
                                                usockaddr_len);
                fput_light(sock->file, fput_needed);
        }
@@ -1576,21 +1591,16 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
                           int addr_len)
 {
        struct socket *sock;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        int err;
        struct msghdr msg;
        struct iovec iov;
        int fput_needed;
-       struct file *sock_file;
 
-       sock_file = fget_light(fd, &fput_needed);
-       err = -EBADF;
-       if (!sock_file)
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       if (!sock)
                goto out;
 
-       sock = sock_from_file(sock_file, &err);
-       if (!sock)
-               goto out_put;
        iov.iov_base = buff;
        iov.iov_len = len;
        msg.msg_name = NULL;
@@ -1600,10 +1610,10 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
        msg.msg_controllen = 0;
        msg.msg_namelen = 0;
        if (addr) {
-               err = move_addr_to_kernel(addr, addr_len, address);
+               err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
                if (err < 0)
                        goto out_put;
-               msg.msg_name = address;
+               msg.msg_name = (struct sockaddr *)&address;
                msg.msg_namelen = addr_len;
        }
        if (sock->file->f_flags & O_NONBLOCK)
@@ -1612,7 +1622,7 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
        err = sock_sendmsg(sock, &msg, len);
 
 out_put:
-       fput_light(sock_file, fput_needed);
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -1639,19 +1649,13 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
        struct socket *sock;
        struct iovec iov;
        struct msghdr msg;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        int err, err2;
-       struct file *sock_file;
        int fput_needed;
 
-       sock_file = fget_light(fd, &fput_needed);
-       err = -EBADF;
-       if (!sock_file)
-               goto out;
-
-       sock = sock_from_file(sock_file, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
-               goto out_put;
+               goto out;
 
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
@@ -1659,19 +1663,20 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
        msg.msg_iov = &iov;
        iov.iov_len = size;
        iov.iov_base = ubuf;
-       msg.msg_name = address;
-       msg.msg_namelen = MAX_SOCK_ADDR;
+       msg.msg_name = (struct sockaddr *)&address;
+       msg.msg_namelen = sizeof(address);
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        err = sock_recvmsg(sock, &msg, size, flags);
 
        if (err >= 0 && addr != NULL) {
-               err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
+               err2 = move_addr_to_user((struct sockaddr *)&address,
+                                        msg.msg_namelen, addr, addr_len);
                if (err2 < 0)
                        err = err2;
        }
-out_put:
-       fput_light(sock_file, fput_needed);
+
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -1786,7 +1791,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
        struct compat_msghdr __user *msg_compat =
            (struct compat_msghdr __user *)msg;
        struct socket *sock;
-       char address[MAX_SOCK_ADDR];
+       struct sockaddr_storage address;
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        unsigned char ctl[sizeof(struct cmsghdr) + 20]
            __attribute__ ((aligned(sizeof(__kernel_size_t))));
@@ -1824,9 +1829,13 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
 
        /* This will also move the address data into kernel space */
        if (MSG_CMSG_COMPAT & flags) {
-               err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+               err = verify_compat_iovec(&msg_sys, iov,
+                                         (struct sockaddr *)&address,
+                                         VERIFY_READ);
        } else
-               err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
+               err = verify_iovec(&msg_sys, iov,
+                                  (struct sockaddr *)&address,
+                                  VERIFY_READ);
        if (err < 0)
                goto out_freeiov;
        total_len = err;
@@ -1897,7 +1906,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
        int fput_needed;
 
        /* kernel mode address */
-       char addr[MAX_SOCK_ADDR];
+       struct sockaddr_storage addr;
 
        /* user mode address pointers */
        struct sockaddr __user *uaddr;
@@ -1935,9 +1944,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
        uaddr = (__force void __user *)msg_sys.msg_name;
        uaddr_len = COMPAT_NAMELEN(msg);
        if (MSG_CMSG_COMPAT & flags) {
-               err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+               err = verify_compat_iovec(&msg_sys, iov,
+                                         (struct sockaddr *)&addr,
+                                         VERIFY_WRITE);
        } else
-               err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+               err = verify_iovec(&msg_sys, iov,
+                                  (struct sockaddr *)&addr,
+                                  VERIFY_WRITE);
        if (err < 0)
                goto out_freeiov;
        total_len = err;
@@ -1953,7 +1966,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
        len = err;
 
        if (uaddr != NULL) {
-               err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
+               err = move_addr_to_user((struct sockaddr *)&addr,
+                                       msg_sys.msg_namelen, uaddr,
                                        uaddr_len);
                if (err < 0)
                        goto out_freeiov;
@@ -2207,10 +2221,19 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd,
 {
        struct socket *sock = file->private_data;
        int ret = -ENOIOCTLCMD;
+       struct sock *sk;
+       struct net *net;
+
+       sk = sock->sk;
+       net = sock_net(sk);
 
        if (sock->ops->compat_ioctl)
                ret = sock->ops->compat_ioctl(sock, cmd, arg);
 
+       if (ret == -ENOIOCTLCMD &&
+           (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST))
+               ret = compat_wext_handle_ioctl(net, cmd, arg);
+
        return ret;
 }
 #endif
@@ -2324,9 +2347,6 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
        return sock->ops->shutdown(sock, how);
 }
 
-/* ABI emulation layers need these two */
-EXPORT_SYMBOL(move_addr_to_kernel);
-EXPORT_SYMBOL(move_addr_to_user);
 EXPORT_SYMBOL(sock_create);
 EXPORT_SYMBOL(sock_create_kern);
 EXPORT_SYMBOL(sock_create_lite);