From: Matthias Kruk Date: Thu, 3 Oct 2019 09:41:17 +0000 (+0900) Subject: Add very simplistic socreate() implementation X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=803ad7b7e411a3cfdd03d127930376b7eb263f72;p=corax Add very simplistic socreate() implementation --- diff --git a/kernel/core/socket.c b/kernel/core/socket.c new file mode 100644 index 0000000..51dd1b8 --- /dev/null +++ b/kernel/core/socket.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include +#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 index 0000000..a36681a --- /dev/null +++ b/kernel/core/socket.h @@ -0,0 +1,24 @@ +#ifndef __SOCKET_H +#define __SOCKET_H + +#include +#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 */