summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/i386/i386/linux_machdep.c40
-rw-r--r--sys/compat/linux/linux_socket.c52
-rw-r--r--sys/compat/linux/linux_sockio.h6
-rw-r--r--sys/sys/ioctl_compat.h19
4 files changed, 105 insertions, 12 deletions
diff --git a/sys/arch/i386/i386/linux_machdep.c b/sys/arch/i386/i386/linux_machdep.c
index a2570f84c6c..355f88540b2 100644
--- a/sys/arch/i386/i386/linux_machdep.c
+++ b/sys/arch/i386/i386/linux_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_machdep.c,v 1.18 2002/01/16 20:50:16 miod Exp $ */
+/* $OpenBSD: linux_machdep.c,v 1.19 2002/02/06 01:55:04 jasoni Exp $ */
/* $NetBSD: linux_machdep.c,v 1.29 1996/05/03 19:42:11 christos Exp $ */
/*
@@ -111,8 +111,8 @@ linux_sendsig(catcher, sig, mask, code, type, val)
int type;
union sigval val;
{
- register struct proc *p = curproc;
- register struct trapframe *tf;
+ struct proc *p = curproc;
+ struct trapframe *tf;
struct linux_sigframe *fp, frame;
struct sigacts *psp = p->p_sigacts;
int oonstack;
@@ -212,7 +212,7 @@ linux_sys_sigreturn(p, v, retval)
syscallarg(struct linux_sigcontext *) scp;
} */ *uap = v;
struct linux_sigcontext *scp, context;
- register struct trapframe *tf;
+ struct trapframe *tf;
tf = p->p_md.md_regs;
@@ -451,11 +451,21 @@ linux_machdepioctl(p, v, retval)
struct vt_mode lvt;
caddr_t bvtp, sg;
#endif
+ struct filedesc *fdp;
+ struct file *fp;
+ int fd;
+ int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *));
+ struct ioctl_pt pt;
+ fd = SCARG(uap, fd);
SCARG(&bia, fd) = SCARG(uap, fd);
SCARG(&bia, data) = SCARG(uap, data);
com = SCARG(uap, com);
+ fdp = p->p_fd;
+ if ((fp = fd_getfile(fdp, fd)) == NULL)
+ return (EBADF);
+
switch (com) {
#if (NWSDISPLAY > 0 && defined(WSDISPLAY_COMPAT_USL))
case LINUX_KDGKBMODE:
@@ -570,8 +580,26 @@ linux_machdepioctl(p, v, retval)
return (subyte(SCARG(uap, data), KB_101));
#endif
default:
- printf("linux_machdepioctl: invalid ioctl %08lx\n", com);
- return EINVAL;
+ /*
+ * Unknown to us. If it's on a device, just pass it through
+ * using PTIOCLINUX, the device itself might be able to
+ * make some sense of it.
+ * XXX hack: if the function returns EJUSTRETURN,
+ * it has stuffed a sysctl return value in pt.data.
+ */
+ ioctlf = fp->f_ops->fo_ioctl;
+ pt.com = SCARG(uap, com);
+ pt.data = SCARG(uap, data);
+ error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
+ if (error == EJUSTRETURN) {
+ retval[0] = (register_t)pt.data;
+ error = 0;
+ }
+
+ if (error == ENOTTY)
+ printf("linux_machdepioctl: invalid ioctl %08lx\n",
+ com);
+ return (error);
}
SCARG(&bia, com) = com;
return sys_ioctl(p, &bia, retval);
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);
}
diff --git a/sys/compat/linux/linux_sockio.h b/sys/compat/linux/linux_sockio.h
index 1cb6f323127..44325602a01 100644
--- a/sys/compat/linux/linux_sockio.h
+++ b/sys/compat/linux/linux_sockio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_sockio.h,v 1.7 1999/02/10 08:02:15 deraadt Exp $ */
+/* $OpenBSD: linux_sockio.h,v 1.8 2002/02/06 01:55:04 jasoni Exp $ */
/* $NetBSD: linux_sockio.h,v 1.5 1996/03/08 04:56:07 mycroft Exp $ */
/*
@@ -43,7 +43,9 @@
#define LINUX_SIOCGSTAMP _LINUX_IO(0x89, 6)
#define LINUX_SIOCGIFCONF _LINUX_IO(0x89, 18)
#define LINUX_SIOCGIFFLAGS _LINUX_IO(0x89, 19)
+#define LINUX_SIOCSIFFLAGS _LINUX_IO(0x89, 20)
#define LINUX_SIOCGIFADDR _LINUX_IO(0x89, 21)
+#define LINUX_SIOCSIFADDR _LINUX_IO(0x89, 22)
#define LINUX_SIOCGIFDSTADDR _LINUX_IO(0x89, 23)
#define LINUX_SIOCGIFBRDADDR _LINUX_IO(0x89, 25)
#define LINUX_SIOCGIFNETMASK _LINUX_IO(0x89, 27)
@@ -52,5 +54,7 @@
#define LINUX_SIOCGIFHWADDR _LINUX_IO(0x89, 39)
#define LINUX_SIOCADDMULTI _LINUX_IO(0x89, 49)
#define LINUX_SIOCDELMULTI _LINUX_IO(0x89, 50)
+#define LINUX_SIOCGIFBR _LINUX_IO(0x89, 64)
+#define LINUX_SIOCDEVPRIVATE _LINUX_IO(0x89, 0xf0)
#endif /* _LINUX_SOCKIO_H */
diff --git a/sys/sys/ioctl_compat.h b/sys/sys/ioctl_compat.h
index 4b221a8537b..cfa199946e2 100644
--- a/sys/sys/ioctl_compat.h
+++ b/sys/sys/ioctl_compat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioctl_compat.h,v 1.2 1996/03/03 12:11:51 niklas Exp $ */
+/* $OpenBSD: ioctl_compat.h,v 1.3 2002/02/06 01:55:04 jasoni Exp $ */
/* $NetBSD: ioctl_compat.h,v 1.10 1995/03/31 03:10:15 christos Exp $ */
/*
@@ -169,4 +169,21 @@ struct sgttyb {
#define TIOCGSID _IOR('t', 99, int) /* For svr4 -- get session id */
+/*
+ * Passthrough ioctl commands. These are passed through to devices
+ * as they are, it is expected that the device (an LKM, for example),
+ * will know how to deal with them. One for each emulation, so that
+ * no namespace clashes will occur between them, for devices that
+ * may be dealing with specific ioctls for multiple emulations.
+ *
+ * XXX: Currently only implemented for Linux.
+ */
+
+struct ioctl_pt {
+ unsigned long com;
+ void *data;
+};
+
+#define PTIOCLINUX _IOW('Z', 3, struct ioctl_pt)
+
#endif /* !_SYS_IOCTL_COMPAT_H_ */