summaryrefslogtreecommitdiffstats
path: root/sys/syscall_pcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/syscall_pcb.c')
-rw-r--r--sys/syscall_pcb.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/sys/syscall_pcb.c b/sys/syscall_pcb.c
index a37e4bb..4fe557b 100644
--- a/sys/syscall_pcb.c
+++ b/sys/syscall_pcb.c
@@ -1,4 +1,6 @@
#include "api/error.h"
+#include "api/obj.h"
+#include "api/syscall.h"
#include "jove.h"
#include "lib/printf.h"
#include "proc/process.h"
@@ -19,6 +21,66 @@ s_syscall_pcb_yield(jove_owned_obj_t *pcb_obj,
}
int
+s_syscall_pcb_send(jove_owned_obj_t *pcb_obj,
+ lockstack_t *lockstack,
+ jove_owned_obj_t *objdir_obj,
+ size_t bytes_left,
+ void *payload_data)
+{
+ size_t bytes_needed = sizeof(struct syscall_pcb_send);
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
+
+ struct syscall_pcb_send *payload = payload_data;
+ bytes_needed += payload->send_path_length;
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for subject path");
+
+ jove_perm_obj_t subject_objdir = link_try_traverse_objdir(
+ objdir_obj, lockstack, payload->send_path_length - 1, payload->send_path);
+ if(errno) {
+ klogf("Unable to get subject %P objdir : %s\n",
+ payload->send_path, payload->send_path_length, errstr(errno));
+ return -errno;
+ }
+ CHECK_OBJPERM(subject_objdir, SYSCALL_PERM_PCB_SEND_OBJDIR, "Subject objdir does not permit send");
+
+ jove_owned_obj_t *subject = objdir_trygetlocal(subject_objdir.obj,
+ payload->send_path[payload->send_path_length-1]);
+ if(subject == 0) {
+ klogf("Unable to get subject %P object : %s\n",
+ payload->send_path, payload->send_path_length, errstr(errno));
+ return -errno;
+ }
+
+ return pcb_send(obj_deref(pcb_obj), payload->send_target, subject, payload->send_timeout);
+}
+
+int
+s_syscall_pcb_recv(jove_owned_obj_t *pcb_obj,
+ lockstack_t *lockstack,
+ jove_owned_obj_t *objdir_obj,
+ size_t bytes_left,
+ void *payload_data)
+{
+ size_t bytes_needed = sizeof(struct syscall_pcb_recv);
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");
+
+ struct syscall_pcb_recv *payload = payload_data;
+ bytes_needed += payload->recv_path_length * sizeof(objpath_part_t);
+ CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for destination path");
+
+ jove_perm_obj_t destination = link_try_traverse_objdir(
+ objdir_obj, lockstack, payload->recv_path_length, payload->recv_path);
+ if(errno) {
+ klogf("Unable to get destination %P : %s\n",
+ payload->recv_path, payload->recv_path_length, errstr(errno));
+ return -errno;
+ }
+ CHECK_OBJPERM(destination, SYSCALL_PERM_PCB_RECV_DST, "Destination object does not permit recv.");
+
+ return pcb_recv(obj_deref(pcb_obj), payload->recv_target, destination.obj, payload->recv_timeout);
+}
+
+int
_syscall_handle_pcb(syscall_context_t *ctx)
{
switch(ctx->header->callid) {
@@ -27,6 +89,18 @@ _syscall_handle_pcb(syscall_context_t *ctx)
return s_syscall_pcb_yield(ctx->target.obj, ctx->bytes_left, ctx->payload);
return -EPERM;
+ case SYSCALL_PCB_SEND:
+ if(ctx->target.permissions & SYSCALL_PERM_PCB_SEND)
+ return s_syscall_pcb_send(
+ ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload);
+ return -EPERM;
+
+ case SYSCALL_PCB_RECV:
+ if(ctx->target.permissions & SYSCALL_PERM_PCB_RECV)
+ return s_syscall_pcb_recv(
+ ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload);
+ return -EPERM;
+
default:
return -EBADCALL;
}