[libc-commits] [libc] [libc] Add if_nameindex and if_freenameindex as an experimental entrypoint (PR #208438)
via libc-commits
libc-commits at lists.llvm.org
Thu Jul 9 04:58:24 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Pavel Labath (labath)
<details>
<summary>Changes</summary>
This is a fairly complex function, so this patch implements bare minimum needed to demonstrate the overall direction. The functionality is implemented by communicating with the linux kernel over a netlink socket, and the complexity comes from parsing the messages. In this patch, parsing stops at the first interface, and we don't handle multiple messages or deduplication resulting from restarted dumps.
Some notable implementation choices are:
- using a single allocation (including both the interface vector and the strings it points to). This makes deallocation fast, reduces heap fragmentation, and doesn't make the final code much more complex since we still need auxiliary data structures for deduplication.
- using linux kernel headers for all the netlink structures. I think this is fine as we're not exposing that to the user.
- while this information is available via /sys, that would mean we require /sys to be mounted, and it wouldn't make the code much simpler. This also matches other libc implementations.
Testing is a completely separate story, and the main source of complexity of this patch. To make the code testable without requiring root or live interfaces, the core function
(`net::if_nameindex<Policy>()`) is templated on a syscall policy class (`NetworkSyscallPolicy`). The production entrypoint uses `DefaultNetworkSyscallPolicy` forwarding directly to syscall wrappers (`socket`, `sendto`, `recvfrom`, `close`), while the unit tests use `FakeNetworkSyscallPolicy` to feed crafted netlink buffers from memory and verify `sendto` request formation.
The fake policy is set up such that one can program the mock to return certain values, and validate arguments. It does not resemble the googletest functionality (mocks) very closely, but I've tried to put it in a form where it is possible to morph it into that -- if that's the direction we desire to go.
While doing this, I ran into the limitations of various container classes (mainly the inability to handle non-trivial types). To avoid growing the scope of this even further, I worked around those limitations locally, and left TODOs which I intend to resolve in follow-ups. The only thing I couldn't avoid is the addition of cpp::expected default constructor (which is actually a consequence of how FixedVector constructs elements). However, this is a simple addition and it is consistent with the STL class it is emulating.
---
Patch is 42.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/208438.diff
22 Files Affected:
- (modified) libc/config/linux/aarch64/entrypoints.txt (+4)
- (modified) libc/config/linux/riscv/entrypoints.txt (+4)
- (modified) libc/config/linux/x86_64/entrypoints.txt (+4)
- (modified) libc/hdr/types/CMakeLists.txt (+9)
- (added) libc/hdr/types/struct_if_nameindex.h (+26)
- (modified) libc/include/CMakeLists.txt (+1)
- (modified) libc/include/llvm-libc-macros/linux/sys-socket-macros.h (+7-5)
- (modified) libc/include/llvm-libc-types/CMakeLists.txt (+1)
- (added) libc/include/llvm-libc-types/struct_if_nameindex.h (+22)
- (modified) libc/include/net/if.yaml (+12)
- (modified) libc/src/__support/CPP/expected.h (+1)
- (modified) libc/src/__support/OSUtil/linux/CMakeLists.txt (+16)
- (added) libc/src/__support/OSUtil/linux/network_syscall_policy.h (+58)
- (modified) libc/src/net/CMakeLists.txt (+14)
- (added) libc/src/net/if_freenameindex.h (+26)
- (added) libc/src/net/if_nameindex.h (+26)
- (modified) libc/src/net/linux/CMakeLists.txt (+46)
- (added) libc/src/net/linux/if_freenameindex.cpp (+26)
- (added) libc/src/net/linux/if_nameindex.cpp (+32)
- (added) libc/src/net/linux/if_nameindex.h (+142)
- (modified) libc/test/src/net/linux/CMakeLists.txt (+27)
- (added) libc/test/src/net/linux/if_nameindex_test.cpp (+514)
``````````diff
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index af89add35f01e..8387e7f08b993 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1311,6 +1311,10 @@ endif()
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
if(LLVM_LIBC_FULL_BUILD)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # net/if.h entrypoints
+ libc.src.net.if_freenameindex
+ libc.src.net.if_nameindex
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 15e774fb453b7..9a8fbd7344ec8 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1445,6 +1445,10 @@ endif()
if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
if(LLVM_LIBC_FULL_BUILD)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # net/if.h entrypoints
+ libc.src.net.if_freenameindex
+ libc.src.net.if_nameindex
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index ae457e1cb79e0..290653a1f01e8 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1541,6 +1541,10 @@ if(LLVM_LIBC_ENABLE_EXPERIMENTAL_ENTRYPOINTS)
if(LLVM_LIBC_FULL_BUILD)
list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # net/if.h entrypoints
+ libc.src.net.if_freenameindex
+ libc.src.net.if_nameindex
+
# regex.h entrypoints
libc.src.regex.regcomp
libc.src.regex.regexec
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 5a6b17ef67f2d..8f61cca3364ae 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -547,6 +547,15 @@ add_proxy_header_library(
libc.include.net_if
)
+add_proxy_header_library(
+ struct_if_nameindex
+ HDRS
+ struct_if_nameindex.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_if_nameindex
+ libc.include.net_if
+)
+
add_proxy_header_library(
struct_sockaddr
HDRS
diff --git a/libc/hdr/types/struct_if_nameindex.h b/libc/hdr/types/struct_if_nameindex.h
new file mode 100644
index 0000000000000..569e33a7c53ed
--- /dev/null
+++ b/libc/hdr/types/struct_if_nameindex.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Proxy for struct if_nameindex.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_IF_NAMEINDEX_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_IF_NAMEINDEX_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_if_nameindex.h"
+
+#else
+
+#include <net/if.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_IF_NAMEINDEX_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 57310e6c6291b..053df1b63f256 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -905,6 +905,7 @@ add_header_macro(
DEPENDS
.llvm_libc_common_h
.llvm-libc-macros.net_if_macros
+ .llvm-libc-types.struct_if_nameindex
.llvm-libc-types.struct_ifreq
)
diff --git a/libc/include/llvm-libc-macros/linux/sys-socket-macros.h b/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
index 5478521be02b6..2c7d55c114328 100644
--- a/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
+++ b/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
@@ -12,11 +12,12 @@
// IEEE Std 1003.1-2017 - basedefs/sys_socket.h.html
// Macro values come from the Linux syscall interface.
-#define AF_UNSPEC 0 // Unspecified
-#define AF_UNIX 1 // Unix domain sockets
-#define AF_LOCAL 1 // POSIX name for AF_UNIX
-#define AF_INET 2 // Internet IPv4 Protocol
-#define AF_INET6 10 // IP version 6
+#define AF_UNSPEC 0 // Unspecified
+#define AF_UNIX 1 // Unix domain sockets
+#define AF_LOCAL 1 // POSIX name for AF_UNIX
+#define AF_INET 2 // Internet IPv4 Protocol
+#define AF_INET6 10 // IP version 6
+#define AF_NETLINK 16 // Netlink sockets
// 4.2BSD protocol families
#define PF_UNSPEC AF_UNSPEC
@@ -24,6 +25,7 @@
#define PF_LOCAL AF_LOCAL
#define PF_INET AF_INET
#define PF_INET6 AF_INET6
+#define PF_NETLINK AF_NETLINK
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 5ea8ca0634834..855af87d35429 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -227,6 +227,7 @@ add_header(
add_header(struct_sockaddr_storage HDR struct_sockaddr_storage.h DEPENDS .sa_family_t)
add_header(struct_sockaddr_un HDR struct_sockaddr_un.h DEPENDS .sa_family_t)
add_header(struct_ifreq HDR struct_ifreq.h DEPENDS libc.include.llvm-libc-macros.net_if_macros .struct_sockaddr)
+add_header(struct_if_nameindex HDR struct_if_nameindex.h)
add_header(struct_iovec HDR struct_iovec.h DEPENDS .size_t)
add_header(struct_linger HDR struct_linger.h)
add_header(struct_cmsghdr HDR struct_cmsghdr.h DEPENDS .size_t)
diff --git a/libc/include/llvm-libc-types/struct_if_nameindex.h b/libc/include/llvm-libc-types/struct_if_nameindex.h
new file mode 100644
index 0000000000000..c876a0ece541b
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_if_nameindex.h
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definition of struct if_nameindex.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_STRUCT_IF_NAMEINDEX_H
+#define LLVM_LIBC_TYPES_STRUCT_IF_NAMEINDEX_H
+
+struct if_nameindex {
+ unsigned int if_index;
+ char *if_name;
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_IF_NAMEINDEX_H
diff --git a/libc/include/net/if.yaml b/libc/include/net/if.yaml
index 51034d84e4428..3b6d807e2fceb 100644
--- a/libc/include/net/if.yaml
+++ b/libc/include/net/if.yaml
@@ -6,9 +6,16 @@ macros:
macro_header: net-if-macros.h
types:
- type_name: struct_ifreq
+ - type_name: struct_if_nameindex
enums: []
objects: []
functions:
+ - name: if_freenameindex
+ standards:
+ - posix
+ return_type: void
+ arguments:
+ - type: struct if_nameindex *
- name: if_indextoname
standards:
- posix
@@ -16,6 +23,11 @@ functions:
arguments:
- type: unsigned int
- type: char *
+ - name: if_nameindex
+ standards:
+ - posix
+ return_type: struct if_nameindex *
+ arguments: []
- name: if_nametoindex
standards:
- posix
diff --git a/libc/src/__support/CPP/expected.h b/libc/src/__support/CPP/expected.h
index 8a93091f0ebfb..a8fac975b7478 100644
--- a/libc/src/__support/CPP/expected.h
+++ b/libc/src/__support/CPP/expected.h
@@ -35,6 +35,7 @@ template <class T, class E> class expected {
bool is_expected;
public:
+ LIBC_INLINE constexpr expected() : exp(), is_expected(true) {}
LIBC_INLINE constexpr expected(T exp) : exp(exp), is_expected(true) {}
LIBC_INLINE constexpr expected(unexpected<E> unexp)
: unexp(unexp.error()), is_expected(false) {}
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index 1f11067f0154f..de9d8f4f477b7 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -44,6 +44,22 @@ add_header_library(
libc.src.__support.threads.callonce
)
+add_header_library(
+ network_syscall_policy
+ HDRS
+ network_syscall_policy.h
+ DEPENDS
+ libc.hdr.types.socklen_t
+ libc.hdr.types.ssize_t
+ libc.hdr.types.struct_sockaddr
+ libc.src.__support.OSUtil.linux.syscall_wrappers.close
+ libc.src.__support.OSUtil.linux.syscall_wrappers.recvfrom
+ libc.src.__support.OSUtil.linux.syscall_wrappers.sendto
+ libc.src.__support.OSUtil.linux.syscall_wrappers.socket
+ libc.src.__support.common
+ libc.src.__support.error_or
+)
+
add_header_library(
path
HDRS
diff --git a/libc/src/__support/OSUtil/linux/network_syscall_policy.h b/libc/src/__support/OSUtil/linux/network_syscall_policy.h
new file mode 100644
index 0000000000000..f02111800db3a
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/network_syscall_policy.h
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Policy class wrapper for network-related system calls.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_NETWORK_SYSCALL_POLICY_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_NETWORK_SYSCALL_POLICY_H
+
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_sockaddr.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/recvfrom.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/sendto.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/socket.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace net {
+
+struct DefaultNetworkSyscallPolicy {
+ LIBC_INLINE static ErrorOr<int> socket(int domain, int type, int protocol) {
+ return linux_syscalls::socket(domain, type, protocol);
+ }
+
+ LIBC_INLINE static ErrorOr<ssize_t> sendto(int fd, const void *buf,
+ size_t len, int flags,
+ const struct sockaddr *dest_addr,
+ socklen_t addrlen) {
+ return linux_syscalls::sendto(fd, buf, len, flags, dest_addr, addrlen);
+ }
+
+ LIBC_INLINE static ErrorOr<ssize_t> recvfrom(int fd, void *buf, size_t len,
+ int flags,
+ struct sockaddr *src_addr,
+ socklen_t *addrlen) {
+ return linux_syscalls::recvfrom(fd, buf, len, flags, src_addr, addrlen);
+ }
+
+ LIBC_INLINE static ErrorOr<int> close(int fd) {
+ return linux_syscalls::close(fd);
+ }
+};
+
+} // namespace net
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_NETWORK_SYSCALL_POLICY_H
diff --git a/libc/src/net/CMakeLists.txt b/libc/src/net/CMakeLists.txt
index 2173a111cff4f..2860ba2be02cb 100644
--- a/libc/src/net/CMakeLists.txt
+++ b/libc/src/net/CMakeLists.txt
@@ -15,3 +15,17 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.if_nametoindex
)
+
+add_entrypoint_object(
+ if_nameindex
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.if_nameindex
+)
+
+add_entrypoint_object(
+ if_freenameindex
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.if_freenameindex
+)
diff --git a/libc/src/net/if_freenameindex.h b/libc/src/net/if_freenameindex.h
new file mode 100644
index 0000000000000..eb0ac7eb2ddd4
--- /dev/null
+++ b/libc/src/net/if_freenameindex.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for if_freenameindex.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NET_IF_FREENAMEINDEX_H
+#define LLVM_LIBC_SRC_NET_IF_FREENAMEINDEX_H
+
+#include "hdr/types/struct_if_nameindex.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+void if_freenameindex(struct if_nameindex *ptr);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NET_IF_FREENAMEINDEX_H
diff --git a/libc/src/net/if_nameindex.h b/libc/src/net/if_nameindex.h
new file mode 100644
index 0000000000000..bf6cf034e64c1
--- /dev/null
+++ b/libc/src/net/if_nameindex.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for if_nameindex.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NET_IF_NAMEINDEX_H
+#define LLVM_LIBC_SRC_NET_IF_NAMEINDEX_H
+
+#include "hdr/types/struct_if_nameindex.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+struct if_nameindex *if_nameindex();
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NET_IF_NAMEINDEX_H
diff --git a/libc/src/net/linux/CMakeLists.txt b/libc/src/net/linux/CMakeLists.txt
index 9c82636d1c54c..8dd040ef3908f 100644
--- a/libc/src/net/linux/CMakeLists.txt
+++ b/libc/src/net/linux/CMakeLists.txt
@@ -42,3 +42,49 @@ add_entrypoint_object(
libc.src.errno.errno
libc.src.string.memory_utils.inline_memcpy
)
+
+add_header_library(
+ if_nameindex_internal
+ HDRS
+ if_nameindex.h
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.hdr.net_if_macros
+ libc.hdr.sys_socket_macros
+ libc.hdr.types.socklen_t
+ libc.hdr.types.ssize_t
+ libc.hdr.types.struct_if_nameindex
+ libc.src.__support.CPP.new
+ libc.src.__support.CPP.scope
+ libc.src.__support.alloc_checker
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.string.memory_utils.inline_memcpy
+ libc.src.string.memory_utils.inline_memset
+ libc.src.string.string_utils
+)
+
+add_entrypoint_object(
+ if_nameindex
+ SRCS
+ if_nameindex.cpp
+ HDRS
+ ../if_nameindex.h
+ DEPENDS
+ .if_nameindex_internal
+ libc.hdr.types.struct_if_nameindex
+ libc.src.__support.OSUtil.linux.network_syscall_policy
+ libc.src.__support.error_or
+ libc.src.errno.errno
+)
+
+add_entrypoint_object(
+ if_freenameindex
+ SRCS
+ if_freenameindex.cpp
+ HDRS
+ ../if_freenameindex.h
+ DEPENDS
+ libc.hdr.types.struct_if_nameindex
+ libc.src.__support.CPP.new
+)
diff --git a/libc/src/net/linux/if_freenameindex.cpp b/libc/src/net/linux/if_freenameindex.cpp
new file mode 100644
index 0000000000000..0090f4a7430da
--- /dev/null
+++ b/libc/src/net/linux/if_freenameindex.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of if_freenameindex.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/net/if_freenameindex.h"
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/struct_if_nameindex.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(void, if_freenameindex, (struct if_nameindex * ptr)) {
+ delete[] reinterpret_cast<uint8_t *>(ptr);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/net/linux/if_nameindex.cpp b/libc/src/net/linux/if_nameindex.cpp
new file mode 100644
index 0000000000000..2a9ffcd8047f2
--- /dev/null
+++ b/libc/src/net/linux/if_nameindex.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of if_nameindex.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/net/if_nameindex.h"
+#include "src/__support/OSUtil/linux/network_syscall_policy.h"
+#include "src/__support/error_or.h"
+#include "src/__support/libc_errno.h"
+#include "src/net/linux/if_nameindex.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(struct if_nameindex *, if_nameindex, ()) {
+ ErrorOr<struct if_nameindex *> result =
+ net::if_nameindex<net::DefaultNetworkSyscallPolicy>();
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return nullptr;
+ }
+ return *result;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/net/linux/if_nameindex.h b/libc/src/net/linux/if_nameindex.h
new file mode 100644
index 0000000000000..4b9c43ebbfbed
--- /dev/null
+++ b/libc/src/net/linux/if_nameindex.h
@@ -0,0 +1,142 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Internal templatized implementation of if_nameindex for Linux.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NET_LINUX_IF_NAMEINDEX_H
+#define LLVM_LIBC_SRC_NET_LINUX_IF_NAMEINDEX_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/net_if_macros.h"
+#include "hdr/sys_socket_macros.h"
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_if_nameindex.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/CPP/scope.h"
+#include "src/__support/alloc-checker.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/string/memory_utils/inline_memcpy.h"
+#include "src/string/memory_utils/inline_memset.h"
+#include "src/string/string_utils.h"
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace net {
+
+template <typename Policy> ErrorOr<struct if_nameindex *> if_nameindex() {
+ ErrorOr<int> fd_or_err =
+ Policy::socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
+ if (!fd_or_err.has_value())
+ return Error(fd_or_err.error());
+ int fd = *fd_or_err;
+ cpp::scope_exit close_fd([fd]() { Policy::close(fd); });
+
+ struct {
+ struct nlmsghdr nlh;
+ struct ifinfomsg ifm;
+ } req = {};
+ static_assert(sizeof(req) >= NLMSG_LENGTH(sizeof(req.ifm)));
+ req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifm));
+ req.nlh.nlmsg_type = RTM_GETLINK;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ req.ifm.ifi_family = AF_UNSPEC;
+
+ ErrorOr<ssize_t> send_res =
+ Policy::sendto(fd, &req, req.nlh.nlmsg_len, 0, nullptr, 0);
+ if (!send_res.has_value())
+ return Error(send_res.error());
+
+ alignas(struct nlmsghdr) uint8_t buf[4096];
+ ErrorOr<ssize_t> recv_res =
+ Policy::recvfrom(fd, buf, sizeof(buf), 0, nullptr, nullptr);
+ if (!recv_res.has_value())
+ return Error(recv_res.error());
+
+ close_fd.re...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/208438
More information about the libc-commits
mailing list