diff options
author | Ian Moffett <ian@osmora.org> | 2025-07-29 02:49:09 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-07-29 02:49:09 -0400 |
commit | 81e14b45173bbb0dae73a4dbaaec2d6a300abd8e (patch) | |
tree | a0059eb80dbcbd258c1589940697736df962bbfd | |
parent | 71decb670bd84630d3639623891e46f332d58084 (diff) |
kernel: Add SYS_sendmsg and SYS_recvmsg
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | sys/include/sys/socket.h | 3 | ||||
-rw-r--r-- | sys/include/sys/syscall.h | 2 | ||||
-rw-r--r-- | sys/kern/kern_socket.c | 97 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 2 |
4 files changed, 104 insertions, 0 deletions
diff --git a/sys/include/sys/socket.h b/sys/include/sys/socket.h index de5ab61..5ce1ec6 100644 --- a/sys/include/sys/socket.h +++ b/sys/include/sys/socket.h @@ -164,6 +164,9 @@ scret_t sys_bind(struct syscall_args *scargs); scret_t sys_recv(struct syscall_args *scargs); scret_t sys_send(struct syscall_args *scargs); + +scret_t sys_recvmsg(struct syscall_args *scargs); +scret_t sys_sendmsg(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 51a1016..d79a697 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -63,6 +63,8 @@ #define SYS_bind 22 #define SYS_recv 23 #define SYS_send 24 +#define SYS_sendmsg 25 +#define SYS_recvmsg 26 #if defined(_KERNEL) /* Syscall return value and arg type */ diff --git a/sys/kern/kern_socket.c b/sys/kern/kern_socket.c index 99ef3b4..9b98ccc 100644 --- a/sys/kern/kern_socket.c +++ b/sys/kern/kern_socket.c @@ -547,6 +547,103 @@ sys_send(struct syscall_args *scargs) return send(sockfd, buf, len, flags); } +/* + * recvmsg(3) syscall + * + * arg0: socket + * arg1: msg + * arg2: flags + */ +scret_t +sys_recvmsg(struct syscall_args *scargs) +{ + struct msghdr *u_msg = (void *)scargs->arg1; + void *u_control; + size_t controllen; + struct iovec msg_iov; + struct msghdr msg; + ssize_t retval; + int socket = scargs->arg0; + int flags = scargs->arg2; + int error; + + /* Read the message header */ + error = copyin(u_msg, &msg, sizeof(msg)); + if (error < 0) { + pr_error("sys_recvmsg: bad msg\n"); + return error; + } + + /* Grab the message I/O vector */ + error = uio_copyin(msg.msg_iov, &msg_iov, msg.msg_iovlen); + if (error < 0) { + return error; + } + + /* Save control fields */ + u_control = msg.msg_control; + controllen = msg.msg_controllen; + + /* Allocate a new control field to copy in */ + msg.msg_control = dynalloc(controllen); + if (msg.msg_control == NULL) { + uio_copyin_clean(&msg_iov, msg.msg_iovlen); + return -ENOMEM; + } + + error = copyin(u_control, msg.msg_control, controllen); + if (error < 0) { + retval = error; + goto done; + } + + msg.msg_iov = &msg_iov; + retval = recvmsg(socket, &msg, flags); +done: + uio_copyin_clean(&msg_iov, msg.msg_iovlen); + dynfree(msg.msg_control); + return retval; +} + +/* + * sendmsg(3) syscall + * + * arg0: socket + * arg1: msg + * arg2: flags + */ +scret_t +sys_sendmsg(struct syscall_args *scargs) +{ + struct iovec msg_iov; + struct msghdr *u_msg = (void *)scargs->arg1; + struct msghdr msg; + ssize_t retval; + int socket = scargs->arg0; + int flags = scargs->arg2; + int error; + + /* Read the message header */ + error = copyin(u_msg, &msg, sizeof(msg)); + if (error < 0) { + pr_error("sys_sendmsg: bad msg\n"); + return error; + } + + /* Grab the message I/O vector */ + error = uio_copyin(msg.msg_iov, &msg_iov, msg.msg_iovlen); + if (error < 0) { + return error; + } + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &msg_iov; + retval = sendmsg(socket, &msg, flags); + uio_copyin_clean(&msg_iov, msg.msg_iovlen); + 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 dd3de4f..7b037aa 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -65,6 +65,8 @@ scret_t(*g_sctab[])(struct syscall_args *) = { sys_bind, /* SYS_bind */ sys_recv, /* SYS_recv */ sys_send, /* SYS_send */ + sys_sendmsg, /* SYS_sendmsg */ + sys_recvmsg, /* SYS_recvmsg */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); |