diff options
author | fenner <fenner@FreeBSD.org> | 2001-10-26 23:10:08 +0000 |
---|---|---|
committer | fenner <fenner@FreeBSD.org> | 2001-10-26 23:10:08 +0000 |
commit | 9246a16af858019b295cc1274132b8af3d4d67a3 (patch) | |
tree | 7ca4135fcd8b2c0eed5ba3a21c5d4cb9647f75e2 | |
parent | 3f40eb9fd53858048b455ea565ccfd0b0fecdd6d (diff) | |
download | FreeBSD-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.
-rw-r--r-- | sys/compat/linux/linux_socket.c | 25 |
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); |