#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/tux.h>
#include <linux/wanrouter.h>
#include <linux/if_bridge.h>
#include <linux/init.h>
#endif /* CONFIG_NET_RADIO */
#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
#include <net/compat.h>
#include <net/sock.h>
* in the operation structures but are done directly via the socketcall() multiplexor.
*/
-static struct file_operations socket_file_ops = {
+struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.aio_read = sock_aio_read,
ei->socket.ops = NULL;
ei->socket.sk = NULL;
ei->socket.file = NULL;
- ei->socket.passcred = 0;
+ ei->socket.flags = 0;
return &ei->vfs_inode;
}
static int init_inodecache(void)
{
sock_inode_cachep = kmem_cache_create("sock_inode_cache",
- sizeof(struct socket_alloc),
- 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
- init_once, NULL);
+ sizeof(struct socket_alloc),
+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+ init_once, NULL);
if (sock_inode_cachep == NULL)
return -ENOMEM;
return 0;
* but we take care of internal coherence yet.
*/
-int sock_map_fd(struct socket *sock)
+struct file * sock_map_file(struct socket *sock)
{
- int fd;
+ struct file *file;
struct qstr this;
char name[32];
- /*
- * Find a file descriptor suitable for return to the user.
- */
+ file = get_empty_filp();
- fd = get_unused_fd();
- if (fd >= 0) {
- struct file *file = get_empty_filp();
-
- if (!file) {
- put_unused_fd(fd);
- fd = -ENFILE;
- goto out;
- }
+ if (!file)
+ return ERR_PTR(-ENFILE);
- sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
- this.name = name;
- this.len = strlen(name);
- this.hash = SOCK_INODE(sock)->i_ino;
-
- file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
- if (!file->f_dentry) {
- put_filp(file);
- put_unused_fd(fd);
- fd = -ENOMEM;
- goto out;
- }
- file->f_dentry->d_op = &sockfs_dentry_operations;
- d_add(file->f_dentry, SOCK_INODE(sock));
- file->f_vfsmnt = mntget(sock_mnt);
- file->f_mapping = file->f_dentry->d_inode->i_mapping;
+ sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
+ this.name = name;
+ this.len = strlen(name);
+ this.hash = SOCK_INODE(sock)->i_ino;
- sock->file = file;
- file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
- file->f_mode = 3;
- file->f_flags = O_RDWR;
- file->f_pos = 0;
- fd_install(fd, file);
+ file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
+ if (!file->f_dentry) {
+ put_filp(file);
+ return ERR_PTR(-ENOMEM);
}
+ file->f_dentry->d_op = &sockfs_dentry_operations;
+ d_add(file->f_dentry, SOCK_INODE(sock));
+ file->f_vfsmnt = mntget(sock_mnt);
+file->f_mapping = file->f_dentry->d_inode->i_mapping;
+
+ if (sock->file)
+ BUG();
+ sock->file = file;
+ file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
+ file->f_mode = 3;
+ file->f_flags = O_RDWR;
+ file->f_pos = 0;
+
+ return file;
+}
-out:
+int sock_map_fd(struct socket *sock)
+{
+ int fd;
+ struct file *file;
+
+ /*
+ * Find a file descriptor suitable for return to the user.
+ */
+
+ fd = get_unused_fd();
+ if (fd < 0)
+ return fd;
+
+ file = sock_map_file(sock);
+ if (IS_ERR(file)) {
+ put_unused_fd(fd);
+ return PTR_ERR(file);
+ }
+ fd_install(fd, file);
+
return fd;
}
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)
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,
*/
static DECLARE_MUTEX(br_ioctl_mutex);
-static int (*br_ioctl_hook)(unsigned long arg) = NULL;
+static int (*br_ioctl_hook)(unsigned int cmd, unsigned long arg) = NULL;
-void brioctl_set(int (*hook)(unsigned long))
+void brioctl_set(int (*hook)(unsigned int, unsigned long))
{
down(&br_ioctl_mutex);
br_ioctl_hook = hook;
unlock_kernel();
sock = SOCKET_I(inode);
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
- err = dev_ioctl(cmd, (void *)arg);
+ err = dev_ioctl(cmd, (void __user *)arg);
} else
#ifdef WIRELESS_EXT
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- err = dev_ioctl(cmd, (void *)arg);
+ err = dev_ioctl(cmd, (void __user *)arg);
} else
#endif /* WIRELESS_EXT */
switch (cmd) {
case FIOSETOWN:
case SIOCSPGRP:
err = -EFAULT;
- if (get_user(pid, (int *)arg))
+ if (get_user(pid, (int __user *)arg))
break;
err = f_setown(sock->file, pid, 1);
break;
case FIOGETOWN:
case SIOCGPGRP:
- err = put_user(sock->file->f_owner.pid, (int *)arg);
+ err = put_user(sock->file->f_owner.pid, (int __user *)arg);
break;
case SIOCGIFBR:
case SIOCSIFBR:
+ case SIOCBRADDBR:
+ case SIOCBRDELBR:
err = -ENOPKG;
if (!br_ioctl_hook)
request_module("bridge");
down(&br_ioctl_mutex);
if (br_ioctl_hook)
- err = br_ioctl_hook(arg);
+ err = br_ioctl_hook(cmd, arg);
up(&br_ioctl_mutex);
break;
case SIOCGIFVLAN:
}
out:
+ if (sock->sk != sk)
+ BUG();
release_sock(sock->sk);
return 0;
}
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)
return err;
}
+#ifdef __ARCH_WANT_SYS_SOCKETCALL
+
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned long))
static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
return err;
}
+#endif /* __ARCH_WANT_SYS_SOCKETCALL */
+
/*
* This function is called by a protocol handler that wants to
* advertise its address family, and have it linked into the
#endif
}
+int tux_Dprintk;
+int tux_TDprintk;
+
+#ifdef CONFIG_TUX_MODULE
+
+asmlinkage long (*sys_tux_ptr) (unsigned int action, user_req_t *u_info) = NULL;
+
+struct module *tux_module = NULL;
+spinlock_t tux_module_lock = SPIN_LOCK_UNLOCKED;
+
+asmlinkage long sys_tux (unsigned int action, user_req_t *u_info)
+{
+ int ret;
+
+ if (current->tux_info)
+ return sys_tux_ptr(action, u_info);
+
+ ret = -ENOSYS;
+ spin_lock(&tux_module_lock);
+ if (!tux_module)
+ goto out_unlock;
+ if (!try_module_get(tux_module))
+ goto out_unlock;
+ spin_unlock(&tux_module_lock);
+
+ if (!sys_tux_ptr)
+ TUX_BUG();
+ ret = sys_tux_ptr(action, u_info);
+
+ spin_lock(&tux_module_lock);
+ module_put(tux_module);
+out_unlock:
+ spin_unlock(&tux_module_lock);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(tux_module);
+EXPORT_SYMBOL_GPL(tux_module_lock);
+EXPORT_SYMBOL_GPL(sys_tux_ptr);
+
+EXPORT_SYMBOL_GPL(tux_Dprintk);
+EXPORT_SYMBOL_GPL(tux_TDprintk);
+
+#endif
#ifdef CONFIG_PROC_FS
void socket_seq_show(struct seq_file *seq)
{