summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux/linux_socket.c
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2006-03-18 18:20:17 +0000
committernetchild <netchild@FreeBSD.org>2006-03-18 18:20:17 +0000
commitc1829f604cdf8a3f393bfa6cb85fe9a6d4908919 (patch)
tree0bfbd4f21076e4935e7376b8d0502c8d258d4cfa /sys/compat/linux/linux_socket.c
parentd4f801f4ab01a2c0d88e59ddabc9757533800554 (diff)
downloadFreeBSD-src-c1829f604cdf8a3f393bfa6cb85fe9a6d4908919.zip
FreeBSD-src-c1829f604cdf8a3f393bfa6cb85fe9a6d4908919.tar.gz
Get rid of the need of COMPAT_43 in the linuxolator.
Submitted by: Divacky Roman <xdivac02@stud.fit.vutbr.cz> Obtained from: DragonFly (some parts)
Diffstat (limited to 'sys/compat/linux/linux_socket.c')
-rw-r--r--sys/compat/linux/linux_socket.c99
1 files changed, 84 insertions, 15 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index ce1135c..e7e98f8 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -33,10 +33,6 @@ __FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include "opt_inet6.h"
-#ifndef COMPAT_43
-#error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
-#endif
-
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
@@ -62,8 +58,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6_var.h>
#endif
-#include "opt_compat.h"
-
#ifdef COMPAT_LINUX32
#include <machine/../linux32/linux.h>
#include <machine/../linux32/linux32_proto.h>
@@ -343,6 +337,48 @@ linux_to_bsd_msg_flags(int flags)
return ret_flags;
}
+/*
+* If bsd_to_linux_sockaddr() or linux_to_bsd_sockaddr() faults, then the
+* native syscall will fault. Thus, we don't really need to check the
+* return values for these functions.
+*/
+
+static int
+bsd_to_linux_sockaddr(struct sockaddr *arg)
+{
+ struct sockaddr sa;
+ size_t sa_len = sizeof(struct sockaddr);
+ int error;
+
+ if ((error = copyin(arg, &sa, sa_len)))
+ return (error);
+
+ *(u_short *)&sa = sa.sa_family;
+
+ error = copyout(&sa, arg, sa_len);
+
+ return (error);
+}
+
+static int
+linux_to_bsd_sockaddr(struct sockaddr *arg, int len)
+{
+ struct sockaddr sa;
+ size_t sa_len = sizeof(struct sockaddr);
+ int error;
+
+ if ((error = copyin(arg, &sa, sa_len)))
+ return (error);
+
+ sa.sa_family = *(sa_family_t *)&sa;
+ sa.sa_len = len;
+
+ error = copyout(&sa, arg, sa_len);
+
+ return (error);
+}
+
+
static int
linux_sa_put(struct osockaddr *osa)
{
@@ -685,7 +721,8 @@ linux_accept(struct thread *td, struct linux_accept_args *args)
/* XXX: */
bsd_args.name = (struct sockaddr * __restrict)PTRIN(linux_args.addr);
bsd_args.anamelen = PTRIN(linux_args.namelen);/* XXX */
- error = oaccept(td, &bsd_args);
+ error = accept(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name);
if (error)
return (error);
if (linux_args.addr) {
@@ -732,7 +769,8 @@ linux_getsockname(struct thread *td, struct linux_getsockname_args *args)
/* XXX: */
bsd_args.asa = (struct sockaddr * __restrict)PTRIN(linux_args.addr);
bsd_args.alen = PTRIN(linux_args.namelen); /* XXX */
- error = ogetsockname(td, &bsd_args);
+ error = getsockname(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
if (error)
return (error);
error = linux_sa_put(PTRIN(linux_args.addr));
@@ -751,7 +789,7 @@ static int
linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
{
struct linux_getpeername_args linux_args;
- struct ogetpeername_args /* {
+ struct getpeername_args /* {
int fdes;
caddr_t asa;
int *alen;
@@ -762,9 +800,10 @@ linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
return (error);
bsd_args.fdes = linux_args.s;
- bsd_args.asa = (caddr_t)PTRIN(linux_args.addr);
+ bsd_args.asa = (struct sockaddr *)PTRIN(linux_args.addr);
bsd_args.alen = (int *)PTRIN(linux_args.namelen);
- error = ogetpeername(td, &bsd_args);
+ error = getpeername(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
if (error)
return (error);
error = linux_sa_put(PTRIN(linux_args.addr));
@@ -920,11 +959,15 @@ linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
struct sockaddr * __restrict from;
socklen_t * __restrict fromlenaddr;
} */ bsd_args;
+ size_t len;
int error;
if ((error = copyin(args, &linux_args, sizeof(linux_args))))
return (error);
+ if ((error = copyin(PTRIN(linux_args.fromlen), &len, sizeof(size_t))))
+ return (error);
+
bsd_args.s = linux_args.s;
bsd_args.buf = PTRIN(linux_args.buf);
bsd_args.len = linux_args.len;
@@ -932,7 +975,11 @@ linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
/* XXX: */
bsd_args.from = (struct sockaddr * __restrict)PTRIN(linux_args.from);
bsd_args.fromlenaddr = PTRIN(linux_args.fromlen);/* XXX */
- error = orecvfrom(td, &bsd_args);
+
+ linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len);
+ error = recvfrom(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from);
+
if (error)
return (error);
if (linux_args.from) {
@@ -1004,7 +1051,13 @@ linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
bsd_args.s = linux_args.s;
bsd_args.msg = PTRIN(linux_args.msg);
bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
- error = recvmsg(td, &bsd_args);
+ if (msg.msg_name) {
+ linux_to_bsd_sockaddr((struct sockaddr *)msg.msg_name,
+ msg.msg_namelen);
+ error = recvmsg(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)msg.msg_name);
+ } else
+ error = recvmsg(td, &bsd_args);
if (error)
return (error);
@@ -1092,7 +1145,16 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
bsd_args.name = name;
bsd_args.val = PTRIN(linux_args.optval);
bsd_args.valsize = linux_args.optlen;
- return (setsockopt(td, &bsd_args));
+
+ if (name == IPV6_NEXTHOP) {
+ linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.val,
+ bsd_args.valsize);
+ error = setsockopt(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
+ } else
+ error = setsockopt(td, &bsd_args);
+
+ return (error);
}
struct linux_getsockopt_args {
@@ -1142,7 +1204,14 @@ linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
bsd_args.name = name;
bsd_args.val = PTRIN(linux_args.optval);
bsd_args.avalsize = PTRIN(linux_args.optlen);
- return (getsockopt(td, &bsd_args));
+
+ if (name == IPV6_NEXTHOP) {
+ error = getsockopt(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
+ } else
+ error = getsockopt(td, &bsd_args);
+
+ return (error);
}
int
OpenPOWER on IntegriCloud