From 5197cdba2a6b42ee050244422c433e4959ce3dcb Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 13 Apr 2024 20:58:03 -0300 Subject: [PATCH] syscalls: accept connect listen --- kernel-src/arch/x86-64/syscall.asm | 8 +++- kernel-src/arch/x86-64/syscalllog.c | 10 +++- kernel-src/include/kernel/abi.h | 6 +++ kernel-src/include/kernel/sock.h | 21 ++++++++ kernel-src/sys/syscalls/accept.c | 66 ++++++++++++++++++++++++++ kernel-src/sys/syscalls/connect.c | 57 ++++++++++++++++++++++ kernel-src/sys/syscalls/listen.c | 30 ++++++++++++ kernel-src/sys/syscalls/recvmsg.c | 7 ++- kernel-src/sys/syscalls/sendmsg.c | 7 ++- kernel-src/sys/syscalls/setsockopt.c | 6 +++ kernel-src/sys/syscalls/socket.c | 4 +- patches/mlibc/jinx-working-patch.patch | 28 +++++++++-- 12 files changed, 240 insertions(+), 10 deletions(-) create mode 100644 kernel-src/sys/syscalls/accept.c create mode 100644 kernel-src/sys/syscalls/connect.c create mode 100644 kernel-src/sys/syscalls/listen.c diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index a7de3533..d5fb4ebc 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -45,6 +45,9 @@ extern syscall_bind extern syscall_sendmsg extern syscall_setsockopt extern syscall_recvmsg +extern syscall_listen +extern syscall_connect +extern syscall_accept syscalltab: dq syscall_print dq syscall_mmap @@ -92,7 +95,10 @@ dq syscall_bind dq syscall_sendmsg dq syscall_setsockopt dq syscall_recvmsg -syscallcount equ 46 +dq syscall_listen +dq syscall_connect +dq syscall_accept +syscallcount equ 49 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/arch/x86-64/syscalllog.c b/kernel-src/arch/x86-64/syscalllog.c index 6ba58b7c..c94320fc 100644 --- a/kernel-src/arch/x86-64/syscalllog.c +++ b/kernel-src/arch/x86-64/syscalllog.c @@ -4,7 +4,7 @@ #ifdef SYSCALL_LOGGING -#define SYSCALL_COUNT 46 +#define SYSCALL_COUNT 48 #define LOGSTR(x) arch_e9_puts(x) static char *name[] = { @@ -53,7 +53,10 @@ static char *name[] = { "bind", "sendmsg", "setsockopt", - "recvmsg" + "recvmsg", + "listen", + "connect", + "accept" }; static char *args[] = { @@ -103,6 +106,9 @@ static char *args[] = { "fd %d msghdr %p flags %d", // sendmsg "fd %d level %d optname %d optval %p optlen %lu", // setsockopt "fd %d msghdr %p flags %d", // recvmsg + "fd %d backlog %d", // listen + "fd %d addr %p addrlen %lu", // connect + "fd %d addr %p addrlen %p" // accept }; #endif diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index 975e847c..cf18e0f6 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -81,6 +81,7 @@ typedef struct { #define AT_SYMLINK_NOFOLLOW 0x100 #define AT_EMPTY_PATH 0x1000 +#define AF_LOCAL 1 #define AF_INET 2 #define SOCK_STREAM 1 @@ -103,6 +104,11 @@ typedef struct { uint32_t sin_addr; } __attribute__((packed)) inaddr_t; +typedef struct { + uint16_t sun_family; + char sun_path[108]; +} __attribute__((packed)) unaddr_t; + typedef struct { void *addr; size_t len; diff --git a/kernel-src/include/kernel/sock.h b/kernel-src/include/kernel/sock.h index 2f44c2b6..a93bf458 100644 --- a/kernel-src/include/kernel/sock.h +++ b/kernel-src/include/kernel/sock.h @@ -21,11 +21,21 @@ typedef struct { int type; } socket_t; +typedef struct { + union { + ipv4addr_t ipv4addr; + char path[256]; + }; +} sockaddr_t; + typedef struct socketops_t { int (*bind)(socket_t *socket, sockaddr_t *addr); int (*send)(socket_t *socket, sockaddr_t *addr, void *buffer, size_t count, uintmax_t flags, size_t *sendcount); int (*recv)(socket_t *socket, sockaddr_t *addr, void *buffer, size_t count, uintmax_t flags, size_t *recvcount); int (*poll)(socket_t *socket, polldata_t *data, int events); + int (*connect)(socket_t *socket, sockaddr_t *addr, uintmax_t data); + int (*listen)(socket_t *socket, int backlog); + int (*accept)(socket_t *server, socket_t *client, sockaddr_t *addr, uintmax_t flags); void (*destroy)(socket_t *socket); } socketops_t; @@ -36,6 +46,7 @@ typedef struct { } socketnode_t; #define SOCKET_TYPE_UDP 0 +#define SOCKET_TYPE_LOCAL 1 #define SOCKFS_SOCKET_FROM_NODE(nodep) (((socketnode_t *)(nodep))->socket) static inline int sock_convertaddress(sockaddr_t *sockaddr, abisockaddr_t *abisockaddr) { @@ -45,6 +56,10 @@ static inline int sock_convertaddress(sockaddr_t *sockaddr, abisockaddr_t *abiso sockaddr->ipv4addr.addr = be_to_cpu_d(inaddr->sin_addr); sockaddr->ipv4addr.port = be_to_cpu_w(inaddr->sin_port); break; + case AF_LOCAL: + unaddr_t *unaddr = (unaddr_t *)abisockaddr; + strcpy(sockaddr->path, unaddr->sun_path); + break; default: return EINVAL; } @@ -59,6 +74,10 @@ static inline int sock_addrtoabiaddr(int socktype, sockaddr_t *sockaddr, abisock inaddr->sin_addr = cpu_to_be_d(sockaddr->ipv4addr.addr); inaddr->sin_port = cpu_to_be_w(sockaddr->ipv4addr.port); break; + case SOCKET_TYPE_LOCAL: + unaddr_t *unaddr = (unaddr_t *)abisockaddr; + strcpy(unaddr->sun_path, sockaddr->path); + break; default: return EINVAL; } @@ -93,6 +112,8 @@ static inline void sock_freemsghdr(msghdr_t *hdr) { free(hdr->addr); } +void localsock_leavebinding(vnode_t *vnode); +socket_t *localsock_createsocket(); socket_t *udp_createsocket(); socket_t *socket_create(int type); int sockfs_newsocket(vnode_t **vnodep, socket_t *socket); diff --git a/kernel-src/sys/syscalls/accept.c b/kernel-src/sys/syscalls/accept.c new file mode 100644 index 00000000..e290e09e --- /dev/null +++ b/kernel-src/sys/syscalls/accept.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +syscallret_t syscall_accept(context_t *, int oldfd, abisockaddr_t *abisockaddr, size_t *addrlen, int acceptflags) { + syscallret_t ret = { + .ret = -1 + }; + + file_t *oldfile = fd_get(oldfd); + if (oldfile == NULL) { + ret.errno = EBADF; + return ret; + } + + if (oldfile->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + + socket_t *server = SOCKFS_SOCKET_FROM_NODE(oldfile->vnode); + + socket_t *client = socket_create(server->type); + if (client == NULL) { + ret.errno = ENOMEM; + goto cleanup; + } + + vnode_t *vnode; + ret.errno = sockfs_newsocket(&vnode, client); + if (ret.errno) { + client->ops->destroy(client); + goto cleanup; + } + + sockaddr_t addr; + ret.errno = server->ops->accept(server, client, &addr, fileflagstovnodeflags(oldfile->flags)); + if (ret.errno) { + // socket gets deleted by node cleanup + VOP_RELEASE(vnode); + goto cleanup; + } + + file_t *newfile; + int newfd; + + ret.errno = fd_new(0, &newfile, &newfd); + if (ret.errno) { + // socket gets deleted by node cleanup + VOP_RELEASE(vnode); + goto cleanup; + } + + newfile->vnode = vnode; + newfile->flags = FILE_READ | FILE_WRITE | (acceptflags & (O_CLOEXEC | O_NONBLOCK)); + newfile->offset = 0; + newfile->mode = 0777; + + ret.ret = newfd; + + cleanup: + fd_release(oldfile); + + return ret; +} diff --git a/kernel-src/sys/syscalls/connect.c b/kernel-src/sys/syscalls/connect.c new file mode 100644 index 00000000..50dbd0bd --- /dev/null +++ b/kernel-src/sys/syscalls/connect.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +syscallret_t syscall_connect(context_t *, int fd, abisockaddr_t *uaddr, size_t addrlen) { + syscallret_t ret = { + .ret = -1 + }; + + if (addrlen > 1024) { + ret.errno = EINVAL; + return ret; + } + + abisockaddr_t *addr = alloc(addrlen); + if (addr == NULL) { + ret.errno = ENOMEM; + return ret; + } + + file_t *file = fd_get(fd); + if (file == NULL) { + ret.errno = EBADF; + goto cleanup; + } + + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + + memcpy(addr, uaddr, addrlen); + + sockaddr_t sockaddr; + ret.errno = sock_convertaddress(&sockaddr, addr); + if (ret.errno) + goto cleanup; + + socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); + + ret.errno = socket->ops->connect ? socket->ops->connect(socket, &sockaddr, fileflagstovnodeflags(file->flags)) : EOPNOTSUPP; + ret.ret = ret.errno ? -1 : 0; + + cleanup: + if (file) + fd_release(file); + + free(addr); + return ret; +} diff --git a/kernel-src/sys/syscalls/listen.c b/kernel-src/sys/syscalls/listen.c new file mode 100644 index 00000000..9165deac --- /dev/null +++ b/kernel-src/sys/syscalls/listen.c @@ -0,0 +1,30 @@ +#include +#include +#include + +syscallret_t syscall_listen(context_t *, int fd, int backlog) { + syscallret_t ret = { + .ret = -1 + }; + + file_t *file = fd_get(fd); + if (file == NULL) { + ret.errno = EBADF; + return ret; + } + + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + + socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); + + ret.errno = socket->ops->listen ? socket->ops->listen(socket, backlog) : EOPNOTSUPP; + ret.ret = ret.errno ? -1 : 0; + + cleanup: + fd_release(file); + + return ret; +} diff --git a/kernel-src/sys/syscalls/recvmsg.c b/kernel-src/sys/syscalls/recvmsg.c index f2655cb4..213e6d33 100644 --- a/kernel-src/sys/syscalls/recvmsg.c +++ b/kernel-src/sys/syscalls/recvmsg.c @@ -29,10 +29,15 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) goto cleanup; } + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + sockaddr_t sockaddr; socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); size_t recvcount; - ret.errno = socket->ops->recv(socket, &sockaddr, buffer, buffersize, 0, &recvcount); + ret.errno = socket->ops->recv(socket, &sockaddr, buffer, buffersize, fileflagstovnodeflags(file->flags), &recvcount); ret.ret = ret.errno ? -1 : recvcount; uintmax_t iovoffset = 0; diff --git a/kernel-src/sys/syscalls/sendmsg.c b/kernel-src/sys/syscalls/sendmsg.c index 2c51cd2e..550de3f5 100644 --- a/kernel-src/sys/syscalls/sendmsg.c +++ b/kernel-src/sys/syscalls/sendmsg.c @@ -35,6 +35,11 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) goto cleanup; } + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + sockaddr_t sockaddr; if (msghdr.addr) { ret.errno = sock_convertaddress(&sockaddr, msghdr.addr); @@ -44,7 +49,7 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); size_t sendcount; - ret.errno = socket->ops->send(socket, msghdr.addr ? &sockaddr : NULL, buffer, buffersize, 0, &sendcount); + ret.errno = socket->ops->send(socket, msghdr.addr ? &sockaddr : NULL, buffer, buffersize, fileflagstovnodeflags(file->flags), &sendcount); ret.ret = ret.errno ? -1 : sendcount; cleanup: diff --git a/kernel-src/sys/syscalls/setsockopt.c b/kernel-src/sys/syscalls/setsockopt.c index f019edb6..df17faa5 100644 --- a/kernel-src/sys/syscalls/setsockopt.c +++ b/kernel-src/sys/syscalls/setsockopt.c @@ -31,6 +31,11 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi return ret; } + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); @@ -58,6 +63,7 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi MUTEX_RELEASE(&socket->mutex); + cleanup: ret.ret = ret.errno ? -1 : 0; fd_release(file); diff --git a/kernel-src/sys/syscalls/socket.c b/kernel-src/sys/syscalls/socket.c index e4d5633a..445a5d45 100644 --- a/kernel-src/sys/syscalls/socket.c +++ b/kernel-src/sys/syscalls/socket.c @@ -17,6 +17,8 @@ syscallret_t syscall_socket(context_t *, int domain, int type, int protocol) { socktype = SOCKET_TYPE_UDP; break; + case AF_LOCAL: + socktype = SOCKET_TYPE_LOCAL; } if (socktype == -1) { @@ -33,7 +35,7 @@ syscallret_t syscall_socket(context_t *, int domain, int type, int protocol) { vnode_t *vnode; ret.errno = sockfs_newsocket(&vnode, socket); if (ret.errno) { - // TODO delete socket + socket->ops->destroy(socket); return ret; } diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index 08edf620..2c46425a 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -188,10 +188,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..8d990b7 +index 0000000..37e2732 --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,553 @@ +@@ -0,0 +1,570 @@ +#include +#include +#include @@ -322,6 +322,23 @@ index 0000000..8d990b7 + return 0; + } + ++ int sys_listen(int fd, int backlog) { ++ long ret; ++ return syscall(SYSCALL_LISTEN, &ret, fd, backlog); ++ } ++ ++ int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags) { ++ long ret; ++ long error = syscall(SYSCALL_ACCEPT, &ret, fd, (uint64_t)addr_ptr, (uint64_t)addr_length, flags); ++ *newfd = ret; ++ return error; ++ } ++ ++ int sys_connect(int fd, const struct sockaddr *addr_ptr, socklen_t addr_length) { ++ long ret; ++ return syscall(SYSCALL_CONNECT, &ret, fd, (uint64_t)addr_ptr, addr_length); ++ } ++ + int sys_msg_recv(int fd, struct msghdr *hdr, int flags, ssize_t *length) { + long ret; + long err = syscall(SYSCALL_RECVMSG, &ret, fd, (uint64_t)hdr, flags); @@ -764,10 +781,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..29ce601 +index 0000000..52590c3 --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,69 @@ +@@ -0,0 +1,72 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -817,6 +834,9 @@ index 0000000..29ce601 +#define SYSCALL_SENDMSG 43 +#define SYSCALL_SETSOCKOPT 44 +#define SYSCALL_RECVMSG 45 ++#define SYSCALL_LISTEN 46 ++#define SYSCALL_CONNECT 47 ++#define SYSCALL_ACCEPT 48 + +#include +#include