[libc-commits] [libc] [libc] Add bind function (PR #74014)
via libc-commits
libc-commits at lists.llvm.org
Thu Nov 30 16:42:00 PST 2023
https://github.com/michaelrj-google created https://github.com/llvm/llvm-project/pull/74014
This patch adds the bind function to go with the socket function. It
also cleans up a lot of socket related data structures.
>From b839e06282d22f09fe52f28f6917c365c95c302c Mon Sep 17 00:00:00 2001
From: Michael Jones <michaelrj at google.com>
Date: Thu, 30 Nov 2023 16:39:01 -0800
Subject: [PATCH] [libc] Add bind function
This patch adds the bind function to go with the socket function. It
also cleans up a lot of socket related data structures.
---
libc/config/linux/api.td | 7 ++-
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/include/CMakeLists.txt | 4 +-
libc/include/llvm-libc-types/CMakeLists.txt | 2 +
libc/include/llvm-libc-types/socklen_t.h | 18 ++++++
.../include/llvm-libc-types/struct_sockaddr.h | 10 ++--
.../llvm-libc-types/struct_sockaddr_un.h | 22 ++++++++
libc/spec/posix.td | 17 +++++-
libc/src/sys/socket/CMakeLists.txt | 7 +++
libc/src/sys/socket/bind.h | 20 +++++++
libc/src/sys/socket/linux/CMakeLists.txt | 13 +++++
libc/src/sys/socket/linux/bind.cpp | 43 +++++++++++++++
libc/src/sys/socket/linux/socket.cpp | 4 +-
libc/test/src/sys/socket/linux/CMakeLists.txt | 16 ++++++
libc/test/src/sys/socket/linux/bind_test.cpp | 55 +++++++++++++++++++
.../test/src/sys/socket/linux/socket_test.cpp | 4 +-
16 files changed, 231 insertions(+), 12 deletions(-)
create mode 100644 libc/include/llvm-libc-types/socklen_t.h
create mode 100644 libc/include/llvm-libc-types/struct_sockaddr_un.h
create mode 100644 libc/src/sys/socket/bind.h
create mode 100644 libc/src/sys/socket/linux/bind.cpp
create mode 100644 libc/test/src/sys/socket/linux/bind_test.cpp
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 726e58f376eaa76..85f6b59264eb06d 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -205,7 +205,12 @@ def SysSelectAPI : PublicAPI<"sys/select.h"> {
}
def SysSocketAPI : PublicAPI<"sys/socket.h"> {
- let Types = ["struct sockaddr", "sa_family_t"];
+ let Types = [
+ "sa_family_t",
+ "socklen_t",
+ "struct sockaddr",
+ "struct sockaddr_un",
+ ];
}
def SysResourceAPI : PublicAPI<"sys/resource.h"> {
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index eb5457678e99091..58a90c1ceaa0372 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -156,6 +156,7 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/socket.h entrypoints
libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
# sys/stat.h entrypoints
libc.src.sys.stat.chmod
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 429c0f1f12866a8..59c6c4a9bb42000 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -417,8 +417,10 @@ add_gen_header(
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.sys_socket_macros
- .llvm-libc-types.struct_sockaddr
.llvm-libc-types.sa_family_t
+ .llvm-libc-types.socklen_t
+ .llvm-libc-types.struct_sockaddr
+ .llvm-libc-types.struct_sockaddr_un
)
add_gen_header(
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 225ad780c4d01f2..500900ffa0bbb05 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -89,6 +89,8 @@ add_header(__getoptargv_t HDR __getoptargv_t.h)
add_header(wchar_t HDR wchar_t.h)
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(rpc_opcodes_t HDR rpc_opcodes_t.h)
add_header(ACTION HDR ACTION.h)
diff --git a/libc/include/llvm-libc-types/socklen_t.h b/libc/include/llvm-libc-types/socklen_t.h
new file mode 100644
index 000000000000000..3134a53390e71ed
--- /dev/null
+++ b/libc/include/llvm-libc-types/socklen_t.h
@@ -0,0 +1,18 @@
+//===-- Definition of socklen_t type ------------------------------------===//
+//
+// 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_SOCKLEN_T_H__
+#define __LLVM_LIBC_TYPES_SOCKLEN_T_H__
+
+// The posix standard only says of socklen_t that it must be an integer type of
+// width of at least 32 bits. The long type is defined as being at least 32
+// bits, so an unsigned long should be fine.
+
+typedef unsigned long socklen_t;
+
+#endif // __LLVM_LIBC_TYPES_SOCKLEN_T_H__
diff --git a/libc/include/llvm-libc-types/struct_sockaddr.h b/libc/include/llvm-libc-types/struct_sockaddr.h
index 1ef907904ca3ec1..9a6214c7d3e6b9b 100644
--- a/libc/include/llvm-libc-types/struct_sockaddr.h
+++ b/libc/include/llvm-libc-types/struct_sockaddr.h
@@ -1,4 +1,4 @@
-//===-- Definition of struct stat -----------------------------------------===//
+//===-- Definition of 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.
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef __LLVM_LIBC_TYPES_STRUCT_STAT_H__
-#define __LLVM_LIBC_TYPES_STRUCT_STAT_H__
+#ifndef __LLVM_LIBC_TYPES_STRUCT_SOCKADDR_H__
+#define __LLVM_LIBC_TYPES_STRUCT_SOCKADDR_H__
#include <llvm-libc-types/sa_family_t.h>
@@ -15,7 +15,7 @@ struct sockaddr {
sa_family_t sa_family;
// sa_data is a variable length array. It is provided with a length of one
// here as a placeholder.
- char sa_data[1];
+ char sa_data[];
};
-#endif // __LLVM_LIBC_TYPES_STRUCT_STAT_H__
+#endif // __LLVM_LIBC_TYPES_STRUCT_SOCKADDR_H__
diff --git a/libc/include/llvm-libc-types/struct_sockaddr_un.h b/libc/include/llvm-libc-types/struct_sockaddr_un.h
new file mode 100644
index 000000000000000..9c3efea279256ec
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_sockaddr_un.h
@@ -0,0 +1,22 @@
+//===-- Definition of struct sockaddr_un ----------------------------------===//
+//
+// 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_SOCKADDR_UN_H__
+#define __LLVM_LIBC_TYPES_STRUCT_SOCKADDR_UN_H__
+
+#include <llvm-libc-types/sa_family_t.h>
+
+// This is the sockaddr specialization for AF_UNIX or AF_LOCAL sockets, as
+// defined by posix.
+
+struct sockaddr_un {
+ sa_family_t sun_family; /* AF_UNIX */
+ char sun_path[108]; /* Pathname */
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_SOCKADDR_UN_H__
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index c7acf6d25a2d873..7e1cf892135acf9 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -81,9 +81,14 @@ def RestrictedFdSetPtr : RestrictedPtrType<FdSet>;
def GetoptArgvT : NamedType<"__getoptargv_t">;
+def SAFamilyType : NamedType<"sa_family_t">;
+def SocklenType : NamedType<"socklen_t">;
+
def StructSockAddr : NamedType<"struct sockaddr">;
def StructSockAddrPtr : PtrType<StructSockAddr>;
-def SAFamilyType : NamedType<"sa_family_t">;
+def ConstStructSockAddrPtr : ConstType<StructSockAddrPtr>;
+
+def StructSockAddrUn : NamedType<"struct sockaddr_un">;
def POSIX : StandardSpec<"POSIX"> {
PtrType CharPtr = PtrType<CharType>;
@@ -1400,7 +1405,10 @@ def POSIX : StandardSpec<"POSIX"> {
Macro<"SOCK_PACKET">,
], // Macros
[
- StructSockAddr, SAFamilyType,
+ SAFamilyType,
+ StructSockAddr,
+ StructSockAddrUn,
+ SocklenType,
], // Types
[], // Enumerations
[
@@ -1409,6 +1417,11 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<IntType>,
[ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<IntType>]
>,
+ FunctionSpec<
+ "bind",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<ConstStructSockAddrPtr>, ArgSpec<SocklenType>]
+ >,
] // Functions
>;
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index 7079d6e4466c683..d9e9922582074e8 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -9,3 +9,10 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.socket
)
+add_entrypoint_object(
+ bind
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.bind
+)
+
diff --git a/libc/src/sys/socket/bind.h b/libc/src/sys/socket/bind.h
new file mode 100644
index 000000000000000..62e6221bf1b2d74
--- /dev/null
+++ b/libc/src/sys/socket/bind.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for bind --------------------------*- 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_BIND_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_BIND_H
+
+#include <sys/socket.h>
+
+namespace LIBC_NAMESPACE {
+
+int bind(int domain, const struct sockaddr *address, socklen_t address_len);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_BIND_H
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index 41bcc9c9055f476..fc9febdec2cc3c3 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -10,3 +10,16 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ bind
+ SRCS
+ bind.cpp
+ HDRS
+ ../bind.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/bind.cpp b/libc/src/sys/socket/linux/bind.cpp
new file mode 100644
index 000000000000000..36afc646d29f6d0
--- /dev/null
+++ b/libc/src/sys/socket/linux/bind.cpp
@@ -0,0 +1,43 @@
+//===-- Linux implementation of bind --------------------------------------===//
+//
+// 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/bind.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, bind,
+ (int domain, const struct sockaddr *address,
+ socklen_t address_len)) {
+#ifdef SYS_socket
+ int ret =
+ LIBC_NAMESPACE::syscall_impl<int>(SYS_bind, 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_BIND,
+ 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/socket.cpp b/libc/src/sys/socket/linux/socket.cpp
index 6429fd12013ea04..90a7dc632e26960 100644
--- a/libc/src/sys/socket/linux/socket.cpp
+++ b/libc/src/sys/socket/linux/socket.cpp
@@ -23,7 +23,9 @@ LLVM_LIBC_FUNCTION(int, socket, (int domain, int type, int protocol)) {
int ret =
LIBC_NAMESPACE::syscall_impl<int>(SYS_socket, domain, type, protocol);
#elif defined(SYS_socketcall)
- unsigned long sockcall_args[3] = {domain, type, protocol};
+ unsigned long sockcall_args[3] = {static_cast<unsigned long>(domain),
+ static_cast<unsigned long>(type),
+ static_cast<unsigned long>(protocol)};
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_SOCKET,
sockcall_args);
#else
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 4380597e5515799..666dc28c7e4ee19 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -12,3 +12,19 @@ add_libc_unittest(
libc.src.sys.socket.socket
libc.src.unistd.close
)
+
+
+add_libc_unittest(
+ bind_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ bind_test.cpp
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.errno.errno
+ libc.src.sys.socket.socket
+ libc.src.sys.socket.bind
+ libc.src.stdio.remove
+ libc.src.unistd.close
+)
diff --git a/libc/test/src/sys/socket/linux/bind_test.cpp b/libc/test/src/sys/socket/linux/bind_test.cpp
new file mode 100644
index 000000000000000..5a3a1c227c9b58e
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/bind_test.cpp
@@ -0,0 +1,55 @@
+//===-- Unittests for bind ------------------------------------------------===//
+//
+// 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/bind.h"
+#include "src/sys/socket/socket.h"
+
+#include "src/stdio/remove.h"
+#include "src/unistd/close.h"
+
+#include "src/errno/libc_errno.h"
+#include "test/UnitTest/LibcTest.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
+
+TEST(LlvmLibcSocketTest, BindLocalSocket) {
+
+ const char *FILENAME = "bind_file.test";
+ auto SOCK_PATH = libc_make_test_file_path(FILENAME);
+
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0);
+ ASSERT_GE(sock, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ 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));
+
+ ASSERT_EQ(result, 0);
+ ASSERT_EQ(libc_errno, 0);
+
+ LIBC_NAMESPACE::close(sock);
+
+ LIBC_NAMESPACE::remove(SOCK_PATH);
+}
diff --git a/libc/test/src/sys/socket/linux/socket_test.cpp b/libc/test/src/sys/socket/linux/socket_test.cpp
index 9037888441a357f..9d5bfacde0a4099 100644
--- a/libc/test/src/sys/socket/linux/socket_test.cpp
+++ b/libc/test/src/sys/socket/linux/socket_test.cpp
@@ -13,10 +13,10 @@
#include "src/errno/libc_errno.h"
#include "test/UnitTest/Test.h"
-#include <sys/socket.h> // For AF_LOCAL and SOCK_DGRAM
+#include <sys/socket.h> // For AF_UNIX and SOCK_DGRAM
TEST(LlvmLibcSocketTest, LocalSocket) {
- int sock = LIBC_NAMESPACE::socket(AF_LOCAL, SOCK_DGRAM, 0);
+ int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0);
ASSERT_GE(sock, 0);
ASSERT_EQ(libc_errno, 0);
More information about the libc-commits
mailing list