summaryrefslogtreecommitdiff
path: root/Libraries/LibC
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2020-09-16 11:45:00 -0400
committerAndreas Kling <kling@serenityos.org>2020-09-17 17:23:01 +0200
commitb36a2d66865ae8205b6a7589b8566f27746002f4 (patch)
treef3d72289d78ca87784817cdeaf3552bd8ad05620 /Libraries/LibC
parent19f2203b53d3f895b4335bb1e46f703168288d4f (diff)
downloadserenity-b36a2d66865ae8205b6a7589b8566f27746002f4.zip
Kernel+LibC+UserspaceEmulator: Mostly add recvmsg(), sendmsg()
The implementation only supports a single iovec for now. Some might say having more than one iovec is the main point of recvmsg() and sendmsg(), but I'm interested in the control message bits.
Diffstat (limited to 'Libraries/LibC')
-rw-r--r--Libraries/LibC/sys/socket.cpp37
-rw-r--r--Libraries/LibC/sys/socket.h13
2 files changed, 44 insertions, 6 deletions
diff --git a/Libraries/LibC/sys/socket.cpp b/Libraries/LibC/sys/socket.cpp
index f6584bcb85..55c754b32e 100644
--- a/Libraries/LibC/sys/socket.cpp
+++ b/Libraries/LibC/sys/socket.cpp
@@ -28,7 +28,9 @@
#include <Kernel/API/Syscall.h>
#include <errno.h>
#include <stdio.h>
+#include <string.h>
#include <sys/socket.h>
+#include <sys/uio.h>
extern "C" {
@@ -68,25 +70,48 @@ int shutdown(int sockfd, int how)
__RETURN_WITH_ERRNO(rc, rc, -1);
}
-ssize_t sendto(int sockfd, const void* data, size_t data_length, int flags, const struct sockaddr* addr, socklen_t addr_length)
+ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags)
{
- Syscall::SC_sendto_params params { sockfd, { data, data_length }, flags, addr, addr_length };
- int rc = syscall(SC_sendto, &params);
+ int rc = syscall(SC_sendmsg, sockfd, msg, flags);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
+ssize_t sendto(int sockfd, const void* data, size_t data_length, int flags, const struct sockaddr* addr, socklen_t addr_length)
+{
+ iovec iov = { const_cast<void*>(data), data_length };
+ msghdr msg = { const_cast<struct sockaddr*>(addr), addr_length, &iov, 1, nullptr, 0, 0 };
+ return sendmsg(sockfd, &msg, flags);
+}
+
ssize_t send(int sockfd, const void* data, size_t data_length, int flags)
{
return sendto(sockfd, data, data_length, flags, nullptr, 0);
}
-ssize_t recvfrom(int sockfd, void* buffer, size_t buffer_length, int flags, struct sockaddr* addr, socklen_t* addr_length)
+ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags)
{
- Syscall::SC_recvfrom_params params { sockfd, { buffer, buffer_length }, flags, addr, addr_length };
- int rc = syscall(SC_recvfrom, &params);
+ int rc = syscall(SC_recvmsg, sockfd, msg, flags);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
+ssize_t recvfrom(int sockfd, void* buffer, size_t buffer_length, int flags, struct sockaddr* addr, socklen_t* addr_length)
+{
+ if (!addr_length && addr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sockaddr_storage internal_addr;
+ iovec iov = { buffer, buffer_length };
+ msghdr msg = { addr ? &internal_addr : nullptr, addr ? sizeof(internal_addr) : 0, &iov, 1, nullptr, 0, 0 };
+ ssize_t rc = recvmsg(sockfd, &msg, flags);
+ if (rc >= 0 && addr) {
+ memcpy(addr, &internal_addr, min(*addr_length, msg.msg_namelen));
+ *addr_length = msg.msg_namelen;
+ }
+ return rc;
+}
+
ssize_t recv(int sockfd, void* buffer, size_t buffer_length, int flags)
{
return recvfrom(sockfd, buffer, buffer_length, flags, nullptr, nullptr);
diff --git a/Libraries/LibC/sys/socket.h b/Libraries/LibC/sys/socket.h
index f14e1d7005..898269fb8e 100644
--- a/Libraries/LibC/sys/socket.h
+++ b/Libraries/LibC/sys/socket.h
@@ -61,10 +61,21 @@ __BEGIN_DECLS
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
+#define MSG_TRUNC 0x1
#define MSG_DONTWAIT 0x40
typedef uint16_t sa_family_t;
+struct msghdr {
+ void* msg_name;
+ socklen_t msg_namelen;
+ struct iovec* msg_iov;
+ int msg_iovlen;
+ void* msg_control;
+ socklen_t msg_controllen;
+ int msg_flags;
+};
+
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
@@ -102,8 +113,10 @@ int accept(int sockfd, struct sockaddr*, socklen_t*);
int connect(int sockfd, const struct sockaddr*, socklen_t);
int shutdown(int sockfd, int how);
ssize_t send(int sockfd, const void*, size_t, int flags);
+ssize_t sendmsg(int sockfd, const struct msghdr*, int flags);
ssize_t sendto(int sockfd, const void*, size_t, int flags, const struct sockaddr*, socklen_t);
ssize_t recv(int sockfd, void*, size_t, int flags);
+ssize_t recvmsg(int sockfd, struct msghdr*, int flags);
ssize_t recvfrom(int sockfd, void*, size_t, int flags, struct sockaddr*, socklen_t*);
int getsockopt(int sockfd, int level, int option, void*, socklen_t*);
int setsockopt(int sockfd, int level, int option, const void*, socklen_t);