diff options
| author | fvdl <fvdl@NetBSD.org> | 2000-12-18 14:46:36 +0000 |
|---|---|---|
| committer | fvdl <fvdl@NetBSD.org> | 2000-12-18 14:46:36 +0000 |
| commit | 865e7b1375ffc76f3e9a796e4bbc35b5f32f2fc0 (patch) | |
| tree | 479b3beebff79306193a846b7c074305b71f0884 /sys/compat/linux/common/linux_socket.c | |
| parent | 8578d458e5d9c653127b08285693197a6cf5bc2d (diff) | |
Pass SIOC* calls that are done on devices (not sockets) through
without trying to interpret done, as is done on Linux. The device
will get them as PTIOCLINUX, with command and arg in the structure
passed in.
Diffstat (limited to 'sys/compat/linux/common/linux_socket.c')
| -rw-r--r-- | sys/compat/linux/common/linux_socket.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/sys/compat/linux/common/linux_socket.c b/sys/compat/linux/common/linux_socket.c index 1682a025e15..fd17972ec7d 100644 --- a/sys/compat/linux/common/linux_socket.c +++ b/sys/compat/linux/common/linux_socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socket.c,v 1.24 2000/05/03 21:41:43 thorpej Exp $ */ +/* $NetBSD: linux_socket.c,v 1.25 2000/12/18 14:46:36 fvdl Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -597,7 +597,41 @@ linux_ioctl_socket(p, uap, retval) register_t *retval; { u_long com; + int error = 0, isdev = 0, dosys = 1; 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; + + fdp = p->p_fd; + if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || + (fp->f_iflags & FIF_WANTCLOSE) != 0) + return (EBADF); + + FILE_USE(fp); + + 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) { + ioctlf = fp->f_ops->fo_ioctl; + pt.com = SCARG(uap, com); + pt.data = SCARG(uap, data); + error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p); + goto out; + } com = SCARG(uap, com); retval[0] = 0; @@ -609,6 +643,9 @@ linux_ioctl_socket(p, uap, retval) case LINUX_SIOCGIFFLAGS: SCARG(&ia, com) = SIOCGIFFLAGS; break; + case LINUX_SIOCSIFFLAGS: + SCARG(&ia, com) = SIOCSIFFLAGS; + break; case LINUX_SIOCGIFADDR: SCARG(&ia, com) = OSIOCGIFADDR; break; @@ -628,15 +665,23 @@ linux_ioctl_socket(p, uap, retval) SCARG(&ia, com) = SIOCDELMULTI; break; case LINUX_SIOCGIFHWADDR: - return linux_getifhwaddr(p, retval, SCARG(uap, fd), + error = linux_getifhwaddr(p, retval, SCARG(uap, fd), SCARG(uap, data)); + break; default: - return EINVAL; + error = EINVAL; } - SCARG(&ia, fd) = SCARG(uap, fd); - SCARG(&ia, data) = SCARG(uap, data); - return sys_ioctl(p, &ia, retval); +out: + FILE_UNUSE(fp, p); + + if (error ==0 && dosys) { + SCARG(&ia, fd) = SCARG(uap, fd); + SCARG(&ia, data) = SCARG(uap, data); + error = sys_ioctl(p, &ia, retval); + } + + return error; } int |
