]> git.corax.cc Git - corax/commitdiff
Implement sys_getsockopt() and sys_setsockopt() functions
authorMatthias Kruk <m@m10k.eu>
Sat, 5 Oct 2019 06:32:37 +0000 (15:32 +0900)
committerMatthias Kruk <m@m10k.eu>
Sat, 5 Oct 2019 06:32:37 +0000 (15:32 +0900)
kernel/core/cxnet.c

index c369d58f5ee3d670bba267d5df837be4d96671ec..364996b2bddb63d989e723373ff803ebeb9d3837 100644 (file)
@@ -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)