From a24ecf4b83b01656cc86e5607c878ca47a658c2e Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Fri, 28 Feb 2014 17:10:08 +0100 Subject: [PATCH] Add getsockopt(2) and setsockopt(2). --- kernel/descriptor.cpp | 12 +++++ kernel/fs/user.cpp | 54 +++++++++++++++++++++++ kernel/include/sortix/kernel/descriptor.h | 4 ++ kernel/include/sortix/kernel/inode.h | 8 ++++ kernel/include/sortix/kernel/vnode.h | 4 ++ kernel/include/sortix/syscallnum.h | 4 +- kernel/inode.cpp | 12 +++++ kernel/io.cpp | 24 ++++++++++ kernel/vnode.cpp | 12 +++++ libc/include/fsmarshall-msg.h | 28 +++++++++++- libc/sys/socket/getsockopt.cpp | 13 +++--- libc/sys/socket/setsockopt.cpp | 13 +++--- 12 files changed, 174 insertions(+), 14 deletions(-) diff --git a/kernel/descriptor.cpp b/kernel/descriptor.cpp index c1b2958e..19fd6ec6 100644 --- a/kernel/descriptor.cpp +++ b/kernel/descriptor.cpp @@ -628,4 +628,16 @@ ssize_t Descriptor::send(ioctx_t* ctx, const uint8_t* buf, size_t count, int fla return vnode->send(ctx, buf, count, flags); } +int Descriptor::getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr) +{ + return vnode->getsockopt(ctx, level, option_name, option_value, option_size_ptr); +} + +int Descriptor::setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size) +{ + return vnode->setsockopt(ctx, level, option_name, option_value, option_size); +} + } // namespace Sortix diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index 54a26d9a..b9ff82cc 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -232,6 +232,10 @@ public: virtual ssize_t recv(ioctx_t* ctx, uint8_t* buf, size_t count, int flags); virtual ssize_t send(ioctx_t* ctx, const uint8_t* buf, size_t count, int flags); + virtual int getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr); + virtual int setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size); private: bool SendMessage(Channel* channel, size_t type, void* ptr, size_t size, @@ -1294,6 +1298,56 @@ ssize_t Unode::send(ioctx_t* /*ctx*/, const uint8_t* /*buf*/, size_t /*count*/, return errno = ENOTSOCK, -1; } +int Unode::getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr) +{ + size_t option_size; + if ( !ctx->copy_from_src(&option_size, option_size_ptr, sizeof(option_size)) ) + return -1; + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + int ret = -1; + struct fsm_req_getsockopt msg; + struct fsm_resp_getsockopt resp; + msg.ino = ino; + msg.level = level; + msg.option_name = option_name; + msg.max_option_size = option_size; + if ( SendMessage(channel, FSM_REQ_GETSOCKOPT, &msg, sizeof(msg)) && + RecvMessage(channel, FSM_RESP_GETSOCKOPT, &resp, sizeof(resp)) ) + { + if ( resp.option_size < option_size ) + option_size = resp.option_size; + if ( channel->KernelRecv(ctx, option_value, option_size) ) + ret = 0; + if ( !ctx->copy_to_dest(option_size_ptr, &option_size, sizeof(option_size)) ) + ret = -1; + } + channel->KernelClose(); + return ret; +} + +int Unode::setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + int ret = -1; + struct fsm_req_setsockopt msg; + msg.ino = ino; + msg.level = level; + msg.option_name = option_name; + msg.option_size = option_size; + if ( SendMessage(channel, FSM_REQ_SETSOCKOPT, &msg, sizeof(msg)) && + channel->KernelSend(ctx, option_value, option_size) && + RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) ) + ret = 0; + channel->KernelClose(); + return ret; +} + // // Initialization. // diff --git a/kernel/include/sortix/kernel/descriptor.h b/kernel/include/sortix/kernel/descriptor.h index ffab1594..664ff1e9 100644 --- a/kernel/include/sortix/kernel/descriptor.h +++ b/kernel/include/sortix/kernel/descriptor.h @@ -96,6 +96,10 @@ public: int listen(ioctx_t* ctx, int backlog); ssize_t recv(ioctx_t* ctx, uint8_t* buf, size_t count, int flags); ssize_t send(ioctx_t* ctx, const uint8_t* buf, size_t count, int flags); + int getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr); + int setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size); private: Ref open_elem(ioctx_t* ctx, const char* filename, int flags, diff --git a/kernel/include/sortix/kernel/inode.h b/kernel/include/sortix/kernel/inode.h index a79fe82b..29033d3b 100644 --- a/kernel/include/sortix/kernel/inode.h +++ b/kernel/include/sortix/kernel/inode.h @@ -106,6 +106,10 @@ public: virtual ssize_t recv(ioctx_t* ctx, uint8_t* buf, size_t count, int flags) = 0; virtual ssize_t send(ioctx_t* ctx, const uint8_t* buf, size_t count, int flags) = 0; + virtual int getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr) = 0; + virtual int setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size) = 0; }; @@ -186,6 +190,10 @@ public: virtual ssize_t recv(ioctx_t* ctx, uint8_t* buf, size_t count, int flags); virtual ssize_t send(ioctx_t* ctx, const uint8_t* buf, size_t count, int flags); + virtual int getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr); + virtual int setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size); }; diff --git a/kernel/include/sortix/kernel/vnode.h b/kernel/include/sortix/kernel/vnode.h index 7d1acfb5..af69d68d 100644 --- a/kernel/include/sortix/kernel/vnode.h +++ b/kernel/include/sortix/kernel/vnode.h @@ -96,6 +96,10 @@ public: int listen(ioctx_t* ctx, int backlog); ssize_t recv(ioctx_t* ctx, uint8_t* buf, size_t count, int flags); ssize_t send(ioctx_t* ctx, const uint8_t* buf, size_t count, int flags); + int getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr); + int setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size); public /*TODO: private*/: Ref inode; diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index 782c6742..a77069dd 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -165,6 +165,8 @@ #define SYSCALL_SIGSUSPEND 137 #define SYSCALL_SENDMSG 138 #define SYSCALL_RECVMSG 139 -#define SYSCALL_MAX_NUM 140 /* index of highest constant + 1 */ +#define SYSCALL_GETSOCKOPT 140 +#define SYSCALL_SETSOCKOPT 141 +#define SYSCALL_MAX_NUM 142 /* index of highest constant + 1 */ #endif diff --git a/kernel/inode.cpp b/kernel/inode.cpp index 0e841372..8eee915b 100644 --- a/kernel/inode.cpp +++ b/kernel/inode.cpp @@ -384,4 +384,16 @@ ssize_t AbstractInode::send(ioctx_t* /*ctx*/, const uint8_t* /*buf*/, return errno = ENOTSOCK, -1; } +int AbstractInode::getsockopt(ioctx_t* /*ctx*/, int /*level*/, int /*option_name*/, + void* /*option_value*/, size_t* /*option_size_ptr*/) +{ + return errno = ENOTSOCK, -1; +} + +int AbstractInode::setsockopt(ioctx_t* /*ctx*/, int /*level*/, int /*option_name*/, + const void* /*option_value*/, size_t /*option_size*/) +{ + return errno = ENOTSOCK, -1; +} + } // namespace Sortix diff --git a/kernel/io.cpp b/kernel/io.cpp index bab9fe04..952974d7 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -1010,6 +1010,28 @@ static ssize_t sys_recvmsg(int fd, struct msghdr* user_msg, int flags) return result; } +static int sys_getsockopt(int fd, int level, int option_name, + void* option_value, size_t* option_size_ptr) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + + ioctx_t ctx; SetupUserIOCtx(&ctx); + return desc->getsockopt(&ctx, level, option_name, option_value, option_size_ptr); +} + +static int sys_setsockopt(int fd, int level, int option_name, + const void* option_value, size_t option_size) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + + ioctx_t ctx; SetupUserIOCtx(&ctx); + return desc->setsockopt(&ctx, level, option_name, option_value, option_size); +} + void Init() { Syscall::Register(SYSCALL_ACCEPT4, (void*) sys_accept4); @@ -1036,6 +1058,7 @@ void Init() Syscall::Register(SYSCALL_FSYNC, (void*) sys_fsync); Syscall::Register(SYSCALL_FTRUNCATE, (void*) sys_ftruncate); Syscall::Register(SYSCALL_FUTIMENS, (void*) sys_futimens); + Syscall::Register(SYSCALL_GETSOCKOPT, (void*) sys_getsockopt); Syscall::Register(SYSCALL_GETTERMMODE, (void*) sys_gettermmode); Syscall::Register(SYSCALL_IOCTL, (void*) sys_ioctl); Syscall::Register(SYSCALL_ISATTY, (void*) sys_isatty); @@ -1058,6 +1081,7 @@ void Init() Syscall::Register(SYSCALL_RENAMEAT, (void*) sys_renameat); Syscall::Register(SYSCALL_SENDMSG, (void*) sys_sendmsg); Syscall::Register(SYSCALL_SEND, (void*) sys_send); + Syscall::Register(SYSCALL_SETSOCKOPT, (void*) sys_setsockopt); Syscall::Register(SYSCALL_SETTERMMODE, (void*) sys_settermmode); Syscall::Register(SYSCALL_SYMLINKAT, (void*) sys_symlinkat); Syscall::Register(SYSCALL_TCGETPGRP, (void*) sys_tcgetpgrp); diff --git a/kernel/vnode.cpp b/kernel/vnode.cpp index c2e3f47c..659d8039 100644 --- a/kernel/vnode.cpp +++ b/kernel/vnode.cpp @@ -294,4 +294,16 @@ ssize_t Vnode::send(ioctx_t* ctx, const uint8_t* buf, size_t count, int flags) return inode->send(ctx, buf, count, flags); } +int Vnode::getsockopt(ioctx_t* ctx, int level, int option_name, + void* option_value, size_t* option_size_ptr) +{ + return inode->getsockopt(ctx, level, option_name, option_value, option_size_ptr); +} + +int Vnode::setsockopt(ioctx_t* ctx, int level, int option_name, + const void* option_value, size_t option_size) +{ + return inode->setsockopt(ctx, level, option_name, option_value, option_size); +} + } // namespace Sortix diff --git a/libc/include/fsmarshall-msg.h b/libc/include/fsmarshall-msg.h index bf0901f9..158a073f 100644 --- a/libc/include/fsmarshall-msg.h +++ b/libc/include/fsmarshall-msg.h @@ -368,7 +368,33 @@ struct fsm_resp_statvfs struct statvfs stvfs; }; -#define FSM_MSG_NUM 45 +#define FSM_REQ_SETSOCKOPT 46 +struct fsm_req_setsockopt +{ + ino_t ino; + int level; + int option_name; + size_t option_size; + /*uint8_t option[option_size];*/ +}; + +#define FSM_REQ_GETSOCKOPT 47 +struct fsm_req_getsockopt +{ + ino_t ino; + int level; + int option_name; + size_t max_option_size; +}; + +#define FSM_RESP_GETSOCKOPT 48 +struct fsm_resp_getsockopt +{ + size_t option_size; + /*uint8_t option[option_size];*/ +}; + +#define FSM_MSG_NUM 49 #if defined(__cplusplus) } /* extern "C" */ diff --git a/libc/sys/socket/getsockopt.cpp b/libc/sys/socket/getsockopt.cpp index a0a48aee..a9db4d25 100644 --- a/libc/sys/socket/getsockopt.cpp +++ b/libc/sys/socket/getsockopt.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,13 @@ *******************************************************************************/ #include +#include -#include -#include +DEFN_SYSCALL5(int, sys_getsockopt, SYSCALL_GETSOCKOPT, int, int, int, const void*, size_t*); -extern "C" int getsockopt(int, int, int, void* restrict, socklen_t* restrict) +extern "C" +int getsockopt(int fd, int level, int option_name, void* restrict option_value, + socklen_t* restrict option_size) { - fprintf(stderr, "%s is not implemented yet.\n", __func__); - return errno = ENOSYS, -1; + return sys_getsockopt(fd, level, option_name, option_value, option_size); } diff --git a/libc/sys/socket/setsockopt.cpp b/libc/sys/socket/setsockopt.cpp index 12c4c630..d3be27e2 100644 --- a/libc/sys/socket/setsockopt.cpp +++ b/libc/sys/socket/setsockopt.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,13 @@ *******************************************************************************/ #include +#include -#include -#include +DEFN_SYSCALL5(int, sys_setsockopt, SYSCALL_SETSOCKOPT, int, int, int, const void*, size_t); -extern "C" int setsockopt(int, int, int, const void*, socklen_t) +extern "C" +int setsockopt(int fd, int level, int option_name, const void* option_value, + socklen_t option_size) { - fprintf(stderr, "%s is not implemented yet.\n", __func__); - return errno = ENOSYS, -1; + return sys_setsockopt(fd, level, option_name, option_value, option_size); }