[libc-commits] [libc] [libc] Implement if_nametoindex and if_indextoname (PR #206082)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Tue Jun 30 03:05:12 PDT 2026


https://github.com/labath updated https://github.com/llvm/llvm-project/pull/206082

>From e28bca53b3a97db0d4f50c226f7c4c5b05fb5475 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 22 Jun 2026 08:52:03 +0000
Subject: [PATCH] [libc] Implement if_nametoindex and if_indextoname

This patch implements if_nametoindex and if_indextoname for Linux.

Both functions work by creating a temporary AF_UNIX socket and issuing
ioctl calls (SIOCGIFINDEX and SIOCGIFNAME, respectively).

The main implementation details:
- for if_nametoindex, I check that the interface name fits within
  IF_NAMESIZE before issuing the ioctl
- for if_indextoname, if the kernel returns ENODEV for an unknown
  index, I map it to ENXIO to comply with POSIX requirements
- added the definition of struct ifreq to support these operations.
  Similar to the other net structure definitions, I'm using an anonymous
  union to avoid #defining members.

Assisted by Gemini.
---
 libc/config/linux/aarch64/entrypoints.txt     |  4 ++
 libc/config/linux/riscv/entrypoints.txt       |  4 ++
 libc/config/linux/x86_64/entrypoints.txt      |  4 ++
 libc/hdr/CMakeLists.txt                       |  9 +++
 libc/hdr/net_if_macros.h                      | 22 ++++++
 libc/hdr/types/CMakeLists.txt                 |  9 +++
 libc/hdr/types/struct_ifreq.h                 | 26 +++++++
 libc/include/CMakeLists.txt                   | 12 ++++
 libc/include/llvm-libc-macros/CMakeLists.txt  |  6 ++
 .../llvm-libc-macros/linux/CMakeLists.txt     |  6 ++
 .../llvm-libc-macros/linux/net-if-macros.h    | 19 ++++++
 libc/include/llvm-libc-macros/net-if-macros.h | 21 ++++++
 libc/include/llvm-libc-types/CMakeLists.txt   |  1 +
 libc/include/llvm-libc-types/struct_ifreq.h   | 40 +++++++++++
 libc/include/net/if.yaml                      | 24 +++++++
 libc/src/CMakeLists.txt                       |  1 +
 libc/src/net/CMakeLists.txt                   | 17 +++++
 libc/src/net/if_indextoname.h                 | 25 +++++++
 libc/src/net/if_nametoindex.h                 | 25 +++++++
 libc/src/net/linux/CMakeLists.txt             | 44 ++++++++++++
 libc/src/net/linux/if_indextoname.cpp         | 68 +++++++++++++++++++
 libc/src/net/linux/if_nametoindex.cpp         | 62 +++++++++++++++++
 libc/test/src/CMakeLists.txt                  |  1 +
 libc/test/src/net/CMakeLists.txt              |  4 ++
 libc/test/src/net/linux/CMakeLists.txt        | 27 ++++++++
 .../src/net/linux/if_indextoname_test.cpp     | 51 ++++++++++++++
 .../src/net/linux/if_nametoindex_test.cpp     | 42 ++++++++++++
 27 files changed, 574 insertions(+)
 create mode 100644 libc/hdr/net_if_macros.h
 create mode 100644 libc/hdr/types/struct_ifreq.h
 create mode 100644 libc/include/llvm-libc-macros/linux/net-if-macros.h
 create mode 100644 libc/include/llvm-libc-macros/net-if-macros.h
 create mode 100644 libc/include/llvm-libc-types/struct_ifreq.h
 create mode 100644 libc/include/net/if.yaml
 create mode 100644 libc/src/net/CMakeLists.txt
 create mode 100644 libc/src/net/if_indextoname.h
 create mode 100644 libc/src/net/if_nametoindex.h
 create mode 100644 libc/src/net/linux/CMakeLists.txt
 create mode 100644 libc/src/net/linux/if_indextoname.cpp
 create mode 100644 libc/src/net/linux/if_nametoindex.cpp
 create mode 100644 libc/test/src/net/CMakeLists.txt
 create mode 100644 libc/test/src/net/linux/CMakeLists.txt
 create mode 100644 libc/test/src/net/linux/if_indextoname_test.cpp
 create mode 100644 libc/test/src/net/linux/if_nametoindex_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 8ac16f5401b87..304c951171ad3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1028,6 +1028,10 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.arpa.inet.ntohl
     libc.src.arpa.inet.ntohs
 
+    # net/if.h entrypoints
+    libc.src.net.if_indextoname
+    libc.src.net.if_nametoindex
+
     # netinet/in.h entrypoints
     libc.src.netinet.in6addr_any
     libc.src.netinet.in6addr_loopback
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index f87bc98052193..eb2deb5576de9 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1161,6 +1161,10 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.arpa.inet.ntohl
     libc.src.arpa.inet.ntohs
 
+    # net/if.h entrypoints
+    libc.src.net.if_indextoname
+    libc.src.net.if_nametoindex
+
     # netinet/in.h entrypoints
     libc.src.netinet.in6addr_any
     libc.src.netinet.in6addr_loopback
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index ea95855da8ef8..6ab026fca8c55 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -41,6 +41,10 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.fcntl.open
     libc.src.fcntl.openat
 
+    # net/if.h entrypoints
+    libc.src.net.if_indextoname
+    libc.src.net.if_nametoindex
+
     # netinet/in.h entrypoints
     libc.src.netinet.in6addr_any
     libc.src.netinet.in6addr_loopback
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index cf3e76d5c005b..1885e65cdfacd 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -77,6 +77,15 @@ add_proxy_header_library(
     libc.include.fenv
 )
 
+add_proxy_header_library(
+  net_if_macros
+  HDRS
+    net_if_macros.h
+  FULL_BUILD_DEPENDS
+    libc.include.net_if
+    libc.include.llvm-libc-macros.net_if_macros
+)
+
 add_proxy_header_library(
   netinet_in_macros
   HDRS
diff --git a/libc/hdr/net_if_macros.h b/libc/hdr/net_if_macros.h
new file mode 100644
index 0000000000000..e87f486088dc4
--- /dev/null
+++ b/libc/hdr/net_if_macros.h
@@ -0,0 +1,22 @@
+//===-- Definition of macros from net/if.h --------------------------------===//
+//
+// 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_NET_IF_MACROS_H
+#define LLVM_LIBC_HDR_NET_IF_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/net-if-macros.h"
+
+#else // Overlay mode
+
+#include <net/if.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_NET_IF_MACROS_H
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index a130f7ee0000a..49d8583db1204 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -509,6 +509,15 @@ add_proxy_header_library(
     libc.include.arpa_inet
 )
 
+add_proxy_header_library(
+  struct_ifreq
+  HDRS
+    struct_ifreq.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.struct_ifreq
+    libc.include.net_if
+)
+
 add_proxy_header_library(
   struct_sockaddr
   HDRS
diff --git a/libc/hdr/types/struct_ifreq.h b/libc/hdr/types/struct_ifreq.h
new file mode 100644
index 0000000000000..3f34ffa4a9d7c
--- /dev/null
+++ b/libc/hdr/types/struct_ifreq.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 ifreq.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_IFREQ_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_IFREQ_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_ifreq.h"
+
+#else
+
+#include <net/if.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_IFREQ_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index caf5d61dfc1cb..b35785d16bbdb 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -895,6 +895,18 @@ add_header_macro(
     .llvm-libc-types.siginfo_t
 )
 
+file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/net)
+
+add_header_macro(
+  net_if
+  ../libc/include/net/if.yaml
+  net/if.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.net_if_macros
+    .llvm-libc-types.struct_ifreq
+)
+
 # TODO: This should be conditional on POSIX networking being included.
 file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/netinet)
 
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 892f2a8b5b198..8f21d9811a160 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -314,6 +314,12 @@ add_macro_header(
     sys-socket-macros.h
 )
 
