diff options
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 |
