patch-2.1.23 linux/net/socket.c
Next file: linux/net/unix/af_unix.c
Previous file: linux/net/rose/af_rose.c
Back to the patch index
Back to the overall index
- Lines: 911
- Date:
Sun Jan 26 12:07:52 1997
- Orig file:
v2.1.22/linux/net/socket.c
- Orig date:
Thu Jan 23 21:06:59 1997
diff -u --recursive --new-file v2.1.22/linux/net/socket.c linux/net/socket.c
@@ -61,6 +61,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/stat.h>
@@ -101,7 +103,7 @@
const char *buf, unsigned long size);
static void sock_close(struct inode *inode, struct file *file);
-static int sock_select(struct inode *inode, struct file *file, int which, select_table *seltable);
+static unsigned int sock_poll(struct file *file, poll_table *wait);
static int sock_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static int sock_fasync(struct inode *inode, struct file *filp, int on);
@@ -117,7 +119,7 @@
sock_read,
sock_write,
NULL, /* readdir */
- sock_select,
+ sock_poll,
sock_ioctl,
NULL, /* mmap */
NULL, /* no special open code... */
@@ -444,19 +446,19 @@
}
-static int sock_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
+static unsigned int sock_poll(struct file *file, poll_table * wait)
{
struct socket *sock;
- sock = socki_lookup(inode);
+ sock = socki_lookup(file->f_inode);
/*
- * We can't return errors to select, so it's either yes or no.
+ * We can't return errors to poll, so it's either yes or no.
*/
- if (sock->ops->select)
- return sock->ops->select(sock, sel_type, wait);
- return(0);
+ if (sock->ops->poll)
+ return sock->ops->poll(sock, wait);
+ return 0;
}
@@ -556,16 +558,18 @@
asmlinkage int sys_socket(int family, int type, int protocol)
{
- int i, fd;
+ int i, fd, err;
struct socket *sock;
- /*
- * Check protocol is in range
- */
-
- if(family<0||family>=NPROTO)
- return -EINVAL;
-
+ lock_kernel();
+
+ /*
+ * Check protocol is in range
+ */
+ err = -EINVAL;
+ if(family<0||family>=NPROTO)
+ goto out;
+
#if defined(CONFIG_KERNELD) && defined(CONFIG_NET)
/* Attempt to load a protocol module if the find failed.
*
@@ -582,7 +586,7 @@
#endif
if (net_families[family]==NULL)
- return -EINVAL;
+ goto out;
/*
* Check that this is a type that we know how to manipulate and
@@ -593,7 +597,7 @@
if ((type != SOCK_STREAM && type != SOCK_DGRAM &&
type != SOCK_SEQPACKET && type != SOCK_RAW &&
type != SOCK_PACKET) || protocol < 0)
- return(-EINVAL);
+ goto out;
/*
* Allocate the socket and allow the family to set things up. if
@@ -601,10 +605,11 @@
* default.
*/
+ err = -ENFILE;
if (!(sock = sock_alloc()))
{
printk(KERN_WARNING "socket: no more sockets\n");
- return(-ENFILE); /* Not exactly a match, but its the
+ goto out; /* Not exactly a match, but its the
closest posix thing */
}
@@ -613,18 +618,21 @@
if ((i = net_families[family]->create(sock, protocol)) < 0)
{
sock_release(sock);
- return(i);
+ err = i;
}
-
- if ((fd = get_fd(sock->inode)) < 0)
+ else if ((fd = get_fd(sock->inode)) < 0)
{
sock_release(sock);
- return(-EINVAL);
+ err = -EINVAL;
}
-
- sock->file = current->files->fd[fd];
-
- return(fd);
+ else
+ {
+ sock->file = current->files->fd[fd];
+ err = fd;
+ }
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -637,50 +645,59 @@
struct socket *sock1, *sock2;
int err;
+ lock_kernel();
+
/*
* Obtain the first socket and check if the underlying protocol
* supports the socketpair call.
*/
- if ((fd1 = sys_socket(family, type, protocol)) < 0)
- return(fd1);
+ if ((fd1 = sys_socket(family, type, protocol)) < 0) {
+ err = fd1;
+ goto out;
+ }
sock1 = sockfd_lookup(fd1, &err);
if (!sock1)
- return err;
+ goto out;
+ err = -EOPNOTSUPP;
if (!sock1->ops->socketpair)
{
sys_close(fd1);
- return -EOPNOTSUPP;
+ goto out;
}
/*
* Now grab another socket and try to connect the two together.
*/
-
+ err = -EINVAL;
if ((fd2 = sys_socket(family, type, protocol)) < 0)
{
sys_close(fd1);
- return(-EINVAL);
+ goto out;
}
sock2 = sockfd_lookup(fd2,&err);
if (!sock2)
- return err;
+ goto out;
if ((i = sock1->ops->socketpair(sock1, sock2)) < 0)
{
sys_close(fd1);
sys_close(fd2);
- return(i);
+ err = i;
}
-
- err = put_user(fd1, &usockvec[0]);
- if (!err)
- err = put_user(fd2, &usockvec[1]);
- if (err) {
- sys_close(fd1);
- sys_close(fd2);
+ else
+ {
+ err = put_user(fd1, &usockvec[0]);
+ if (!err)
+ err = put_user(fd2, &usockvec[1]);
+ if (err) {
+ sys_close(fd1);
+ sys_close(fd2);
+ }
}
+out:
+ unlock_kernel();
return err;
}
@@ -700,15 +717,20 @@
char address[MAX_SOCK_ADDR];
int err;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd,&err)))
- return err;
+ goto out;
if((err=move_addr_to_kernel(umyaddr,addrlen,address))<0)
- return err;
+ goto out;
if ((i = sock->ops->bind(sock, (struct sockaddr *)address, addrlen)) < 0)
- return(i);
- return(0);
+ err = i;
+ else
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
@@ -723,11 +745,14 @@
struct socket *sock;
int err=-EOPNOTSUPP;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
if (sock->ops && sock->ops->listen)
err=sock->ops->listen(sock, backlog);
+out:
+ unlock_kernel();
return err;
}
@@ -748,45 +773,48 @@
{
struct inode *inode;
struct socket *sock, *newsock;
- int i;
int err;
char address[MAX_SOCK_ADDR];
int len;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
+ err = -EOPNOTSUPP;
if (!sock->ops->accept)
- return -EOPNOTSUPP;
+ goto out;
+ err = -ENOSR;
if (!(newsock = sock_alloc()))
{
printk(KERN_WARNING "accept: no more sockets\n");
- return(-ENOSR); /* Was: EAGAIN, but we are out of system
+ goto out; /* Was: EAGAIN, but we are out of system
resources! */
}
inode = newsock->inode;
newsock->type = sock->type;
- if ((i = sock->ops->dup(newsock, sock)) < 0)
+ if ((err = sock->ops->dup(newsock, sock)) < 0)
{
sock_release(newsock);
- return(i);
+ goto out;
}
- i = newsock->ops->accept(sock, newsock, current->files->fd[fd]->f_flags);
+ err = newsock->ops->accept(sock, newsock, current->files->fd[fd]->f_flags);
- if (i < 0)
+ if (err < 0)
{
sock_release(newsock);
- return(i);
+ goto out;
}
newsock = socki_lookup(inode);
if ((fd = get_fd(inode)) < 0)
{
sock_release(newsock);
- return(-EINVAL);
+ err = -EINVAL;
+ goto out;
}
newsock->file = current->files->fd[fd];
@@ -796,7 +824,10 @@
newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 1);
move_addr_to_user(address,len, upeer_sockaddr, upeer_addrlen);
}
- return fd;
+ err = fd;
+out:
+ unlock_kernel();
+ return err;
}
@@ -815,21 +846,23 @@
asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen)
{
struct socket *sock;
- int i;
char address[MAX_SOCK_ADDR];
int err;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd,&err)))
- return err;
+ goto out;
if((err=move_addr_to_kernel(uservaddr,addrlen,address))<0)
- return err;
+ goto out;
- i = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
+ err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
current->files->fd[fd]->f_flags);
- if (i < 0)
- return(i);
- return(0);
+ if (err >= 0)
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -844,15 +877,19 @@
int len;
int err;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
err=sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
if(err)
- return err;
+ goto out;
if((err=move_addr_to_user(address,len, usockaddr, usockaddr_len))<0)
- return err;
- return 0;
+ goto out;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -867,15 +904,19 @@
int len;
int err;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
err=sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
if(err)
- return err;
+ goto out;
if((err=move_addr_to_user(address,len, usockaddr, usockaddr_len))<0)
- return err;
- return 0;
+ goto out;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -890,14 +931,16 @@
struct msghdr msg;
struct iovec iov;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
+ err = -EINVAL;
if(len<0)
- return -EINVAL;
+ goto out;
err=verify_area(VERIFY_READ, buff, len);
if(err)
- return err;
+ goto out;
iov.iov_base=buff;
iov.iov_len=len;
@@ -911,7 +954,10 @@
flags |= MSG_DONTWAIT;
msg.msg_flags=flags;
- return sock_sendmsg(sock, &msg, len);
+ err = sock_sendmsg(sock, &msg, len);
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -929,13 +975,14 @@
struct msghdr msg;
struct iovec iov;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd,&err)))
- return err;
+ goto out;
err=verify_area(VERIFY_READ,buff,len);
if(err)
- return err;
-
+ goto out;
+
iov.iov_base=buff;
iov.iov_len=len;
msg.msg_name=NULL;
@@ -948,15 +995,18 @@
{
err=move_addr_to_kernel(addr,addr_len,address);
if (err < 0)
- return err;
+ goto out;
msg.msg_name=address;
}
-
+
if (current->files->fd[fd]->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
msg.msg_flags=flags;
- return sock_sendmsg(sock, &msg, len);
+ err = sock_sendmsg(sock, &msg, len);
+out:
+ unlock_kernel();
+ return err;
}
@@ -971,15 +1021,17 @@
struct socket *sock;
int err;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
-
+ goto out;
+
+ err = 0;
if(size==0)
- return 0;
+ goto out;
err=verify_area(VERIFY_WRITE, ubuf, size);
if(err)
- return err;
-
+ goto out;
+
msg.msg_name=NULL;
msg.msg_iov=&iov;
msg.msg_iovlen=1;
@@ -988,8 +1040,12 @@
iov.iov_base=ubuf;
iov.iov_len=size;
- return sock_recvmsg(sock, &msg, size,
- (current->files->fd[fd]->f_flags & O_NONBLOCK) ? flags | MSG_DONTWAIT : flags);
+ err = sock_recvmsg(sock, &msg, size,
+ (current->files->fd[fd]->f_flags & O_NONBLOCK)
+ ? flags | MSG_DONTWAIT : flags);
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1007,15 +1063,17 @@
char address[MAX_SOCK_ADDR];
int err;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
+ err = 0;
if (size==0)
- return 0;
+ goto out;
err=verify_area(VERIFY_WRITE,ubuf,size);
if(err)
- return err;
-
+ goto out;
+
msg.msg_control=NULL;
msg.msg_controllen=0;
msg.msg_iovlen=1;
@@ -1024,17 +1082,20 @@
iov.iov_base=ubuf;
msg.msg_name=address;
msg.msg_namelen=MAX_SOCK_ADDR;
- err=sock_recvmsg(sock, &msg, size,
- (current->files->fd[fd]->f_flags & O_NONBLOCK) ? (flags | MSG_DONTWAIT) : flags);
+ err = sock_recvmsg(sock, &msg, size,
+ (current->files->fd[fd]->f_flags & O_NONBLOCK)
+ ? (flags | MSG_DONTWAIT) : flags);
if(err<0)
- return err;
+ goto out;
size=err;
-
- if(addr!=NULL && (err=move_addr_to_user(address, msg.msg_namelen, addr, addr_len))<0)
- return err;
-
- return size;
+ if(addr!=NULL &&
+ (err=move_addr_to_user(address, msg.msg_namelen, addr, addr_len))<0)
+ goto out;
+ err = size;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1047,16 +1108,19 @@
int err;
struct socket *sock;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
if (level == SOL_SOCKET)
- return sock_setsockopt(sock,level,optname,optval,optlen);
-
- if (sock->ops->setsockopt)
- return sock->ops->setsockopt(sock, level, optname, optval, optlen);
-
- return -EOPNOTSUPP;
+ err = sock_setsockopt(sock,level,optname,optval,optlen);
+ else if (sock->ops->setsockopt)
+ err = sock->ops->setsockopt(sock, level, optname, optval, optlen);
+ else
+ err = -EOPNOTSUPP;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1069,16 +1133,19 @@
int err;
struct socket *sock;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
if (level == SOL_SOCKET)
- return sock_getsockopt(sock,level,optname,optval,optlen);
-
- if (sock->ops->getsockopt)
- return sock->ops->getsockopt(sock, level, optname, optval, optlen);
-
- return -EOPNOTSUPP;
+ err = sock_getsockopt(sock,level,optname,optval,optlen);
+ else if (sock->ops->getsockopt)
+ err = sock->ops->getsockopt(sock, level, optname, optval, optlen);
+ else
+ err = -EOPNOTSUPP;
+out:
+ unlock_kernel();
+ return err;
}
@@ -1091,10 +1158,14 @@
int err;
struct socket *sock;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
- return sock->ops->shutdown(sock, how);
+ err = sock->ops->shutdown(sock, how);
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1111,23 +1182,27 @@
int err;
int total_len;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd,&err)))
- return err;
+ goto out;
+ err = -EOPNOTSUPP;
if (sock->ops->sendmsg==NULL)
- return -EOPNOTSUPP;
+ goto out;
+ err = -EFAULT;
if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
- return -EFAULT;
+ goto out;
/* do not move before msg_sys is valid */
+ err = -EINVAL;
if (msg_sys.msg_iovlen>UIO_MAXIOV)
- return -EINVAL;
+ goto out;
/* This will also move the address data into kernel space */
err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
if (err < 0)
- return err;
+ goto out;
total_len=err;
if (msg_sys.msg_controllen) {
@@ -1159,6 +1234,8 @@
failed2:
if (msg_sys.msg_iov != iov)
kfree(msg_sys.msg_iov);
+out:
+ unlock_kernel();
return err;
}
@@ -1184,14 +1261,17 @@
struct sockaddr *uaddr;
int *uaddr_len;
+ lock_kernel();
if (!(sock = sockfd_lookup(fd, &err)))
- return err;
+ goto out;
+ err = -EFAULT;
if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
- return -EFAULT;
+ goto out;
+ err = -EINVAL;
if (msg_sys.msg_iovlen>UIO_MAXIOV)
- return -EINVAL;
+ goto out;
/*
* Save the user-mode address (verify_iovec will change the
@@ -1202,7 +1282,7 @@
uaddr_len = &msg->msg_namelen;
err=verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
if (err<0)
- return err;
+ goto out;
total_len=err;
@@ -1214,20 +1294,26 @@
len=sock_recvmsg(sock, &msg_sys, total_len, flags);
if (msg_sys.msg_iov != iov)
kfree(msg_sys.msg_iov);
- if (len<0)
- return len;
+ if (len<0) {
+ err = len;
+ goto out;
+ }
if (uaddr != NULL)
{
err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
if (err)
- return err;
+ goto out;
}
+ err = -EFAULT;
if (put_user(msg_sys.msg_flags, &msg->msg_flags))
- return -EFAULT;
+ goto out;
if (put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, &msg->msg_controllen))
- return -EFAULT;
- return len;
+ goto out;
+ err = len;
+out:
+ unlock_kernel();
+ return err;
}
@@ -1249,7 +1335,7 @@
/*
* System call vectors. Since I (RIB) want to rewrite sockets as streams,
* we have this level of indirection. Not a lot of overhead, since more of
- * the work is done via read/write/select directly.
+ * the work is done via read/write/poll directly.
*
* I'm now expanding this up to a higher level to separate the assorted
* kernel/user space manipulations and global assumptions from the protocol
@@ -1264,89 +1350,80 @@
4,4,4,6,6,2,5,5,3,3};
unsigned long a[6];
unsigned long a0,a1;
+ int err = -EINVAL;
+ lock_kernel();
if(call<1||call>SYS_RECVMSG)
- return -EINVAL;
-
+ goto out;
+ err = -EFAULT;
if ((copy_from_user(a, args, nargs[call] * sizeof(unsigned long))))
- return -EFAULT;
+ goto out;
a0=a[0];
a1=a[1];
-
switch(call)
{
case SYS_SOCKET:
- return(sys_socket(a0,a1,a[2]));
+ err = sys_socket(a0,a1,a[2]);
+ break;
case SYS_BIND:
- return(sys_bind(a0,(struct sockaddr *)a1,
- a[2]));
+ err = sys_bind(a0,(struct sockaddr *)a1, a[2]);
+ break;
case SYS_CONNECT:
- return(sys_connect(a0, (struct sockaddr *)a1,
- a[2]));
+ err = sys_connect(a0, (struct sockaddr *)a1, a[2]);
+ break;
case SYS_LISTEN:
- return(sys_listen(a0,a1));
+ err = sys_listen(a0,a1);
+ break;
case SYS_ACCEPT:
- return(sys_accept(a0,(struct sockaddr *)a1,
- (int *)a[2]));
+ err = sys_accept(a0,(struct sockaddr *)a1, (int *)a[2]);
+ break;
case SYS_GETSOCKNAME:
- return(sys_getsockname(a0,(struct sockaddr *)a1,
- (int *)a[2]));
+ err = sys_getsockname(a0,(struct sockaddr *)a1, (int *)a[2]);
+ break;
case SYS_GETPEERNAME:
- return(sys_getpeername(a0, (struct sockaddr *)a1,
- (int *)a[2]));
+ err = sys_getpeername(a0, (struct sockaddr *)a1, (int *)a[2]);
+ break;
case SYS_SOCKETPAIR:
- return(sys_socketpair(a0,a1,
- a[2],
- (int *)a[3]));
+ err = sys_socketpair(a0,a1, a[2], (int *)a[3]);
+ break;
case SYS_SEND:
- return(sys_send(a0,
- (void *)a1,
- a[2],
- a[3]));
+ err = sys_send(a0, (void *)a1, a[2], a[3]);
+ break;
case SYS_SENDTO:
- return(sys_sendto(a0,(void *)a1,
- a[2],
- a[3],
- (struct sockaddr *)a[4],
- a[5]));
+ err = sys_sendto(a0,(void *)a1, a[2], a[3],
+ (struct sockaddr *)a[4], a[5]);
+ break;
case SYS_RECV:
- return(sys_recv(a0,
- (void *)a1,
- a[2],
- a[3]));
+ err = sys_recv(a0, (void *)a1, a[2], a[3]);
+ break;
case SYS_RECVFROM:
- return(sys_recvfrom(a0,
- (void *)a1,
- a[2],
- a[3],
- (struct sockaddr *)a[4],
- (int *)a[5]));
+ err = sys_recvfrom(a0, (void *)a1, a[2], a[3],
+ (struct sockaddr *)a[4], (int *)a[5]);
+ break;
case SYS_SHUTDOWN:
- return(sys_shutdown(a0,a1));
+ err = sys_shutdown(a0,a1);
+ break;
case SYS_SETSOCKOPT:
- return(sys_setsockopt(a0,
- a1,
- a[2],
- (char *)a[3],
- a[4]));
+ err = sys_setsockopt(a0, a1, a[2], (char *)a[3], a[4]);
+ break;
case SYS_GETSOCKOPT:
- return(sys_getsockopt(a0,
- a1,
- a[2],
- (char *)a[3],
- (int *)a[4]));
+ err = sys_getsockopt(a0, a1, a[2], (char *)a[3], (int *)a[4]);
+ break;
case SYS_SENDMSG:
- return sys_sendmsg(a0,
- (struct msghdr *) a1,
- a[2]);
+ err = sys_sendmsg(a0, (struct msghdr *) a1, a[2]);
+ break;
case SYS_RECVMSG:
- return sys_recvmsg(a0,
- (struct msghdr *) a1,
- a[2]);
+ err = sys_recvmsg(a0, (struct msghdr *) a1, a[2]);
+ break;
+ default:
+ err = -EINVAL;
+ break;
}
- return -EINVAL; /* to keep gcc happy */
+out:
+ unlock_kernel();
+ return err;
}
@@ -1389,6 +1466,7 @@
/* We're all done... */
}
+extern void sk_init(void);
void sock_init(void)
{
@@ -1401,6 +1479,12 @@
*/
for (i = 0; i < NPROTO; i++) net_families[i] = NULL;
+
+ /*
+ * Initialize sock SLAB cache.
+ */
+
+ sk_init();
/*
* The netlink device handler may be needed early.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov