From 208a83880e014c683bb40de1ec5d131473fe960f Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 23 May 2026 11:09:55 -0300 Subject: [PATCH] localsocket: implement getopt and setopt --- kernel-src/include/kernel/abi.h | 2 + kernel-src/io/net/localsocket.c | 68 ++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index 283646cb..01f073cb 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -114,7 +114,9 @@ typedef struct { #define SO_RCVBUF 8 #define SO_KEEPALIVE 9 #define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 #define SO_LINGER 13 +#define SO_PEERCRED 17 #define SO_RCVLOWAT 18 #define SO_SNDLOWAT 19 #define SO_BINDTODEVICE 25 diff --git a/kernel-src/io/net/localsocket.c b/kernel-src/io/net/localsocket.c index 67785f5c..4c997696 100644 --- a/kernel-src/io/net/localsocket.c +++ b/kernel-src/io/net/localsocket.c @@ -1045,7 +1045,71 @@ static int localsock_shutdown(socket_t *socket, int how) { MUTEX_RELEASE(&socket->mutex); return error; +} +// called with socket locked +static int localsock_setopt(socket_t *socket, int layer, int optname, void *buffer, socklen_t len, cred_t *cred) { + int error = 0; + + if (layer == SOL_SOCKET) { + switch (optname) { + case SO_SNDLOWAT: + case SO_OOBINLINE: + case SO_KEEPALIVE: + case SO_SNDBUF: + case SO_RCVBUF: + case SO_REUSEADDR: + case SO_NO_CHECK: + break; + default: + error = ENOPROTOOPT; + } + } + + if (error == ENOPROTOOPT) { + printf("localsock_setopt: unknown %lu %lu called\n", layer, optname); + } + + return error; +} + +static int localsock_getopt(socket_t *socket, int layer, int optname, void *unsafe_buffer, socklen_t *unsafe_len, cred_t *cred) { + socklen_t len; + int error = USERCOPY_POSSIBLY_FROM_USER(&len, unsafe_len, sizeof(len)); + if (error) + return error; + + if (layer == SOL_SOCKET) { + switch (optname) { + case SO_SNDLOWAT: { + int value = 1; + return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &value, len); + } + case SO_TYPE: { + if (len != 4) + return EINVAL; + + int type = SOCK_STREAM; + return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &type, len); + } + case SO_OOBINLINE: + case SO_KEEPALIVE: + case SO_REUSEADDR: + case SO_NO_CHECK: + return USERCOPY_POSSIBLY_MEMSET_TO_USER(unsafe_buffer, 0, len); + case SO_SNDBUF: + case SO_RCVBUF: { + if (len != 4) + return EINVAL; + + int value = SOCKET_BUFFER; + return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &value, 4); + } + } + } + + printf("localsock_getopt unknown %lu %lu\n", layer, optname); + return ENOPROTOOPT; } static socketops_t socketops = { @@ -1060,7 +1124,9 @@ static socketops_t socketops = { .datacount = localsocket_datacount, .getname = localsock_getname, .getpeername = localsock_getpeername, - .shutdown = localsock_shutdown + .shutdown = localsock_shutdown, + .getopt = localsock_getopt, + .setopt = localsock_setopt }; socket_t *localsock_createsocket() {