[libc-commits] [libc] [libc] Implement inet_ntoa (PR #208702)

via libc-commits libc-commits at lists.llvm.org
Fri Jul 10 04:38:56 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Pavel Labath (labath)

<details>
<summary>Changes</summary>

Implement inet_ntoa, reusing the internal net::ipv4_to_str helper that backs inet_ntop.

The result is stored in a *thread-local* static buffer. A thread-local buffer is not required for POSIX conformance, but there is some precedent for that, both in llvm libc (e.g. `strsignal`) and in glibc (whose `inet_ntoa` uses it). I'm doing the same for maximum compatiblity.

Assisted by Gemini.

---
Full diff: https://github.com/llvm/llvm-project/pull/208702.diff


9 Files Affected:

- (modified) libc/config/linux/aarch64/entrypoints.txt (+1) 
- (modified) libc/config/linux/riscv/entrypoints.txt (+1) 
- (modified) libc/config/linux/x86_64/entrypoints.txt (+1) 
- (modified) libc/include/arpa/inet.yaml (+6-1) 
- (modified) libc/src/arpa/inet/CMakeLists.txt (+16-1) 
- (added) libc/src/arpa/inet/inet_ntoa.cpp (+29) 
- (added) libc/src/arpa/inet/inet_ntoa.h (+26) 
- (modified) libc/test/src/arpa/inet/CMakeLists.txt (+13-1) 
- (added) libc/test/src/arpa/inet/inet_ntoa_test.cpp (+46) 


``````````diff
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 97625b28a2555..81ff70d0086c6 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1039,6 +1039,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.arpa.inet.htons
     libc.src.arpa.inet.inet_addr
     libc.src.arpa.inet.inet_aton
+    libc.src.arpa.inet.inet_ntoa
     libc.src.arpa.inet.inet_ntop
     libc.src.arpa.inet.ntohl
     libc.src.arpa.inet.ntohs
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 90a93715b5d1e..71c94b1444992 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1172,6 +1172,7 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.arpa.inet.htons
     libc.src.arpa.inet.inet_addr
     libc.src.arpa.inet.inet_aton
+    libc.src.arpa.inet.inet_ntoa
     libc.src.arpa.inet.inet_ntop
     libc.src.arpa.inet.ntohl
     libc.src.arpa.inet.ntohs
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index bac62464a6c45..58691a296179b 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -4,6 +4,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.arpa.inet.htons
     libc.src.arpa.inet.inet_addr
     libc.src.arpa.inet.inet_aton
+    libc.src.arpa.inet.inet_ntoa
     libc.src.arpa.inet.inet_ntop
     libc.src.arpa.inet.ntohl
     libc.src.arpa.inet.ntohs
diff --git a/libc/include/arpa/inet.yaml b/libc/include/arpa/inet.yaml
index c7b5aed4267a9..6629974844186 100644
--- a/libc/include/arpa/inet.yaml
+++ b/libc/include/arpa/inet.yaml
@@ -22,7 +22,6 @@ types:
   - type_name: in_addr_t
   - type_name: socklen_t
   - type_name: struct_in_addr
-  - type_name: socklen_t
 enums: []
 objects: []
 functions:
@@ -39,6 +38,12 @@ functions:
     arguments:
       - type: const char *
       - type: struct in_addr *
+  - name: inet_ntoa
+    standards:
+      - posix
+    return_type: char *
+    arguments:
+      - type: struct in_addr
   - name: inet_ntop
     standards:
       - posix
diff --git a/libc/src/arpa/inet/CMakeLists.txt b/libc/src/arpa/inet/CMakeLists.txt
index 9705d3c263188..9e065b474ca1e 100644
--- a/libc/src/arpa/inet/CMakeLists.txt
+++ b/libc/src/arpa/inet/CMakeLists.txt
@@ -51,6 +51,22 @@ add_entrypoint_object(
     libc.src.__support.net.address
 )
 
+add_entrypoint_object(
+  inet_ntoa
+  SRCS
+    inet_ntoa.cpp
+  HDRS
+    inet_ntoa.h
+  DEPENDS
+    libc.include.arpa_inet
+    libc.hdr.inet_address_macros
+    libc.hdr.types.struct_in_addr
+    libc.src.__support.common
+    libc.src.__support.CPP.span
+    libc.src.__support.macros.config
+    libc.src.__support.net.address
+)
+
 add_entrypoint_object(
   inet_ntop
   SRCS
@@ -72,7 +88,6 @@ add_entrypoint_object(
     libc.src.__support.net.address
 )
 
-
 add_entrypoint_object(
   ntohl
   SRCS
diff --git a/libc/src/arpa/inet/inet_ntoa.cpp b/libc/src/arpa/inet/inet_ntoa.cpp
new file mode 100644
index 0000000000000..de213a3e6b27a
--- /dev/null
+++ b/libc/src/arpa/inet/inet_ntoa.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 of inet_ntoa function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/arpa/inet/inet_ntoa.h"
+#include "hdr/inet-address-macros.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/common.h"
+#include "src/__support/net/address.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, inet_ntoa, (struct in_addr in)) {
+  static LIBC_THREAD_LOCAL char buffer[INET_ADDRSTRLEN];
+  // Buffer is large enough for any address.
+  (void)net::ipv4_to_str(in, cpp::span<char>(buffer, INET_ADDRSTRLEN));
+  return buffer;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/arpa/inet/inet_ntoa.h b/libc/src/arpa/inet/inet_ntoa.h
new file mode 100644
index 0000000000000..054f7e35b5a41
--- /dev/null
+++ b/libc/src/arpa/inet/inet_ntoa.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 of inet_ntoa.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_ARPA_INET_INET_NTOA_H
+#define LLVM_LIBC_SRC_ARPA_INET_INET_NTOA_H
+
+#include "hdr/types/struct_in_addr.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *inet_ntoa(struct in_addr in);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_ARPA_INET_INET_NTOA_H
diff --git a/libc/test/src/arpa/inet/CMakeLists.txt b/libc/test/src/arpa/inet/CMakeLists.txt
index 5a6da519b2782..b81f2418e8cc8 100644
--- a/libc/test/src/arpa/inet/CMakeLists.txt
+++ b/libc/test/src/arpa/inet/CMakeLists.txt
@@ -44,6 +44,19 @@ add_libc_unittest(
     libc.src.arpa.inet.inet_aton
 )
 
+add_libc_unittest(
+  inet_ntoa
+  SUITE
+    libc_arpa_inet_unittests
+  SRCS
+    inet_ntoa_test.cpp
+  DEPENDS
+    libc.src.arpa.inet.inet_ntoa
+    libc.hdr.types.struct_in_addr
+    libc.src.__support.common
+    libc.src.__support.endian_internal
+)
+
 add_libc_unittest(
   inet_ntop
   SUITE
@@ -60,7 +73,6 @@ add_libc_unittest(
     libc.test.UnitTest.ErrnoCheckingTest
 )
 
-
 add_libc_unittest(
   ntohl
   SUITE
diff --git a/libc/test/src/arpa/inet/inet_ntoa_test.cpp b/libc/test/src/arpa/inet/inet_ntoa_test.cpp
new file mode 100644
index 0000000000000..bdc78644513b0
--- /dev/null
+++ b/libc/test/src/arpa/inet/inet_ntoa_test.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 inet_ntoa.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/types/struct_in_addr.h"
+#include "src/__support/endian_internal.h"
+#include "src/arpa/inet/inet_ntoa.h"
+#include "test/UnitTest/Test.h"
+
+static struct in_addr make_addr(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
+  struct in_addr addr;
+  addr.s_addr = LIBC_NAMESPACE::Endian::to_big_endian(
+      static_cast<uint32_t>(a) << 24 | static_cast<uint32_t>(b) << 16 |
+      static_cast<uint32_t>(c) << 8 | static_cast<uint32_t>(d));
+  return addr;
+}
+
+TEST(LlvmLibcInetNtoaTest, BasicConversion) {
+  EXPECT_STREQ("127.0.0.1", LIBC_NAMESPACE::inet_ntoa(make_addr(127, 0, 0, 1)));
+  EXPECT_STREQ("0.0.0.0", LIBC_NAMESPACE::inet_ntoa(make_addr(0, 0, 0, 0)));
+  EXPECT_STREQ("255.255.255.255",
+               LIBC_NAMESPACE::inet_ntoa(make_addr(255, 255, 255, 255)));
+  EXPECT_STREQ("192.168.1.100",
+               LIBC_NAMESPACE::inet_ntoa(make_addr(192, 168, 1, 100)));
+  EXPECT_STREQ("10.0.0.1", LIBC_NAMESPACE::inet_ntoa(make_addr(10, 0, 0, 1)));
+}
+
+TEST(LlvmLibcInetNtoaTest, BufferReuseAndOverwrite) {
+  char *ptr1 = LIBC_NAMESPACE::inet_ntoa(make_addr(1, 2, 3, 4));
+  EXPECT_STREQ("1.2.3.4", ptr1);
+
+  char *ptr2 = LIBC_NAMESPACE::inet_ntoa(make_addr(5, 6, 7, 8));
+  // Our implementation returns pointer to the same static buffer
+  EXPECT_EQ(ptr1, ptr2);
+  EXPECT_STREQ("5.6.7.8", ptr1);
+  EXPECT_STREQ("5.6.7.8", ptr2);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/208702


More information about the libc-commits mailing list