diff options
-rw-r--r-- | sys/arch/i386/i386/linux_machdep.c | 40 | ||||
-rw-r--r-- | sys/compat/linux/linux_socket.c | 52 | ||||
-rw-r--r-- | sys/compat/linux/linux_sockio.h | 6 | ||||
-rw-r--r-- | sys/sys/ioctl_compat.h | 19 |
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_ */ |