diff options
author | netchild <netchild@FreeBSD.org> | 2006-03-18 18:20:17 +0000 |
---|---|---|
committer | netchild <netchild@FreeBSD.org> | 2006-03-18 18:20:17 +0000 |
commit | c1829f604cdf8a3f393bfa6cb85fe9a6d4908919 (patch) | |
tree | 0bfbd4f21076e4935e7376b8d0502c8d258d4cfa /sys/compat/linux/linux_socket.c | |
parent | d4f801f4ab01a2c0d88e59ddabc9757533800554 (diff) | |
download | FreeBSD-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.c | 99 |
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 |