]> git.corax.cc Git - corax/commitdiff
Add very simplistic socreate() implementation
authorMatthias Kruk <m@m10k.eu>
Thu, 3 Oct 2019 09:41:17 +0000 (18:41 +0900)
committerMatthias Kruk <m@m10k.eu>
Thu, 3 Oct 2019 09:41:17 +0000 (18:41 +0900)
kernel/core/socket.c [new file with mode: 0644]
kernel/core/socket.h [new file with mode: 0644]

diff --git a/kernel/core/socket.c b/kernel/core/socket.c
new file mode 100644 (file)
index 0000000..51dd1b8
--- /dev/null
@@ -0,0 +1,166 @@
+#include <config.h>
+#include <corax/types.h>
+#include <corax/heap.h>
+#include <corax/errno.h>
+#include <sys/socket.h>
+#include <arch.h>
+#include "socket.h"
+#include "process.h"
+
+static struct socket *_sockets[CONFIG_SOCKET_MAX];
+static int _nsockets;
+
+#define SOCKET_PREALLOC ((void*)0xffffffff)
+
+static inline int allocsockfd(void)
+{
+       int ret_val;
+       int i;
+
+       ret_val = -ENFILE;
+
+       if(_nsockets < CONFIG_SOCKET_MAX) {
+               _nsockets++;
+
+               for(i = 0; i < CONFIG_SOCKET_MAX; i++) {
+                       if(!_sockets[i]) {
+                               _sockets[i] = SOCKET_PREALLOC;
+                               ret_val = i;
+                               break;
+                       }
+               }
+       }
+
+       return(ret_val);
+}
+
+static inline int freesockfd(int fd)
+{
+       int ret_val;
+
+       ret_val = -EINVAL;
+
+       if(fd >= 0 && fd < CONFIG_SOCKET_MAX) {
+               ret_val = -EBADF;
+
+               if(_sockets[fd]) {
+                       _sockets[fd] = NULL;
+                       _nsockets--;
+                       ret_val = 0;
+               }
+       }
+
+       return(ret_val);
+}
+
+int socreate(int dom, int type, int proto)
+{
+       struct task *cur_task;
+       struct process *cur_proc;
+#if 0
+       struct protosw *psw;
+#endif
+       struct socket *so;
+       int ret_val;
+       int sfd;
+       int pfd;
+
+       sfd = -1;
+       pfd = -1;
+       ret_val = -EINVAL;
+
+       /* first of all, make sure all input makes sense */
+       if(!PF_VALID(dom) || !SOCK_VALID(type)) {
+               goto gtfo;
+       }
+
+       ret_val = -ENFILE;
+
+       /* check if the system-wide socket limit has been hit */
+       if(_nsockets >= CONFIG_SOCKET_MAX) {
+               goto gtfo;
+       }
+
+       /*
+        * This function is only executed as a result of a syscall,
+        * so it's safe to assume that task_get_current() will never
+        * return NULL.
+        */
+       cur_task = task_get_current();
+       cur_proc = cur_task->t_proc;
+
+       sfd = allocsockfd();
+
+       if(sfd < 0) {
+               ret_val = sfd;
+               goto gtfo;
+       }
+
+       pfd = process_falloc(cur_proc, sfd);
+
+       if(pfd < 0) {
+               ret_val = pfd;
+               goto gtfo;
+       }
+
+#if 0
+       /* FIXME: Look up the domain/protocol */
+       if(proto) {
+               psw = pffindproto(dom, proto, type);
+       } else {
+               psw = pffindtype(dom, type);
+       }
+
+       if(!psw) {
+               ret_val = -EPROTONOSUPPORT;
+               goto gtfo;
+       }
+
+       if(psw->pr_type != type) {
+               ret_val = -EPROTOTYPE;
+               goto gtfo;
+       }
+#endif
+
+       so = kmalloc(sizeof(*so));
+
+       if(!so) {
+               ret_val = -ENOMEM;
+               goto gtfo;
+       }
+
+       so->so_type = type;
+#if 0
+       so->so_proto = psw;
+#endif
+
+       /*
+        * FIXME: set SS_PRIV on so->so_state if the calling process is
+        * executing as root; initialize remaining members, attach the
+        * socket by meansof psw->pr_usrreq(so, PRU_ATTACH, ...).
+        * ref: TCP/IP Illustrated Vol. 2, p. 426
+        */
+
+       _sockets[sfd] = so;
+       ret_val = pfd;
+
+gtfo:
+       if(ret_val < 0) {
+               if(sfd > 0) {
+                       freesockfd(sfd);
+                       sfd = -1;
+               }
+
+               if(cur_proc && pfd > 0) {
+                       process_ffree(cur_proc, pfd);
+                       pfd = -1;
+               }
+
+               if(so) {
+                       kfree(so);
+                       so = NULL;
+               }
+       }
+
+       return(ret_val);
+}
diff --git a/kernel/core/socket.h b/kernel/core/socket.h
new file mode 100644 (file)
index 0000000..a36681a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __SOCKET_H
+#define __SOCKET_H
+
+#include <corax/types.h>
+#if 0
+#include "protocol.h"
+#endif
+
+struct socket {
+       u16_t so_type;
+       /* that's all for now */
+#if 0
+       u16_t so_options;
+       u16_t so_state;
+       u16_t so_linger;
+
+       void *so_pcb;
+       struct protosw *so_protosw;
+#endif
+};
+
+int socreate(int, int, int);
+
+#endif /* __SOCKET_H */