+add_macro_header(
+  net_if_macros
+  HDR
+    net-if-macros.h
+)
+
 add_macro_header(
   sys_time_macros
   HDR
diff --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt
index c97270413197e..374e7e6159a5d 100644
--- a/libc/include/llvm-libc-macros/linux/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt
@@ -64,6 +64,12 @@ add_header(
     sys-socket-macros.h
 )
 
+add_header(
+  net_if_macros
+  HDR
+    net-if-macros.h
+)
+
 add_header(
   sys_wait_macros
   HDR
diff --git a/libc/include/llvm-libc-macros/linux/net-if-macros.h b/libc/include/llvm-libc-macros/linux/net-if-macros.h
new file mode 100644
index 0000000000000..b5cd2c2ef144d
--- /dev/null
+++ b/libc/include/llvm-libc-macros/linux/net-if-macros.h
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Macros defined in net/if.h header file.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_MACROS_LINUX_NET_IF_MACROS_H
+#define LLVM_LIBC_MACROS_LINUX_NET_IF_MACROS_H
+
+#define IF_NAMESIZE 16
+
+#endif // LLVM_LIBC_MACROS_LINUX_NET_IF_MACROS_H
diff --git a/libc/include/llvm-libc-macros/net-if-macros.h b/libc/include/llvm-libc-macros/net-if-macros.h
new file mode 100644
index 0000000000000..4af2b0bf401d5
--- /dev/null
+++ b/libc/include/llvm-libc-macros/net-if-macros.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Macros defined in net/if.h header file.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_MACROS_NET_IF_MACROS_H
+#define LLVM_LIBC_MACROS_NET_IF_MACROS_H
+
+#ifdef __linux__
+#include "linux/net-if-macros.h"
+#endif
+
+#endif // LLVM_LIBC_MACROS_NET_IF_MACROS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 0512d3f0e642a..308523d5de55b 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -225,6 +225,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_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_ifreq.h b/libc/include/llvm-libc-types/struct_ifreq.h
new file mode 100644
index 0000000000000..b9ad182f97802
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_ifreq.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 ifreq.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_STRUCT_IFREQ_H
+#define LLVM_LIBC_TYPES_STRUCT_IFREQ_H
+
+#include "../llvm-libc-macros/net-if-macros.h"
+#include "struct_sockaddr.h"
+
+struct ifreq {
+  char ifr_name[IF_NAMESIZE];
+  __extension__ union {
+    struct sockaddr ifr_hwaddr;
+    struct sockaddr ifr_addr;
+    struct sockaddr ifr_dstaddr;
+    struct sockaddr ifr_broadaddr;
+    struct sockaddr ifr_netmask;
+    short int ifr_flags;
+    int ifr_metric;
+    int ifr_mtu;
+    int ifr_ifindex;
+    int ifr_bandwidth;
+    int ifr_qlen;
+    char ifr_newname[IF_NAMESIZE];
+    char ifr_slave[IF_NAMESIZE];
+    char *ifr_data;
+  };
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_IFREQ_H
diff --git a/libc/include/net/if.yaml b/libc/include/net/if.yaml
new file mode 100644
index 0000000000000..51034d84e4428
--- /dev/null
+++ b/libc/include/net/if.yaml
@@ -0,0 +1,24 @@
+header: net/if.h
+standards:
+  - posix
+macros:
+  - macro_name: IF_NAMESIZE
+    macro_header: net-if-macros.h
+types:
+  - type_name: struct_ifreq
+enums: []
+objects: []
+functions:
+  - name: if_indextoname
+    standards:
+      - posix
+    return_type: char *
+    arguments:
+      - type: unsigned int
+      - type: char *
+  - name: if_nametoindex
+    standards:
+      - posix
+    return_type: unsigned int
+    arguments:
+      - type: const char *
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 62aa164b35ee7..6ada1bef26a88 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -10,6 +10,7 @@ add_subdirectory(inttypes)
 add_subdirectory(libgen)
 add_subdirectory(link)
 add_subdirectory(math)
+add_subdirectory(net)
 add_subdirectory(netinet)
 add_subdirectory(stdbit)
 add_subdirectory(stdfix)
diff --git a/libc/src/net/CMakeLists.txt b/libc/src/net/CMakeLists.txt
new file mode 100644
index 0000000000000..2173a111cff4f
--- /dev/null
+++ b/libc/src/net/CMakeLists.txt
@@ -0,0 +1,17 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  if_indextoname
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.if_indextoname
+)
+
+add_entrypoint_object(
+  if_nametoindex
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.if_nametoindex
+)
diff --git a/libc/src/net/if_indextoname.h b/libc/src/net/if_indextoname.h
new file mode 100644
index 0000000000000..215535328fbee
--- /dev/null
+++ b/libc/src/net/if_indextoname.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_indextoname.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NET_IF_INDEXTONAME_H
+#define LLVM_LIBC_SRC_NET_IF_INDEXTONAME_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *if_indextoname(unsigned int ifindex, char *ifname);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NET_IF_INDEXTONAME_H
diff --git a/libc/src/net/if_nametoindex.h b/libc/src/net/if_nametoindex.h
new file mode 100644
index 0000000000000..c3b27986cc5e7
--- /dev/null
+++ b/libc/src/net/if_nametoindex.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_nametoindex.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NET_IF_NAMETOINDEX_H
+#define LLVM_LIBC_SRC_NET_IF_NAMETOINDEX_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned int if_nametoindex(const char *ifname);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NET_IF_NAMETOINDEX_H
diff --git a/libc/src/net/linux/CMakeLists.txt b/libc/src/net/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..9c82636d1c54c
--- /dev/null
+++ b/libc/src/net/linux/CMakeLists.txt
@@ -0,0 +1,44 @@
+add_entrypoint_object(
+  if_indextoname
+  SRCS
+    if_indextoname.cpp
+  HDRS
+    ../if_indextoname.h
+  DEPENDS
+    libc.hdr.net_if_macros
+    libc.hdr.errno_macros
+    libc.hdr.sys_ioctl_macros
+    libc.hdr.sys_socket_macros
+    libc.hdr.types.struct_ifreq
+    libc.src.__support.CPP.string_view
+    libc.src.__support.common
+    libc.src.__support.macros.null_check
+    libc.src.__support.OSUtil.linux.syscall_wrappers.socket
+    libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
+    libc.src.__support.OSUtil.linux.syscall_wrappers.close
+    libc.src.errno.errno
+    libc.src.string.memory_utils.inline_memcpy
+    libc.src.string.string_utils
+)
+
+add_entrypoint_object(
+  if_nametoindex
+  SRCS
+    if_nametoindex.cpp
+  HDRS
+    ../if_nametoindex.h
+  DEPENDS
+    libc.hdr.net_if_macros
+    libc.hdr.errno_macros
+    libc.hdr.sys_ioctl_macros
+    libc.hdr.sys_socket_macros
+    libc.hdr.types.struct_ifreq
+    libc.src.__support.CPP.string_view
+    libc.src.__support.common
+    libc.src.__support.macros.null_check
+    libc.src.__support.OSUtil.linux.syscall_wrappers.socket
+    libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
+    libc.src.__support.OSUtil.linux.syscall_wrappers.close
+    libc.src.errno.errno
+    libc.src.string.memory_utils.inline_memcpy
+)
diff --git a/libc/src/net/linux/if_indextoname.cpp b/libc/src/net/linux/if_indextoname.cpp
new file mode 100644
index 0000000000000..f046adc1ad220
--- /dev/null
+++ b/libc/src/net/linux/if_indextoname.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_indextoname.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/net/if_indextoname.h"
+#include "hdr/errno_macros.h"
+#include "hdr/net_if_macros.h"
+#include "hdr/sys_ioctl_macros.h"
+#include "hdr/sys_socket_macros.h"
+#include "hdr/types/struct_ifreq.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/socket.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/null_check.h"
+#include "src/string/memory_utils/inline_memcpy.h"
+#include "src/string/string_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, if_indextoname,
+                   (unsigned int ifindex, char *ifname)) {
+  LIBC_CRASH_ON_NULLPTR(ifname);
+
+  ErrorOr<int> fd =
+      linux_syscalls::socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+  if (!fd.has_value()) {
+    libc_errno = fd.error();
+    return nullptr;
+  }
+
+  struct ifreq ifr;
+  ifr.ifr_ifindex = static_cast<int>(ifindex);
+
+  ErrorOr<int> ioctl_res = linux_syscalls::ioctl(*fd, SIOCGIFNAME, &ifr);
+
+  linux_syscalls::close(*fd);
+
+  if (!ioctl_res.has_value()) {
+    // Map kernel ENODEV to POSIX-mandated ENXIO.
+    libc_errno = (ioctl_res.error() == ENODEV) ? ENXIO : ioctl_res.error();
+    return nullptr;
+  }
+
+  cpp::string_view k_name(
+      ifr.ifr_name, internal::strnlen(ifr.ifr_name, sizeof(ifr.ifr_name)));
+  inline_memcpy(ifname, k_name.data(), k_name.size());
+  // Linux kernel does allow network devices exactly IF_NAMESIZE long (it leaves
+  // room for the terminating \0). But if that happens, let's not overrun the
+  // user provided buffer.
+  if (k_name.size() < IF_NAMESIZE)
+    ifname[k_name.size()] = '\0';
+
+  return ifname;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/net/linux/if_nametoindex.cpp b/libc/src/net/linux/if_nametoindex.cpp
new file mode 100644
index 0000000000000..507e7f59f1423
--- /dev/null
+++ b/libc/src/net/linux/if_nametoindex.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_nametoindex.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/net/if_nametoindex.h"
+#include "hdr/errno_macros.h"
+#include "hdr/net_if_macros.h"
+#include "hdr/sys_ioctl_macros.h"
+#include "hdr/sys_socket_macros.h"
+#include "hdr/types/struct_ifreq.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/socket.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/null_check.h"
+#include "src/string/memory_utils/inline_memcpy.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(unsigned int, if_nametoindex, (const char *ifname)) {
+  LIBC_CRASH_ON_NULLPTR(ifname);
+
+  cpp::string_view name(ifname);
+  if (name.empty() || name.size() >= IF_NAMESIZE) {
+    libc_errno = ENODEV;
+    return 0;
+  }
+
+  ErrorOr<int> fd =
+      linux_syscalls::socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+  if (!fd.has_value()) {
+    libc_errno = fd.error();
+    return 0;
+  }
+
+  struct ifreq ifr;
+  inline_memcpy(ifr.ifr_name, name.data(), name.size() + 1);
+
+  ErrorOr<int> ioctl_res = linux_syscalls::ioctl(*fd, SIOCGIFINDEX, &ifr);
+
+  linux_syscalls::close(*fd);
+
+  if (!ioctl_res.has_value()) {
+    libc_errno = ioctl_res.error();
+    return 0;
+  }
+
+  return static_cast<unsigned int>(ifr.ifr_ifindex);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index 45815c9bba8ca..077327d987dac 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -66,6 +66,7 @@ add_subdirectory(fenv)
 add_subdirectory(libgen)
 add_subdirectory(link)
 add_subdirectory(math)
+add_subdirectory(net)
 add_subdirectory(netinet)
 add_subdirectory(search)
 add_subdirectory(setjmp)
diff --git a/libc/test/src/net/CMakeLists.txt b/libc/test/src/net/CMakeLists.txt
new file mode 100644
index 0000000000000..8e285dd5b94c5
--- /dev/null
+++ b/libc/test/src/net/CMakeLists.txt
@@ -0,0 +1,4 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
+
diff --git a/libc/test/src/net/linux/CMakeLists.txt b/libc/test/src/net/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..c9119a954ad9c
--- /dev/null
+++ b/libc/test/src/net/linux/CMakeLists.txt
@@ -0,0 +1,27 @@
+add_custom_target(libc_net_unittests)
+
+add_libc_unittest(
+  if_indextoname_test
+  SUITE
+    libc_net_unittests
+  SRCS
+    if_indextoname_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.net_if_macros
+    libc.src.net.if_indextoname
+    libc.src.net.if_nametoindex
+    libc.test.UnitTest.ErrnoCheckingTest
+)
+
+add_libc_unittest(
+  if_nametoindex_test
+  SUITE
+    libc_net_unittests
+  SRCS
+    if_nametoindex_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.src.net.if_nametoindex
+    libc.test.UnitTest.ErrnoCheckingTest
+)
diff --git a/libc/test/src/net/linux/if_indextoname_test.cpp b/libc/test/src/net/linux/if_indextoname_test.cpp
new file mode 100644
index 0000000000000..6c7f3888e300a
--- /dev/null
+++ b/libc/test/src/net/linux/if_indextoname_test.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for if_indextoname.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/net_if_macros.h"
+#include "src/net/if_indextoname.h"
+#include "src/net/if_nametoindex.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcIfIndexToNameTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcIfIndexToNameTest, Loopback) {
+  unsigned int lo_idx = LIBC_NAMESPACE::if_nametoindex("lo");
+  ASSERT_GT(lo_idx, 0u);
+
+  char buf[IF_NAMESIZE];
+  char *res = LIBC_NAMESPACE::if_indextoname(lo_idx, buf);
+  ASSERT_EQ(res, buf);
+  ASSERT_STREQ(buf, "lo");
+  ASSERT_ERRNO_SUCCESS();
+}
+
+TEST_F(LlvmLibcIfIndexToNameTest, InvalidIndex) {
+  char buf[IF_NAMESIZE];
+  char *res = LIBC_NAMESPACE::if_indextoname(-1u, buf);
+  ASSERT_EQ(res, static_cast<char *>(nullptr));
+  ASSERT_ERRNO_EQ(ENXIO);
+}
+
+TEST_F(LlvmLibcIfIndexToNameTest, ZeroIndex) {
+  char buf[IF_NAMESIZE];
+  char *res = LIBC_NAMESPACE::if_indextoname(0u, buf);
+  ASSERT_EQ(res, static_cast<char *>(nullptr));
+  ASSERT_ERRNO_EQ(ENXIO);
+}
+
+TEST_F(LlvmLibcIfIndexToNameTest, NullPtrDeath) {
+  ASSERT_DEATH([]() { LIBC_NAMESPACE::if_indextoname(1u, nullptr); },
+               WITH_SIGNAL(-1));
+}
diff --git a/libc/test/src/net/linux/if_nametoindex_test.cpp b/libc/test/src/net/linux/if_nametoindex_test.cpp
new file mode 100644
index 0000000000000..353b781a018ee
--- /dev/null
+++ b/libc/test/src/net/linux/if_nametoindex_test.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittests for if_nametoindex.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/net/if_nametoindex.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcIfNameToIndexTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcIfNameToIndexTest, Loopback) {
+  unsigned int idx = LIBC_NAMESPACE::if_nametoindex("lo");
+  ASSERT_GT(idx, 0u);
+  ASSERT_ERRNO_SUCCESS();
+}
+
+TEST_F(LlvmLibcIfNameToIndexTest, InvalidName) {
+  unsigned int idx = LIBC_NAMESPACE::if_nametoindex("nonexistent_if");
+  ASSERT_EQ(idx, 0u);
+  ASSERT_ERRNO_EQ(ENODEV);
+}
+
+TEST_F(LlvmLibcIfNameToIndexTest, EmptyName) {
+  unsigned int idx = LIBC_NAMESPACE::if_nametoindex("");
+  ASSERT_EQ(idx, 0u);
+  ASSERT_ERRNO_EQ(ENODEV);
+}
+
+TEST_F(LlvmLibcIfNameToIndexTest, NullPtrDeath) {
+  ASSERT_DEATH([]() { LIBC_NAMESPACE::if_nametoindex(nullptr); },
+               WITH_SIGNAL(-1));
+}



More information about the libc-commits mailing list