diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 36 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/mp.c | 2 | ||||
-rw-r--r-- | sys/include/sys/proc.h | 2 | ||||
-rw-r--r-- | sys/include/sys/sched.h | 2 | ||||
-rw-r--r-- | sys/include/sys/socket.h | 17 | ||||
-rw-r--r-- | sys/include/sys/syscall.h | 1 | ||||
-rw-r--r-- | sys/include/sys/sysctl.h | 17 | ||||
-rw-r--r-- | sys/include/sys/systm.h | 1 | ||||
-rw-r--r-- | sys/kern/init_main.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_cpu.c | 61 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 33 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 86 | ||||
-rw-r--r-- | sys/kern/kern_socket.c | 211 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 77 | ||||
-rw-r--r-- | sys/kern/vfs_vcache.c | 2 |
17 files changed, 519 insertions, 34 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 19dcf44..9ff96e1 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -47,6 +47,13 @@ #include <dev/cons/cons.h> #include <string.h> +/* + * This defines the max number of frames + * we will pass while walking the callstack + * in md_backtrace() + */ +#define MAX_FRAME_DEPTH 16 + #define pr_trace(fmt, ...) kprintf("cpu: " fmt, ##__VA_ARGS__) #define pr_error(...) pr_trace(__VA_ARGS__) #define pr_trace_bsp(...) \ @@ -259,24 +266,43 @@ void md_backtrace(void) { uintptr_t *rbp; - uintptr_t rip; + uintptr_t rip, tmp; off_t off; const char *name; char line[256]; + uint8_t n = 0; __ASMV("mov %%rbp, %0" : "=r" (rbp) :: "memory"); while (1) { + if (n >= MAX_FRAME_DEPTH) { + break; + } + rip = rbp[1]; rbp = (uintptr_t *)rbp[0]; - name = backtrace_addr_to_name(rip, &off); - if (rbp == NULL) + /* + * RBP should be aligned on an 8-byte + * boundary... Don't trust this state + * anymore if it is not. + */ + tmp = (uintptr_t)rbp; + if ((tmp & (8 - 1)) != 0) { + break; + } + + /* + * This is not a valid value, get out + * of this loop!! + */ + if (rbp == NULL || rip == 0) { break; - if (name == NULL) - name = "???"; + } + name = backtrace_addr_to_name(rip, &off); snprintf(line, sizeof(line), "%p @ <%s+0x%x>\n", rip, name, off); cons_putstr(&g_root_scr, line, strlen(line)); + ++n; } } diff --git a/sys/arch/amd64/amd64/mp.c b/sys/arch/amd64/amd64/mp.c index 20f550f..43830ba 100644 --- a/sys/arch/amd64/amd64/mp.c +++ b/sys/arch/amd64/amd64/mp.c @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/limine.h> #include <sys/limits.h> +#include <sys/systm.h> #include <sys/syslog.h> #include <sys/proc.h> #include <sys/spinlock.h> @@ -149,4 +150,5 @@ mp_bootstrap_aps(struct cpu_info *ci) /* Wait for all cores to be ready */ while ((ncpu_up - 1) < cpu_init_counter); + cpu_report_count(ncpu_up); } diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 89fe638..809ee23 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -122,8 +122,10 @@ struct proc { #define PROC_PINNED BIT(7) /* Pinned to CPU */ struct proc *this_td(void); +struct proc *td_copy(struct proc *td); struct proc *get_child(struct proc *cur, pid_t pid); +int proc_init(struct proc *td, struct proc *parent); void proc_pin(struct proc *td, affinity_t cpu); void proc_unpin(struct proc *td); diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index 7a859b2..19ceb7e 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -33,6 +33,7 @@ #include <sys/proc.h> #include <sys/cdefs.h> #include <sys/limits.h> +#include <sys/time.h> /* * Scheduler CPU information @@ -66,6 +67,7 @@ void sched_stat(struct sched_stat *statp); void sched_init(void); void sched_yield(void); +void sched_suspend(struct proc *td, const struct timeval *tv); void sched_detach(struct proc *td); __dead void sched_enter(void); diff --git a/sys/include/sys/socket.h b/sys/include/sys/socket.h index c82ae4e..1a33108 100644 --- a/sys/include/sys/socket.h +++ b/sys/include/sys/socket.h @@ -69,6 +69,10 @@ typedef uint32_t socklen_t; /* Socket types */ #define SOCK_STREAM 1 +/* Socket option names */ +#define SO_RCVTIMEO 0 /* Max time recv(2) waits */ +#define _SO_MAX 1 /* Max socket options */ + struct sockaddr_un { sa_family_t sun_family; char sun_path[108]; @@ -149,12 +153,22 @@ struct cmsg_list { uint8_t is_init : 1; }; +/* + * Socket option that may be applied to + * sockets on the system. + */ +struct sockopt { + socklen_t len; + char data[]; +}; + struct ksocket { int sockfd; union { struct sockaddr sockaddr; struct sockaddr_un un; }; + struct sockopt *opt[_SO_MAX]; struct proc *owner; struct cmsg_list cmsg_list; struct sockbuf buf; @@ -170,10 +184,13 @@ scret_t sys_send(struct syscall_args *scargs); scret_t sys_recvmsg(struct syscall_args *scargs); scret_t sys_sendmsg(struct syscall_args *scargs); +scret_t sys_setsockopt(struct syscall_args *scargs); #endif /* _KERNEL */ int socket(int domain, int type, int protocol); int bind(int sockfd, const struct sockaddr *addr, socklen_t len); + +int setsockopt(int sockfd, int level, int name, const void *v, socklen_t len); int connect(int sockfd, const struct sockaddr *addr, socklen_t len); ssize_t send(int sockfd, const void *buf, size_t size, int flags); diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index 9798d80..f53db8f 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -66,6 +66,7 @@ #define SYS_sendmsg 25 #define SYS_recvmsg 26 #define SYS_connect 27 +#define SYS_setsockopt 28 #if defined(_KERNEL) /* Syscall return value and arg type */ diff --git a/sys/include/sys/sysctl.h b/sys/include/sys/sysctl.h index 078135b..3b8d3c7 100644 --- a/sys/include/sys/sysctl.h +++ b/sys/include/sys/sysctl.h @@ -30,16 +30,30 @@ #ifndef _SYS_SYSCTL_H_ #define _SYS_SYSCTL_H_ -#include <sys/types.h> #if defined(_KERNEL) +#include <sys/types.h> #include <sys/syscall.h> +#else +#include <stdint.h> +#include <stddef.h> #endif #include <sys/param.h> +/* + * List of 'kern.* ' identifiers + */ #define KERN_OSTYPE 0 #define KERN_OSRELEASE 1 #define KERN_VERSION 2 #define KERN_VCACHE_TYPE 3 +#define KERN_HOSTNAME 4 + +/* + * List of 'hw.* ' identifiers + */ +#define HW_PAGESIZE 5 +#define HW_NCPU 6 +#define HW_MACHINE 7 /* * Option types (i.e., int, string, etc) for @@ -61,6 +75,7 @@ struct sysctl_entry { }; scret_t sys_sysctl(struct syscall_args *scargs); +int sysctl_clearstr(int name); #endif /* _KERNEL */ /* diff --git a/sys/include/sys/systm.h b/sys/include/sys/systm.h index 42e1723..2f69175 100644 --- a/sys/include/sys/systm.h +++ b/sys/include/sys/systm.h @@ -39,6 +39,7 @@ int copyin(const void *uaddr, void *kaddr, size_t len); int copyout(const void *kaddr, void *uaddr, size_t len); int copyinstr(const void *uaddr, char *kaddr, size_t len); +int cpu_report_count(uint32_t count); __always_inline static inline void __sigraise(int signo) diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 5e351a8..541355a 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -35,6 +35,7 @@ #include <sys/exec.h> #include <sys/driver.h> #include <sys/panic.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <dev/acpi/uacpi.h> #include <dev/cons/cons.h> @@ -113,6 +114,7 @@ main(void) sched_init(); memset(&g_proc0, 0, sizeof(g_proc0)); + sysctl_clearstr(KERN_HOSTNAME); /* Startup pid 1 */ spawn(&g_proc0, start_init, NULL, 0, &g_init); diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c new file mode 100644 index 0000000..69d44c4 --- /dev/null +++ b/sys/kern/kern_cpu.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * 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 Hyra 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/systm.h> +#include <sys/sysctl.h> +#include <sys/types.h> + +/* + * Report the number of processors that are online + * in the machine. + * + * @count: Number of processors active + * + * Returns zero on success, otherwise a less + * than zero value is returned. + */ +int +cpu_report_count(uint32_t count) +{ + struct sysctl_args args; + int error, name = HW_NCPU; + + args.name = &name; + args.nlen = 1; + args.oldlenp = 0; + args.oldp = NULL; + args.newp = &count; + args.newlen = sizeof(count); + + if ((error = sysctl(&args)) != 0) { + return error; + } + + return 0; +} diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index c8f8357..83845f6 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -241,7 +241,7 @@ fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write) /* Increment the offset per read */ filedes->offset += n; - retval = count; + retval = n; done: if (kbuf != NULL) { dynfree(kbuf); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c new file mode 100644 index 0000000..2755ea0 --- /dev/null +++ b/sys/kern/kern_fork.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * 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 Hyra 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/types.h> +#include <sys/proc.h> + + diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 23a1ebb..9c5e215 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -315,6 +315,92 @@ proc_unpin(struct proc *td) td->flags &= ~PROC_PINNED; } +/* + * Suspend a process for a specified amount + * of time. This calling process will yield for + * the amount of time specified in 'tv' + * + * @td: Process to suspend (NULL for current) + * @tv: Time value to use + * + * XXX: 'tv' being NULL is equivalent to calling + * sched_detach() + */ +void +sched_suspend(struct proc *td, const struct timeval *tv) +{ + struct timer tmr; + const time_t USEC_PER_SEC = 1000000; + ssize_t usec; + time_t usec_cur, usec_tmp; + bool have_timer = true; + tmrr_status_t tmr_status; + + if (td == NULL) + td = this_td(); + if (__unlikely(td == NULL)) + return; + + if (tv == NULL) { + sched_detach(td); + return; + } + + /* + * Now, we need a generic timer so that we can compute + * how much time has elapsed since this process has + * requested to be suspended. However, we cannot assume + * that it would be present. If the lookup fails, all we + * can do is try to estimate how much time went by which + * works fine too, just not as accurate. + */ + tmr_status = req_timer(TIMER_GP, &tmr); + if (tmr_status != TMRR_SUCCESS) { + have_timer = false; + } + + /* We need microsecond precision */ + if (tmr.get_time_sec == NULL) { + have_timer = false; + } + + /* + * Compute the max time in microseconds that + * we will wait. We are using both tv->tv_sec + * and tv->tv_usec + */ + usec = tv->tv_usec; + usec += tv->tv_sec * USEC_PER_SEC; + usec_cur = (have_timer) ? tmr.get_time_usec() : 0; + + for (;;) { + sched_yield(); + + /* + * If we have a timer in our paws, compute how much + * time went by. Otherwise we estimate by subtracting + * the scheduler quantum. + * + * XXX: The timing here works decently as intended. However, + * it would be nice to smoothen out any jitter. Such can + * probably be done by subtracting 'usec' by the exponential + * moving average of 'usec_tmp' rather than the raw original + * value. + */ + if (have_timer) { + usec_tmp = (tmr.get_time_usec() - usec_cur); + } else { + usec_tmp = DEFAULT_TIMESLICE_USEC; + } + + /* We are done here! */ + usec -= usec_tmp; + if (usec <= 0) { + break; + } + } +} + void sched_init(void) { diff --git a/sys/kern/kern_socket.c b/sys/kern/kern_socket.c index 1717f5a..d0fbe19 100644 --- a/sys/kern/kern_socket.c +++ b/sys/kern/kern_socket.c @@ -31,6 +31,7 @@ #include <sys/sio.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/time.h> #include <sys/namei.h> #include <sys/sched.h> #include <sys/errno.h> @@ -47,6 +48,17 @@ static struct vops socket_vops; /* + * This table maps socket option names to + * lengths of their underlying structure. + * + * This is used for bounds/length checking within + * setsockopt() + */ +static size_t sockopt_lentab[_SO_MAX] = { + [ SO_RCVTIMEO ] = sizeof(struct timeval) +}; + +/* * Get a kernel socket structure from a * file descriptor. * @@ -101,6 +113,7 @@ static int socket_reclaim(struct vnode *vp) { struct ksocket *ksock; + struct sockopt *opt; /* Is this even a socket? */ if (vp->type != VSOCK) { @@ -112,6 +125,15 @@ socket_reclaim(struct vnode *vp) return -EIO; } + /* Free up any used options */ + for (int i = 0; i < _SO_MAX; ++i) { + opt = ksock->opt[i]; + if (opt != NULL) { + dynfree(opt); + ksock->opt[i] = NULL; + } + } + fd_close(ksock->sockfd); mutex_free(ksock->mtx); dynfree(ksock); @@ -185,6 +207,46 @@ connect_domain(int sockfd, struct ksocket *ksock, struct sockaddr_un *un) } /* + * Wait until data is received for the + * recv() function. + * + * @sockfd: Socket we are waiting on + * + * Returns zero on success, otherwise a less + * than zero value is returned. + */ +static int +socket_rx_wait(int sockfd) +{ + struct ksocket *ksock; + struct sockopt *opt; + struct timeval tv; + int error; + + if (ksock == NULL) { + return -EINVAL; + } + + error = get_ksock(sockfd, &ksock); + if (error < 0) { + return error; + } + + /* + * If the socket does not have this option set, + * we will assume that there is no timeout value. + */ + opt = ksock->opt[SO_RCVTIMEO]; + if (opt == NULL) { + return 0; + } + + memcpy(&tv, opt->data, opt->len); + sched_suspend(NULL, &tv); + return 0; +} + +/* * Send data to socket - POSIX send(2) core * * @sockfd: File descriptor that backs this socket @@ -254,7 +316,7 @@ send(int sockfd, const void *buf, size_t size, int flags) * @size: Size of the buffer * @flags: Optional flags * - * Returns zero on success, otherwise a less + * Returns length on success, otherwise a less * than zero errno. */ ssize_t @@ -264,6 +326,7 @@ recv(int sockfd, void *buf, size_t len, int flags) struct sockbuf *sbuf; struct netbuf *netbuf; size_t head; + ssize_t retval = len; int error; /* Length cannot be zero */ @@ -283,7 +346,8 @@ recv(int sockfd, void *buf, size_t len, int flags) if (netbuf->len == 0) { sbuf->head = 0; sbuf->tail = 0; - return -EAGAIN; + retval = -EAGAIN; + goto done; } if (len > netbuf->len) { @@ -292,10 +356,10 @@ recv(int sockfd, void *buf, size_t len, int flags) head = sbuf->head; memcpy(buf, &netbuf->data[head], len); - sbuf->head = (sbuf->head + len) % NETBUF_LEN; +done: mutex_release(ksock->mtx); - return len; + return retval; } /* @@ -322,6 +386,7 @@ socket(int domain, int type, int protocol) goto fail; } + memset(ksock, 0, sizeof(*ksock)); sbuf = &ksock->buf; sbuf->head = 0; sbuf->tail = 0; @@ -394,6 +459,68 @@ bind(int sockfd, const struct sockaddr *addr, socklen_t len) } /* + * Set socket options - POSIX setsockopt(3) core + * + * @sockfd: File descriptor of socket + * @level: Protocol level + * @v: Options value + * @len: Length of data pointed to by 'v' + */ +int +setsockopt(int sockfd, int level, int name, const void *v, socklen_t len) +{ + struct ksocket *ksock; + struct sockopt *opt; + size_t exp_len; + int error; + + /* Must have a valid fd */ + if (sockfd < 0) { + return -EBADF; + } + + /* Ensure value and length are valid */ + if (v == NULL || len == 0) { + return -EINVAL; + } + + /* Verify the name */ + if (name >= _SO_MAX) { + return -EINVAL; + } + + /* Grab a new socket */ + if ((error = get_ksock(sockfd, &ksock)) < 0) { + return error; + } + + /* Clamp the input length as needed */ + exp_len = sockopt_lentab[name]; + if (len > exp_len) { + len = exp_len; + } + + /* + * Here we will grab the socket options. If it is + * NULL, we'll need to allocate one. + */ + if ((opt = ksock->opt[name]) == NULL) { + opt = dynalloc(sizeof(*opt) + len); + + if (opt == NULL) { + return -ENOMEM; + } + + opt->len = len; + ksock->opt[name] = opt; + } + + memcpy(opt->data, v, len); + opt->len = len; + return 0; +} + +/* * Connect to a socket * * @sockfd: File descriptor to connect @@ -614,10 +741,29 @@ sys_recv(struct syscall_args *scargs) return -ENOBUFS; } - do { + for (;;) { error = recv(sockfd, buf, len, flags); - sched_yield(); - } while (error == -EAGAIN); + if (error <= 0 && error != -EAGAIN) { + break; + } + + /* + * Wait for data to be ready on the socket. + * If a less than zero value is returned, don't + * handle timeouts. + */ + error = socket_rx_wait(sockfd); + if (error < 0) { + continue; + } + + /* Try one more time, obey timeout */ + error = recv(sockfd, buf, len, flags); + if (error == -EAGAIN) { + return error; + } + break; + } if (error < 0) { pr_error("sys_recv: recv() fail (fd=%d)\n", sockfd); @@ -776,7 +922,7 @@ sys_sendmsg(struct syscall_args *scargs) } /* - * connnect(3) syscall + * connect(3) syscall * * arg0: sockfd * arg1: address @@ -807,6 +953,55 @@ sys_connect(struct syscall_args *scargs) return connect(sockfd, sockaddr, len); } +/* + * POSIX setsockopt(3) syscall + * + * arg0: sockfd + * arg1: level + * arg2: name + * arg3: data + * arg4: len + */ +scret_t +sys_setsockopt(struct syscall_args *scargs) +{ + int sockfd = scargs->arg0; + int level = scargs->arg1; + int name = scargs->arg2; + void *u_data = (void *)scargs->arg3; + socklen_t len = scargs->arg4; + void *data; + size_t exp_len; + int retval; + + /* Verify that the name is correct */ + if (name >= _SO_MAX) { + return -EINVAL; + } + + /* Clamp length as needed */ + exp_len = sockopt_lentab[name]; + if (len > exp_len) { + len = exp_len; + } + + data = dynalloc(len); + if (data == NULL) { + return -ENOMEM; + } + + /* Grab data from userland */ + retval = copyin(u_data, data, len); + if (retval < 0) { + dynfree(data); + return retval; + } + + retval = setsockopt(sockfd, level, name, data, len); + dynfree(data); + return retval; +} + static struct vops socket_vops = { .read = NULL, .write = NULL, diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 576b7aa..ba70b12 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -68,6 +68,7 @@ scret_t(*g_sctab[])(struct syscall_args *) = { sys_sendmsg, /* SYS_sendmsg */ sys_recvmsg, /* SYS_recvmsg */ sys_connect, /* SYS_connect */ + sys_setsockopt, /* SYS_setsockopt */ }; const size_t MAX_SYSCALLS = NELEM(g_sctab); diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 7679aa1..a4c16bb 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -33,12 +33,15 @@ #include <sys/errno.h> #include <sys/systm.h> #include <vm/dynalloc.h> +#include <vm/vm.h> #include <string.h> #define HYRA_RELEASE "Hyra/" HYRA_ARCH " " \ HYRA_VERSION " " \ HYRA_BUILDDATE +static uint32_t pagesize = DEFAULT_PAGESIZE; +static char machine[] = HYRA_ARCH; static char hyra[] = "Hyra"; static char hyra_version[] = HYRA_VERSION; static char osrelease[] = HYRA_RELEASE; @@ -49,10 +52,17 @@ static char osrelease[] = HYRA_RELEASE; * allocated through dynalloc(9). */ static struct sysctl_entry common_optab[] = { + /* 'kern.*' */ [KERN_OSTYPE] = { KERN_OSTYPE, SYSCTL_OPTYPE_STR_RO, hyra }, [KERN_OSRELEASE] = { KERN_OSRELEASE, SYSCTL_OPTYPE_STR_RO, &osrelease }, [KERN_VERSION] = { KERN_VERSION, SYSCTL_OPTYPE_STR_RO, &hyra_version }, - [KERN_VCACHE_TYPE] = { KERN_VCACHE_TYPE, SYSCTL_OPTYPE_STR, NULL } + [KERN_VCACHE_TYPE] = { KERN_VCACHE_TYPE, SYSCTL_OPTYPE_STR, NULL }, + [KERN_HOSTNAME] = { KERN_HOSTNAME, SYSCTL_OPTYPE_STR, NULL }, + + /* 'hw.*' */ + [HW_PAGESIZE] = { HW_PAGESIZE, SYSCTL_OPTYPE_INT_RO, &pagesize }, + [HW_NCPU] = { HW_NCPU, SYSCTL_OPTYPE_INT, NULL }, + [HW_MACHINE] = {HW_MACHINE, SYSCTL_OPTYPE_STR_RO, &machine } }; static int @@ -91,19 +101,18 @@ static int do_sysctl(struct sysctl_args *args) { struct sysctl_args new_args; - size_t name_len, oldlenp; + size_t name_len = 1, oldlenp = 0; int *name = NULL; void *oldp = NULL, *newp = NULL; - int retval = 0; - - if (args->oldlenp == NULL) { - return -EINVAL; - } - - name_len = args->nlen; - retval = copyin(args->oldlenp, &oldlenp, sizeof(oldlenp)); - if (retval != 0) { - goto done; + int retval = 0, have_oldlen = 0; + + if (args->oldlenp != NULL) { + have_oldlen = 1; + name_len = args->nlen; + retval = copyin(args->oldlenp, &oldlenp, sizeof(oldlenp)); + if (retval != 0) { + goto done; + } } /* Copy in newp if it is set */ @@ -124,25 +133,30 @@ do_sysctl(struct sysctl_args *args) return retval; } - oldp = dynalloc(oldlenp); - retval = copyin(args->oldp, oldp, oldlenp); - if (retval != 0) { - return retval; + if (oldlenp != 0) { + oldp = dynalloc(oldlenp); + retval = copyin(args->oldp, oldp, oldlenp); + if (retval != 0) { + return retval; + } } /* Prepare the arguments for the sysctl call */ new_args.name = name; new_args.nlen = name_len; new_args.oldp = oldp; - new_args.oldlenp = &oldlenp; + new_args.oldlenp = (have_oldlen) ? &oldlenp : NULL; new_args.newp = newp; + new_args.newlen = args->newlen; retval = sysctl(&new_args); if (retval != 0) { goto done; } - copyout(oldp, args->oldp, oldlenp); + if (oldlenp != 0) { + copyout(oldp, args->oldp, oldlenp); + } done: if (name != NULL) dynfree(name); @@ -154,6 +168,33 @@ done: return retval; } +/* + * Clear a writable sysctl string variable to the + * value of "(undef)" + * + * @name: Name to clear + */ +int +sysctl_clearstr(int name) +{ + struct sysctl_args args; + char val[] = "(undef)"; + int error; + + args.name = &name; + args.nlen = 1; + args.oldlenp = 0; + args.oldp = NULL; + args.newp = val; + args.newlen = sizeof(val); + + if ((error = sysctl(&args)) != 0) { + return error; + } + + return 0; +} + int sysctl(struct sysctl_args *args) { diff --git a/sys/kern/vfs_vcache.c b/sys/kern/vfs_vcache.c index 25e244c..6c08caf 100644 --- a/sys/kern/vfs_vcache.c +++ b/sys/kern/vfs_vcache.c @@ -161,7 +161,7 @@ vfs_vcache_migrate(int newtype) args.oldp = NULL; args.oldlenp = NULL; args.newp = sysctl_val; - args.newlen = strlen(sysctl_val); + args.newlen = strlen(sysctl_val) + 1; if ((retval = sysctl(&args)) != 0) { return retval; |