summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/fs/tmpfs.c18
-rw-r--r--src/sys/include/compat/unix/syscall.h5
-rw-r--r--src/sys/include/os/filedesc.h24
-rw-r--r--src/sys/include/os/vnode.h7
-rw-r--r--src/sys/include/sys/socket.h83
-rw-r--r--src/sys/include/sys/syscall.h2
-rw-r--r--src/sys/io/cons/cons.c20
-rw-r--r--src/sys/os/os_filedes.c22
-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.c3
11 files changed, 417 insertions, 24 deletions
diff --git a/src/sys/fs/tmpfs.c b/src/sys/fs/tmpfs.c
index af1537f..3048fb4 100644
--- a/src/sys/fs/tmpfs.c
+++ b/src/sys/fs/tmpfs.c
@@ -49,6 +49,7 @@ struct tmpfs_node {
size_t len;
size_t real_len;
int ref;
+ vtype_t vtype; /* vnode vtype mapping */
TAILQ_ENTRY(tmpfs_node) link;
};
@@ -62,13 +63,14 @@ static struct vop tmpfs_vops;
* Create a new tmpfs node
*
* @name: Name of node to create
+ * @type: Type of vnode file should be associated with
* @np_res: Result pointer is written here
*
* Returns zero on success, otherwise a less than
* zero value on failure
*/
static int
-tmpfs_new(const char *name, struct tmpfs_node **np_res)
+tmpfs_new(const char *name, vtype_t type, struct tmpfs_node **np_res)
{
struct tmpfs_node *np;
size_t name_len;
@@ -97,6 +99,7 @@ tmpfs_new(const char *name, struct tmpfs_node **np_res)
np->real_len = 0;
np->len = TMPFS_INIT_SIZE;
np->ref = 1;
+ np->vtype = type;
memset(np->data, 0, TMPFS_INIT_SIZE);
memcpy(np->name, name, name_len);
@@ -162,7 +165,7 @@ tmpfs_lookup(struct vop_lookup_args *args)
return error;
}
- error = vfs_valloc(&vp, VTYPE_FILE, 0);
+ error = vfs_valloc(&vp, np->vtype, 0);
if (error < 0) {
return error;
}
@@ -197,7 +200,16 @@ tmpfs_create(struct vop_create_args *args)
return -EEXIST;
}
- return tmpfs_new(ndp->path, NULL);
+ /* Only accept the types we support */
+ switch (args->vtype) {
+ case VTYPE_FILE:
+ case VTYPE_SOCK:
+ break;
+ default:
+ return -ENOTSUP;
+ }
+
+ return tmpfs_new(ndp->path, args->vtype, NULL);
}
/*
diff --git a/src/sys/include/compat/unix/syscall.h b/src/sys/include/compat/unix/syscall.h
index 42dc4c0..38419af 100644
--- a/src/sys/include/compat/unix/syscall.h
+++ b/src/sys/include/compat/unix/syscall.h
@@ -31,6 +31,7 @@
#define _UNIX_SYSCALL_H_ 1
#include <sys/proc.h>
+#include <sys/socket.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/syscall.h>
@@ -95,7 +96,9 @@ scret_t(*g_unix_sctab[])(struct syscall_args *) = {
[SYS_dmsio] = sys_dmsio,
[SYS_read] = sys_read,
[SYS_close] = sys_close,
- [SYS_lseek] = sys_lseek
+ [SYS_lseek] = sys_lseek,
+ [SYS_socket] = sys_socket,
+ [SYS_listen] = sys_listen
};
#endif /* !_NEED_UNIX_SCTAB */
diff --git a/src/sys/include/os/filedesc.h b/src/sys/include/os/filedesc.h
index b773de9..95400ed 100644
--- a/src/sys/include/os/filedesc.h
+++ b/src/sys/include/os/filedesc.h
@@ -52,6 +52,18 @@ struct filedesc {
};
/*
+ * 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
+ */
+int fd_alloc(struct proc *procp, struct filedesc **fd_res);
+
+/*
* Duplicate a file descriptor
*
* @procp: Process to duplicate from
@@ -63,6 +75,18 @@ struct filedesc {
struct filedesc *fd_dup(struct proc *procp, int fd);
/*
+ * 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
+ */
+struct filedesc *fd_get(struct proc *procp, int fd);
+
+/*
* Initialize a process file descriptor table
* and set up standard streams
*
diff --git a/src/sys/include/os/vnode.h b/src/sys/include/os/vnode.h
index 77cadb2..8cdcded 100644
--- a/src/sys/include/os/vnode.h
+++ b/src/sys/include/os/vnode.h
@@ -44,12 +44,14 @@ struct vop;
* @VTYPE_NONE: Vnode is yet to be assigned a type
* @VTYPE_FILE: Vnode references a file
* @VTYPE_DIR: Vnode references a directory
+ * @VTYPE_SOCK: Vnode references a socket
* @__N_VTYPE: Number of valid nodes on the system
*/
typedef enum {
VTYPE_NONE,
VTYPE_FILE,
VTYPE_DIR,
+ VTYPE_SOCK,
__N_VTYPE
} vtype_t;
@@ -88,9 +90,11 @@ struct vop_rw_data {
* filesystem
*
* @ndp: Path component to create
+ * @vtype: Vnode type
*/
struct vop_create_args {
struct nameidata *ndp;
+ vtype_t vtype;
};
/*
@@ -204,11 +208,12 @@ int vop_reclaim(struct vnode *vp, int flags);
*
* @vp: Vnode of parent directory
* @ndp: Namei descriptor of path component
+ * @type: Vnode type to create with
*
* Returns zero on success, otherwise a less than zero
* value on failure.
*/
-int vop_create(struct vnode *vp, struct nameidata *ndp);
+int vop_create(struct vnode *vp, struct nameidata *ndp, vtype_t type);
/*
* Get the attributes of a file
diff --git a/src/sys/include/sys/socket.h b/src/sys/include/sys/socket.h
new file mode 100644
index 0000000..0ca041f
--- /dev/null
+++ b/src/sys/include/sys/socket.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef _SYS_SOCKET_H_
+#define _SYS_SOCKET_H_ 1
+
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+/* Address family defines */
+#define AF_UNIX 0x00 /* Local comms / IPC */
+#define AF_LOCAL AF_UNIX /* AF_UNIX alias */
+
+/* Socket type defines */
+#define SOCK_STREAM 0x00
+#define SOCK_DGRAM 0x01
+
+/*
+ * Get a socket as a file descriptor
+ *
+ * @domain: Socket domain (AF_*)
+ * @type: Socket type SOCK_*
+ *
+ * Returns file descriptor on success, otherwise
+ * a less than zero value on failure
+ */
+int socket(int domain, int type, int protocol);
+
+/*
+ * @socket: Socket to listen on
+ * @backlog: Max connections
+ */
+int listen(int socket, int backlog);
+
+#if defined(_KERNEL)
+
+/*
+ * Kernel representation of a socket
+ *
+ * @backlog: Maximum connections (< 0 means socket not active)
+ */
+struct ksocket {
+ int backlog;
+};
+
+/*
+ * Socket syscall
+ */
+scret_t sys_socket(struct syscall_args *scargs);
+
+/*
+ * Listen syscall
+ */
+scret_t sys_listen(struct syscall_args *scargs);
+
+#endif /* _KERNEL */
+#endif /* !_SYS_SOCKET_H_ */
diff --git a/src/sys/include/sys/syscall.h b/src/sys/include/sys/syscall.h
index c97d5ea..2ca712f 100644
--- a/src/sys/include/sys/syscall.h
+++ b/src/sys/include/sys/syscall.h
@@ -59,6 +59,8 @@
#define SYS_read 0x0E /* read a file descriptor */
#define SYS_close 0x0F /* close a file */
#define SYS_lseek 0x10 /* seek to end of file */
+#define SYS_socket 0x11 /* get a socket fd */
+#define SYS_listen 0x12 /* listen on a socket */
typedef __ssize_t scret_t;
typedef __ssize_t scarg_t;
diff --git a/src/sys/io/cons/cons.c b/src/sys/io/cons/cons.c
index a80644c..65d1f1b 100644
--- a/src/sys/io/cons/cons.c
+++ b/src/sys/io/cons/cons.c
@@ -37,6 +37,8 @@
#include <stdbool.h>
#include <string.h>
+#define TAB_WIDTH (FONT_WIDTH * 4)
+
/* kconf background color config */
#if defined(__CONS_BG)
#define DEFAULT_BG __CONS_BG
@@ -180,6 +182,21 @@ cons_backspace(struct cons_scr *scr)
cons_draw_cursor(scr, false);
}
+static void
+cons_tab(struct cons_scr *scr)
+{
+ cons_draw_cursor(scr, true);
+ scr->text_x += TAB_WIDTH;
+ scr->cursor_x += TAB_WIDTH;
+
+ /* Wrap to next line if needed */
+ if (scr->cursor_x >= scr->max_col) {
+ cons_newline(scr);
+ }
+
+ cons_draw_cursor(scr, false);
+}
+
/*
* Fill a screen with a desired background
* color
@@ -224,6 +241,9 @@ cons_handle_spec(struct cons_scr *scr, int c)
case ASCII_BS:
cons_backspace(scr);
return c;
+ case ASCII_HT:
+ cons_tab(scr);
+ return c;
}
return -1;
diff --git a/src/sys/os/os_filedes.c b/src/sys/os/os_filedes.c
index 36748a6..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;
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 2ae18af..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,6 +244,7 @@ vop_create(struct vnode *vp, struct nameidata *ndp)
}
args.ndp = ndp;
+ args.vtype = type;
return vops->create(&args);
}