summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/include/sys/socket.h3
-rw-r--r--sys/include/sys/syscall.h2
-rw-r--r--sys/kern/kern_socket.c97
-rw-r--r--sys/kern/kern_syscall.c2
4 files changed, 104 insertions, 0 deletions
diff --git a/sys/include/sys/socket.h b/sys/include/sys/socket.h
index de5ab61..5ce1ec6 100644
--- a/sys/include/sys/socket.h
+++ b/sys/include/sys/socket.h
@@ -164,6 +164,9 @@ scret_t sys_bind(struct syscall_args *scargs);
scret_t sys_recv(struct syscall_args *scargs);
scret_t sys_send(struct syscall_args *scargs);
+
+scret_t sys_recvmsg(struct syscall_args *scargs);
+scret_t sys_sendmsg(struct syscall_args *scargs);
#endif /* _KERNEL */
int socket(int domain, int type, int protocol);
diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h
index 51a1016..d79a697 100644
--- a/sys/include/sys/syscall.h
+++ b/sys/include/sys/syscall.h
@@ -63,6 +63,8 @@
#define SYS_bind 22
#define SYS_recv 23
#define SYS_send 24
+#define SYS_sendmsg 25
+#define SYS_recvmsg 26
#if defined(_KERNEL)
/* Syscall return value and arg type */
diff --git a/sys/kern/kern_socket.c b/sys/kern/kern_socket.c
index 99ef3b4..9b98ccc 100644
--- a/sys/kern/kern_socket.c
+++ b/sys/kern/kern_socket.c
@@ -547,6 +547,103 @@ sys_send(struct syscall_args *scargs)
return send(sockfd, buf, len, flags);
}
+/*
+ * recvmsg(3) syscall
+ *
+ * arg0: socket
+ * arg1: msg
+ * arg2: flags
+ */
+scret_t
+sys_recvmsg(struct syscall_args *scargs)
+{
+ struct msghdr *u_msg = (void *)scargs->arg1;
+ void *u_control;
+ size_t controllen;
+ struct iovec msg_iov;
+ struct msghdr msg;
+ ssize_t retval;
+ int socket = scargs->arg0;
+ int flags = scargs->arg2;
+ int error;
+
+ /* Read the message header */
+ error = copyin(u_msg, &msg, sizeof(msg));
+ if (error < 0) {
+ pr_error("sys_recvmsg: bad msg\n");
+ return error;
+ }
+
+ /* Grab the message I/O vector */
+ error = uio_copyin(msg.msg_iov, &msg_iov, msg.msg_iovlen);
+ if (error < 0) {
+ return error;
+ }
+
+ /* Save control fields */
+ u_control = msg.msg_control;
+ controllen = msg.msg_controllen;
+
+ /* Allocate a new control field to copy in */
+ msg.msg_control = dynalloc(controllen);
+ if (msg.msg_control == NULL) {
+ uio_copyin_clean(&msg_iov, msg.msg_iovlen);
+ return -ENOMEM;
+ }
+
+ error = copyin(u_control, msg.msg_control, controllen);
+ if (error < 0) {
+ retval = error;
+ goto done;
+ }
+
+ msg.msg_iov = &msg_iov;
+ retval = recvmsg(socket, &msg, flags);
+done:
+ uio_copyin_clean(&msg_iov, msg.msg_iovlen);
+ dynfree(msg.msg_control);
+ return retval;
+}
+
+/*
+ * sendmsg(3) syscall
+ *
+ * arg0: socket
+ * arg1: msg
+ * arg2: flags
+ */
+scret_t
+sys_sendmsg(struct syscall_args *scargs)
+{
+ struct iovec msg_iov;
+ struct msghdr *u_msg = (void *)scargs->arg1;
+ struct msghdr msg;
+ ssize_t retval;
+ int socket = scargs->arg0;
+ int flags = scargs->arg2;
+ int error;
+
+ /* Read the message header */
+ error = copyin(u_msg, &msg, sizeof(msg));
+ if (error < 0) {
+ pr_error("sys_sendmsg: bad msg\n");
+ return error;
+ }
+
+ /* Grab the message I/O vector */
+ error = uio_copyin(msg.msg_iov, &msg_iov, msg.msg_iovlen);
+ if (error < 0) {
+ return error;
+ }
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &msg_iov;
+ retval = sendmsg(socket, &msg, flags);
+ uio_copyin_clean(&msg_iov, msg.msg_iovlen);
+ 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 dd3de4f..7b037aa 100644
--- a/sys/kern/kern_syscall.c
+++ b/sys/kern/kern_syscall.c
@@ -65,6 +65,8 @@ scret_t(*g_sctab[])(struct syscall_args *) = {
sys_bind, /* SYS_bind */
sys_recv, /* SYS_recv */
sys_send, /* SYS_send */
+ sys_sendmsg, /* SYS_sendmsg */
+ sys_recvmsg, /* SYS_recvmsg */
};
const size_t MAX_SYSCALLS = NELEM(g_sctab);