summaryrefslogtreecommitdiff
path: root/sys/compat/linux/linux_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux/linux_socket.c')
-rw-r--r--sys/compat/linux/linux_socket.c52
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);
}