From 9246a16af858019b295cc1274132b8af3d4d67a3 Mon Sep 17 00:00:00 2001 From: fenner Date: Fri, 26 Oct 2001 23:10:08 +0000 Subject: 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. --- sys/compat/linux/linux_socket.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'sys/compat/linux/linux_socket.c') 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 #include +/* + * 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); -- cgit v1.1