From bb2f82724992fc35b433e9355112a98bf34e6244 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Sat, 5 Oct 2019 15:32:37 +0900 Subject: [PATCH] Implement sys_getsockopt() and sys_setsockopt() functions --- kernel/core/cxnet.c | 88 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/kernel/core/cxnet.c b/kernel/core/cxnet.c index c369d58..364996b 100644 --- a/kernel/core/cxnet.c +++ b/kernel/core/cxnet.c @@ -84,16 +84,96 @@ int sys_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) return(-ENOSYS); } -int sys_setsockopt(int sockfd, int level, int optname, +int sys_setsockopt(int procfd, int level, int optname, const void *optval, socklen_t optlen) { - return(-ENOSYS); + process_t *cproc; + int sockfd; + int ret_val; + + if(level != SOL_SOCKET) { + ret_val = -EINVAL; + goto gtfo; + } + + ret_val = -EFAULT; + cproc = process_get_current(); + + if(cproc) { + sockfd = process_flookup(cproc, procfd); + + if(sockfd < 0) { + ret_val = sockfd; + } else { + char koptbuf[128]; + socklen_t koptlen; + + /* + * The memory referenced by `optval' is in the process's + * address space, so we have to copy it into the kernel's + * address space before being able to use it. Since the + * process's buffer may sit on the boundary of two non- + * consecutive pages, we can't just use the linear + * address. + */ + + koptlen = optlen < sizeof(koptbuf) ? optlen : sizeof(koptbuf); + process_memcpy_ptok(cproc, koptbuf, (void*)optval, koptlen); + + ret_val = sosetopt(sockfd, optname, koptbuf, koptlen); + } + } + +gtfo: + return(ret_val); } -int sys_getsockopt(int sockfd, int level, int optname, +int sys_getsockopt(int procfd, int level, int optname, void *optval, socklen_t *optlen) { - return(-ENOSYS); + process_t *cproc; + int sockfd; + int ret_val; + + /* + * This function is essentially the same as sys_setsockopt(), except that it + * calls sogetopt() instead of sosetopt(), and the buffer is copied after that + * call, in the opposite direction. + */ + + if(level != SOL_SOCKET) { + ret_val = -EINVAL; + goto gtfo; + } + + ret_val = -EFAULT; + cproc = process_get_current(); + + if(cproc) { + sockfd = process_flookup(cproc, procfd); + + if(sockfd < 0) { + ret_val = sockfd; + } else { + char koptbuf[128]; + socklen_t koptlen; + + koptlen = *optlen < sizeof(koptbuf) ? *optlen : sizeof(koptbuf); + + ret_val = sogetopt(sockfd, optname, koptbuf, &koptlen); + + if(!ret_val) { + /* return data to user-space if the call was successful */ + + process_memcpy_ktop(cproc, optval, koptbuf, koptlen); + /* as annoying (and unlikely) as it may be, optlen may also sit on a page-boundary */ + process_memcpy_ktop(cproc, optlen, &koptlen, sizeof(koptlen)); + } + } + } + +gtfo: + return(ret_val); } int sys_shutdown(int sockfd, int how) -- 2.47.3