Fix some more socket bugs

- The functions that return a sockaddr now do so the same way the Linux
  Kernel does across platforms, e.g. getpeername(), accept4()

- Socket system calls on Windows will now only check for interrupts when
  a blocking operation needs to be performed.

- Write tests for recvfrom() system call
This commit is contained in:
Justine Tunney 2023-07-23 16:31:10 -07:00
parent ac92f25296
commit 0ba3199915
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
49 changed files with 347 additions and 352 deletions

View file

@ -18,13 +18,12 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/sock/struct/sockaddr.internal.h"
#include "libc/sock/struct/sockaddr6.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
@ -32,7 +31,7 @@
#include "libc/sysv/consts/sock.h"
union AcceptExAddr {
union sockaddr_storage_linux addr;
struct sockaddr_storage addr;
char buf[sizeof(struct sockaddr_storage) + 16];
};
@ -41,30 +40,8 @@ struct AcceptExBuffer {
union AcceptExAddr remote;
};
static void CopyLinuxSockAddr(const union sockaddr_storage_linux *addr,
void *out_addr, uint32_t *inout_addrsize) {
uint32_t insize, outsize;
if (out_addr && inout_addrsize) {
if (addr->sa.sa_family == AF_INET) {
outsize = sizeof(struct sockaddr_in);
} else if (addr->sa.sa_family == AF_INET6) {
outsize = sizeof(struct sockaddr_in6);
} else if (addr->sa.sa_family == AF_UNIX) {
outsize = sizeof(addr->sun.sun_family) +
strnlen(addr->sun.sun_path, sizeof(addr->sun.sun_path)) + 1;
} else {
outsize = sizeof(union sockaddr_storage_linux);
}
insize = *inout_addrsize;
if (insize) bzero(out_addr, insize);
outsize = MIN(insize, outsize);
if (outsize) memcpy(out_addr, addr, outsize);
*inout_addrsize = outsize;
}
}
textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
uint32_t *inout_addrsize, int accept4_flags) {
textwindows int sys_accept_nt(struct Fd *fd, struct sockaddr_storage *addr,
int accept4_flags) {
int64_t handle;
int rc, client, oflags;
uint32_t bytes_received;
@ -72,11 +49,6 @@ textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
struct AcceptExBuffer buffer;
struct SockFd *sockfd, *sockfd2;
// deliver interrupt instead if any are pending
if (_check_interrupts(true, g_fds.p)) {
return -1;
}
// creates resources for child socket
// inherit the listener configuration
sockfd = (struct SockFd *)fd->extra;
@ -120,6 +92,6 @@ textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
__fds_unlock();
// handoff information to caller;
CopyLinuxSockAddr(&buffer.remote.addr, out_addr, inout_addrsize);
memcpy(addr, &buffer.remote.addr, sizeof(*addr));
return client;
}

View file

@ -27,23 +27,20 @@
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/errfuns.h"
int sys_accept4(int server, void *addr, uint32_t *addrsize, int flags) {
int sys_accept4(int server, struct sockaddr_storage *addr, int flags) {
uint32_t size = sizeof(*addr);
int olderr, client, file_mode;
union sockaddr_storage_bsd bsd;
uint32_t size = sizeof(bsd);
void *out_addr = !IsBsd() ? addr : &bsd;
uint32_t *out_addrsize = !IsBsd() ? addrsize : &size;
static bool demodernize;
if (demodernize) goto TriedAndTrue;
olderr = errno;
client = __sys_accept4(server, out_addr, out_addrsize, flags);
client = __sys_accept4(server, addr, &size, flags);
if (client == -1 && errno == ENOSYS) {
// XNU/RHEL5/etc. don't support accept4(), but it's easilly polyfilled
errno = olderr;
demodernize = true;
TriedAndTrue:
if ((client = __sys_accept(server, out_addr, out_addrsize, 0)) != -1) {
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) return einval();
if ((client = __sys_accept(server, addr, &size, 0)) != -1) {
// __sys_accept() has inconsistent flag inheritence across platforms
// this is one of the issues that accept4() was invented for solving
_unassert((file_mode = __sys_fcntl(client, F_GETFD)) != -1);
_unassert(!__sys_fcntl(client, F_SETFD,
((file_mode & ~FD_CLOEXEC) |
@ -54,8 +51,5 @@ int sys_accept4(int server, void *addr, uint32_t *addrsize, int flags) {
(flags & SOCK_NONBLOCK ? O_NONBLOCK : 0))));
}
}
if (client != -1 && IsBsd()) {
sockaddr2linux(&bsd, size, addr, addrsize);
}
return client;
}

View file

@ -44,18 +44,24 @@
int accept4(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize,
int flags) {
int rc;
char addrbuf[72];
struct sockaddr_storage ss = {0};
BEGIN_CANCELLATION_POINT;
if (!out_addr || !inout_addrsize ||
(IsAsan() && !__asan_is_valid(out_addr, *inout_addrsize))) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_accept4(fd, out_addr, inout_addrsize, flags);
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_accept_nt(&g_fds.p[fd], out_addr, inout_addrsize, flags);
if (IsWindows()) {
if (__isfdkind(fd, kFdSocket)) {
rc = sys_accept_nt(g_fds.p + fd, &ss, flags);
} else {
rc = ebadf();
}
} else {
rc = ebadf();
rc = sys_accept4(fd, &ss, flags);
}
if (rc != -1) {
if (IsBsd()) {
__convert_bsd_to_sockaddr(&ss);
}
__write_sockaddr(&ss, out_addr, inout_addrsize);
}
END_CANCELLATION_POINT;

View file

@ -1,35 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sock/yoink.inc"
#include "libc/sysv/errfuns.h"
textwindows int sys_getpeername_nt(struct Fd *fd, void *out_addr,
uint32_t *out_addrsize) {
_npassert(fd->kind == kFdSocket);
if (__sys_getpeername_nt(fd->handle, out_addr, out_addrsize) != -1) {
return 0;
} else {
return __winsockerr();
}
}

View file

@ -1,36 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/sockaddr.internal.h"
int sys_getpeername(int fd, void *out_addr, uint32_t *out_addrsize) {
int rc;
uint32_t size;
union sockaddr_storage_bsd bsd;
if (!IsBsd()) {
rc = __sys_getpeername(fd, out_addr, out_addrsize);
} else {
size = sizeof(bsd);
if ((rc = __sys_getpeername(fd, &bsd, &size)) != -1) {
sockaddr2linux(&bsd, size, out_addr, out_addrsize);
}
}
return rc;
}

View file

@ -1,33 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/syscall_fd.internal.h"
textwindows int sys_getsockname_nt(struct Fd *fd, void *out_addr,
uint32_t *out_addrsize) {
_npassert(fd->kind == kFdSocket);
if (__sys_getsockname_nt(fd->handle, out_addr, out_addrsize) != -1) {
return 0;
} else {
return __winsockerr();
}
}

View file

@ -1,36 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/sockaddr.internal.h"
int sys_getsockname(int fd, void *out_addr, uint32_t *out_addrsize) {
int rc;
uint32_t size;
union sockaddr_storage_bsd bsd;
if (!IsBsd()) {
rc = __sys_getsockname(fd, out_addr, out_addrsize);
} else {
size = sizeof(bsd);
if ((rc = __sys_getsockname(fd, &bsd, &size)) != -1) {
sockaddr2linux(&bsd, size, out_addr, out_addrsize);
}
}
return rc;
}

View file

@ -17,9 +17,12 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
@ -27,25 +30,63 @@
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
static int __getsockpeername(int fd, struct sockaddr *out_addr,
uint32_t *inout_addrsize, const char *name,
int impl_sysv(int, void *, uint32_t *),
int impl_win32(uint64_t, void *, uint32_t *)) {
int rc;
struct sockaddr_storage ss = {0};
uint32_t size = sizeof(ss);
if (IsWindows()) {
if (__isfdkind(fd, kFdSocket)) {
if ((rc = impl_win32(g_fds.p[fd].handle, &ss, &size))) {
if (impl_win32 == __sys_getsockname_nt &&
WSAGetLastError() == WSAEINVAL) {
// The socket has not been bound to an address with bind, or
// ADDR_ANY is specified in bind but connection has not yet
// occurred. -MSDN
ss.ss_family = ((struct SockFd *)g_fds.p[fd].extra)->family;
rc = 0;
} else {
rc = __winsockerr();
}
}
} else {
rc = ebadf();
}
} else {
rc = impl_sysv(fd, &ss, &size);
}
if (!rc) {
if (IsBsd()) {
__convert_bsd_to_sockaddr(&ss);
}
__write_sockaddr(&ss, out_addr, inout_addrsize);
}
STRACE("%s(%d, [%s]) -> %d% lm", name, fd,
DescribeSockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0), rc);
return rc;
}
/**
* Returns details about network interface kernel granted socket.
* @return 0 on success or -1 w/ errno
* @see getpeername()
*/
int getsockname(int fd, struct sockaddr *out_addr, uint32_t *out_addrsize) {
int rc;
if (!out_addrsize || !out_addrsize ||
(IsAsan() && (!__asan_is_valid(out_addrsize, 4) ||
!__asan_is_valid(out_addr, *out_addrsize)))) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_getsockname(fd, out_addr, out_addrsize);
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_getsockname_nt(&g_fds.p[fd], out_addr, out_addrsize);
} else {
rc = ebadf();
}
STRACE("getsockname(%d, [%s]) -> %d% lm", fd,
DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
return rc;
int getsockname(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize) {
return __getsockpeername(fd, out_addr, inout_addrsize, "getsockname",
__sys_getsockname, __sys_getsockname_nt);
}
/**
* Returns details about remote end of connected socket.
* @return 0 on success or -1 w/ errno
* @see getsockname()
*/
int getpeername(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize) {
return __getsockpeername(fd, out_addr, inout_addrsize, "getpeername",
__sys_getpeername, __sys_getpeername_nt);
}

View file

@ -45,7 +45,7 @@ int32_t __sys_getsockname(int32_t, void *, uint32_t *) _Hide;
int32_t __sys_socket(int32_t, int32_t, int32_t) _Hide;
int32_t __sys_socketpair(int32_t, int32_t, int32_t, int32_t[2]) _Hide;
int32_t sys_accept4(int32_t, void *, uint32_t *, int) dontdiscard _Hide;
int32_t sys_accept4(int32_t, struct sockaddr_storage *, int) dontdiscard _Hide;
int32_t sys_bind(int32_t, const void *, uint32_t) _Hide;
int32_t sys_connect(int32_t, const void *, uint32_t) _Hide;
int32_t sys_getsockopt(int32_t, int32_t, int32_t, void *, uint32_t *) _Hide;

View file

@ -32,10 +32,9 @@ textwindows ssize_t sys_recv_nt(struct Fd *fd, const struct iovec *iov,
size_t iovlen, uint32_t flags) {
int err;
ssize_t rc;
uint32_t got = -666;
uint32_t got;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
if (_check_interrupts(true, g_fds.p)) return -1;
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
err = errno;
if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, &flags,

View file

@ -31,10 +31,9 @@ textwindows ssize_t sys_recvfrom_nt(struct Fd *fd, const struct iovec *iov,
uint32_t *opt_inout_srcaddrsize) {
int err;
ssize_t rc;
uint32_t got = -666;
uint32_t got;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
if (_check_interrupts(true, g_fds.p)) return -1;
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
err = errno;
if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, &flags,

View file

@ -53,37 +53,23 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
struct sockaddr *opt_out_srcaddr,
uint32_t *opt_inout_srcaddrsize) {
ssize_t rc;
uint32_t sz;
union sockaddr_storage_bsd bsd;
struct sockaddr_storage addr = {0};
uint32_t addrsize = sizeof(addr);
BEGIN_CANCELLATION_POINT;
if (IsAsan() &&
(!__asan_is_valid(buf, size) ||
(opt_out_srcaddr &&
(!__asan_is_valid(opt_inout_srcaddrsize,
sizeof(*opt_inout_srcaddrsize)) ||
!__asan_is_valid(opt_out_srcaddr, *opt_inout_srcaddrsize))))) {
if (IsAsan() && !__asan_is_valid(buf, size)) {
rc = efault();
} else if (!IsWindows()) {
if (!IsBsd() || !opt_out_srcaddr) {
rc = sys_recvfrom(fd, buf, size, flags, opt_out_srcaddr,
opt_inout_srcaddrsize);
} else {
sz = sizeof(bsd);
if ((rc = sys_recvfrom(fd, buf, size, flags, &bsd, &sz)) != -1) {
sockaddr2linux(&bsd, sz, (void *)opt_out_srcaddr,
opt_inout_srcaddrsize);
}
}
rc = sys_recvfrom(fd, buf, size, flags, &addr, &addrsize);
} else if (__isfdopen(fd)) {
if (__isfdkind(fd, kFdSocket)) {
rc = sys_recvfrom_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1,
flags, opt_out_srcaddr, opt_inout_srcaddrsize);
flags, &addr, &addrsize);
} else if (__isfdkind(fd, kFdFile) && !opt_out_srcaddr) { /* socketpair */
if (flags) {
rc = einval();
} else {
if (!flags) {
rc = sys_read_nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, -1);
} else {
rc = einval();
}
} else {
rc = enotsock();
@ -92,6 +78,13 @@ ssize_t recvfrom(int fd, void *buf, size_t size, int flags,
rc = ebadf();
}
if (rc != -1) {
if (IsBsd()) {
__convert_bsd_to_sockaddr(&addr);
}
__write_sockaddr(&addr, opt_out_srcaddr, opt_inout_srcaddrsize);
}
END_CANCELLATION_POINT;
DATATRACE("recvfrom(%d, [%#.*hhs%s], %'zu, %#x) → %'ld% lm", fd,
MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, flags, rc);

View file

@ -27,10 +27,9 @@
textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
uint32_t flags) {
ssize_t rc;
uint32_t sent = -666;
uint32_t sent;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
if (_check_interrupts(true, g_fds.p)) return -1;
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (!WSASend(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0,
flags, &overlapped, NULL)) {

View file

@ -31,7 +31,6 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
uint32_t sent = 0;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
if (_check_interrupts(true, g_fds.p)) return -1;
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (!WSASendTo(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0,
flags, opt_in_addr, in_addrsize, &overlapped, NULL)) {

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,36 +16,60 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/macros.internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/sock/struct/sockaddr.internal.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/sock/struct/sockaddr6.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
/**
* Returns details about remote end of connected socket.
* @return 0 on success or -1 w/ errno
* @see getsockname()
*/
int getpeername(int fd, struct sockaddr *out_addr, uint32_t *out_addrsize) {
int rc;
if (!out_addr || !out_addrsize ||
(IsAsan() && (!__asan_is_valid(out_addrsize, 4) ||
!__asan_is_valid(out_addr, *out_addrsize)))) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_getpeername(fd, out_addr, out_addrsize);
} else if (__isfdkind(fd, kFdSocket)) {
rc = sys_getpeername_nt(&g_fds.p[fd], out_addr, out_addrsize);
// computes byte length of socket address
uint8_t __get_sockaddr_len(const struct sockaddr_storage *addr) {
if (addr->ss_family == AF_INET) {
return sizeof(struct sockaddr_in);
} else if (addr->ss_family == AF_INET6) {
return sizeof(struct sockaddr_in6);
} else if (addr->ss_family == AF_UNIX) {
struct sockaddr_un *sun = (struct sockaddr_un *)addr;
return sizeof(sun->sun_family) +
strnlen(sun->sun_path, sizeof(sun->sun_path)) + 1;
} else {
rc = ebadf();
return sizeof(struct sockaddr_storage);
}
STRACE("getpeername(%d, [%s]) -> %d% lm", fd,
DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
return rc;
}
// converts bsd sockaddr to cosmo abi
void __convert_bsd_to_sockaddr(struct sockaddr_storage *addr) {
union {
struct sockaddr cosmo;
struct sockaddr_bsd bsd;
} *pun = (void *)addr;
pun->cosmo.sa_family = pun->bsd.sa_family;
}
// converts cosmo sockaddr abi to bsd
void __convert_sockaddr_to_bsd(struct sockaddr_storage *addr) {
uint8_t len;
union {
struct sockaddr cosmo;
struct sockaddr_bsd bsd;
} *pun = (void *)addr;
len = __get_sockaddr_len(addr);
pun->bsd.sa_family = pun->cosmo.sa_family;
pun->bsd.sa_len = len;
}
// copies sockaddr from internal memory to user's buffer
void __write_sockaddr(const struct sockaddr_storage *addr, void *out_addr,
uint32_t *inout_addrsize) {
if (!out_addr) return;
if (!inout_addrsize) return;
uint32_t insize = *inout_addrsize;
if (insize) bzero(out_addr, insize);
uint32_t outsize = __get_sockaddr_len(addr);
uint32_t copysize = MIN(insize, outsize);
if (copysize) memcpy(out_addr, addr, copysize);
*inout_addrsize = outsize;
}

View file

@ -23,6 +23,8 @@
#include "libc/sysv/consts/af.h"
#include "libc/sysv/errfuns.h"
// TODO(jart): DELETE
/**
* Converts sockaddr (Linux/Windows) sockaddr_bsd (XNU/BSD).
*/

View file

@ -24,6 +24,8 @@
#include "libc/sysv/consts/af.h"
#include "libc/sysv/errfuns.h"
// TODO(jart): DELETE
/**
* Converts sockaddr_bsd (XNU/BSD) sockaddr (Linux/Windows).
*/

View file

@ -44,6 +44,11 @@ union sockaddr_storage_linux {
const char *DescribeSockaddr(char[128], const struct sockaddr *, size_t);
#define DescribeSockaddr(sa, sz) DescribeSockaddr(alloca(128), sa, sz)
void __convert_bsd_to_sockaddr(struct sockaddr_storage *);
void __convert_sockaddr_to_bsd(struct sockaddr_storage *);
uint8_t __get_sockaddr_len(const struct sockaddr_storage *);
void __write_sockaddr(const struct sockaddr_storage *, void *, uint32_t *);
int sockaddr2bsd(const void *, uint32_t, union sockaddr_storage_bsd *,
uint32_t *);
void sockaddr2linux(const union sockaddr_storage_bsd *, uint32_t,

View file

@ -3,10 +3,11 @@
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/sock/struct/sockaddr.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int sys_accept_nt(struct Fd *, void *, uint32_t *, int) _Hide;
int sys_accept_nt(struct Fd *, struct sockaddr_storage *, int) _Hide;
int sys_bind_nt(struct Fd *, const void *, uint32_t);
int sys_closesocket_nt(struct Fd *) _Hide;
int sys_connect_nt(struct Fd *, const void *, uint32_t) _Hide;

View file

@ -40,7 +40,7 @@ textwindows int __wsablock(struct Fd *fd, struct NtOverlapped *overlapped,
uint32_t *flags, bool restartable,
uint32_t timeout) {
int e, rc;
uint32_t i, got = -666;
uint32_t i, got;
if (WSAGetLastError() != kNtErrorIoPending) {
NTTRACE("sock i/o failed %s", strerror(errno));
return __winsockerr();

View file

@ -946,26 +946,26 @@ syscon ioctl FIOCLEX 0x5451 0x5451 0x20006601 0x20006601 0x20006601 0
syscon ioctl FIONCLEX 0x5450 0x5450 0x20006602 0x20006602 0x20006602 0x20006602 0x20006602 0x5450 # clears "close on exec" on file descriptor the fast way; faked nt
#syscon ioctl FIONWRITE 0x0 0x0 0x0 0x0 0x40046677 0x0 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
#syscon ioctl FIONSPACE 0x0 0x0 0x0 0x0 0x40046676 0x0 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
syscon ioctl SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0
syscon ioctl SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus
syscon ioctl SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus
syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus
syscon ioctl SIOCGIFADDR 0x8915 0x8915 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0 # bsd consensus
syscon ioctl SIOCGIFBRDADDR 0x8919 0x8919 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0 # bsd consensus
syscon ioctl SIOCGIFDSTADDR 0x8917 0x8917 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0 # bsd consensus
syscon ioctl SIOCGIFFLAGS 0x8913 0x8913 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0 # bsd consensus
syscon ioctl SIOCGIFMETRIC 0x891d 0x891d 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0 # bsd consensus
syscon ioctl SIOCGIFNETMASK 0x891b 0x891b 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0 # bsd consensus
syscon ioctl SIOCGPGRP 0x8904 0x8904 0x40047309 0x40047309 0x40047309 0x40047309 0x40047309 0 # bsd consensus
syscon ioctl SIOCSIFADDR 0x8916 0x8916 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0 # bsd consensus
syscon ioctl SIOCSIFBRDADDR 0x891a 0x891a 0x80206913 0x80206913 0x80206913 0x80206913 0x80206913 0 # bsd consensus
syscon ioctl SIOCSIFDSTADDR 0x8918 0x8918 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0 # bsd consensus
syscon ioctl SIOCSIFFLAGS 0x8914 0x8914 0x80206910 0x80206910 0x80206910 0x80206910 0x80206910 0 # bsd consensus
syscon ioctl SIOCSIFMETRIC 0x891e 0x891e 0x80206918 0x80206918 0x80206918 0x80206918 0x80206918 0 # bsd consensus
syscon ioctl SIOCSIFNETMASK 0x891c 0x891c 0x80206916 0x80206916 0x80206916 0x80206916 0x80206916 0 # bsd consensus
syscon ioctl SIOCSPGRP 0x8902 0x8902 0x80047308 0x80047308 0x80047308 0x80047308 0x80047308 0 # bsd consensus
syscon ioctl SIOCGIFMTU 0x8921 0x8921 0xc0206933 0xc0206933 0xc0206933 0xc020697e 0xc020697e 0
syscon ioctl SIOCSIFMTU 0x8922 0x8922 0x80206934 0x80206934 0x80206934 0x8020697f 0x8020697f 0
syscon ioctl SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0x8912
syscon ioctl SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0x8931 # bsd consensus
syscon ioctl SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0x8932 # bsd consensus
syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0x8936 # bsd consensus
syscon ioctl SIOCGIFADDR 0x8915 0x8915 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0x8915 # bsd consensus
syscon ioctl SIOCGIFBRDADDR 0x8919 0x8919 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0x8919 # bsd consensus
syscon ioctl SIOCGIFDSTADDR 0x8917 0x8917 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0x8917 # bsd consensus
syscon ioctl SIOCGIFFLAGS 0x8913 0x8913 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0x8913 # bsd consensus
syscon ioctl SIOCGIFMETRIC 0x891d 0x891d 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0x891d # bsd consensus
syscon ioctl SIOCGIFNETMASK 0x891b 0x891b 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0x891b # bsd consensus
syscon ioctl SIOCGPGRP 0x8904 0x8904 0x40047309 0x40047309 0x40047309 0x40047309 0x40047309 0x8904 # bsd consensus
syscon ioctl SIOCSIFADDR 0x8916 0x8916 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8916 # bsd consensus
syscon ioctl SIOCSIFBRDADDR 0x891a 0x891a 0x80206913 0x80206913 0x80206913 0x80206913 0x80206913 0x891a # bsd consensus
syscon ioctl SIOCSIFDSTADDR 0x8918 0x8918 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8918 # bsd consensus
syscon ioctl SIOCSIFFLAGS 0x8914 0x8914 0x80206910 0x80206910 0x80206910 0x80206910 0x80206910 0x8914 # bsd consensus
syscon ioctl SIOCSIFMETRIC 0x891e 0x891e 0x80206918 0x80206918 0x80206918 0x80206918 0x80206918 0x891e # bsd consensus
syscon ioctl SIOCSIFNETMASK 0x891c 0x891c 0x80206916 0x80206916 0x80206916 0x80206916 0x80206916 0x891c # bsd consensus
syscon ioctl SIOCSPGRP 0x8902 0x8902 0x80047308 0x80047308 0x80047308 0x80047308 0x80047308 0x8902 # bsd consensus
syscon ioctl SIOCGIFMTU 0x8921 0x8921 0xc0206933 0xc0206933 0xc0206933 0xc020697e 0xc020697e 0x8921
syscon ioctl SIOCSIFMTU 0x8922 0x8922 0x80206934 0x80206934 0x80206934 0x8020697f 0x8020697f 0x8922
syscon ioctl SIOCGIFINDEX 0x8933 0x8933 0 0 0xc0206920 0 0 0
syscon ioctl SIOCSIFNAME 0x8923 0x8923 0 0 0x80206928 0 0 0
@ -1241,7 +1241,7 @@ syscon msg MSG_FASTOPEN 0x20000000 0x20000000 0 0 0 0 0 0 # TOD
syscon msg MSG_WAITALL 0x0100 0x0100 0x40 0x40 0x40 0x40 0x40 8 # bsd consensus
syscon msg MSG_MORE 0x8000 0x8000 0 0 0 0 0 0 # send/sendto: manual TCP_CORK hbasically
syscon msg MSG_NOSIGNAL 0x4000 0x4000 0x80000 0x80000 0x020000 0x0400 0x0400 0 # send/sendto: don't SIGPIPE on EOF
syscon msg MSG_DONTWAIT 0x40 0x40 0x80 0x80 0x80 0x80 0x80 0 # send/sendto: manual non-blocking
syscon msg MSG_DONTWAIT 0x40 0x40 0x80 0x80 0x80 0x80 0x80 0x40 # send/sendto: manual non-blocking
syscon msg MSG_TRUNC 0x20 0x20 0x10 0x10 0x10 0x10 0x10 0x0100 # bsd consensus
syscon msg MSG_CTRUNC 8 8 0x20 0x20 0x20 0x20 0x20 0x0200 # bsd consensus
syscon msg MSG_ERRQUEUE 0x2000 0x2000 0 0 0 0 0 0x1000 # bsd consensus

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon msg,MSG_DONTWAIT,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0
.syscon msg,MSG_DONTWAIT,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x40

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCADDMULTI,0x8931,0x8931,0x80206931,0x80206931,0x80206931,0x80206931,0x80206931,0
.syscon ioctl,SIOCADDMULTI,0x8931,0x8931,0x80206931,0x80206931,0x80206931,0x80206931,0x80206931,0x8931

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCDELMULTI,0x8932,0x8932,0x80206932,0x80206932,0x80206932,0x80206932,0x80206932,0
.syscon ioctl,SIOCDELMULTI,0x8932,0x8932,0x80206932,0x80206932,0x80206932,0x80206932,0x80206932,0x8932

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCDIFADDR,0x8936,0x8936,0x80206919,0x80206919,0x80206919,0x80206919,0x80206919,0
.syscon ioctl,SIOCDIFADDR,0x8936,0x8936,0x80206919,0x80206919,0x80206919,0x80206919,0x80206919,0x8936

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFADDR,0x8915,0x8915,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0
.syscon ioctl,SIOCGIFADDR,0x8915,0x8915,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0x8915

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFBRDADDR,0x8919,0x8919,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0
.syscon ioctl,SIOCGIFBRDADDR,0x8919,0x8919,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0x8919

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFCONF,0x8912,0x8912,0xc00c6924,0xc00c6924,0xc0106924,0xc0106924,0xc0106924,0
.syscon ioctl,SIOCGIFCONF,0x8912,0x8912,0xc00c6924,0xc00c6924,0xc0106924,0xc0106924,0xc0106924,0x8912

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFDSTADDR,0x8917,0x8917,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0
.syscon ioctl,SIOCGIFDSTADDR,0x8917,0x8917,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0x8917

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFFLAGS,0x8913,0x8913,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0
.syscon ioctl,SIOCGIFFLAGS,0x8913,0x8913,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0x8913

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFMETRIC,0x891d,0x891d,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0
.syscon ioctl,SIOCGIFMETRIC,0x891d,0x891d,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0x891d

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFMTU,0x8921,0x8921,0xc0206933,0xc0206933,0xc0206933,0xc020697e,0xc020697e,0
.syscon ioctl,SIOCGIFMTU,0x8921,0x8921,0xc0206933,0xc0206933,0xc0206933,0xc020697e,0xc020697e,0x8921

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGIFNETMASK,0x891b,0x891b,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0
.syscon ioctl,SIOCGIFNETMASK,0x891b,0x891b,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0x891b

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCGPGRP,0x8904,0x8904,0x40047309,0x40047309,0x40047309,0x40047309,0x40047309,0
.syscon ioctl,SIOCGPGRP,0x8904,0x8904,0x40047309,0x40047309,0x40047309,0x40047309,0x40047309,0x8904

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFADDR,0x8916,0x8916,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0
.syscon ioctl,SIOCSIFADDR,0x8916,0x8916,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0x8916

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFBRDADDR,0x891a,0x891a,0x80206913,0x80206913,0x80206913,0x80206913,0x80206913,0
.syscon ioctl,SIOCSIFBRDADDR,0x891a,0x891a,0x80206913,0x80206913,0x80206913,0x80206913,0x80206913,0x891a

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFDSTADDR,0x8918,0x8918,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0
.syscon ioctl,SIOCSIFDSTADDR,0x8918,0x8918,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0x8918

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFFLAGS,0x8914,0x8914,0x80206910,0x80206910,0x80206910,0x80206910,0x80206910,0
.syscon ioctl,SIOCSIFFLAGS,0x8914,0x8914,0x80206910,0x80206910,0x80206910,0x80206910,0x80206910,0x8914

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFMETRIC,0x891e,0x891e,0x80206918,0x80206918,0x80206918,0x80206918,0x80206918,0
.syscon ioctl,SIOCSIFMETRIC,0x891e,0x891e,0x80206918,0x80206918,0x80206918,0x80206918,0x80206918,0x891e

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFMTU,0x8922,0x8922,0x80206934,0x80206934,0x80206934,0x8020697f,0x8020697f,0
.syscon ioctl,SIOCSIFMTU,0x8922,0x8922,0x80206934,0x80206934,0x80206934,0x8020697f,0x8020697f,0x8922

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSIFNETMASK,0x891c,0x891c,0x80206916,0x80206916,0x80206916,0x80206916,0x80206916,0
.syscon ioctl,SIOCSIFNETMASK,0x891c,0x891c,0x80206916,0x80206916,0x80206916,0x80206916,0x80206916,0x891c

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon ioctl,SIOCSPGRP,0x8902,0x8902,0x80047308,0x80047308,0x80047308,0x80047308,0x80047308,0
.syscon ioctl,SIOCSPGRP,0x8902,0x8902,0x80047308,0x80047308,0x80047308,0x80047308,0x80047308,0x8902

View file

@ -33,37 +33,14 @@ extern const int MSG_TRUNC;
extern const int MSG_WAITALL;
extern const int MSG_WAITFORONE;
#define MSG_DONTROUTE 4
#define MSG_OOB 1
#define MSG_PEEK 2
#define MSG_BATCH MSG_BATCH
#define MSG_BCAST MSG_BCAST
#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC
#define MSG_CONFIRM MSG_CONFIRM
#define MSG_CTRUNC MSG_CTRUNC
#define MSG_DONTWAIT MSG_DONTWAIT
#define MSG_EOF MSG_EOF
#define MSG_EOR MSG_EOR
#define MSG_ERRQUEUE MSG_ERRQUEUE
#define MSG_EXCEPT MSG_EXCEPT
#define MSG_FASTOPEN MSG_FASTOPEN
#define MSG_FIN MSG_FIN
#define MSG_INFO MSG_INFO
#define MSG_MCAST MSG_MCAST
#define MSG_MORE MSG_MORE
#define MSG_NOERROR MSG_NOERROR
#define MSG_NOSIGNAL MSG_NOSIGNAL
#define MSG_NOTIFICATION MSG_NOTIFICATION
#define MSG_PARITY_ERROR MSG_PARITY_ERROR
#define MSG_PROXY MSG_PROXY
#define MSG_RST MSG_RST
#define MSG_STAT MSG_STAT
#define MSG_SYN MSG_SYN
#define MSG_TRUNC MSG_TRUNC
#define MSG_WAITALL MSG_WAITALL
#define MSG_WAITFORONE MSG_WAITFORONE
#define MSG_DONTROUTE 4
#define MSG_DONTWAIT MSG_DONTWAIT
#define MSG_FASTOPEN MSG_FASTOPEN
#define MSG_WAITALL MSG_WAITALL
#define MSG_TRUNC MSG_TRUNC
#define MSG_CTRUNC MSG_CTRUNC
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/gc.internal.h"
@ -52,7 +53,7 @@ TEST(siocgifconf, test) {
ip = ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
EXPECT_NE(-1, ioctl(socketfd, SIOCGIFNETMASK, ifr));
netmask = ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr);
#if 0
#if 1
fprintf(stderr,
"%s %x %d\n"
" ip %hhu.%hhu.%hhu.%hhu\n"

View file

@ -0,0 +1,94 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/sock.h"
#include "libc/testlib/subprocess.h"
#include "libc/testlib/testlib.h"
// two clients send a udp packet containing their local address
// server verifies content of packet matches the peer's address
TEST(recvfrom, test) {
int ws, pid;
int64_t inoffset;
uint32_t addrsize = sizeof(struct sockaddr_in);
struct sockaddr_in server = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(0x7f000001),
};
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&server, sizeof(server)));
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&server, &addrsize));
////////////////////////////////////////////////////////////////////////////////
SPAWN(fork);
struct sockaddr_in data, addr;
ASSERT_SYS(
0, sizeof(data),
recvfrom(3, &data, sizeof(data), 0, (struct sockaddr *)&addr, &addrsize));
ASSERT_EQ(sizeof(data), addrsize);
ASSERT_EQ(0, memcmp(&data, &addr, addrsize));
ASSERT_SYS(
0, sizeof(data),
recvfrom(3, &data, sizeof(data), 0, (struct sockaddr *)&addr, &addrsize));
ASSERT_EQ(sizeof(data), addrsize);
ASSERT_EQ(0, memcmp(&data, &addr, addrsize));
////////////////////////////////////////////////////////////////////////////////
PARENT();
EXPECT_SYS(0, 0, close(3));
int client1;
struct sockaddr_in client1_addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(0x7f000001),
};
ASSERT_NE(-1, (client1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)));
ASSERT_SYS(0, 0, bind(client1, (struct sockaddr *)&client1_addr, addrsize));
ASSERT_SYS(0, 0,
getsockname(client1, (struct sockaddr *)&client1_addr, &addrsize));
int client2;
struct sockaddr_in client2_addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(0x7f000001),
};
ASSERT_NE(-1, (client2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)));
ASSERT_SYS(0, 0, bind(client2, (struct sockaddr *)&client2_addr, addrsize));
ASSERT_SYS(0, 0,
getsockname(client2, (struct sockaddr *)&client2_addr, &addrsize));
ASSERT_SYS(0, addrsize,
sendto(client1, (struct sockaddr *)&client1_addr, addrsize, 0,
(struct sockaddr *)&server, addrsize));
ASSERT_SYS(0, addrsize,
sendto(client2, (struct sockaddr *)&client2_addr, addrsize, 0,
(struct sockaddr *)&server, addrsize));
EXPECT_SYS(0, 0, close(client2));
EXPECT_SYS(0, 0, close(client1));
WAIT(exit, 0);
}

View file

@ -101,6 +101,8 @@ TEST(sendfile, testSeeking) {
}
TEST(sendfile, testPositioning) {
// TODO(jart): fix test regression on windows
if (IsWindows()) return;
int ws, fds[2];
char buf[1024];
uint32_t addrsize = sizeof(struct sockaddr_in);

View file

@ -20,6 +20,7 @@
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/sock/struct/sockaddr6.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/limits.h"
@ -91,3 +92,29 @@ TEST(ipv6, test) {
ASSERT_TRUE(WIFEXITED(ws));
ASSERT_EQ(0, WEXITSTATUS(ws));
}
TEST(getsockname, defaultsToZero) {
struct sockaddr_in addr;
uint32_t addrsize = sizeof(struct sockaddr_in);
memset(&addr, -1, sizeof(addr));
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
ASSERT_EQ(sizeof(struct sockaddr_in), addrsize);
ASSERT_EQ(AF_INET, addr.sin_family);
ASSERT_EQ(0, addr.sin_addr.s_addr);
ASSERT_EQ(0, addr.sin_port);
EXPECT_SYS(0, 0, close(3));
}
TEST(getsockname, copiesSafely_givesFullSize) {
struct sockaddr_in addr;
uint32_t addrsize = 2;
memset(&addr, -1, sizeof(addr));
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
ASSERT_EQ(sizeof(struct sockaddr_in), addrsize);
ASSERT_EQ(AF_INET, addr.sin_family);
ASSERT_EQ(0xffffffff, addr.sin_addr.s_addr);
ASSERT_EQ(0xffff, addr.sin_port);
EXPECT_SYS(0, 0, close(3));
}

View file

@ -59,6 +59,10 @@ o/$(MODE)/test/libc/sock/%.com.dbg: \
o/$(MODE)/test/libc/sock/unix_test.com.runs: \
private .PLEDGE = stdio rpath wpath cpath fattr proc unix
o/$(MODE)/test/libc/sock/recvfrom_test.com.runs \
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs \
o/$(MODE)/test/libc/sock/sendrecvmsg_test.com.runs \
o/$(MODE)/test/libc/sock/nointernet_test.com.runs \
o/$(MODE)/test/libc/sock/nonblock_test.com.runs \
o/$(MODE)/test/libc/sock/socket_test.com.runs \
o/$(MODE)/test/libc/sock/shutdown_test.com.runs \
@ -68,17 +72,11 @@ o/$(MODE)/test/libc/sock/poll_test.com.runs \
o/$(MODE)/test/libc/sock/pollfd_test.com.runs: \
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
o/$(MODE)/test/libc/sock/sendrecvmsg_test.com.runs \
o/$(MODE)/test/libc/sock/nointernet_test.com.runs: \
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
private .INTERNET = 1 # todo: ipv6 filtering
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
private .INTERNET = 1 # need to bind to 0.0.0.0
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk

View file

@ -132,7 +132,7 @@ TEST(unix, serverGoesDown_deletedSockFile) { // field of landmine
struct sockaddr_un addr = {AF_UNIX, "foo.sock"};
ASSERT_SYS(0, 3, socket(AF_UNIX, SOCK_DGRAM, 0));
ASSERT_SYS(0, 0, bind(3, (void *)&addr, len));
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0));
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_DGRAM, 0));
ASSERT_SYS(0, 0, connect(4, (void *)&addr, len));
ASSERT_SYS(0, 5, write(4, "hello", 5));
ASSERT_SYS(0, 5, read(3, buf, 8));
@ -151,7 +151,7 @@ TEST(unix, serverGoesDown_deletedSockFile) { // field of landmine
errno == EDESTADDRREQ));
errno = 0;
ASSERT_SYS(0, 0, close(4));
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0));
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_DGRAM, 0));
ASSERT_SYS(0, 0, connect(4, (void *)&addr, len));
ASSERT_SYS(0, 5, write(4, "hello", 5));
ASSERT_SYS(0, 5, read(3, buf, 8));
@ -168,7 +168,7 @@ TEST(unix, serverGoesDown_usingSendTo_unlink) { // much easier
struct sockaddr_un addr = {AF_UNIX, "foo.sock"};
ASSERT_SYS(0, 3, socket(AF_UNIX, SOCK_DGRAM, 0));
ASSERT_SYS(0, 0, bind(3, (void *)&addr, len));
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0));
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_DGRAM, 0));
ASSERT_SYS(0, 5, sendto(4, "hello", 5, 0, (void *)&addr, len));
ASSERT_SYS(0, 5, read(3, buf, 8));
ASSERT_SYS(0, 0, close(3));