summaryrefslogtreecommitdiff
path: root/sys/compat/linux32/common/linux32_socket.c
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2008-06-19 16:09:25 +0000
committerchristos <christos@NetBSD.org>2008-06-19 16:09:25 +0000
commitd83ff0cd7b268b215986e1db436abec99b86f9d1 (patch)
tree672f467874bd4147a77907ef0c15d83471d11726 /sys/compat/linux32/common/linux32_socket.c
parent5bbd2ba0982a53799f0f2989ef45b0374e868d49 (diff)
an attempt at linux32_ioctl_socket().
Diffstat (limited to 'sys/compat/linux32/common/linux32_socket.c')
-rw-r--r--sys/compat/linux32/common/linux32_socket.c116
1 files changed, 114 insertions, 2 deletions
diff --git a/sys/compat/linux32/common/linux32_socket.c b/sys/compat/linux32/common/linux32_socket.c
index f2253e4b8ca..487f95bac77 100644
--- a/sys/compat/linux32/common/linux32_socket.c
+++ b/sys/compat/linux32/common/linux32_socket.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux32_socket.c,v 1.5 2007/12/20 23:02:58 dsl Exp $ */
+/* $NetBSD: linux32_socket.c,v 1.6 2008/06/19 16:09:25 christos Exp $ */
/*-
* Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -33,7 +33,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.5 2007/12/20 23:02:58 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.6 2008/06/19 16:09:25 christos Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -46,20 +46,29 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.5 2007/12/20 23:02:58 dsl Exp $
#include <sys/proc.h>
#include <sys/ucred.h>
#include <sys/swap.h>
+#include <sys/file.h>
+#include <sys/vnode.h>
+#include <sys/filedesc.h>
#include <machine/types.h>
+#include <net/if.h>
+
#include <sys/syscallargs.h>
#include <compat/netbsd32/netbsd32.h>
#include <compat/netbsd32/netbsd32_conv.h>
#include <compat/netbsd32/netbsd32_syscallargs.h>
+#include <compat/sys/sockio.h>
#include <compat/linux/common/linux_types.h>
+#include <compat/linux/common/linux_types.h>
#include <compat/linux/common/linux_signal.h>
#include <compat/linux/common/linux_machdep.h>
#include <compat/linux/common/linux_misc.h>
#include <compat/linux/common/linux_oldolduname.h>
+#include <compat/linux/common/linux_ioctl.h>
+#include <compat/linux/common/linux_sockio.h>
#include <compat/linux/linux_syscallargs.h>
#include <compat/linux32/common/linux32_types.h>
@@ -67,6 +76,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.5 2007/12/20 23:02:58 dsl Exp $
#include <compat/linux32/common/linux32_machdep.h>
#include <compat/linux32/common/linux32_sysctl.h>
#include <compat/linux32/common/linux32_socketcall.h>
+#include <compat/linux32/common/linux32_ioctl.h>
#include <compat/linux32/linux32_syscallargs.h>
int
@@ -360,3 +370,105 @@ linux32_sys_recv(struct lwp *l, const struct linux32_sys_recv_args *uap, registe
return sys_recvfrom(l, &ua, retval);
}
+
+int
+linux32_ioctl_socket(struct lwp *l, const struct linux32_sys_ioctl_args *uap, register_t *retval)
+{
+ /* {
+ syscallarg(int) fd;
+ syscallarg(u_long) com;
+ syscallarg(void *) data;
+ } */
+ u_long com;
+ int error = 0, isdev = 0, dosys = 1;
+ struct netbsd32_ioctl_args ia;
+ file_t *fp;
+ struct vnode *vp;
+ int (*ioctlf)(file_t *, u_long, void *);
+ struct ioctl_pt pt;
+
+ if ((fp = fd_getfile(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 = (void *)NETBSD32PTR64(SCARG(uap, data));
+ error = ioctlf(fp, PTIOCLINUX, &pt);
+ /*
+ * 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;
+
+ switch (com) {
+ case LINUX_SIOCGIFCONF:
+ SCARG(&ia, com) = OOSIOCGIFCONF;
+ break;
+ case LINUX_SIOCGIFFLAGS:
+ SCARG(&ia, com) = OSIOCGIFFLAGS;
+ break;
+ case LINUX_SIOCSIFFLAGS:
+ SCARG(&ia, com) = OSIOCSIFFLAGS;
+ break;
+ case LINUX_SIOCGIFADDR:
+ SCARG(&ia, com) = OOSIOCGIFADDR;
+ break;
+ case LINUX_SIOCGIFDSTADDR:
+ SCARG(&ia, com) = OOSIOCGIFDSTADDR;
+ break;
+ case LINUX_SIOCGIFBRDADDR:
+ SCARG(&ia, com) = OOSIOCGIFBRDADDR;
+ break;
+ case LINUX_SIOCGIFNETMASK:
+ SCARG(&ia, com) = OOSIOCGIFNETMASK;
+ break;
+ case LINUX_SIOCADDMULTI:
+ SCARG(&ia, com) = OSIOCADDMULTI;
+ break;
+ case LINUX_SIOCDELMULTI:
+ SCARG(&ia, com) = OSIOCDELMULTI;
+ break;
+#ifdef notyet
+ case LINUX_SIOCGIFHWADDR:
+ error = linux_getifhwaddr(l, retval, SCARG(uap, fd),
+ SCARG(uap, data));
+ dosys = 0;
+ break;
+#endif
+ default:
+ error = EINVAL;
+ }
+
+ out:
+ fd_putfile(SCARG(uap, fd));
+
+ if (error == 0 && dosys) {
+ SCARG(&ia, fd) = SCARG(uap, fd);
+ SCARG(&ia, data) = SCARG(uap, data);
+ error = netbsd32_ioctl(curlwp, &ia, retval);
+ }
+
+ return error;
+}