Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/compat/linux/common Do address family (AF_*) number tran...
details: https://anonhg.NetBSD.org/src/rev/4006886b5152
branches: trunk
changeset: 512047:4006886b5152
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Wed Jul 04 10:09:24 2001 +0000
description:
Do address family (AF_*) number translation for socket system calls which
pass socket address in our or out. This makes Linux programs using IPv6
working under emulation. This addresses kern/13279 by Jun-ichiro itojun Hagino.
Change sendmsg()/recvmsg() to expect the control information
to be passed the standard way (not 4.3BSD one, imlied by compat_43 code
or MSG_COMPAT). Linux uses different (arguably broken) CMSG_ALIGN() on some
architectures unfortunately, that would need to be handled eventually.
Also provide some other trivial stubs (like linux_sys_send()) to avoid
unneeded dependance on uipc_syscalls_43.c.
diffstat:
sys/compat/linux/common/linux_socket.c | 534 ++++++++++++++++++++++++++--
sys/compat/linux/common/linux_socketcall.c | 20 +-
sys/compat/linux/common/linux_socketcall.h | 88 ++--
3 files changed, 542 insertions(+), 100 deletions(-)
diffs (truncated from 834 to 300 lines):
diff -r b8042f1ddcb0 -r 4006886b5152 sys/compat/linux/common/linux_socket.c
--- a/sys/compat/linux/common/linux_socket.c Wed Jul 04 05:57:39 2001 +0000
+++ b/sys/compat/linux/common/linux_socket.c Wed Jul 04 10:09:24 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socket.c,v 1.31 2001/06/25 19:55:02 jdolecek Exp $ */
+/* $NetBSD: linux_socket.c,v 1.32 2001/07/04 10:09:24 jdolecek Exp $ */
/*-
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -39,8 +39,17 @@
/*
* Functions in multiarch:
* linux_sys_socketcall : linux_socketcall.c
+ *
+ * XXX Note: Linux CMSG_ALIGN() uses (sizeof(long)-1). For architectures
+ * where our CMSG_ALIGN() differs (like powerpc, sparc, sparc64), the passed
+ * control structure would need to be adjusted accordingly in sendmsg() and
+ * recvmsg().
*/
+#if defined(_KERNEL_OPT)
+#include "opt_inet.h"
+#endif
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -63,6 +72,8 @@
#include <sys/vnode.h>
#include <sys/device.h>
#include <sys/protosw.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
#include <sys/syscallargs.h>
@@ -84,48 +95,103 @@
* than a normal syscall.
*/
-int linux_to_bsd_domain __P((int));
+static int linux_to_bsd_domain __P((int));
+static int bsd_to_linux_domain __P((int));
int linux_to_bsd_sopt_level __P((int));
int linux_to_bsd_so_sockopt __P((int));
int linux_to_bsd_ip_sockopt __P((int));
int linux_to_bsd_tcp_sockopt __P((int));
int linux_to_bsd_udp_sockopt __P((int));
int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
+static int linux_sa_get __P((caddr_t *sgp, struct sockaddr **sap,
+ struct osockaddr *osa, int osalen));
+static int linux_sa_put __P((struct osockaddr *osa));
+
+static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
+ AF_UNSPEC,
+ AF_UNIX,
+ AF_INET,
+ AF_CCITT, /* LINUX_AF_AX25 */
+ AF_IPX,
+ AF_APPLETALK,
+ -1, /* LINUX_AF_NETROM */
+ -1, /* LINUX_AF_BRIDGE */
+ -1, /* LINUX_AF_ATMPVC */
+ AF_CCITT, /* LINUX_AF_X25 */
+ AF_INET6,
+ -1, /* LINUX_AF_ROSE */
+ AF_DECnet,
+ -1, /* LINUX_AF_NETBEUI */
+ -1, /* LINUX_AF_SECURITY */
+ pseudo_AF_KEY,
+ AF_ROUTE, /* LINUX_AF_NETLINK */
+ -1, /* LINUX_AF_PACKET */
+ -1, /* LINUX_AF_ASH */
+ -1, /* LINUX_AF_ECONET */
+ -1, /* LINUX_AF_ATMSVC */
+ AF_SNA,
+ /* rest up to LINUX_AF_MAX-1 is not allocated */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static const int bsd_to_linux_domain_[AF_MAX] = {
+ LINUX_AF_UNSPEC,
+ LINUX_AF_UNIX,
+ LINUX_AF_INET,
+ -1, /* AF_IMPLINK */
+ -1, /* AF_PUP */
+ -1, /* AF_CHAOS */
+ -1, /* AF_NS */
+ -1, /* AF_ISO */
+ -1, /* AF_ECMA */
+ -1, /* AF_DATAKIT */
+ LINUX_AF_AX25, /* AF_CCITT */
+ LINUX_AF_SNA,
+ LINUX_AF_DECnet,
+ -1, /* AF_DLI */
+ -1, /* AF_LAT */
+ -1, /* AF_HYLINK */
+ LINUX_AF_APPLETALK,
+ LINUX_AF_NETLINK,
+ -1, /* AF_LINK */
+ -1, /* AF_XTP */
+ -1, /* AF_COIP */
+ -1, /* AF_CNT */
+ -1, /* pseudo_AF_RTIP */
+ LINUX_AF_IPX,
+ LINUX_AF_INET6,
+ -1, /* pseudo_AF_PIP */
+ -1, /* AF_ISDN */
+ -1, /* AF_NATM */
+ -1, /* AF_ARP */
+ LINUX_pseudo_AF_KEY,
+ -1, /* pseudo_AF_HDRCMPLT */
+};
/*
* Convert between Linux and BSD socket domain values
*/
-int
+static int
linux_to_bsd_domain(ldom)
int ldom;
{
+ if (ldom < 0 || ldom >= LINUX_AF_MAX)
+ return (-1);
- switch (ldom) {
- case LINUX_AF_UNSPEC:
- return AF_UNSPEC;
- case LINUX_AF_UNIX:
- return AF_LOCAL;
- case LINUX_AF_INET:
- return AF_INET;
- case LINUX_AF_AX25:
- return AF_CCITT;
- case LINUX_AF_IPX:
- return AF_IPX;
- case LINUX_AF_APPLETALK:
- return AF_APPLETALK;
- case LINUX_AF_X25:
- return AF_CCITT;
- case LINUX_AF_INET6:
- return AF_INET6;
- case LINUX_AF_DECnet:
- return AF_DECnet;
- case LINUX_AF_NETLINK:
- return AF_ROUTE;
- /* NETROM, BRIDGE, ATMPVC, ROSE, NETBEUI, SECURITY, */
- /* pseudo_AF_KEY, PACKET, ASH, ECONET, ATMSVC, SNA */
- default:
- return -1;
- }
+ return linux_to_bsd_domain_[ldom];
+}
+
+/*
+ * Convert between BSD and Linux socket domain values
+ */
+static int
+bsd_to_linux_domain(bdom)
+ int bdom;
+{
+ if (bdom < 0 || bdom >= AF_MAX)
+ return (-1);
+
+ return bsd_to_linux_domain_[bdom];
}
int
@@ -180,26 +246,92 @@
register_t *retval;
{
struct linux_sys_sendto_args /* {
- syscallarg(int) s;
- syscallarg(void *) msg;
- syscallarg(int) len;
- syscallarg(int) flags;
- syscallarg(sockaddr *) to;
- syscallarg(int) tolen;
+ syscallarg(int) s;
+ syscallarg(void *) msg;
+ syscallarg(int) len;
+ syscallarg(int) flags;
+ syscallarg(struct osockaddr *) to;
+ syscallarg(int) tolen;
} */ *uap = v;
struct sys_sendto_args bsa;
SCARG(&bsa, s) = SCARG(uap, s);
SCARG(&bsa, buf) = SCARG(uap, msg);
- SCARG(&bsa, len) = SCARG(uap, len);
+ SCARG(&bsa, len) = (size_t) SCARG(uap, len);
SCARG(&bsa, flags) = SCARG(uap, flags);
- SCARG(&bsa, to) = (void *) SCARG(uap, to);
+ if (SCARG(uap, to)) {
+ struct sockaddr *sa;
+ int error;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ if ((error = linux_sa_get(&sg, &sa, SCARG(uap, to),
+ SCARG(uap, tolen))))
+ return (error);
+
+ SCARG(&bsa, to) = sa;
+ } else
+ SCARG(&bsa, to) = NULL;
SCARG(&bsa, tolen) = SCARG(uap, tolen);
- return sys_sendto(p, &bsa, retval);
+ return (sys_sendto(p, &bsa, retval));
}
int
+linux_sys_sendmsg(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sendmsg_args /* {
+ syscallarg(int) s;
+ syscallarg(struct msghdr *) msg;
+ syscallarg(u_int) flags;
+ } */ *uap = v;
+ struct msghdr msg;
+ int error;
+ struct sys_sendmsg_args bsa;
+ struct msghdr *nmsg = NULL;
+
+ error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
+ if (error)
+ return (error);
+
+ if (msg.msg_name) {
+ struct sockaddr *sa;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ nmsg = (struct msghdr *) stackgap_alloc(&sg,
+ sizeof(struct msghdr));
+ if (!nmsg)
+ return (ENOMEM);
+
+ error = linux_sa_get(&sg, &sa,
+ (struct osockaddr *) msg.msg_name, msg.msg_namelen);
+ if (error)
+ return (error);
+
+ msg.msg_name = (struct sockaddr *) sa;
+ if ((error = copyout(&msg, nmsg, sizeof(struct msghdr))))
+ return (error);
+ }
+
+ /*
+ * XXX handle different alignment of cmsg data on architectures where
+ * the Linux alignment is different (powerpc, sparc, sparc64).
+ */
+
+ SCARG(&bsa, s) = SCARG(uap, s);
+ SCARG(&bsa, msg) = nmsg;
+ SCARG(&bsa, flags) = SCARG(uap, flags);
+
+ if ((error = sys_sendmsg(p, &bsa, retval)))
+ return (error);
+
+ return (0);
+}
+
+
+int
linux_sys_recvfrom(p, v, retval)
struct proc *p;
void *v;
@@ -210,19 +342,57 @@
syscallarg(void *) buf;
syscallarg(int) len;
syscallarg(int) flags;
- syscallarg(struct sockaddr *) from;
- syscallarg(int *) fromlen;
+ syscallarg(struct osockaddr *) from;
+ syscallarg(int *) fromlenaddr;
} */ *uap = v;
- struct compat_43_sys_recvfrom_args bra;
+ int error;
+ struct sys_recvfrom_args bra;
SCARG(&bra, s) = SCARG(uap, s);
SCARG(&bra, buf) = SCARG(uap, buf);
SCARG(&bra, len) = SCARG(uap, len);
SCARG(&bra, flags) = SCARG(uap, flags);
- SCARG(&bra, from) = (caddr_t) SCARG(uap, from);
- SCARG(&bra, fromlenaddr) = SCARG(uap, fromlen);
+ SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from);
+ SCARG(&bra, fromlenaddr) = SCARG(uap, fromlenaddr);
+
+ if ((error = sys_recvfrom(p, &bra, retval)))
+ return (error);
+
+ if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from))))
+ return (error);
+
+ return (0);
+}
Home |
Main Index |
Thread Index |
Old Index