From 708bcb4735994cdf2fc3ffb4624e9beb127a0bd9 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Thu, 16 Jan 2014 20:46:56 +0100 Subject: [PATCH] Add recvmsg(2) and sendmsg(2). --- kernel/include/sortix/syscallnum.h | 4 ++- kernel/io.cpp | 44 ++++++++++++++++++++++++++++++ libc/include/sys/socket.h | 2 ++ libc/sys/socket/recvmsg.cpp | 12 ++++---- libc/sys/socket/sendmsg.cpp | 10 ++++--- 5 files changed, 62 insertions(+), 10 deletions(-) diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index f2f40f95..782c6742 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -163,6 +163,8 @@ #define SYSCALL_SIGPENDING 135 #define SYSCALL_SIGPROCMASK 136 #define SYSCALL_SIGSUSPEND 137 -#define SYSCALL_MAX_NUM 138 /* index of highest constant + 1 */ +#define SYSCALL_SENDMSG 138 +#define SYSCALL_RECVMSG 139 +#define SYSCALL_MAX_NUM 140 /* index of highest constant + 1 */ #endif diff --git a/kernel/io.cpp b/kernel/io.cpp index 87b0f288..bab9fe04 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -22,6 +22,7 @@ *******************************************************************************/ +#include #include #include @@ -968,6 +969,47 @@ static int sys_mkpartition(int fd, off_t start, off_t length, int flags) return CurrentProcess()->GetDTable()->Allocate(partition_desc, fdflags); } +static ssize_t sys_sendmsg(int fd, const struct msghdr* user_msg, int flags) +{ + struct msghdr msg; + if ( !CopyFromUser(&msg, user_msg, sizeof(msg)) ) + return -1; + // TODO: MSG_DONTWAIT and MSG_NOSIGNAL aren't actually supported here! + if ( flags & ~(MSG_EOR | MSG_DONTWAIT | MSG_NOSIGNAL) ) + return errno = EINVAL, -1; + if ( msg.msg_name ) + return errno = EINVAL, -1; + if ( msg.msg_control && msg.msg_controllen ) + return errno = EINVAL, -1; + return sys_writev(fd, msg.msg_iov, msg.msg_iovlen); +} + +static ssize_t sys_recvmsg(int fd, struct msghdr* user_msg, int flags) +{ + struct msghdr msg; + if ( !CopyFromUser(&msg, user_msg, sizeof(msg)) ) + return -1; + if ( flags & ~(MSG_CMSG_CLOEXEC | MSG_DONTWAIT) ) + return errno = EINVAL, -1; + if ( msg.msg_name ) + return errno = EINVAL, -1; + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + + // TODO: This is not atomic. + int old_flags = desc->GetFlags(); + desc->SetFlags(old_flags | O_NONBLOCK); + ssize_t result = sys_readv(fd, msg.msg_iov, msg.msg_iovlen); + desc->SetFlags(old_flags); + + msg.msg_flags = 0; + if ( !CopyToUser(&user_msg->msg_flags, &msg.msg_flags, sizeof(msg.msg_flags)) ) + return -1; + + return result; +} + void Init() { Syscall::Register(SYSCALL_ACCEPT4, (void*) sys_accept4); @@ -1011,8 +1053,10 @@ void Init() Syscall::Register(SYSCALL_READLINKAT, (void*) sys_readlinkat); Syscall::Register(SYSCALL_READ, (void*) sys_read); Syscall::Register(SYSCALL_READV, (void*) sys_readv); + Syscall::Register(SYSCALL_RECVMSG, (void*) sys_recvmsg); Syscall::Register(SYSCALL_RECV, (void*) sys_recv); Syscall::Register(SYSCALL_RENAMEAT, (void*) sys_renameat); + Syscall::Register(SYSCALL_SENDMSG, (void*) sys_sendmsg); Syscall::Register(SYSCALL_SEND, (void*) sys_send); Syscall::Register(SYSCALL_SETTERMMODE, (void*) sys_settermmode); Syscall::Register(SYSCALL_SYMLINKAT, (void*) sys_symlinkat); diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h index e3ca149b..a6357dba 100644 --- a/libc/include/sys/socket.h +++ b/libc/include/sys/socket.h @@ -137,6 +137,8 @@ struct linger #define MSG_PEEK (1<<5) #define MSG_TRUNC (1<<6) #define MSG_WAITALL (1<<7) +#define MSG_DONTWAIT (1<<8) +#define MSG_CMSG_CLOEXEC (1<<9) #define AF_UNSPEC 0 #define AF_INET 1 diff --git a/libc/sys/socket/recvmsg.cpp b/libc/sys/socket/recvmsg.cpp index 08acefd9..144e30a5 100644 --- a/libc/sys/socket/recvmsg.cpp +++ b/libc/sys/socket/recvmsg.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2013. + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014. This file is part of the Sortix C Library. @@ -18,17 +18,19 @@ along with the Sortix C Library. If not, see . sys/socket/recvmsg.cpp - Receive a message from a socket. + Receive a message on a socket. *******************************************************************************/ #include +#include #include #include -extern "C" ssize_t recvmsg(int, struct msghdr*, int) +DEFN_SYSCALL3(ssize_t, sys_recvmsg, SYSCALL_RECVMSG, int, struct msghdr*, int); + +extern "C" ssize_t recvmsg(int fd, struct msghdr* msg, int flags) { - fprintf(stderr, "%s is not implemented yet.\n", __func__); - return errno = ENOSYS, -1; + return sys_recvmsg(fd, msg, flags); } diff --git a/libc/sys/socket/sendmsg.cpp b/libc/sys/socket/sendmsg.cpp index 2f9b7559..73b15887 100644 --- a/libc/sys/socket/sendmsg.cpp +++ b/libc/sys/socket/sendmsg.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2013. + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014. This file is part of the Sortix C Library. @@ -23,12 +23,14 @@ *******************************************************************************/ #include +#include #include #include -extern "C" ssize_t sendmsg(int, const struct msghdr*, int) +DEFN_SYSCALL3(ssize_t, sys_sendmsg, SYSCALL_SENDMSG, int, const struct msghdr*, int); + +extern "C" ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) { - fprintf(stderr, "%s is not implemented yet.\n", __func__); - return errno = ENOSYS, -1; + return sys_sendmsg(fd, msg, flags); }