#include <net/sock.h>
#include <linux/netfilter.h>
+#include <linux/vs_base.h>
+#include <linux/vs_socket.h>
static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
ei->socket.ops = NULL;
ei->socket.sk = NULL;
ei->socket.file = NULL;
- ei->socket.passcred = 0;
+ ei->socket.flags = 0;
return &ei->vfs_inode;
}
struct msghdr *msg, size_t size)
{
struct sock_iocb *si = kiocb_to_siocb(iocb);
- int err;
+ int err, len;
si->sock = sock;
si->scm = NULL;
if (err)
return err;
- return sock->ops->sendmsg(iocb, sock, msg, size);
+ len = sock->ops->sendmsg(iocb, sock, msg, size);
+ if (sock->sk) {
+ if (len == size)
+ vx_sock_send(sock->sk, size);
+ else
+ vx_sock_fail(sock->sk, size);
+ }
+ vxdprintk("__sock_sendmsg: %p[%p,%p,%p;%d]:%d/%d\n",
+ sock, sock->sk,
+ (sock->sk)?sock->sk->sk_nx_info:0,
+ (sock->sk)?sock->sk->sk_vx_info:0,
+ (sock->sk)?sock->sk->sk_xid:0,
+ size, len);
+ return len;
}
int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct kiocb iocb;
+ struct sock_iocb siocb;
int ret;
init_sync_kiocb(&iocb, NULL);
+ iocb.private = &siocb;
ret = __sock_sendmsg(&iocb, sock, msg, size);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{
- int err;
+ int err, len;
struct sock_iocb *si = kiocb_to_siocb(iocb);
si->sock = sock;
if (err)
return err;
- return sock->ops->recvmsg(iocb, sock, msg, size, flags);
+ len = sock->ops->recvmsg(iocb, sock, msg, size, flags);
+ if ((len >= 0) && sock->sk)
+ vx_sock_recv(sock->sk, len);
+ vxdprintk("__sock_recvmsg: %p[%p,%p,%p;%d]:%d/%d\n",
+ sock, sock->sk,
+ (sock->sk)?sock->sk->sk_nx_info:0,
+ (sock->sk)?sock->sk->sk_vx_info:0,
+ (sock->sk)?sock->sk->sk_xid:0,
+ size, len);
+ return len;
}
int sock_recvmsg(struct socket *sock, struct msghdr *msg,
size_t size, int flags)
{
struct kiocb iocb;
+ struct sock_iocb siocb;
int ret;
init_sync_kiocb(&iocb, NULL);
+ iocb.private = &siocb;
ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb);
return ret;
}
+static void sock_aio_dtor(struct kiocb *iocb)
+{
+ kfree(iocb->private);
+}
+
/*
* Read data from a socket. ubuf is a user mode pointer. We make sure the user
* area ubuf...ubuf+size-1 is writable before asking the protocol.
static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
size_t size, loff_t pos)
{
- struct sock_iocb *x = kiocb_to_siocb(iocb);
+ struct sock_iocb *x, siocb;
struct socket *sock;
int flags;
if (size==0) /* Match SYS5 behaviour */
return 0;
+ if (is_sync_kiocb(iocb))
+ x = &siocb;
+ else {
+ x = kmalloc(sizeof(struct sock_iocb), GFP_KERNEL);
+ if (!x)
+ return -ENOMEM;
+ iocb->ki_dtor = sock_aio_dtor;
+ }
+ iocb->private = x;
+ x->kiocb = iocb;
sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode);
x->async_msg.msg_name = NULL;
static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
size_t size, loff_t pos)
{
- struct sock_iocb *x = kiocb_to_siocb(iocb);
+ struct sock_iocb *x, siocb;
struct socket *sock;
if (pos != 0)
if(size==0) /* Match SYS5 behaviour */
return 0;
+ if (is_sync_kiocb(iocb))
+ x = &siocb;
+ else {
+ x = kmalloc(sizeof(struct sock_iocb), GFP_KERNEL);
+ if (!x)
+ return -ENOMEM;
+ iocb->ki_dtor = sock_aio_dtor;
+ }
+ iocb->private = x;
+ x->kiocb = iocb;
sock = SOCKET_I(iocb->ki_filp->f_dentry->d_inode);
x->async_msg.msg_name = NULL;
if (type < 0 || type >= SOCK_MAX)
return -EINVAL;
+ /* disable IPv6 inside vservers for now */
+ if (family == PF_INET6 && !vx_check(0, VX_ADMIN))
+ return -EAFNOSUPPORT;
+
/* Compatibility.
This uglymoron is moved from INET layer to here to avoid
if (retval < 0)
goto out;
+ set_bit(SOCK_USER_SOCKET, &sock->flags);
retval = sock_map_fd(sock);
if (retval < 0)
goto out_release;
err = sock_create(family, type, protocol, &sock1);
if (err < 0)
goto out;
+ set_bit(SOCK_USER_SOCKET, &sock1->flags);
err = sock_create(family, type, protocol, &sock2);
if (err < 0)
goto out_release_1;
+ set_bit(SOCK_USER_SOCKET, &sock2->flags);
err = sock1->ops->socketpair(sock1, sock2);
if (err < 0)