summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorfenner <fenner@FreeBSD.org>2001-10-26 23:10:08 +0000
committerfenner <fenner@FreeBSD.org>2001-10-26 23:10:08 +0000
commit9246a16af858019b295cc1274132b8af3d4d67a3 (patch)
tree7ca4135fcd8b2c0eed5ba3a21c5d4cb9647f75e2 /sys/compat
parent3f40eb9fd53858048b455ea565ccfd0b0fecdd6d (diff)
downloadFreeBSD-src-9246a16af858019b295cc1274132b8af3d4d67a3.zip
FreeBSD-src-9246a16af858019b295cc1274132b8af3d4d67a3.tar.gz
Force the length of the sockaddr to be correct for AF_INET and AF_INET6
in bind() and connect(). Linux doesn't care if the length of the sockaddr matches its address family; FreeBSD does. This fixes the known issues with the resolver in linux_base-7.
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linux/linux_socket.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index de74054..c09c0bd 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -54,6 +54,27 @@
#include <compat/linux/linux_socket.h>
#include <compat/linux/linux_util.h>
+/*
+ * 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);
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ }
+ return namelen;
+}
+
#ifndef __alpha__
static int
linux_to_bsd_domain(int domain)
@@ -373,7 +394,7 @@ linux_bind(struct thread *td, struct linux_bind_args *args)
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 +428,7 @@ linux_connect(struct thread *td, struct linux_connect_args *args)
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);
OpenPOWER on IntegriCloud