[libc-commits] [libc] [libc] Add functions to send/recv messages (PR #106467)
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Wed Aug 28 16:12:34 PDT 2024
https://github.com/michaelrj-google created https://github.com/llvm/llvm-project/pull/106467
This patch adds the necessary functions to send and receive messages
over a socket. Those functions are: accept, bind, connect, listen, recv,
recvfrom, recvmsg, send, sendto, and sendmsg.
>From 46510503182d6ccc3c1c10765e127eab1fcc38e6 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Wed, 7 Feb 2024 15:57:05 -0800
Subject: [PATCH] [libc] Add functions to send/recv messages
This patch adds the necessary functions to send and receive messages
over a socket. Those functions are: accept, bind, connect, listen, recv,
recvfrom, recvmsg, send, sendto, and sendmsg.
---
libc/config/linux/api.td | 4 +
libc/config/linux/x86_64/entrypoints.txt | 11 +-
libc/include/CMakeLists.txt | 2 +
libc/include/llvm-libc-types/CMakeLists.txt | 6 +-
libc/include/llvm-libc-types/struct_iovec.h | 19 +++
libc/include/llvm-libc-types/struct_msghdr.h | 26 ++++
libc/newhdrgen/yaml/sys/socket.yaml | 83 +++++++++++++
libc/spec/posix.td | 31 +++++
libc/src/sys/socket/CMakeLists.txt | 63 ++++++++++
libc/src/sys/socket/accept.h | 21 ++++
libc/src/sys/socket/connect.h | 20 +++
libc/src/sys/socket/linux/CMakeLists.txt | 117 ++++++++++++++++++
libc/src/sys/socket/linux/accept.cpp | 43 +++++++
libc/src/sys/socket/linux/bind.cpp | 2 +-
libc/src/sys/socket/linux/connect.cpp | 43 +++++++
libc/src/sys/socket/linux/listen.cpp | 40 ++++++
libc/src/sys/socket/linux/recv.cpp | 45 +++++++
libc/src/sys/socket/linux/recvfrom.cpp | 47 +++++++
libc/src/sys/socket/linux/recvmsg.cpp | 41 ++++++
libc/src/sys/socket/linux/send.cpp | 44 +++++++
libc/src/sys/socket/linux/sendmsg.cpp | 41 ++++++
libc/src/sys/socket/linux/sendto.cpp | 47 +++++++
libc/src/sys/socket/listen.h | 18 +++
libc/src/sys/socket/recv.h | 20 +++
libc/src/sys/socket/recvfrom.h | 21 ++++
libc/src/sys/socket/recvmsg.h | 20 +++
libc/src/sys/socket/send.h | 20 +++
libc/src/sys/socket/sendmsg.h | 20 +++
libc/src/sys/socket/sendto.h | 21 ++++
libc/test/src/sys/socket/linux/CMakeLists.txt | 20 ++-
libc/test/src/sys/socket/linux/send_test.cpp | 73 +++++++++++
.../src/sys/socket/linux/sendmsg_test.cpp | 1 +
.../test/src/sys/socket/linux/sendto_test.cpp | 1 +
33 files changed, 1026 insertions(+), 5 deletions(-)
create mode 100644 libc/include/llvm-libc-types/struct_iovec.h
create mode 100644 libc/include/llvm-libc-types/struct_msghdr.h
create mode 100644 libc/src/sys/socket/accept.h
create mode 100644 libc/src/sys/socket/connect.h
create mode 100644 libc/src/sys/socket/linux/accept.cpp
create mode 100644 libc/src/sys/socket/linux/connect.cpp
create mode 100644 libc/src/sys/socket/linux/listen.cpp
create mode 100644 libc/src/sys/socket/linux/recv.cpp
create mode 100644 libc/src/sys/socket/linux/recvfrom.cpp
create mode 100644 libc/src/sys/socket/linux/recvmsg.cpp
create mode 100644 libc/src/sys/socket/linux/send.cpp
create mode 100644 libc/src/sys/socket/linux/sendmsg.cpp
create mode 100644 libc/src/sys/socket/linux/sendto.cpp
create mode 100644 libc/src/sys/socket/listen.h
create mode 100644 libc/src/sys/socket/recv.h
create mode 100644 libc/src/sys/socket/recvfrom.h
create mode 100644 libc/src/sys/socket/recvmsg.h
create mode 100644 libc/src/sys/socket/send.h
create mode 100644 libc/src/sys/socket/sendmsg.h
create mode 100644 libc/src/sys/socket/sendto.h
create mode 100644 libc/test/src/sys/socket/linux/send_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/sendmsg_test.cpp
create mode 100644 libc/test/src/sys/socket/linux/sendto_test.cpp
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 6a7c64296bf922..46523b4ca4b8df 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -193,6 +193,10 @@ def SysSocketAPI : PublicAPI<"sys/socket.h"> {
"socklen_t",
"struct sockaddr",
"struct sockaddr_un",
+ "struct msghdr",
+ "struct iovec",
+ "size_t",
+ "ssize_t",
];
}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 141dc70463d64a..d7220131046008 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1026,8 +1026,17 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.sys.select.select
# sys/socket.h entrypoints
- libc.src.sys.socket.bind
libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.sys.socket.send
+ libc.src.sys.socket.sendto
+ libc.src.sys.socket.sendmsg
+ libc.src.sys.socket.recv
+ libc.src.sys.socket.recvfrom
+ libc.src.sys.socket.recvmsg
+ libc.src.sys.socket.connect
+ libc.src.sys.socket.listen
+ libc.src.sys.socket.accept
)
endif()
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 910f9eea015f27..d2289ab160ba14 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -592,6 +592,8 @@ add_header_macro(
.llvm-libc-macros.sys_socket_macros
.llvm-libc-types.sa_family_t
.llvm-libc-types.socklen_t
+ .llvm-libc-types.struct_iovec
+ .llvm-libc-types.struct_msghdr
.llvm-libc-types.struct_sockaddr
.llvm-libc-types.struct_sockaddr_un
)
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 583b84ccaae67c..a4cf4631c8470e 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -117,8 +117,10 @@ add_header(
add_header(wint_t HDR wint_t.h)
add_header(sa_family_t HDR sa_family_t.h)
add_header(socklen_t HDR socklen_t.h)
-add_header(struct_sockaddr_un HDR struct_sockaddr_un.h)
-add_header(struct_sockaddr HDR struct_sockaddr.h)
+add_header(struct_sockaddr_un HDR struct_sockaddr_un.h DEPENDS .sa_family_t)
+add_header(struct_sockaddr HDR struct_sockaddr.h DEPENDS .sa_family_t)
+add_header(struct_iovec HDR struct_iovec.h DEPENDS .size_t)
+add_header(struct_msghdr HDR struct_msghdr.h DEPENDS .size_t .socklen_t .struct_iovec)
add_header(rpc_opcodes_t HDR rpc_opcodes_t.h)
add_header(ACTION HDR ACTION.h)
add_header(ENTRY HDR ENTRY.h)
diff --git a/libc/include/llvm-libc-types/struct_iovec.h b/libc/include/llvm-libc-types/struct_iovec.h
new file mode 100644
index 00000000000000..36e7bb79d0787f
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_iovec.h
@@ -0,0 +1,19 @@
+//===-- Definition of struct iovec ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
+#define __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
+
+#include <llvm-libc-types/size_t.h>
+
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
diff --git a/libc/include/llvm-libc-types/struct_msghdr.h b/libc/include/llvm-libc-types/struct_msghdr.h
new file mode 100644
index 00000000000000..5af6d56218c0fc
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_msghdr.h
@@ -0,0 +1,26 @@
+//===-- Definition of struct msghdr ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
+#define __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
+
+#include <llvm-libc-types/size_t.h>
+#include <llvm-libc-types/socklen_t.h>
+#include <llvm-libc-types/struct_iovec.h>
+
+struct msghdr {
+ void *msg_name; /* Optional address */
+ socklen_t msg_namelen; /* Size of address */
+ struct iovec *msg_iov; /* Scatter/gather array */
+ size_t msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* Ancillary data, see below */
+ size_t msg_controllen; /* Ancillary data buffer len */
+ int msg_flags; /* Flags (unused) */
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_MSGHDR_H__
diff --git a/libc/newhdrgen/yaml/sys/socket.yaml b/libc/newhdrgen/yaml/sys/socket.yaml
index 3b8bf4cecfe5aa..4f7b1109d99456 100644
--- a/libc/newhdrgen/yaml/sys/socket.yaml
+++ b/libc/newhdrgen/yaml/sys/socket.yaml
@@ -5,9 +5,21 @@ types:
- type_name: struct_sockaddr
- type_name: socklen_t
- type_name: sa_family_t
+ - type_name: struct_msghdr
+ - type_name: struct_iovec
+ - type_name: size_t
+ - type_name: ssize_t
enums: []
objects: []
functions:
+ - name: accept
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: sockaddr *__restrict
+ - type: socklen_t *__restrict
- name: bind
standards:
- POSIX
@@ -16,6 +28,77 @@ functions:
- type: int
- type: const struct sockaddr *
- type: socklen_t
+ - name: connect
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: const struct sockaddr *
+ - type: socklen_t
+ - name: listen
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: int
+ - type: int
+ - name: recv
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void *
+ - type: size_t
+ - type: int
+ - name: recvfrom
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void*
+ - type: size_t
+ - type: int
+ - type: const struct sockaddr *
+ - type: socklen_t
+ - name: recvmsg
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const struct msghdr *
+ - type: int
+ - name: send
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void*
+ - type: size_t
+ - type: int
+ - name: sendmsg
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const struct msghdr *
+ - type: int
+ - name: sendto
+ standards:
+ - POSIX
+ return_type: ssize_t
+ arguments:
+ - type: int
+ - type: const void *
+ - type: size_t
+ - type: int
+ - type: const struct sockaddr *
+ - type: socklen_t
- name: socket
standards:
- POSIX
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 085f2ec34ab346..b2c53c9a1bd2f5 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -85,6 +85,14 @@ def StructSockAddr : NamedType<"struct sockaddr">;
def StructSockAddrPtr : PtrType<StructSockAddr>;
def ConstStructSockAddrPtr : ConstType<StructSockAddrPtr>;
+def StructMsghdr : NamedType<"struct msghdr">;
+def StructMsghdrPtr : PtrType<StructMsghdr>;
+def ConstStructMsghdrPtr : ConstType<StructMsghdrPtr>;
+
+def StructIovec : NamedType<"struct iovec">;
+def StructIovecPtr : PtrType<StructIovec>;
+def ConstStructIovecPtr : ConstType<StructIovecPtr>;
+
def StructSockAddrUn : NamedType<"struct sockaddr_un">;
def StructStatvfs : NamedType<"struct statvfs">;
@@ -1711,10 +1719,14 @@ def POSIX : StandardSpec<"POSIX"> {
Macro<"SOCK_PACKET">,
], // Macros
[
+ SizeTType,
+ SSizeTType,
SAFamilyType,
StructSockAddr,
StructSockAddrUn,
SocklenType,
+ StructIovec,
+ StructMsghdr,
], // Types
[], // Enumerations
[
@@ -1728,6 +1740,25 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<IntType>,
[ArgSpec<IntType>, ArgSpec<ConstStructSockAddrPtr>, ArgSpec<SocklenType>]
>,
+ FunctionSpec<
+ "send",
+ RetValSpec<SSizeTType>,
+ [ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "sendto",
+ RetValSpec<SSizeTType>,
+ [
+ ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>,
+ ArgSpec<IntType>, ArgSpec<ConstStructSockAddrPtr>,
+ ArgSpec<SocklenType>
+ ]
+ >,
+ FunctionSpec<
+ "sendmsg",
+ RetValSpec<SSizeTType>,
+ [ArgSpec<IntType>, ArgSpec<ConstStructMsghdrPtr>, ArgSpec<IntType>]
+ >,
] // Functions
>;
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index e0bc48735a0314..cd877b923f9f37 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -15,3 +15,66 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.bind
)
+
+add_entrypoint_object(
+ send
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.send
+)
+
+add_entrypoint_object(
+ sendto
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sendto
+)
+
+add_entrypoint_object(
+ sendmsg
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sendmsg
+)
+
+add_entrypoint_object(
+ recv
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.recv
+)
+
+add_entrypoint_object(
+ recvfrom
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.recvfrom
+)
+
+add_entrypoint_object(
+ recvmsg
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.recvmsg
+)
+
+add_entrypoint_object(
+ connect
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.connect
+)
+
+add_entrypoint_object(
+ accept
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.accept
+)
+
+add_entrypoint_object(
+ listen
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.listen
+)
diff --git a/libc/src/sys/socket/accept.h b/libc/src/sys/socket/accept.h
new file mode 100644
index 00000000000000..b523d9e3b7586a
--- /dev/null
+++ b/libc/src/sys/socket/accept.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for accept ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+int accept(int domain, sockaddr *__restrict address,
+ socklen_t *__restrict address_len);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
diff --git a/libc/src/sys/socket/connect.h b/libc/src/sys/socket/connect.h
new file mode 100644
index 00000000000000..0588c56504be39
--- /dev/null
+++ b/libc/src/sys/socket/connect.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for connect -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index fc9febdec2cc3c..4a73f87fbd7bef 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -23,3 +23,120 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ send
+ SRCS
+ send.cpp
+ HDRS
+ ../send.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sendto
+ SRCS
+ sendto.cpp
+ HDRS
+ ../sendto.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ sendmsg
+ SRCS
+ sendmsg.cpp
+ HDRS
+ ../sendmsg.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ connect
+ SRCS
+ connect.cpp
+ HDRS
+ ../connect.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ recv
+ SRCS
+ recv.cpp
+ HDRS
+ ../recv.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ recvfrom
+ SRCS
+ recvfrom.cpp
+ HDRS
+ ../recvfrom.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ recvmsg
+ SRCS
+ recvmsg.cpp
+ HDRS
+ ../recvmsg.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ accept
+ SRCS
+ accept.cpp
+ HDRS
+ ../accept.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ listen
+ SRCS
+ listen.cpp
+ HDRS
+ ../listen.h
+ DEPENDS
+ libc.include.sys_syscall
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
diff --git a/libc/src/sys/socket/linux/accept.cpp b/libc/src/sys/socket/linux/accept.cpp
new file mode 100644
index 00000000000000..ea615be36762f0
--- /dev/null
+++ b/libc/src/sys/socket/linux/accept.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of accept ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/accept.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, accept,
+ (int domain, sockaddr *__restrict address,
+ socklen_t *__restrict address_len)) {
+#ifdef SYS_accept
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_accept, domain, address,
+ address_len);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(domain),
+ reinterpret_cast<unsigned long>(address),
+ static_cast<unsigned long>(address_len)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_ACCEPT,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/bind.cpp b/libc/src/sys/socket/linux/bind.cpp
index 3289e9f0852e86..925fca81e56810 100644
--- a/libc/src/sys/socket/linux/bind.cpp
+++ b/libc/src/sys/socket/linux/bind.cpp
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, bind,
(int domain, const struct sockaddr *address,
socklen_t address_len)) {
-#ifdef SYS_socket
+#ifdef SYS_bind
int ret =
LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, domain, address, address_len);
#elif defined(SYS_socketcall)
diff --git a/libc/src/sys/socket/linux/connect.cpp b/libc/src/sys/socket/linux/connect.cpp
new file mode 100644
index 00000000000000..d1e7265c1ddbc3
--- /dev/null
+++ b/libc/src/sys/socket/linux/connect.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of connect
+//--------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/connect.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, connect,
+ (int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen)) {
+#ifdef SYS_connect
+ int ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_connect, sockfd, addr, addrlen);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(addr),
+ static_cast<unsigned long>(addrlen)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_CONNECT,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/listen.cpp b/libc/src/sys/socket/linux/listen.cpp
new file mode 100644
index 00000000000000..e57738e5ce4a94
--- /dev/null
+++ b/libc/src/sys/socket/linux/listen.cpp
@@ -0,0 +1,40 @@
+//===-- Linux implementation of listen
+//--------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/listen.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, listen, (int socket, int backlog)) {
+#ifdef SYS_listen
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_listen, socket, backlog);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[2] = {static_cast<unsigned long>(socket),
+ reinterpret_cast<unsigned long>(backlog)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_LISTEN,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp
new file mode 100644
index 00000000000000..2d19d761215478
--- /dev/null
+++ b/libc/src/sys/socket/linux/recv.cpp
@@ -0,0 +1,45 @@
+//===-- Linux implementation of recv --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recv.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, recv,
+ (int sockfd, const void *buf, size_t len, int flags)) {
+#ifdef SYS_recv
+ ssize_t ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_recv, sockfd, buf, len, flags);
+#elif defined(SYS_recvfrom)
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_recvfrom, sockfd,
+ reinterpret_cast<long>(buf),
+ len, flags, nullptr, 0);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {
+ static_cast<unsigned long>(sockfd), reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len), static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_RECV,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
new file mode 100644
index 00000000000000..550ae4c11389b9
--- /dev/null
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -0,0 +1,47 @@
+//===-- Linux implementation of recvfrom ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recvfrom.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
+ (int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)) {
+#ifdef SYS_recvfrom
+
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_recvfrom, sockfd, reinterpret_cast<long>(buf), len, flags,
+ reinterpret_cast<long>(dest_addr), addrlen);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[6] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len),
+ static_cast<unsigned long>(flags),
+ reinterpret_cast<unsigned long>(dest_addr),
+ static_cast<unsigned long>(addrlen)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_RECVFROM,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp
new file mode 100644
index 00000000000000..1bae39694833c4
--- /dev/null
+++ b/libc/src/sys/socket/linux/recvmsg.cpp
@@ -0,0 +1,41 @@
+//===-- Linux implementation of recvmsg -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/recvmsg.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, recvmsg,
+ (int sockfd, const struct msghdr *msg, int flags)) {
+#ifdef SYS_recvmsg
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_recvmsg, sockfd, reinterpret_cast<long>(msg), flags);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(msg),
+ static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_RECVMSG,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp
new file mode 100644
index 00000000000000..4fa0da72a0c9f0
--- /dev/null
+++ b/libc/src/sys/socket/linux/send.cpp
@@ -0,0 +1,44 @@
+//===-- Linux implementation of send --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/send.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, send,
+ (int sockfd, const void *buf, size_t len, int flags)) {
+#ifdef SYS_send
+ ssize_t ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_send, sockfd, buf, len, flags);
+#elif defined(SYS_sendto)
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sendto, sockfd, reinterpret_cast<long>(buf), len, flags, nullptr, 0);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {
+ static_cast<unsigned long>(sockfd), reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len), static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SEND,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp
new file mode 100644
index 00000000000000..3eeaef38d76ca7
--- /dev/null
+++ b/libc/src/sys/socket/linux/sendmsg.cpp
@@ -0,0 +1,41 @@
+//===-- Linux implementation of sendmsg -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/sendmsg.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, sendmsg,
+ (int sockfd, const struct msghdr *msg, int flags)) {
+#ifdef SYS_sendmsg
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sendmsg, sockfd, reinterpret_cast<long>(msg), flags);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(msg),
+ static_cast<unsigned long>(flags)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SENDMSG,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp
new file mode 100644
index 00000000000000..7c66408d37e1d5
--- /dev/null
+++ b/libc/src/sys/socket/linux/sendto.cpp
@@ -0,0 +1,47 @@
+//===-- Linux implementation of sendto ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/sendto.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/errno/libc_errno.h"
+#include <linux/net.h> // For SYS_SOCKET socketcall number.
+#include <sys/socket.h> // For the types
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(ssize_t, sendto,
+ (int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)) {
+#ifdef SYS_sendto
+
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(
+ SYS_sendto, sockfd, reinterpret_cast<long>(buf), len, flags,
+ reinterpret_cast<long>(dest_addr), addrlen);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[6] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(buf),
+ static_cast<unsigned long>(len),
+ static_cast<unsigned long>(flags),
+ reinterpret_cast<unsigned long>(dest_addr),
+ static_cast<unsigned long>(addrlen)};
+ ssize_t ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SENDTO,
+ sockcall_args);
+#else
+#error "socket and socketcall syscalls unavailable for this platform."
+#endif
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/socket/listen.h b/libc/src/sys/socket/listen.h
new file mode 100644
index 00000000000000..ad77fac655ce41
--- /dev/null
+++ b/libc/src/sys/socket/listen.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for listen ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
+
+namespace LIBC_NAMESPACE {
+
+int listen(int socket, int backlog);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
diff --git a/libc/src/sys/socket/recv.h b/libc/src/sys/socket/recv.h
new file mode 100644
index 00000000000000..7b626e35d3ef47
--- /dev/null
+++ b/libc/src/sys/socket/recv.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for recv --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
new file mode 100644
index 00000000000000..aee387b3dc0f3a
--- /dev/null
+++ b/libc/src/sys/socket/recvfrom.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for recvfrom ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *address, socklen_t addrlen);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
diff --git a/libc/src/sys/socket/recvmsg.h b/libc/src/sys/socket/recvmsg.h
new file mode 100644
index 00000000000000..cc6a934f705eec
--- /dev/null
+++ b/libc/src/sys/socket/recvmsg.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for recvmsg -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t recvmsg(int sockfd, const struct msghdr *msg, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
diff --git a/libc/src/sys/socket/send.h b/libc/src/sys/socket/send.h
new file mode 100644
index 00000000000000..a06db3b978ac19
--- /dev/null
+++ b/libc/src/sys/socket/send.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for send --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t send(int sockfd, const void *buf, size_t len, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
diff --git a/libc/src/sys/socket/sendmsg.h b/libc/src/sys/socket/sendmsg.h
new file mode 100644
index 00000000000000..4c970585558eb0
--- /dev/null
+++ b/libc/src/sys/socket/sendmsg.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for sendmsg -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
diff --git a/libc/src/sys/socket/sendto.h b/libc/src/sys/socket/sendto.h
new file mode 100644
index 00000000000000..afb1fce9d61fcc
--- /dev/null
+++ b/libc/src/sys/socket/sendto.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for sendto ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 666dc28c7e4ee1..32ae9d7481ed42 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -13,7 +13,6 @@ add_libc_unittest(
libc.src.unistd.close
)
-
add_libc_unittest(
bind_test
SUITE
@@ -28,3 +27,22 @@ add_libc_unittest(
libc.src.stdio.remove
libc.src.unistd.close
)
+
+add_libc_unittest(
+ send_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ send_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.send
+ libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.sys.socket.connect
+ libc.src.sys.socket.listen
+ libc.src.sys.socket.accept
+ libc.src.stdio.remove
+ libc.src.unistd.close
+)
diff --git a/libc/test/src/sys/socket/linux/send_test.cpp b/libc/test/src/sys/socket/linux/send_test.cpp
new file mode 100644
index 00000000000000..def46a0edcb277
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/send_test.cpp
@@ -0,0 +1,73 @@
+//===-- Unittests for send ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/remove.h"
+#include "src/sys/socket/accept.h"
+#include "src/sys/socket/bind.h"
+#include "src/sys/socket/connect.h"
+#include "src/sys/socket/listen.h"
+#include "src/sys/socket/send.h"
+#include "src/sys/socket/socket.h"
+#include "src/unistd/close.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+TEST(LlvmLibcSocketTest, BindLocalSocket) {
+
+ const char *FILENAME = "send_file.test";
+ auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+
+ // if might exist if the test fails
+ LIBC_NAMESPACE::remove(SOCK_PATH);
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0);
+ ASSERT_GE(sock, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr_un my_addr;
+
+ my_addr.sun_family = AF_UNIX;
+ unsigned int i = 0;
+ for (;
+ SOCK_PATH[i] != '\0' && (i < sizeof(sockaddr_un) - sizeof(sa_family_t));
+ ++i)
+ my_addr.sun_path[i] = SOCK_PATH[i];
+ my_addr.sun_path[i] = '\0';
+
+ // It's important that the path fits in the struct, if it doesn't then we
+ // can't try to bind to the file.
+ ASSERT_LT(
+ i, static_cast<unsigned int>(sizeof(sockaddr_un) - sizeof(sa_family_t)));
+
+ int result =
+ LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+ sizeof(struct sockaddr_un));
+
+ EXPECT_EQ(result, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ struct sockaddr *connected_sock;
+
+ // result = LIBC_NAMESPACE::connect(sock, connected_sock, socklen_t addrlen)
+
+ const char TEST_MESSAGE[] = "connection successful";
+ const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+ ssize_t send_result =
+ LIBC_NAMESPACE::send(sock, TEST_MESSAGE, MESSAGE_LEN, 0);
+
+ EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+ ASSERT_ERRNO_SUCCESS();
+
+ LIBC_NAMESPACE::close(sock);
+
+ // LIBC_NAMESPACE::remove(SOCK_PATH);
+}
diff --git a/libc/test/src/sys/socket/linux/sendmsg_test.cpp b/libc/test/src/sys/socket/linux/sendmsg_test.cpp
new file mode 100644
index 00000000000000..b00a271b5497a1
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sendmsg_test.cpp
@@ -0,0 +1 @@
+TODO: TESTS
diff --git a/libc/test/src/sys/socket/linux/sendto_test.cpp b/libc/test/src/sys/socket/linux/sendto_test.cpp
new file mode 100644
index 00000000000000..b00a271b5497a1
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sendto_test.cpp
@@ -0,0 +1 @@
+TODO: TESTS
More information about the libc-commits
mailing list