summaryrefslogtreecommitdiff
path: root/sys/compat/linux/common/linux_socket.c
diff options
context:
space:
mode:
authorfvdl <fvdl@NetBSD.org>2000-12-18 14:46:36 +0000
committerfvdl <fvdl@NetBSD.org>2000-12-18 14:46:36 +0000
commit865e7b1375ffc76f3e9a796e4bbc35b5f32f2fc0 (patch)
tree479b3beebff79306193a846b7c074305b71f0884 /sys/compat/linux/common/linux_socket.c
parent8578d458e5d9c653127b08285693197a6cf5bc2d (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.c57
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