[libc-commits] [libc] [libc] Add functions to send/recv messages (PR #106467)

Michael Jones via libc-commits libc-commits at lists.llvm.org
Tue Sep 17 11:06:20 PDT 2024


https://github.com/michaelrj-google updated https://github.com/llvm/llvm-project/pull/106467

>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 1/4] [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

>From 367640d3ac4387faf97a78d5c1bea8c9cac96a80 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Tue, 10 Sep 2024 10:59:18 -0700
Subject: [PATCH 2/4] move tests to be integration tests.

---
 libc/src/sys/socket/accept.h                  |   5 +-
 libc/src/sys/socket/bind.h                    |   2 +-
 libc/src/sys/socket/connect.h                 |  11 +-
 libc/src/sys/socket/linux/accept.cpp          |   4 +-
 libc/src/sys/socket/linux/bind.cpp            |   6 +-
 libc/src/sys/socket/linux/connect.cpp         |   4 +-
 libc/src/sys/socket/linux/listen.cpp          |   4 +-
 libc/src/sys/socket/linux/recv.cpp            |   4 +-
 libc/src/sys/socket/linux/recvfrom.cpp        |   4 +-
 libc/src/sys/socket/linux/recvmsg.cpp         |   4 +-
 libc/src/sys/socket/linux/send.cpp            |   4 +-
 libc/src/sys/socket/linux/sendmsg.cpp         |   4 +-
 libc/src/sys/socket/linux/sendto.cpp          |   4 +-
 libc/src/sys/socket/listen.h                  |   5 +-
 libc/src/sys/socket/recv.h                    |   5 +-
 libc/src/sys/socket/recvfrom.h                |   5 +-
 libc/src/sys/socket/recvmsg.h                 |   5 +-
 libc/src/sys/socket/send.h                    |   5 +-
 libc/src/sys/socket/sendmsg.h                 |   5 +-
 libc/src/sys/socket/sendto.h                  |   5 +-
 libc/test/integration/src/CMakeLists.txt      |   1 +
 libc/test/integration/src/sys/CMakeLists.txt  |   1 +
 .../integration/src/sys/socket/CMakeLists.txt |   3 +
 .../src/sys/socket/linux/CMakeLists.txt       |  24 +++
 .../socket/linux/socket_send_recv_test.cpp    | 138 ++++++++++++++++++
 libc/test/src/sys/socket/linux/CMakeLists.txt |  19 ---
 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 -
 29 files changed, 219 insertions(+), 137 deletions(-)
 create mode 100644 libc/test/integration/src/sys/CMakeLists.txt
 create mode 100644 libc/test/integration/src/sys/socket/CMakeLists.txt
 create mode 100644 libc/test/integration/src/sys/socket/linux/CMakeLists.txt
 create mode 100644 libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
 delete mode 100644 libc/test/src/sys/socket/linux/send_test.cpp
 delete mode 100644 libc/test/src/sys/socket/linux/sendmsg_test.cpp
 delete mode 100644 libc/test/src/sys/socket/linux/sendto_test.cpp

diff --git a/libc/src/sys/socket/accept.h b/libc/src/sys/socket/accept.h
index b523d9e3b7586a..c7cebc35e987cf 100644
--- a/libc/src/sys/socket/accept.h
+++ b/libc/src/sys/socket/accept.h
@@ -9,13 +9,14 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 int accept(int domain, sockaddr *__restrict address,
            socklen_t *__restrict address_len);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
diff --git a/libc/src/sys/socket/bind.h b/libc/src/sys/socket/bind.h
index 1676ab6a003ad9..cec9c9da0c871e 100644
--- a/libc/src/sys/socket/bind.h
+++ b/libc/src/sys/socket/bind.h
@@ -14,7 +14,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-int bind(int domain, const struct sockaddr *address, socklen_t address_len);
+int bind(int socket, const struct sockaddr *address, socklen_t address_len);
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/sys/socket/connect.h b/libc/src/sys/socket/connect.h
index 0588c56504be39..221f9a44cbaf9a 100644
--- a/libc/src/sys/socket/connect.h
+++ b/libc/src/sys/socket/connect.h
@@ -6,15 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
-#define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
-#endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
diff --git a/libc/src/sys/socket/linux/accept.cpp b/libc/src/sys/socket/linux/accept.cpp
index ea615be36762f0..5a6c70349e048a 100644
--- a/libc/src/sys/socket/linux/accept.cpp
+++ b/libc/src/sys/socket/linux/accept.cpp
@@ -16,7 +16,7 @@
 #include <linux/net.h>   // For SYS_SOCKET socketcall number.
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, accept,
                    (int domain, sockaddr *__restrict address,
@@ -40,4 +40,4 @@ LLVM_LIBC_FUNCTION(int, accept,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/bind.cpp b/libc/src/sys/socket/linux/bind.cpp
index 925fca81e56810..72a3307a91ddd7 100644
--- a/libc/src/sys/socket/linux/bind.cpp
+++ b/libc/src/sys/socket/linux/bind.cpp
@@ -20,13 +20,13 @@
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, bind,
-                   (int domain, const struct sockaddr *address,
+                   (int socket, const struct sockaddr *address,
                     socklen_t address_len)) {
 #ifdef SYS_bind
   int ret =
-      LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, domain, address, address_len);
+      LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, socket, address, address_len);
 #elif defined(SYS_socketcall)
-  unsigned long sockcall_args[3] = {static_cast<unsigned long>(domain),
+  unsigned long sockcall_args[3] = {static_cast<unsigned long>(socket),
                                     reinterpret_cast<unsigned long>(address),
                                     static_cast<unsigned long>(address_len)};
   int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_BIND,
diff --git a/libc/src/sys/socket/linux/connect.cpp b/libc/src/sys/socket/linux/connect.cpp
index d1e7265c1ddbc3..eaf422613f5e62 100644
--- a/libc/src/sys/socket/linux/connect.cpp
+++ b/libc/src/sys/socket/linux/connect.cpp
@@ -16,7 +16,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, connect,
                    (int sockfd, const struct sockaddr *addr,
@@ -40,4 +40,4 @@ LLVM_LIBC_FUNCTION(int, connect,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/listen.cpp b/libc/src/sys/socket/linux/listen.cpp
index e57738e5ce4a94..a5906e57371c9c 100644
--- a/libc/src/sys/socket/linux/listen.cpp
+++ b/libc/src/sys/socket/linux/listen.cpp
@@ -17,7 +17,7 @@
 #include <linux/net.h>   // For SYS_SOCKET socketcall number.
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, listen, (int socket, int backlog)) {
 #ifdef SYS_listen
@@ -37,4 +37,4 @@ LLVM_LIBC_FUNCTION(int, listen, (int socket, int backlog)) {
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp
index 2d19d761215478..afefac73f3db4a 100644
--- a/libc/src/sys/socket/linux/recv.cpp
+++ b/libc/src/sys/socket/linux/recv.cpp
@@ -15,7 +15,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, recv,
                    (int sockfd, const void *buf, size_t len, int flags)) {
@@ -42,4 +42,4 @@ LLVM_LIBC_FUNCTION(ssize_t, recv,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
index 550ae4c11389b9..9b20982bb1fbf3 100644
--- a/libc/src/sys/socket/linux/recvfrom.cpp
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -15,7 +15,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
                    (int sockfd, const void *buf, size_t len, int flags,
@@ -44,4 +44,4 @@ LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp
index 1bae39694833c4..4a2f6fabbc2da1 100644
--- a/libc/src/sys/socket/linux/recvmsg.cpp
+++ b/libc/src/sys/socket/linux/recvmsg.cpp
@@ -15,7 +15,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, recvmsg,
                    (int sockfd, const struct msghdr *msg, int flags)) {
@@ -38,4 +38,4 @@ LLVM_LIBC_FUNCTION(ssize_t, recvmsg,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp
index 4fa0da72a0c9f0..fc5305d5cdfa3d 100644
--- a/libc/src/sys/socket/linux/send.cpp
+++ b/libc/src/sys/socket/linux/send.cpp
@@ -15,7 +15,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, send,
                    (int sockfd, const void *buf, size_t len, int flags)) {
@@ -41,4 +41,4 @@ LLVM_LIBC_FUNCTION(ssize_t, send,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp
index 3eeaef38d76ca7..822a26493dddb4 100644
--- a/libc/src/sys/socket/linux/sendmsg.cpp
+++ b/libc/src/sys/socket/linux/sendmsg.cpp
@@ -15,7 +15,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, sendmsg,
                    (int sockfd, const struct msghdr *msg, int flags)) {
@@ -38,4 +38,4 @@ LLVM_LIBC_FUNCTION(ssize_t, sendmsg,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp
index 7c66408d37e1d5..bc0769bc77d1d7 100644
--- a/libc/src/sys/socket/linux/sendto.cpp
+++ b/libc/src/sys/socket/linux/sendto.cpp
@@ -15,7 +15,7 @@
 #include <sys/socket.h>  // For the types
 #include <sys/syscall.h> // For syscall numbers.
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, sendto,
                    (int sockfd, const void *buf, size_t len, int flags,
@@ -44,4 +44,4 @@ LLVM_LIBC_FUNCTION(ssize_t, sendto,
   return ret;
 }
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/listen.h b/libc/src/sys/socket/listen.h
index ad77fac655ce41..ab943b3b8be3a8 100644
--- a/libc/src/sys/socket/listen.h
+++ b/libc/src/sys/socket/listen.h
@@ -9,10 +9,11 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
 
-namespace LIBC_NAMESPACE {
+#include "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
 
 int listen(int socket, int backlog);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_LISTEN_H
diff --git a/libc/src/sys/socket/recv.h b/libc/src/sys/socket/recv.h
index 7b626e35d3ef47..093e8ca9b12304 100644
--- a/libc/src/sys/socket/recv.h
+++ b/libc/src/sys/socket/recv.h
@@ -9,12 +9,13 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_RECV_H
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
index aee387b3dc0f3a..b1f36467bd574a 100644
--- a/libc/src/sys/socket/recvfrom.h
+++ b/libc/src/sys/socket/recvfrom.h
@@ -9,13 +9,14 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *address, socklen_t addrlen);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
diff --git a/libc/src/sys/socket/recvmsg.h b/libc/src/sys/socket/recvmsg.h
index cc6a934f705eec..0cffb7af7c3d7d 100644
--- a/libc/src/sys/socket/recvmsg.h
+++ b/libc/src/sys/socket/recvmsg.h
@@ -9,12 +9,13 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 ssize_t recvmsg(int sockfd, const struct msghdr *msg, int flags);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
diff --git a/libc/src/sys/socket/send.h b/libc/src/sys/socket/send.h
index a06db3b978ac19..e1706694cd5f5d 100644
--- a/libc/src/sys/socket/send.h
+++ b/libc/src/sys/socket/send.h
@@ -9,12 +9,13 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_SEND_H
diff --git a/libc/src/sys/socket/sendmsg.h b/libc/src/sys/socket/sendmsg.h
index 4c970585558eb0..d902632eee0fa3 100644
--- a/libc/src/sys/socket/sendmsg.h
+++ b/libc/src/sys/socket/sendmsg.h
@@ -9,12 +9,13 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
diff --git a/libc/src/sys/socket/sendto.h b/libc/src/sys/socket/sendto.h
index afb1fce9d61fcc..8b56362b930c97 100644
--- a/libc/src/sys/socket/sendto.h
+++ b/libc/src/sys/socket/sendto.h
@@ -9,13 +9,14 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
 
+#include "src/__support/macros/config.h"
 #include <sys/socket.h>
 
-namespace LIBC_NAMESPACE {
+namespace LIBC_NAMESPACE_DECL {
 
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                const struct sockaddr *dest_addr, socklen_t addrlen);
 
-} // namespace LIBC_NAMESPACE
+} // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
diff --git a/libc/test/integration/src/CMakeLists.txt b/libc/test/integration/src/CMakeLists.txt
index 1104b3de99e9b7..7c97c68d2a7d15 100644
--- a/libc/test/integration/src/CMakeLists.txt
+++ b/libc/test/integration/src/CMakeLists.txt
@@ -5,3 +5,4 @@ add_subdirectory(stdio)
 add_subdirectory(stdlib)
 add_subdirectory(threads)
 add_subdirectory(unistd)
+add_subdirectory(sys)
diff --git a/libc/test/integration/src/sys/CMakeLists.txt b/libc/test/integration/src/sys/CMakeLists.txt
new file mode 100644
index 00000000000000..5a3c0f8150c7ee
--- /dev/null
+++ b/libc/test/integration/src/sys/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(socket)
diff --git a/libc/test/integration/src/sys/socket/CMakeLists.txt b/libc/test/integration/src/sys/socket/CMakeLists.txt
new file mode 100644
index 00000000000000..b4bbe81c92ff2e
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..b31b01cce5dcb5
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
@@ -0,0 +1,24 @@
+add_custom_target(sys-socket-integration-tests)
+add_dependencies(libc-integration-tests sys-socket-integration-tests)
+
+
+add_integration_test(
+  socket_send_recv_test
+  SUITE
+    sys-socket-integration-tests
+  SRCS
+    socket_send_recv_test.cpp
+  DEPENDS
+    libc.include.sys_socket
+    libc.src.errno.errno
+    libc.src.sys.socket.send
+    libc.src.sys.socket.recv
+    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
+    libc.src.unistd.fork
+)
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
new file mode 100644
index 00000000000000..80e65e2290dacd
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
@@ -0,0 +1,138 @@
+//===-- Integration tests for socket functions ----------------------------===//
+//
+// 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/__support/threads/sleep.h"
+
+#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/recv.h"
+#include "src/sys/socket/send.h"
+#include "src/sys/socket/socket.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/IntegrationTest/test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+const char TEST_MESSAGE[] = "connection successful";
+const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+void run_client(const char *SOCK_PATH) {
+  constexpr size_t SPIN_TRIES = 100;
+  int result;
+
+  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+  ASSERT_NE(sock, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  struct sockaddr_un my_addr;
+
+  my_addr.sun_family = AF_UNIX;
+  size_t i = 0;
+  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+    my_addr.sun_path[i] = SOCK_PATH[i];
+  my_addr.sun_path[i] = '\0';
+
+  // If the connection fails with "EAGAIN" then sleep breifly and try again, but
+  // only up to SPIN_TRIES times.
+  LIBC_NAMESPACE::libc_errno = EAGAIN;
+  for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
+       ++j, LIBC_NAMESPACE::sleep_briefly()) {
+    LIBC_NAMESPACE::libc_errno = 0;
+    result = LIBC_NAMESPACE::connect(
+        sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+        sizeof(my_addr.sun_path));
+  }
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  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);
+}
+
+void run_server(const char *SOCK_PATH) {
+  int result;
+
+  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+  ASSERT_NE(sock, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  struct sockaddr_un my_addr;
+
+  my_addr.sun_family = AF_UNIX;
+  size_t i = 0;
+  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+    my_addr.sun_path[i] = SOCK_PATH[i];
+  my_addr.sun_path[i] = '\0';
+
+  result =
+      LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+                           sizeof(my_addr.sun_path));
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  result = LIBC_NAMESPACE::listen(sock, 1);
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  struct sockaddr connected_sock;
+  socklen_t sockaddr_len = sizeof(struct sockaddr);
+
+  int accepted_sock =
+      LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
+  ASSERT_NE(accepted_sock, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  char buffer[256];
+
+  ssize_t recv_result =
+      LIBC_NAMESPACE::recv(accepted_sock, buffer, sizeof(buffer), 0);
+  ASSERT_EQ(recv_result, MESSAGE_LEN);
+  ASSERT_ERRNO_SUCCESS();
+
+  for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+    ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+  }
+
+  LIBC_NAMESPACE::close(sock);
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+
+  const char *FILENAME = "send_file.test";
+  // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+  auto SOCK_PATH = FILENAME;
+
+  // If the test fails, then the file for the socket may not be properly
+  // removed. This ensures a consistent start.
+  LIBC_NAMESPACE::remove(SOCK_PATH);
+  LIBC_NAMESPACE::libc_errno = 0;
+
+  // split into client and server processes.
+  pid_t pid = LIBC_NAMESPACE::fork();
+  ASSERT_NE(pid, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  if (pid == 0) { // child
+    run_client(SOCK_PATH);
+  } else { // parent
+    run_server(SOCK_PATH);
+  }
+
+  return 0;
+}
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 32ae9d7481ed42..566233c2041780 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -27,22 +27,3 @@ 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
deleted file mode 100644
index def46a0edcb277..00000000000000
--- a/libc/test/src/sys/socket/linux/send_test.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===-- 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
deleted file mode 100644
index b00a271b5497a1..00000000000000
--- a/libc/test/src/sys/socket/linux/sendmsg_test.cpp
+++ /dev/null
@@ -1 +0,0 @@
-TODO: TESTS
diff --git a/libc/test/src/sys/socket/linux/sendto_test.cpp b/libc/test/src/sys/socket/linux/sendto_test.cpp
deleted file mode 100644
index b00a271b5497a1..00000000000000
--- a/libc/test/src/sys/socket/linux/sendto_test.cpp
+++ /dev/null
@@ -1 +0,0 @@
-TODO: TESTS

>From 13e2a7a3f2e2fc33ee9d3e8d298d99def2a146f4 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Thu, 12 Sep 2024 16:18:44 -0700
Subject: [PATCH 3/4] add msg tests, also add proxy headers

---
 libc/hdr/types/CMakeLists.txt                 |  27 +++
 libc/hdr/types/socklen_t.h                    |  21 +++
 libc/hdr/types/ssize_t.h                      |  23 +++
 libc/hdr/types/struct_msghdr.h                |  21 +++
 libc/hdr/types/struct_sockaddr.h              |  21 +++
 libc/include/llvm-libc-types/struct_iovec.h   |   2 +-
 libc/include/llvm-libc-types/struct_msghdr.h  |   6 +-
 libc/src/sys/socket/accept.h                  |   3 +-
 libc/src/sys/socket/bind.h                    |   3 +-
 libc/src/sys/socket/connect.h                 |   3 +-
 libc/src/sys/socket/linux/CMakeLists.txt      |  25 ++-
 libc/src/sys/socket/linux/connect.cpp         |   3 +-
 libc/src/sys/socket/linux/recv.cpp            |   4 +-
 libc/src/sys/socket/linux/recvfrom.cpp        |   4 +-
 libc/src/sys/socket/linux/recvmsg.cpp         |   3 +-
 libc/src/sys/socket/linux/send.cpp            |   4 +-
 libc/src/sys/socket/linux/sendmsg.cpp         |   3 +-
 libc/src/sys/socket/linux/sendto.cpp          |   4 +-
 libc/src/sys/socket/recvfrom.h                |   5 +-
 libc/src/sys/socket/recvmsg.h                 |   3 +-
 libc/src/sys/socket/sendmsg.h                 |   3 +-
 libc/src/sys/socket/sendto.h                  |   5 +-
 .../src/sys/socket/linux/CMakeLists.txt       |  24 +++
 .../socket/linux/socket_send_recv_test.cpp    |  12 +-
 .../linux/socket_sendmsg_recvmsg_test.cpp     | 169 ++++++++++++++++++
 25 files changed, 371 insertions(+), 30 deletions(-)
 create mode 100644 libc/hdr/types/socklen_t.h
 create mode 100644 libc/hdr/types/ssize_t.h
 create mode 100644 libc/hdr/types/struct_msghdr.h
 create mode 100644 libc/hdr/types/struct_sockaddr.h
 create mode 100644 libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp

diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index f41576c07d99be..ff6842ae074e56 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -171,3 +171,30 @@ add_proxy_header_library(
     libc.include.llvm-libc-types.locale_t
     libc.include.locale
 )
+
+add_proxy_header_library(
+  struct_msghdr
+  HDRS
+    struct_msghdr.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.struct_msghdr
+    libc.include.sys_socket
+)
+
+add_proxy_header_library(
+  struct_sockaddr
+  HDRS
+    struct_sockaddr.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.struct_sockaddr
+    libc.include.sys_socket
+)
+
+add_proxy_header_library(
+  socklen_t
+  HDRS
+    socklen_t.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.socklen_t
+    libc.include.sys_socket
+)
diff --git a/libc/hdr/types/socklen_t.h b/libc/hdr/types/socklen_t.h
new file mode 100644
index 00000000000000..79a6b9c7deadf0
--- /dev/null
+++ b/libc/hdr/types/socklen_t.h
@@ -0,0 +1,21 @@
+//===-- Proxy for socklen_t -----------------------------------------------===//
+//
+// 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_HDR_TYPES_SOCKLEN_T_H
+#define LLVM_LIBC_HDR_TYPES_SOCKLEN_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/socklen_t.h"
+
+#else
+
+#include <signal.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_SOCKLEN_T_H
diff --git a/libc/hdr/types/ssize_t.h b/libc/hdr/types/ssize_t.h
new file mode 100644
index 00000000000000..4d2000780ee11f
--- /dev/null
+++ b/libc/hdr/types/ssize_t.h
@@ -0,0 +1,23 @@
+//===-- Proxy for ssize_t -------------------------------------------------===//
+//
+// 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_HDR_TYPES_SSIZE_T_H
+#define LLVM_LIBC_HDR_TYPES_SSIZE_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/ssize_t.h"
+
+#else
+
+#define __need_ssize_t
+#include <stddef.h>
+#undef __need_ssize_t
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_SSIZE_T_H
diff --git a/libc/hdr/types/struct_msghdr.h b/libc/hdr/types/struct_msghdr.h
new file mode 100644
index 00000000000000..6a36af791e2147
--- /dev/null
+++ b/libc/hdr/types/struct_msghdr.h
@@ -0,0 +1,21 @@
+//===-- Proxy for 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_HDR_TYPES_STRUCT_MSGHDR_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_MSGHDR_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_msghdr.h"
+
+#else
+
+#include <sys/socket.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_MSGHDR_H
diff --git a/libc/hdr/types/struct_sockaddr.h b/libc/hdr/types/struct_sockaddr.h
new file mode 100644
index 00000000000000..0fc31d53748540
--- /dev/null
+++ b/libc/hdr/types/struct_sockaddr.h
@@ -0,0 +1,21 @@
+//===-- Proxy for struct sockaddr  ----------------------------------------===//
+//
+// 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_HDR_TYPES_STRUCT_SOCKADDR_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_SOCKADDR_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_sockaddr.h"
+
+#else
+
+#include <sys/socket.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_SOCKADDR_H
diff --git a/libc/include/llvm-libc-types/struct_iovec.h b/libc/include/llvm-libc-types/struct_iovec.h
index 36e7bb79d0787f..4f889d3d038a11 100644
--- a/libc/include/llvm-libc-types/struct_iovec.h
+++ b/libc/include/llvm-libc-types/struct_iovec.h
@@ -9,7 +9,7 @@
 #ifndef __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
 #define __LLVM_LIBC_TYPES_STRUCT_IOVEC_H__
 
-#include <llvm-libc-types/size_t.h>
+#include "llvm-libc-types/size_t.h"
 
 struct iovec {
   void *iov_base;
diff --git a/libc/include/llvm-libc-types/struct_msghdr.h b/libc/include/llvm-libc-types/struct_msghdr.h
index 5af6d56218c0fc..afd37263fd22c1 100644
--- a/libc/include/llvm-libc-types/struct_msghdr.h
+++ b/libc/include/llvm-libc-types/struct_msghdr.h
@@ -9,9 +9,9 @@
 #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>
+#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 */
diff --git a/libc/src/sys/socket/accept.h b/libc/src/sys/socket/accept.h
index c7cebc35e987cf..99789e3da70814 100644
--- a/libc/src/sys/socket/accept.h
+++ b/libc/src/sys/socket/accept.h
@@ -9,8 +9,9 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT_H
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/socket/bind.h b/libc/src/sys/socket/bind.h
index cec9c9da0c871e..619cd9f6594ec4 100644
--- a/libc/src/sys/socket/bind.h
+++ b/libc/src/sys/socket/bind.h
@@ -9,8 +9,9 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_BIND_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_BIND_H
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/socket/connect.h b/libc/src/sys/socket/connect.h
index 221f9a44cbaf9a..a91afb34589545 100644
--- a/libc/src/sys/socket/connect.h
+++ b/libc/src/sys/socket/connect.h
@@ -9,8 +9,9 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_CONNECT_H
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index 4a73f87fbd7bef..d0e77c85231091 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -19,7 +19,8 @@ add_entrypoint_object(
     ../bind.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -32,7 +33,8 @@ add_entrypoint_object(
     ../send.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -45,7 +47,8 @@ add_entrypoint_object(
     ../sendto.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -58,7 +61,7 @@ add_entrypoint_object(
     ../sendmsg.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_msghdr
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -71,7 +74,8 @@ add_entrypoint_object(
     ../connect.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -84,7 +88,8 @@ add_entrypoint_object(
     ../recv.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -97,7 +102,8 @@ add_entrypoint_object(
     ../recvfrom.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -110,7 +116,7 @@ add_entrypoint_object(
     ../recvmsg.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_msghdr
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
@@ -123,7 +129,8 @@ add_entrypoint_object(
     ../accept.h
   DEPENDS
     libc.include.sys_syscall
-    libc.include.sys_socket
+    libc.hdr.types.struct_sockaddr
+    libc.hdr.types.socklen_t
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
diff --git a/libc/src/sys/socket/linux/connect.cpp b/libc/src/sys/socket/linux/connect.cpp
index eaf422613f5e62..93cb28ab95fc31 100644
--- a/libc/src/sys/socket/linux/connect.cpp
+++ b/libc/src/sys/socket/linux/connect.cpp
@@ -9,11 +9,12 @@
 
 #include "src/sys/socket/connect.h"
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.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_DECL {
diff --git a/libc/src/sys/socket/linux/recv.cpp b/libc/src/sys/socket/linux/recv.cpp
index afefac73f3db4a..96acf449dc4bfd 100644
--- a/libc/src/sys/socket/linux/recv.cpp
+++ b/libc/src/sys/socket/linux/recv.cpp
@@ -8,11 +8,13 @@
 
 #include "src/sys/socket/recv.h"
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.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_DECL {
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
index 9b20982bb1fbf3..17489a99c922dc 100644
--- a/libc/src/sys/socket/linux/recvfrom.cpp
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -8,11 +8,13 @@
 
 #include "src/sys/socket/recvfrom.h"
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.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_DECL {
diff --git a/libc/src/sys/socket/linux/recvmsg.cpp b/libc/src/sys/socket/linux/recvmsg.cpp
index 4a2f6fabbc2da1..60045d6a80f535 100644
--- a/libc/src/sys/socket/linux/recvmsg.cpp
+++ b/libc/src/sys/socket/linux/recvmsg.cpp
@@ -8,11 +8,12 @@
 
 #include "src/sys/socket/recvmsg.h"
 
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.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_DECL {
diff --git a/libc/src/sys/socket/linux/send.cpp b/libc/src/sys/socket/linux/send.cpp
index fc5305d5cdfa3d..0d29b6fd35b903 100644
--- a/libc/src/sys/socket/linux/send.cpp
+++ b/libc/src/sys/socket/linux/send.cpp
@@ -8,11 +8,13 @@
 
 #include "src/sys/socket/send.h"
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.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_DECL {
diff --git a/libc/src/sys/socket/linux/sendmsg.cpp b/libc/src/sys/socket/linux/sendmsg.cpp
index 822a26493dddb4..ba2b37768cc246 100644
--- a/libc/src/sys/socket/linux/sendmsg.cpp
+++ b/libc/src/sys/socket/linux/sendmsg.cpp
@@ -8,11 +8,12 @@
 
 #include "src/sys/socket/sendmsg.h"
 
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.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_DECL {
diff --git a/libc/src/sys/socket/linux/sendto.cpp b/libc/src/sys/socket/linux/sendto.cpp
index bc0769bc77d1d7..f5c3ffe8954da9 100644
--- a/libc/src/sys/socket/linux/sendto.cpp
+++ b/libc/src/sys/socket/linux/sendto.cpp
@@ -8,11 +8,13 @@
 
 #include "src/sys/socket/sendto.h"
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.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_DECL {
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
index b1f36467bd574a..ee8d52157b705d 100644
--- a/libc/src/sys/socket/recvfrom.h
+++ b/libc/src/sys/socket/recvfrom.h
@@ -9,8 +9,11 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_RECVFROM_H
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
+#include <stddef.h> // For size_t
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/socket/recvmsg.h b/libc/src/sys/socket/recvmsg.h
index 0cffb7af7c3d7d..a506fb0ae68fa0 100644
--- a/libc/src/sys/socket/recvmsg.h
+++ b/libc/src/sys/socket/recvmsg.h
@@ -9,8 +9,9 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_RECVMSG_H
 
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/socket/sendmsg.h b/libc/src/sys/socket/sendmsg.h
index d902632eee0fa3..c11f3bd4beb596 100644
--- a/libc/src/sys/socket/sendmsg.h
+++ b/libc/src/sys/socket/sendmsg.h
@@ -9,8 +9,9 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_SENDMSG_H
 
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_msghdr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/socket/sendto.h b/libc/src/sys/socket/sendto.h
index 8b56362b930c97..6e5e6d4cdab66f 100644
--- a/libc/src/sys/socket/sendto.h
+++ b/libc/src/sys/socket/sendto.h
@@ -9,8 +9,11 @@
 #ifndef LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
 #define LLVM_LIBC_SRC_SYS_SOCKET_SENDTO_H
 
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
 #include "src/__support/macros/config.h"
-#include <sys/socket.h>
+#include <stddef.h> // For size_t
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
index b31b01cce5dcb5..977f895c609fc1 100644
--- a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
@@ -19,6 +19,30 @@ add_integration_test(
     libc.src.sys.socket.listen
     libc.src.sys.socket.accept
     libc.src.stdio.remove
+    libc.src.stdio.puts
+    libc.src.unistd.close
+    libc.src.unistd.fork
+)
+
+
+add_integration_test(
+  socket_sendmsg_recvmsg_test
+  SUITE
+    sys-socket-integration-tests
+  SRCS
+    socket_sendmsg_recvmsg_test.cpp
+  DEPENDS
+    libc.include.sys_socket
+    libc.src.errno.errno
+    libc.src.sys.socket.sendmsg
+    libc.src.sys.socket.recvmsg
+    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.stdio.puts
     libc.src.unistd.close
     libc.src.unistd.fork
 )
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
index 80e65e2290dacd..459738459fbf8a 100644
--- a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
+++ b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/__support/threads/sleep.h"
 
+#include "src/stdio/puts.h"
 #include "src/stdio/remove.h"
 #include "src/sys/socket/accept.h"
 #include "src/sys/socket/bind.h"
@@ -22,13 +23,13 @@
 #include "src/errno/libc_errno.h"
 #include "test/IntegrationTest/test.h"
 
-#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
 
 const char TEST_MESSAGE[] = "connection successful";
 const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
 
 void run_client(const char *SOCK_PATH) {
-  constexpr size_t SPIN_TRIES = 100;
+  constexpr size_t SPIN_TRIES = 1000;
   int result;
 
   int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
@@ -123,16 +124,21 @@ TEST_MAIN(int argc, char **argv, char **envp) {
   LIBC_NAMESPACE::remove(SOCK_PATH);
   LIBC_NAMESPACE::libc_errno = 0;
 
+  LIBC_NAMESPACE::puts("Send/Recv Test Start");
+
   // split into client and server processes.
   pid_t pid = LIBC_NAMESPACE::fork();
   ASSERT_NE(pid, -1);
   ASSERT_ERRNO_SUCCESS();
 
   if (pid == 0) { // child
+    LIBC_NAMESPACE::puts("Send/Recv Child Start");
     run_client(SOCK_PATH);
+    LIBC_NAMESPACE::puts("Send/Recv Child End");
   } else { // parent
+    LIBC_NAMESPACE::puts("Send/Recv Parent Start");
     run_server(SOCK_PATH);
+    LIBC_NAMESPACE::puts("Send/Recv Parent End");
   }
-
   return 0;
 }
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
new file mode 100644
index 00000000000000..7dc0413f8ff157
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
@@ -0,0 +1,169 @@
+//===-- Integration tests for socket functions ----------------------------===//
+//
+// 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/__support/threads/sleep.h"
+
+#include "src/stdio/puts.h"
+#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/recvmsg.h"
+#include "src/sys/socket/sendmsg.h"
+#include "src/sys/socket/socket.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/IntegrationTest/test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
+
+const char TEST_MESSAGE[] = "connection successful";
+const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+void run_client(const char *SOCK_PATH) {
+  constexpr size_t SPIN_TRIES = 1000;
+  int result;
+
+  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+  ASSERT_NE(sock, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  struct sockaddr_un my_addr;
+
+  my_addr.sun_family = AF_UNIX;
+  size_t i = 0;
+  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+    my_addr.sun_path[i] = SOCK_PATH[i];
+  my_addr.sun_path[i] = '\0';
+
+  // If the connection fails with "EAGAIN" then sleep breifly and try again, but
+  // only up to SPIN_TRIES times.
+  LIBC_NAMESPACE::libc_errno = EAGAIN;
+  for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
+       ++j, LIBC_NAMESPACE::sleep_briefly()) {
+    LIBC_NAMESPACE::libc_errno = 0;
+    result = LIBC_NAMESPACE::connect(
+        sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+        sizeof(my_addr.sun_path));
+  }
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  iovec msg_text;
+  msg_text.iov_base =
+      reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
+  msg_text.iov_len = MESSAGE_LEN;
+
+  msghdr message;
+  message.msg_name = nullptr;
+  message.msg_namelen = 0;
+  message.msg_iov = &msg_text;
+  message.msg_iovlen = 1;
+  message.msg_control = nullptr;
+  message.msg_controllen = 0;
+  message.msg_flags = 0;
+
+  ssize_t send_result = LIBC_NAMESPACE::sendmsg(sock, &message, 0);
+
+  EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+  ASSERT_ERRNO_SUCCESS();
+
+  LIBC_NAMESPACE::close(sock);
+}
+
+void run_server(const char *SOCK_PATH) {
+  int result;
+
+  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+  ASSERT_NE(sock, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  struct sockaddr_un my_addr;
+
+  my_addr.sun_family = AF_UNIX;
+  size_t i = 0;
+  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
+    my_addr.sun_path[i] = SOCK_PATH[i];
+  my_addr.sun_path[i] = '\0';
+
+  result =
+      LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
+                           sizeof(my_addr.sun_path));
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  result = LIBC_NAMESPACE::listen(sock, 1);
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  struct sockaddr connected_sock;
+  socklen_t sockaddr_len = sizeof(struct sockaddr);
+
+  int accepted_sock =
+      LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
+  ASSERT_NE(accepted_sock, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  char buffer[256];
+
+  iovec msg_text;
+  msg_text.iov_base = reinterpret_cast<void *>(buffer);
+  msg_text.iov_len = sizeof(buffer);
+
+  msghdr message;
+  message.msg_name = nullptr;
+  message.msg_namelen = 0;
+  message.msg_iov = &msg_text;
+  message.msg_iovlen = 1;
+  message.msg_control = nullptr;
+  message.msg_controllen = 0;
+  message.msg_flags = 0;
+
+  ssize_t recv_result = LIBC_NAMESPACE::recvmsg(accepted_sock, &message, 0);
+  ASSERT_EQ(recv_result, MESSAGE_LEN);
+  ASSERT_ERRNO_SUCCESS();
+
+  for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+    ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+  }
+
+  LIBC_NAMESPACE::close(sock);
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+
+  const char *FILENAME = "sendmsg_file.test";
+  // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+  auto SOCK_PATH = FILENAME;
+
+  // If the test fails, then the file for the socket may not be properly
+  // removed. This ensures a consistent start.
+  LIBC_NAMESPACE::remove(SOCK_PATH);
+  LIBC_NAMESPACE::libc_errno = 0;
+
+  LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Test Start");
+
+  // split into client and server processes.
+  pid_t pid = LIBC_NAMESPACE::fork();
+  ASSERT_NE(pid, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  if (pid == 0) { // child
+    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child Start");
+    run_client(SOCK_PATH);
+    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child End");
+  } else { // parent
+    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent Start");
+    run_server(SOCK_PATH);
+    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent End");
+  }
+  return 0;
+}

>From df5c60ae337f9b2623c636a84054dbb42c851a50 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Tue, 17 Sep 2024 11:05:48 -0700
Subject: [PATCH 4/4] move to socketpair to simplify parallelism

---
 libc/config/linux/x86_64/entrypoints.txt      |   1 +
 libc/src/sys/socket/CMakeLists.txt            |   7 +
 libc/src/sys/socket/linux/CMakeLists.txt      |  13 ++
 libc/src/sys/socket/linux/socketpair.cpp      |  43 ++++
 libc/src/sys/socket/socketpair.h              |  20 ++
 .../src/sys/socket/linux/CMakeLists.txt       |  29 ++-
 .../socket/linux/socket_send_recv_test.cpp    | 131 ++++---------
 .../linux/socket_sendmsg_recvmsg_test.cpp     | 183 ++++++------------
 .../linux/socket_sendto_recvfrom_test.cpp     |  84 ++++++++
 9 files changed, 283 insertions(+), 228 deletions(-)
 create mode 100644 libc/src/sys/socket/linux/socketpair.cpp
 create mode 100644 libc/src/sys/socket/socketpair.h
 create mode 100644 libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index d7220131046008..7e47920245f87a 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1027,6 +1027,7 @@ if(LLVM_LIBC_FULL_BUILD)
 
     # sys/socket.h entrypoints
     libc.src.sys.socket.socket
+    libc.src.sys.socket.socketpair
     libc.src.sys.socket.bind
     libc.src.sys.socket.send
     libc.src.sys.socket.sendto
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index cd877b923f9f37..7a2572fa2781b0 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -9,6 +9,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.socket
 )
 
+add_entrypoint_object(
+  socketpair
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.socketpair
+)
+
 add_entrypoint_object(
   bind
   ALIAS
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index d0e77c85231091..97d4481fec3da1 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -11,6 +11,19 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  socketpair
+  SRCS
+    socketpair.cpp
+  HDRS
+    ../socketpair.h
+  DEPENDS
+    libc.include.sys_syscall
+    libc.include.sys_socket
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   bind
   SRCS
diff --git a/libc/src/sys/socket/linux/socketpair.cpp b/libc/src/sys/socket/linux/socketpair.cpp
new file mode 100644
index 00000000000000..d459a74433906d
--- /dev/null
+++ b/libc/src/sys/socket/linux/socketpair.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of socketpair --------------------------------===//
+//
+// 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/socketpair.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/__support/macros/config.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_DECL {
+
+LLVM_LIBC_FUNCTION(int, socketpair,
+                   (int domain, int type, int protocol, int sv[2])) {
+#ifdef SYS_socketpair
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketpair, domain, type,
+                                              protocol, sv);
+#elif defined(SYS_socketcall)
+  unsigned long sockcall_args[3] = {
+      static_cast<unsigned long>(domain), static_cast<unsigned long>(type),
+      static_cast<unsigned long>(protocol), static_cast<unsigned long>(sv)};
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SOCKETPAIR,
+                                              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_DECL
diff --git a/libc/src/sys/socket/socketpair.h b/libc/src/sys/socket/socketpair.h
new file mode 100644
index 00000000000000..1d847c3284708b
--- /dev/null
+++ b/libc/src/sys/socket/socketpair.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for socketpair --------------------*- 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_SOCKETPAIR_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int socketpair(int domain, int type, int protocol, int sv[2]);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SOCKETPAIR_H
diff --git a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
index 977f895c609fc1..684ad2d48d163f 100644
--- a/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/integration/src/sys/socket/linux/CMakeLists.txt
@@ -13,17 +13,30 @@ add_integration_test(
     libc.src.errno.errno
     libc.src.sys.socket.send
     libc.src.sys.socket.recv
-    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.sys.socket.socketpair
     libc.src.stdio.remove
     libc.src.stdio.puts
     libc.src.unistd.close
     libc.src.unistd.fork
 )
 
+add_integration_test(
+  socket_sendto_recvfrom_test
+  SUITE
+    sys-socket-integration-tests
+  SRCS
+    socket_sendto_recvfrom_test.cpp
+  DEPENDS
+    libc.include.sys_socket
+    libc.src.errno.errno
+    libc.src.sys.socket.sendto
+    libc.src.sys.socket.recvfrom
+    libc.src.sys.socket.socketpair
+    libc.src.stdio.remove
+    libc.src.stdio.puts
+    libc.src.unistd.close
+    libc.src.unistd.fork
+)
 
 add_integration_test(
   socket_sendmsg_recvmsg_test
@@ -36,11 +49,7 @@ add_integration_test(
     libc.src.errno.errno
     libc.src.sys.socket.sendmsg
     libc.src.sys.socket.recvmsg
-    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.sys.socket.socketpair
     libc.src.stdio.remove
     libc.src.stdio.puts
     libc.src.unistd.close
diff --git a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
index 459738459fbf8a..25056bf589bace 100644
--- a/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
+++ b/libc/test/integration/src/sys/socket/linux/socket_send_recv_test.cpp
@@ -10,13 +10,9 @@
 
 #include "src/stdio/puts.h"
 #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/recv.h"
 #include "src/sys/socket/send.h"
-#include "src/sys/socket/socket.h"
+#include "src/sys/socket/socketpair.h"
 #include "src/unistd/close.h"
 #include "src/unistd/fork.h"
 
@@ -28,90 +24,7 @@
 const char TEST_MESSAGE[] = "connection successful";
 const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
 
-void run_client(const char *SOCK_PATH) {
-  constexpr size_t SPIN_TRIES = 1000;
-  int result;
-
-  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
-  ASSERT_NE(sock, -1);
-  ASSERT_ERRNO_SUCCESS();
-
-  struct sockaddr_un my_addr;
-
-  my_addr.sun_family = AF_UNIX;
-  size_t i = 0;
-  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
-    my_addr.sun_path[i] = SOCK_PATH[i];
-  my_addr.sun_path[i] = '\0';
-
-  // If the connection fails with "EAGAIN" then sleep breifly and try again, but
-  // only up to SPIN_TRIES times.
-  LIBC_NAMESPACE::libc_errno = EAGAIN;
-  for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
-       ++j, LIBC_NAMESPACE::sleep_briefly()) {
-    LIBC_NAMESPACE::libc_errno = 0;
-    result = LIBC_NAMESPACE::connect(
-        sock, reinterpret_cast<struct sockaddr *>(&my_addr),
-        sizeof(my_addr.sun_path));
-  }
-  ASSERT_EQ(result, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  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);
-}
-
-void run_server(const char *SOCK_PATH) {
-  int result;
-
-  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
-  ASSERT_NE(sock, -1);
-  ASSERT_ERRNO_SUCCESS();
-
-  struct sockaddr_un my_addr;
-
-  my_addr.sun_family = AF_UNIX;
-  size_t i = 0;
-  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
-    my_addr.sun_path[i] = SOCK_PATH[i];
-  my_addr.sun_path[i] = '\0';
-
-  result =
-      LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
-                           sizeof(my_addr.sun_path));
-  ASSERT_EQ(result, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  result = LIBC_NAMESPACE::listen(sock, 1);
-  ASSERT_EQ(result, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  struct sockaddr connected_sock;
-  socklen_t sockaddr_len = sizeof(struct sockaddr);
-
-  int accepted_sock =
-      LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
-  ASSERT_NE(accepted_sock, -1);
-  ASSERT_ERRNO_SUCCESS();
-
-  char buffer[256];
-
-  ssize_t recv_result =
-      LIBC_NAMESPACE::recv(accepted_sock, buffer, sizeof(buffer), 0);
-  ASSERT_EQ(recv_result, MESSAGE_LEN);
-  ASSERT_ERRNO_SUCCESS();
-
-  for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
-    ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
-  }
-
-  LIBC_NAMESPACE::close(sock);
-}
+#define SEND_TEST_NAME "Send/Recv"
 
 TEST_MAIN(int argc, char **argv, char **envp) {
 
@@ -124,7 +37,13 @@ TEST_MAIN(int argc, char **argv, char **envp) {
   LIBC_NAMESPACE::remove(SOCK_PATH);
   LIBC_NAMESPACE::libc_errno = 0;
 
-  LIBC_NAMESPACE::puts("Send/Recv Test Start");
+  int sockpair[2] = {0, 0};
+
+  int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
 
   // split into client and server processes.
   pid_t pid = LIBC_NAMESPACE::fork();
@@ -132,13 +51,33 @@ TEST_MAIN(int argc, char **argv, char **envp) {
   ASSERT_ERRNO_SUCCESS();
 
   if (pid == 0) { // child
-    LIBC_NAMESPACE::puts("Send/Recv Child Start");
-    run_client(SOCK_PATH);
-    LIBC_NAMESPACE::puts("Send/Recv Child End");
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
+    LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+
+    ssize_t send_result =
+        LIBC_NAMESPACE::send(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0);
+    EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+    ASSERT_ERRNO_SUCCESS();
+
+    LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
   } else { // parent
-    LIBC_NAMESPACE::puts("Send/Recv Parent Start");
-    run_server(SOCK_PATH);
-    LIBC_NAMESPACE::puts("Send/Recv Parent End");
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
+    LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+
+    char buffer[256];
+
+    ssize_t recv_result =
+        LIBC_NAMESPACE::recv(sockpair[1], buffer, sizeof(buffer), 0);
+    ASSERT_EQ(recv_result, MESSAGE_LEN);
+    ASSERT_ERRNO_SUCCESS();
+
+    for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+      ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+    }
+
+    LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
   }
   return 0;
 }
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
index 7dc0413f8ff157..97af9c160bc7a7 100644
--- a/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
+++ b/libc/test/integration/src/sys/socket/linux/socket_sendmsg_recvmsg_test.cpp
@@ -10,13 +10,9 @@
 
 #include "src/stdio/puts.h"
 #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/recvmsg.h"
 #include "src/sys/socket/sendmsg.h"
-#include "src/sys/socket/socket.h"
+#include "src/sys/socket/socketpair.h"
 #include "src/unistd/close.h"
 #include "src/unistd/fork.h"
 
@@ -28,119 +24,11 @@
 const char TEST_MESSAGE[] = "connection successful";
 const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
 
-void run_client(const char *SOCK_PATH) {
-  constexpr size_t SPIN_TRIES = 1000;
-  int result;
-
-  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
-  ASSERT_NE(sock, -1);
-  ASSERT_ERRNO_SUCCESS();
-
-  struct sockaddr_un my_addr;
-
-  my_addr.sun_family = AF_UNIX;
-  size_t i = 0;
-  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
-    my_addr.sun_path[i] = SOCK_PATH[i];
-  my_addr.sun_path[i] = '\0';
-
-  // If the connection fails with "EAGAIN" then sleep breifly and try again, but
-  // only up to SPIN_TRIES times.
-  LIBC_NAMESPACE::libc_errno = EAGAIN;
-  for (size_t j = 0; j < SPIN_TRIES && LIBC_NAMESPACE::libc_errno == EAGAIN;
-       ++j, LIBC_NAMESPACE::sleep_briefly()) {
-    LIBC_NAMESPACE::libc_errno = 0;
-    result = LIBC_NAMESPACE::connect(
-        sock, reinterpret_cast<struct sockaddr *>(&my_addr),
-        sizeof(my_addr.sun_path));
-  }
-  ASSERT_EQ(result, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  iovec msg_text;
-  msg_text.iov_base =
-      reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
-  msg_text.iov_len = MESSAGE_LEN;
-
-  msghdr message;
-  message.msg_name = nullptr;
-  message.msg_namelen = 0;
-  message.msg_iov = &msg_text;
-  message.msg_iovlen = 1;
-  message.msg_control = nullptr;
-  message.msg_controllen = 0;
-  message.msg_flags = 0;
-
-  ssize_t send_result = LIBC_NAMESPACE::sendmsg(sock, &message, 0);
-
-  EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
-  ASSERT_ERRNO_SUCCESS();
-
-  LIBC_NAMESPACE::close(sock);
-}
-
-void run_server(const char *SOCK_PATH) {
-  int result;
-
-  int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
-  ASSERT_NE(sock, -1);
-  ASSERT_ERRNO_SUCCESS();
-
-  struct sockaddr_un my_addr;
-
-  my_addr.sun_family = AF_UNIX;
-  size_t i = 0;
-  for (; SOCK_PATH[i] != '\0' && (i < sizeof(my_addr.sun_path)); ++i)
-    my_addr.sun_path[i] = SOCK_PATH[i];
-  my_addr.sun_path[i] = '\0';
-
-  result =
-      LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
-                           sizeof(my_addr.sun_path));
-  ASSERT_EQ(result, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  result = LIBC_NAMESPACE::listen(sock, 1);
-  ASSERT_EQ(result, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  struct sockaddr connected_sock;
-  socklen_t sockaddr_len = sizeof(struct sockaddr);
-
-  int accepted_sock =
-      LIBC_NAMESPACE::accept(sock, &connected_sock, &sockaddr_len);
-  ASSERT_NE(accepted_sock, -1);
-  ASSERT_ERRNO_SUCCESS();
-
-  char buffer[256];
-
-  iovec msg_text;
-  msg_text.iov_base = reinterpret_cast<void *>(buffer);
-  msg_text.iov_len = sizeof(buffer);
-
-  msghdr message;
-  message.msg_name = nullptr;
-  message.msg_namelen = 0;
-  message.msg_iov = &msg_text;
-  message.msg_iovlen = 1;
-  message.msg_control = nullptr;
-  message.msg_controllen = 0;
-  message.msg_flags = 0;
-
-  ssize_t recv_result = LIBC_NAMESPACE::recvmsg(accepted_sock, &message, 0);
-  ASSERT_EQ(recv_result, MESSAGE_LEN);
-  ASSERT_ERRNO_SUCCESS();
-
-  for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
-    ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
-  }
-
-  LIBC_NAMESPACE::close(sock);
-}
+#define SEND_TEST_NAME "Sendmsg/Recvmsg"
 
 TEST_MAIN(int argc, char **argv, char **envp) {
 
-  const char *FILENAME = "sendmsg_file.test";
+  const char *FILENAME = "send_file.test";
   // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
   auto SOCK_PATH = FILENAME;
 
@@ -149,7 +37,13 @@ TEST_MAIN(int argc, char **argv, char **envp) {
   LIBC_NAMESPACE::remove(SOCK_PATH);
   LIBC_NAMESPACE::libc_errno = 0;
 
-  LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Test Start");
+  int sockpair[2] = {0, 0};
+
+  int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
 
   // split into client and server processes.
   pid_t pid = LIBC_NAMESPACE::fork();
@@ -157,13 +51,58 @@ TEST_MAIN(int argc, char **argv, char **envp) {
   ASSERT_ERRNO_SUCCESS();
 
   if (pid == 0) { // child
-    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child Start");
-    run_client(SOCK_PATH);
-    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Child End");
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
+    LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+
+    iovec msg_text;
+    msg_text.iov_base =
+        reinterpret_cast<void *>(const_cast<char *>(TEST_MESSAGE));
+    msg_text.iov_len = MESSAGE_LEN;
+
+    msghdr message;
+    message.msg_name = nullptr;
+    message.msg_namelen = 0;
+    message.msg_iov = &msg_text;
+    message.msg_iovlen = 1;
+    message.msg_control = nullptr;
+    message.msg_controllen = 0;
+    message.msg_flags = 0;
+
+    ssize_t send_result = LIBC_NAMESPACE::sendmsg(sockpair[0], &message, 0);
+    EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+    ASSERT_ERRNO_SUCCESS();
+
+    LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
   } else { // parent
-    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent Start");
-    run_server(SOCK_PATH);
-    LIBC_NAMESPACE::puts("Sendmsg/Recvmsg Parent End");
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
+    LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+
+    char buffer[256];
+
+    iovec msg_text;
+    msg_text.iov_base = reinterpret_cast<void *>(buffer);
+    msg_text.iov_len = sizeof(buffer);
+
+    msghdr message;
+    message.msg_name = nullptr;
+    message.msg_namelen = 0;
+    message.msg_iov = &msg_text;
+    message.msg_iovlen = 1;
+    message.msg_control = nullptr;
+    message.msg_controllen = 0;
+    message.msg_flags = 0;
+
+    ssize_t recv_result = LIBC_NAMESPACE::recvmsg(sockpair[1], &message, 0);
+    ASSERT_EQ(recv_result, MESSAGE_LEN);
+    ASSERT_ERRNO_SUCCESS();
+
+    for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+      ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+    }
+
+    LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
   }
   return 0;
 }
diff --git a/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp b/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
new file mode 100644
index 00000000000000..0a0904ffcd5483
--- /dev/null
+++ b/libc/test/integration/src/sys/socket/linux/socket_sendto_recvfrom_test.cpp
@@ -0,0 +1,84 @@
+//===-- Integration tests for socket functions ----------------------------===//
+//
+// 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/__support/threads/sleep.h"
+
+#include "src/stdio/puts.h"
+#include "src/stdio/remove.h"
+#include "src/sys/socket/recvfrom.h"
+#include "src/sys/socket/sendto.h"
+#include "src/sys/socket/socketpair.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/IntegrationTest/test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_STREAM
+
+const char TEST_MESSAGE[] = "connection successful";
+const size_t MESSAGE_LEN = sizeof(TEST_MESSAGE);
+
+// macro for easy string pasting, we don't need printf here
+#define SEND_TEST_NAME "Sendto/Recvfrom"
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+
+  const char *FILENAME = "send_file.test";
+  // auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+  auto SOCK_PATH = FILENAME;
+
+  // If the test fails, then the file for the socket may not be properly
+  // removed. This ensures a consistent start.
+  LIBC_NAMESPACE::remove(SOCK_PATH);
+  LIBC_NAMESPACE::libc_errno = 0;
+
+  int sockpair[2] = {0, 0};
+
+  int result = LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair);
+  ASSERT_EQ(result, 0);
+  ASSERT_ERRNO_SUCCESS();
+
+  LIBC_NAMESPACE::puts(SEND_TEST_NAME " Test Start");
+
+  // split into client and server processes.
+  pid_t pid = LIBC_NAMESPACE::fork();
+  ASSERT_NE(pid, -1);
+  ASSERT_ERRNO_SUCCESS();
+
+  if (pid == 0) { // child
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child Start");
+    LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+
+    ssize_t send_result = LIBC_NAMESPACE::sendto(sockpair[0], TEST_MESSAGE,
+                                                 MESSAGE_LEN, 0, nullptr, 0);
+    EXPECT_EQ(send_result, static_cast<ssize_t>(MESSAGE_LEN));
+    ASSERT_ERRNO_SUCCESS();
+
+    LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Child End");
+  } else { // parent
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent Start");
+    LIBC_NAMESPACE::close(sockpair[0]); // close child sock
+
+    char buffer[256];
+
+    ssize_t recv_result = LIBC_NAMESPACE::recvfrom(
+        sockpair[1], buffer, sizeof(buffer), 0, nullptr, 0);
+    ASSERT_EQ(recv_result, MESSAGE_LEN);
+    ASSERT_ERRNO_SUCCESS();
+
+    for (size_t j = 0; buffer[j] != '\0' && TEST_MESSAGE[j] != '\0'; ++j) {
+      ASSERT_EQ(buffer[j], TEST_MESSAGE[j]);
+    }
+
+    LIBC_NAMESPACE::close(sockpair[1]); // close parent sock
+    LIBC_NAMESPACE::puts(SEND_TEST_NAME " Parent End");
+  }
+  return 0;
+}



More information about the libc-commits mailing list