summaryrefslogtreecommitdiff
path: root/sys/compat/linux/common/linux_socket.c
diff options
context:
space:
mode:
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