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

Michael Jones via libc-commits libc-commits at lists.llvm.org
Wed Aug 28 16:12:34 PDT 2024


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

This patch adds the necessary functions to send and receive messages
over a socket. Those functions are: accept, bind, connect, listen, recv,
recvfrom, recvmsg, send, sendto, and sendmsg.


>From 46510503182d6ccc3c1c10765e127eab1fcc38e6 Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Wed, 7 Feb 2024 15:57:05 -0800
Subject: [PATCH] [libc] Add functions to send/recv messages

This patch adds the necessary functions to send and receive messages
over a socket. Those functions are: accept, bind, connect, listen, recv,
recvfrom, recvmsg, send, sendto, and sendmsg.
---
 libc/config/linux/api.td                      |   4 +
 libc/config/linux/x86_64/entrypoints.txt      |  11 +-
 libc/include/CMakeLists.txt                   |   2 +
 libc/include/llvm-libc-types/CMakeLists.txt   |   6 +-
 libc/include/llvm-libc-types/struct_iovec.h   |  19 +++
 libc/include/llvm-libc-types/struct_msghdr.h  |  26 ++++
 libc/newhdrgen/yaml/sys/socket.yaml           |  83 +++++++++++++
 libc/spec/posix.td                            |  31 +++++
 libc/src/sys/socket/CMakeLists.txt            |  63 ++++++++++
 libc/src/sys/socket/accept.h                  |  21 ++++
 libc/src/sys/socket/connect.h                 |  20 +++
 libc/src/sys/socket/linux/CMakeLists.txt      | 117 ++++++++++++++++++
 libc/src/sys/socket/linux/accept.cpp          |  43 +++++++
 libc/src/sys/socket/linux/bind.cpp            |   2 +-
 libc/src/sys/socket/linux/connect.cpp         |  43 +++++++
 libc/src/sys/socket/linux/listen.cpp          |  40 ++++++
 libc/src/sys/socket/linux/recv.cpp            |  45 +++++++
 libc/src/sys/socket/linux/recvfrom.cpp        |  47 +++++++
 libc/src/sys/socket/linux/recvmsg.cpp         |  41 ++++++
 libc/src/sys/socket/linux/send.cpp            |  44 +++++++
 libc/src/sys/socket/linux/sendmsg.cpp         |  41 ++++++
 libc/src/sys/socket/linux/sendto.cpp          |  47 +++++++
 libc/src/sys/socket/listen.h                  |  18 +++
 libc/src/sys/socket/recv.h                    |  20 +++
 libc/src/sys/socket/recvfrom.h                |  21 ++++
 libc/src/sys/socket/recvmsg.h                 |  20 +++
 libc/src/sys/socket/send.h                    |  20 +++
 libc/src/sys/socket/sendmsg.h                 |  20 +++
 libc/src/sys/socket/sendto.h                  |  21 ++++
 libc/test/src/sys/socket/linux/CMakeLists.txt |  20 ++-
 libc/test/src/sys/socket/linux/send_test.cpp  |  73 +++++++++++
 .../src/sys/socket/linux/sendmsg_test.cpp     |   1 +
 .../test/src/sys/socket/linux/sendto_test.cpp |   1 +
 33 files changed, 1026 insertions(+), 5 deletions(-)
 create mode 100644 libc/include/llvm-libc-types/struct_iovec.h
 create mode 100644 libc/include/llvm-libc-types/struct_msghdr.h
 create mode 100644 libc/src/sys/socket/accept.h
 create mode 100644 libc/src/sys/socket/connect.h
 create mode 100644 libc/src/sys/socket/linux/accept.cpp
 create mode 100644 libc/src/sys/socket/linux/connect.cpp
 create mode 100644 libc/src/sys/socket/linux/listen.cpp
 create mode 100644 libc/src/sys/socket/linux/recv.cpp
 create mode 100644 libc/src/sys/socket/linux/recvfrom.cpp
 create mode 100644 libc/src/sys/socket/linux/recvmsg.cpp
 create mode 100644 libc/src/sys/socket/linux/send.cpp
 create mode 100644 libc/src/sys/socket/linux/sendmsg.cpp
 create mode 100644 libc/src/sys/socket/linux/sendto.cpp
 create mode 100644 libc/src/sys/socket/listen.h
 create mode 100644 libc/src/sys/socket/recv.h
 create mode 100644 libc/src/sys/socket/recvfrom.h
 create mode 100644 libc/src/sys/socket/recvmsg.h
 create mode 100644 libc/src/sys/socket/send.h
 create mode 100644 libc/src/sys/socket/sendmsg.h
 create mode 100644 libc/src/sys/socket/sendto.h
 create mode 100644 libc/test/src/sys/socket/linux/send_test.cpp
 create mode 100644 libc/test/src/sys/socket/linux/sendmsg_test.cpp
 create mode 100644 libc/test/src/sys/socket/linux/sendto_test.cpp

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



More information about the libc-commits mailing list