summaryrefslogtreecommitdiff
path: root/sys/kern/kern_socket.c
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/kern/kern_socket.c
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/kern/kern_socket.c')
-rw-r--r--sys/kern/kern_socket.c49
1 files changed, 49 insertions, 0 deletions
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,