diff options
Diffstat (limited to 'sys/compat/linux/linux_socket.c')
-rw-r--r-- | sys/compat/linux/linux_socket.c | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 731f41ca902..ba58a80a85c 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_socket.c,v 1.20 2001/06/21 01:43:57 itojun Exp $ */ +/* $OpenBSD: linux_socket.c,v 1.21 2002/02/06 01:55:04 jasoni Exp $ */ /* $NetBSD: linux_socket.c,v 1.14 1996/04/05 00:01:50 christos Exp $ */ /* @@ -1000,6 +1000,45 @@ linux_ioctl_socket(p, v, retval) } */ *uap = v; u_long com; struct sys_ioctl_args ia; + struct file *fp; + struct filedesc *fdp; + struct vnode *vp; + int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *)); + struct ioctl_pt pt; + int error = 0, isdev = 0, dosys = 1; + + fdp = p->p_fd; + if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) + return (EBADF); + + if (fp->f_type == DTYPE_VNODE) { + vp = (struct vnode *)fp->f_data; + isdev = vp->v_type == VCHR; + } + + /* + * Don't try to interpret socket ioctl calls that are done + * on a device filedescriptor, just pass them through, to + * emulate Linux behaviour. Use PTIOCLINUX so that the + * device will only handle these if it's prepared to do + * so, to avoid unexpected things from happening. + */ + if (isdev) { + dosys = 0; + ioctlf = fp->f_ops->fo_ioctl; + pt.com = SCARG(uap, com); + pt.data = SCARG(uap, data); + error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p); + /* + * XXX hack: if the function returns EJUSTRETURN, + * it has stuffed a sysctl return value in pt.data. + */ + if (error == EJUSTRETURN) { + retval[0] = (register_t)pt.data; + error = 0; + } + goto out; + } com = SCARG(uap, com); retval[0] = 0; @@ -1086,7 +1125,12 @@ linux_ioctl_socket(p, v, retval) return EINVAL; } - SCARG(&ia, fd) = SCARG(uap, fd); - SCARG(&ia, data) = SCARG(uap, data); - return sys_ioctl(p, &ia, retval); +out: + if (error == 0 && dosys) { + SCARG(&ia, fd) = SCARG(uap, fd); + SCARG(&ia, data) = SCARG(uap, data); + error = sys_ioctl(p, &ia, retval); + } + + return (error); } |