summaryrefslogtreecommitdiff
path: root/src/sys/os
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/os')
-rw-r--r--src/sys/os/os_filedes.c75
-rw-r--r--src/sys/os/os_socket.c256
-rw-r--r--src/sys/os/vfs_namei.c1
-rw-r--r--src/sys/os/vfs_subr.c23
4 files changed, 336 insertions, 19 deletions
diff --git a/src/sys/os/os_filedes.c b/src/sys/os/os_filedes.c
index ca56fc3..3eaee0d 100644
--- a/src/sys/os/os_filedes.c
+++ b/src/sys/os/os_filedes.c
@@ -44,16 +44,9 @@
#define STDOUT_FILENO 1
/*
- * Allocate a file descriptor from a specific process's
- * file descriptor table
- *
- * @procp: Process to allocate fd from
- * @fd_res: Result pointer is written here
- *
- * Returns zero on success, otherwise a less than
- * zero value upon failure
+ * Allocate a file descriptor
*/
-static int
+int
fd_alloc(struct proc *procp, struct filedesc **fd_res)
{
struct filedesc *fd;
@@ -91,16 +84,9 @@ fd_alloc(struct proc *procp, struct filedesc **fd_res)
}
/*
- * Look up a file descriptor that belongs to a specific
- * process by using its fd number
- *
- * @procp: Process to look up
- * @fd: File descriptor number
- *
- * Returns the file descriptor pointer on success,
- * otherwise a less than zero value on failure
+ * Get a file descriptor
*/
-static struct filedesc *
+struct filedesc *
fd_get(struct proc *procp, int fd)
{
struct filedesc *fdp;
@@ -359,6 +345,44 @@ read(int fd, void *buf, size_t count)
return retval;
}
+off_t
+lseek(int fd, off_t offset, int whence)
+{
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vattr attr;
+ int error;
+
+ if (fd < 0) {
+ return -EBADF;
+ }
+
+ fdp = fd_get(self, fd);
+ if (fdp == NULL) {
+ return -EBADF;
+ }
+
+ /* Could not get vnode attributes */
+ error = vop_getattr(fdp->vp, &attr);
+ if (error < 0) {
+ return 0;
+ }
+
+ switch (whence) {
+ case SEEK_SET:
+ fdp->off = offset;
+ break;
+ case SEEK_CUR:
+ fdp->off += offset;
+ break;
+ case SEEK_END:
+ fdp->off = attr.size;
+ break;
+ }
+
+ return fdp->off;
+}
+
/*
* ARG0: Path
* ARG1: Mode
@@ -378,3 +402,18 @@ sys_open(struct syscall_args *scargs)
return fd_open(pathbuf, mode);
}
+
+/*
+ * ARG0: Fd
+ * ARG1: Offset
+ * ARG2: Whence
+ */
+scret_t
+sys_lseek(struct syscall_args *scargs)
+{
+ int fd = SCARG(scargs, int, 0);
+ off_t off = SCARG(scargs, off_t, 1);
+ int whence = SCARG(scargs, int, 2);
+
+ return lseek(fd, off, whence);
+}
diff --git a/src/sys/os/os_socket.c b/src/sys/os/os_socket.c
new file mode 100644
index 0000000..a37d15f
--- /dev/null
+++ b/src/sys/os/os_socket.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2025 Ian Marco Moffett and L5 engineers
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/syslog.h>
+#include <sys/errno.h>
+#include <sys/proc.h>
+#include <os/vnode.h>
+#include <os/kalloc.h>
+#include <os/filedesc.h>
+#include <string.h>
+
+static size_t next_sockid = 1;
+
+/*
+ * Allocate a socket file descriptor
+ *
+ * @fdp_res: Result is written here
+ *
+ * XXX: Socket vnodes are never deallocated until explicitly
+ * closed
+ *
+ * Returns file descriptor on success, otherwise a
+ * less than zero value on faulure
+ */
+static int
+get_sock_fd(struct filedesc **fdp_res)
+{
+ char namebuf[256];
+ struct ksocket *sock;
+ struct mount *mp;
+ struct nameidata nd;
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vnode *vp;
+ int error;
+
+ if (fdp_res == NULL) {
+ return -EINVAL;
+ }
+
+ if (self == NULL) {
+ return -EIO;
+ }
+
+ error = mount_lookup("/tmp", &mp);
+ if (error < 0) {
+ printf("socket: could not get /tmp mountpoint\n");
+ return error;
+ }
+
+ error = fd_alloc(self, &fdp);
+ if (error < 0) {
+ printf("socket: could not allocate fd\n");
+ return error;
+ }
+
+ sock = kalloc(sizeof(*sock));
+ if (sock == NULL) {
+ fd_close(fdp->fdno);
+ return -EINVAL;
+ }
+
+ /* Format the name */
+ snprintf(
+ namebuf,
+ sizeof(namebuf),
+ "sock.%d",
+ next_sockid++
+ );
+
+ /* Allocate a persistent vnode */
+ error = vfs_valloc(&vp, VTYPE_SOCK, 0);
+ if (error < 0) {
+ printf("socket: could not allocate vnode\n");
+ fd_close(fdp->fdno);
+ kfree(sock);
+ return error;
+ }
+
+ /* Create the backing file */
+ nd.path = namebuf;
+ error = vop_create(mp->vp, &nd, VTYPE_SOCK);
+ if (error < 0) {
+ printf("socket: failed to create /tmp entry\n");
+ fd_close(fdp->fdno);
+ kfree(sock);
+ return error;
+ }
+
+ /* Mark the socket as inactive */
+ memset(sock, 0, sizeof(*sock));
+ sock->backlog = -1;
+
+ fdp->vp = vp;
+ vp->data = sock;
+ printf("socket: socket created @ /tmp/%s\n", namebuf);
+ return fdp->fdno;
+}
+
+/*
+ * Get a socket descriptor from a fd
+ *
+ * @fd: File descriptor to look up
+ * @sock_res: Result pointer is written here
+ *
+ * Returns zero on success, otherwise a less
+ * than zero value on failure
+ */
+static int
+get_sock(int fd, struct ksocket **sock_res)
+{
+ struct filedesc *fdp;
+ struct proc *self = proc_self();
+ struct vnode *vp;
+
+ if (fd < 0) {
+ return -EBADF;
+ }
+
+ if (sock_res == NULL) {
+ return -1;
+ }
+
+ if (self == NULL) {
+ return -EINVAL;
+ }
+
+ /* Get the file descriptor */
+ fdp = fd_get(
+ self,
+ fd
+ );
+
+ if (fdp == NULL) {
+ return -EBADF;
+ }
+
+ /* We need the vnode */
+ if ((vp = fdp->vp) == NULL) {
+ return -EIO;
+ }
+
+ *sock_res = vp->data;
+ return 0;
+}
+
+/*
+ * Any backlog value > 0 marks the socket
+ * as accepting connections
+ */
+int
+listen(int socket, int backlog)
+{
+ struct ksocket *ksock = NULL;
+ int error;
+
+ if (socket < 0) {
+ return -EBADF;
+ }
+
+ if (backlog < 0) {
+ backlog = 0;
+ }
+
+ error = get_sock(socket, &ksock);
+ if (error < 0) {
+ printf("listen: failed to get socket descriptor\n");
+ return error;
+ }
+
+ /* Set the backlog */
+ ksock->backlog = backlog;
+ return 0;
+}
+
+/*
+ * Handles the AF_UNIX domain
+ */
+static int
+af_unix(int type, int protocol)
+{
+ struct filedesc *desc;
+
+ return get_sock_fd(&desc);
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ if (domain < 0 || type < 0) {
+ return -EINVAL;
+ }
+
+ switch (domain) {
+ case AF_UNIX:
+ return af_unix(type, protocol);
+ }
+
+ return -1;
+}
+
+/*
+ * ARG0: Domain
+ * ARG1: Type
+ * ARG2: Protocol
+ */
+scret_t
+sys_socket(struct syscall_args *scargs)
+{
+ int domain = SCARG(scargs, int, 0);
+ int type = SCARG(scargs, int, 1);
+ int protocol = SCARG(scargs, int, 2);
+
+ return socket(domain, type, protocol);
+}
+
+/*
+ * ARG0: Socket fd
+ * @backlog: Maximum connections
+ */
+scret_t
+sys_listen(struct syscall_args *scargs)
+{
+ int sockfd = SCARG(scargs, int, 0);
+ int backlog = SCARG(scargs, int, 1);
+
+ return listen(sockfd, backlog);
+}
diff --git a/src/sys/os/vfs_namei.c b/src/sys/os/vfs_namei.c
index d417db8..7814181 100644
--- a/src/sys/os/vfs_namei.c
+++ b/src/sys/os/vfs_namei.c
@@ -149,6 +149,7 @@ namei(struct nameidata *ndp)
nd_create.path = namebuf;
create.ndp = &nd_create;
+ create.vtype = VTYPE_FILE;
error = vops->create(&create);
if (error < 0)
return error;
diff --git a/src/sys/os/vfs_subr.c b/src/sys/os/vfs_subr.c
index adfcffb..0e8c605 100644
--- a/src/sys/os/vfs_subr.c
+++ b/src/sys/os/vfs_subr.c
@@ -226,7 +226,7 @@ vop_reclaim(struct vnode *vp, int flags)
}
int
-vop_create(struct vnode *vp, struct nameidata *ndp)
+vop_create(struct vnode *vp, struct nameidata *ndp, vtype_t type)
{
struct vop *vops;
struct vop_create_args args;
@@ -244,5 +244,26 @@ vop_create(struct vnode *vp, struct nameidata *ndp)
}
args.ndp = ndp;
+ args.vtype = type;
return vops->create(&args);
}
+
+int
+vop_getattr(struct vnode *vp, struct vattr *res)
+{
+ struct vop *vops;
+
+ if (vp == NULL || res == NULL) {
+ return -EINVAL;
+ }
+
+ if ((vops = vp->vops) == NULL) {
+ return -EIO;
+ }
+
+ if (vops->getattr == NULL) {
+ return -EIO;
+ }
+
+ return vops->getattr(vp, res);
+}