Date: Mon, 22 Oct 2001 21:43:53 -0700 From: Marcel Moolenaar <marcel@xcllnt.net> To: Martin Blapp <mb@imp.ch> Cc: freebsd-emulation@FreeBSD.ORG, des@FreeBSD.ORG Subject: Re: linux_connect() broken for linux_base-7 Message-ID: <20011022214353.A55317@dhcp01.pn.xcllnt.net> In-Reply-To: <20011022204208.Q29117-200000@levais.imp.ch> References: <20011022204208.Q29117-200000@levais.imp.ch>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Oct 22, 2001 at 08:51:26PM +0200, Martin Blapp wrote:
>
> As you may have seen linux_base-7 is not able to resolve any
> DNS-Query's. For every connect(), we get EINVAL back.
>
Bill Fenner just told me this:
\begin{quote}
Just FYI, the linux_base-7 resolver library uses sockaddr_in6's with
AF_INET and just the inet part filled in, but FreeBSD doesn't allow
using the wrong sized sockaddr. This is going to require some
serious hackery in the Linux compatability stuff, since it's
the FreeBSD syscall's responsibility to copyin() the socket address
argument; if the compatability stuff wants to modify it it's going
to have to find somewhere that it can copyin() from to stash the
modified one...
\end{quote}
In a following email he supplied a patch:
cvs diff: Diffing .
Index: linux_socket.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_socket.c,v
retrieving revision 1.29
diff -u -r1.29 linux_socket.c
--- linux_socket.c 12 Sep 2001 08:36:57 -0000 1.29
+++ linux_socket.c 23 Oct 2001 03:49:33 -0000
@@ -55,6 +55,25 @@
#include <compat/linux/linux_util.h>
#ifndef __alpha__
+/*
+ * FreeBSD's socket calls require the sockaddr struct length to agree
+ * with the address family. Linux does not, so we must force it.
+ */
+static int
+linux_to_bsd_namelen(caddr_t name, int namelen)
+{
+ uint16_t family; /* XXX must match Linux sockaddr */
+
+ if (copyin(name, &family, sizeof(family)))
+ return namelen;
+
+ switch (family) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ }
+ return namelen;
+}
+
static int
linux_to_bsd_domain(int domain)
{
@@ -373,7 +392,7 @@
bsd_args.s = linux_args.s;
bsd_args.name = (caddr_t)linux_args.name;
- bsd_args.namelen = linux_args.namelen;
+ bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen);
return (bind(td, &bsd_args));
}
@@ -407,7 +426,7 @@
bsd_args.s = linux_args.s;
bsd_args.name = (caddr_t)linux_args.name;
- bsd_args.namelen = linux_args.namelen;
+ bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen);
error = connect(td, &bsd_args);
if (error != EISCONN)
return (error);
Try it out...
--
Marcel Moolenaar USPA: A-39004 marcel@xcllnt.net
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-emulation" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011022214353.A55317>
