summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-08-04 20:22:39 -0400
committerIan Moffett <ian@osmora.org>2025-08-04 20:25:14 -0400
commitb5a44ff2933b71347f79273da8fc99f24b3c595b (patch)
tree6a7dd3151c6f1eeb320f2e12c350fcf6c51258c1 /sys
parent24b4eaa97c0ba3c45406ac293a35d78c5342aac8 (diff)
kernel & libc: Add POSIX setsockopt syscall
This commit implements the POSIX setsockopt syscall so that user programs may be able to configure sockets they have created. Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r--sys/include/sys/socket.h1
-rw-r--r--sys/include/sys/syscall.h1
-rw-r--r--sys/kern/kern_socket.c49
-rw-r--r--sys/kern/kern_syscall.c1
4 files changed, 52 insertions, 0 deletions
diff --git a/sys/include/sys/socket.h b/sys/include/sys/socket.h
index 9224542..1a33108 100644
--- a/sys/include/sys/socket.h
+++ b/sys/include/sys/socket.h
@@ -184,6 +184,7 @@ scret_t sys_send(struct syscall_args *scargs);
scret_t sys_recvmsg(struct syscall_args *scargs);
scret_t sys_sendmsg(struct syscall_args *scargs);
+scret_t sys_setsockopt(struct syscall_args *scargs);
#endif /* _KERNEL */
int socket(int domain, int type, int protocol);
diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h
index 9798d80..f53db8f 100644
--- a/sys/include/sys/syscall.h
+++ b/sys/include/sys/syscall.h
@@ -66,6 +66,7 @@
#define SYS_sendmsg 25
#define SYS_recvmsg 26
#define SYS_connect 27
+#define SYS_setsockopt 28
#if defined(_KERNEL)
/* Syscall return value and arg type */
diff --git a/sys/kern/kern_socket.c b/sys/kern/kern_socket.c
index 0b10d0c..edaf32d 100644
--- a/sys/kern/kern_socket.c
+++ b/sys/kern/kern_socket.c
@@ -953,6 +953,55 @@ sys_connect(struct syscall_args *scargs)
return connect(sockfd, sockaddr, len);
}
+/*
+ * POSIX setsockopt(3) syscall
+ *
+ * arg0: sockfd
+ * arg1: level
+ * arg2: name
+ * arg3: data
+ * arg4: len
+ */
+scret_t
+sys_setsockopt(struct syscall_args *scargs)
+{
+ int sockfd = scargs->arg0;
+ int level = scargs->arg1;
+ int name = scargs->arg2;
+ void *u_data = (void *)scargs->arg3;
+ socklen_t len = scargs->arg4;
+ void *data;
+ size_t exp_len;
+ int retval;
+
+ /* Verify that the name is correct */
+ if (name >= _SO_MAX) {
+ return -EINVAL;
+ }
+
+ /* Clamp length as needed */
+ exp_len = sockopt_lentab[name];
+ if (len > exp_len) {
+ len = exp_len;
+ }
+
+ data = dynalloc(len);
+ if (data == NULL) {
+ return -ENOMEM;
+ }
+
+ /* Grab data from userland */
+ retval = copyin(u_data, data, len);
+ if (retval < 0) {
+ dynfree(data);
+ return retval;
+ }
+
+ retval = setsockopt(sockfd, level, name, data, len);
+ dynfree(data);
+ return retval;
+}
+
static struct vops socket_vops = {
.read = NULL,
.write = NULL,
diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c
index 576b7aa..ba70b12 100644
--- a/sys/kern/kern_syscall.c
+++ b/sys/kern/kern_syscall.c
@@ -68,6 +68,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = {
sys_sendmsg, /* SYS_sendmsg */
sys_recvmsg, /* SYS_recvmsg */
sys_connect, /* SYS_connect */
+ sys_setsockopt, /* SYS_setsockopt */
};
const size_t MAX_SYSCALLS = NELEM(g_sctab);