[libc-commits] [libc] [libc] Implement ether_ntoa and ether_ntoa_r (PR #233876)
Pavel Labath via libc-commits
libc-commits at lists.llvm.org
Wed Oct 21 02:11:56 PDT 2026
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/233876
>From 515f097b11661acb0b4efcbe2f444f1aa3a5f458 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Tue, 20 Oct 2026 14:24:32 +0000
Subject: [PATCH 1/2] [libc] Implement ether_ntoa and ether_ntoa_r
This adds <net/ethernet.h> (with struct ether_addr) and
<netinet/ether.h> (with ether_ntoa, ether_ntoa_r).
A few implementation notes:
- following glibc and musl (and the linux man page), octets < 0x10 are
formatted without a leading zero. This differs from some BSD
implementations.
- like inet_ntoa (but unlike GLIBC), ether_ntoa uses a thread-local
static buffer
Assisted-by: Gemini
---
libc/config/linux/aarch64/entrypoints.txt | 4 ++
libc/config/linux/aarch64/headers.txt | 2 +
libc/config/linux/riscv/entrypoints.txt | 4 ++
libc/config/linux/riscv/headers.txt | 2 +
libc/config/linux/x86_64/entrypoints.txt | 4 ++
libc/config/linux/x86_64/headers.txt | 2 +
libc/hdr/types/CMakeLists.txt | 9 ++++
libc/hdr/types/struct_ether_addr.h | 27 ++++++++++
libc/include/CMakeLists.txt | 18 +++++++
libc/include/llvm-libc-types/CMakeLists.txt | 1 +
.../llvm-libc-types/struct_ether_addr.h | 23 +++++++++
libc/include/net/ethernet.yaml | 10 ++++
libc/include/netinet/ether.yaml | 22 ++++++++
libc/src/netinet/CMakeLists.txt | 2 +
libc/src/netinet/ether/CMakeLists.txt | 42 ++++++++++++++++
libc/src/netinet/ether/ether_ntoa.cpp | 29 +++++++++++
libc/src/netinet/ether/ether_ntoa.h | 26 ++++++++++
libc/src/netinet/ether/ether_ntoa_r.cpp | 32 ++++++++++++
libc/src/netinet/ether/ether_ntoa_r.h | 26 ++++++++++
libc/src/netinet/ether/ether_utils.h | 50 +++++++++++++++++++
libc/test/src/netinet/CMakeLists.txt | 2 +
libc/test/src/netinet/ether/CMakeLists.txt | 23 +++++++++
.../src/netinet/ether/ether_ntoa_r_test.cpp | 36 +++++++++++++
.../src/netinet/ether/ether_ntoa_test.cpp | 42 ++++++++++++++++
24 files changed, 438 insertions(+)
create mode 100644 libc/hdr/types/struct_ether_addr.h
create mode 100644 libc/include/llvm-libc-types/struct_ether_addr.h
create mode 100644 libc/include/net/ethernet.yaml
create mode 100644 libc/include/netinet/ether.yaml
create mode 100644 libc/src/netinet/ether/CMakeLists.txt
create mode 100644 libc/src/netinet/ether/ether_ntoa.cpp
create mode 100644 libc/src/netinet/ether/ether_ntoa.h
create mode 100644 libc/src/netinet/ether/ether_ntoa_r.cpp
create mode 100644 libc/src/netinet/ether/ether_ntoa_r.h
create mode 100644 libc/src/netinet/ether/ether_utils.h
create mode 100644 libc/test/src/netinet/ether/CMakeLists.txt
create mode 100644 libc/test/src/netinet/ether/ether_ntoa_r_test.cpp
create mode 100644 libc/test/src/netinet/ether/ether_ntoa_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index f19427f507b037..8570a82b0000e4 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1161,6 +1161,10 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.net.if_indextoname
libc.src.net.if_nametoindex
+ # netinet/ether.h entrypoints
+ libc.src.netinet.ether.ether_ntoa
+ libc.src.netinet.ether.ether_ntoa_r
+
# netinet/in.h entrypoints
libc.src.netinet.in6addr_any
libc.src.netinet.in6addr_loopback
diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt
index 3e96e6637da940..a3301926f2e9b6 100644
--- a/libc/config/linux/aarch64/headers.txt
+++ b/libc/config/linux/aarch64/headers.txt
@@ -27,7 +27,9 @@ set(TARGET_PUBLIC_HEADERS
libc.include.malloc
libc.include.math
libc.include.memory
+ libc.include.net_ethernet
libc.include.net_if
+ libc.include.netinet_ether
libc.include.netinet_in
libc.include.netinet_tcp
libc.include.netinet_udp
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index f9156b9fd6e4ad..93415cbf86489b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -72,6 +72,10 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.net.if_indextoname
libc.src.net.if_nametoindex
+ # netinet/ether.h entrypoints
+ libc.src.netinet.ether.ether_ntoa
+ libc.src.netinet.ether.ether_ntoa_r
+
# netinet/in.h entrypoints
libc.src.netinet.in6addr_any
libc.src.netinet.in6addr_loopback
diff --git a/libc/config/linux/riscv/headers.txt b/libc/config/linux/riscv/headers.txt
index a3c65e50e4e605..ad9998880ef906 100644
--- a/libc/config/linux/riscv/headers.txt
+++ b/libc/config/linux/riscv/headers.txt
@@ -27,7 +27,9 @@ set(TARGET_PUBLIC_HEADERS
libc.include.malloc
libc.include.math
libc.include.memory
+ libc.include.net_ethernet
libc.include.net_if
+ libc.include.netinet_ether
libc.include.netinet_in
libc.include.netinet_tcp
libc.include.netinet_udp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 7125b2248a8752..a0dd937168bf1e 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -72,6 +72,10 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.net.if_indextoname
libc.src.net.if_nametoindex
+ # netinet/ether.h entrypoints
+ libc.src.netinet.ether.ether_ntoa
+ libc.src.netinet.ether.ether_ntoa_r
+
# netinet/in.h entrypoints
libc.src.netinet.in6addr_any
libc.src.netinet.in6addr_loopback
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index fa37b19e50987f..3815a3d996a6ba 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -27,7 +27,9 @@ set(TARGET_PUBLIC_HEADERS
libc.include.malloc
libc.include.math
libc.include.memory
+ libc.include.net_ethernet
libc.include.net_if
+ libc.include.netinet_ether
libc.include.netinet_in
libc.include.netinet_tcp
libc.include.netinet_udp
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 605540a10dbb87..fdd0ca67da3396 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -788,6 +788,15 @@ add_proxy_header_library(
libc.include.netinet_udp
)
+add_proxy_header_library(
+ struct_ether_addr
+ HDRS
+ struct_ether_addr.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_ether_addr
+ libc.include.net_ethernet
+)
+
add_proxy_header_library(
struct_sysinfo
HDRS
diff --git a/libc/hdr/types/struct_ether_addr.h b/libc/hdr/types/struct_ether_addr.h
new file mode 100644
index 00000000000000..6cb544c4e44597
--- /dev/null
+++ b/libc/hdr/types/struct_ether_addr.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 header for struct ether_addr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_ETHER_ADDR_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_ETHER_ADDR_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_ether_addr.h"
+
+#else
+
+#include <net/ethernet.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_ETHER_ADDR_H
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 73c65cbcb90594..73920ce0d7670e 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -1135,6 +1135,15 @@ add_header_macro(
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/net)
+add_header_macro(
+ net_ethernet
+ ../libc/include/net/ethernet.yaml
+ net/ethernet.h
+ DEPENDS
+ .llvm-libc-types.struct_ether_addr
+ .llvm_libc_common_h
+)
+
add_header_macro(
net_if
../libc/include/net/if.yaml
@@ -1149,6 +1158,15 @@ add_header_macro(
# TODO: This should be conditional on POSIX networking being included.
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/netinet)
+add_header_macro(
+ netinet_ether
+ ../libc/include/netinet/ether.yaml
+ netinet/ether.h
+ DEPENDS
+ .llvm-libc-types.struct_ether_addr
+ .llvm_libc_common_h
+)
+
add_header_macro(
netinet_in
../libc/include/netinet/in.yaml
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index dd183643e4243b..46a1a5bcfe6ee9 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -312,6 +312,7 @@ add_header(struct_cmsghdr HDR struct_cmsghdr.h DEPENDS .size_t)
add_header(struct_msghdr HDR struct_msghdr.h DEPENDS .size_t .socklen_t .struct_iovec)
add_header(struct_mmsghdr HDR struct_mmsghdr.h DEPENDS .struct_msghdr)
add_header(struct_udphdr HDR struct_udphdr.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
+add_header(struct_ether_addr HDR struct_ether_addr.h DEPENDS libc.include.llvm-libc-macros.stdint_macros)
add_header(ACTION HDR ACTION.h)
add_header(ENTRY HDR ENTRY.h)
add_header(VISIT HDR VISIT.h)
diff --git a/libc/include/llvm-libc-types/struct_ether_addr.h b/libc/include/llvm-libc-types/struct_ether_addr.h
new file mode 100644
index 00000000000000..4af8e7f3f8eb91
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_ether_addr.h
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 ether_addr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_STRUCT_ETHER_ADDR_H
+#define LLVM_LIBC_TYPES_STRUCT_ETHER_ADDR_H
+
+#include "../llvm-libc-macros/stdint-macros.h"
+
+struct ether_addr {
+ uint8_t ether_addr_octet[6];
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_ETHER_ADDR_H
diff --git a/libc/include/net/ethernet.yaml b/libc/include/net/ethernet.yaml
new file mode 100644
index 00000000000000..b6de7563f23ba7
--- /dev/null
+++ b/libc/include/net/ethernet.yaml
@@ -0,0 +1,10 @@
+header: net/ethernet.h
+standards:
+ - bsd
+macros: []
+types:
+ - type_name: struct_ether_addr
+enums: []
+objects: []
+functions: []
+
diff --git a/libc/include/netinet/ether.yaml b/libc/include/netinet/ether.yaml
new file mode 100644
index 00000000000000..f838b51c556ffb
--- /dev/null
+++ b/libc/include/netinet/ether.yaml
@@ -0,0 +1,22 @@
+header: netinet/ether.h
+standards:
+ - bsd
+ - gnu
+macros: []
+types: []
+enums: []
+objects: []
+functions:
+ - name: ether_ntoa
+ standards:
+ - bsd
+ return_type: char *
+ arguments:
+ - type: const struct ether_addr *
+ - name: ether_ntoa_r
+ standards:
+ - gnu
+ return_type: char *
+ arguments:
+ - type: const struct ether_addr *
+ - type: char *
diff --git a/libc/src/netinet/CMakeLists.txt b/libc/src/netinet/CMakeLists.txt
index 868e09f7a34319..d4dd2f0e307987 100644
--- a/libc/src/netinet/CMakeLists.txt
+++ b/libc/src/netinet/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_subdirectory(ether)
+
add_entrypoint_object(
in6addr_any
SRCS
diff --git a/libc/src/netinet/ether/CMakeLists.txt b/libc/src/netinet/ether/CMakeLists.txt
new file mode 100644
index 00000000000000..4b92f54f6b22a0
--- /dev/null
+++ b/libc/src/netinet/ether/CMakeLists.txt
@@ -0,0 +1,42 @@
+add_header_library(
+ ether_utils
+ HDRS
+ ether_utils.h
+ DEPENDS
+ libc.hdr.stdint_proxy
+ libc.hdr.types.size_t
+ libc.hdr.types.struct_ether_addr
+ libc.src.__support.CPP.span
+ libc.src.__support.common
+ libc.src.__support.ctype_utils
+ libc.src.__support.macros.config
+)
+
+add_entrypoint_object(
+ ether_ntoa
+ SRCS
+ ether_ntoa.cpp
+ HDRS
+ ether_ntoa.h
+ DEPENDS
+ .ether_utils
+ libc.hdr.types.struct_ether_addr
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.null_check
+)
+
+add_entrypoint_object(
+ ether_ntoa_r
+ SRCS
+ ether_ntoa_r.cpp
+ HDRS
+ ether_ntoa_r.h
+ DEPENDS
+ .ether_utils
+ libc.hdr.types.struct_ether_addr
+ libc.src.__support.CPP.span
+ libc.src.__support.common
+ libc.src.__support.macros.config
+ libc.src.__support.macros.null_check
+)
diff --git a/libc/src/netinet/ether/ether_ntoa.cpp b/libc/src/netinet/ether/ether_ntoa.cpp
new file mode 100644
index 00000000000000..140e8c5f9c95c5
--- /dev/null
+++ b/libc/src/netinet/ether/ether_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 ether_ntoa function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/netinet/ether/ether_ntoa.h"
+#include "hdr/types/struct_ether_addr.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/netinet/ether/ether_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, ether_ntoa, (const struct ether_addr *addr)) {
+ LIBC_CRASH_ON_NULLPTR(addr);
+ static LIBC_THREAD_LOCAL char buffer[net::ETHER_ADDR_STR_LEN];
+ return net::ether_ntoa_r(*addr, buffer);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/netinet/ether/ether_ntoa.h b/libc/src/netinet/ether/ether_ntoa.h
new file mode 100644
index 00000000000000..0620288518fdfe
--- /dev/null
+++ b/libc/src/netinet/ether/ether_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 ether_ntoa.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NETINET_ETHER_ETHER_NTOA_H
+#define LLVM_LIBC_SRC_NETINET_ETHER_ETHER_NTOA_H
+
+#include "hdr/types/struct_ether_addr.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *ether_ntoa(const struct ether_addr *addr);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NETINET_ETHER_ETHER_NTOA_H
diff --git a/libc/src/netinet/ether/ether_ntoa_r.cpp b/libc/src/netinet/ether/ether_ntoa_r.cpp
new file mode 100644
index 00000000000000..b467a92f3d3867
--- /dev/null
+++ b/libc/src/netinet/ether/ether_ntoa_r.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
+/// Implementation of ether_ntoa_r function.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/netinet/ether/ether_ntoa_r.h"
+#include "hdr/types/struct_ether_addr.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+#include "src/netinet/ether/ether_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(char *, ether_ntoa_r,
+ (const struct ether_addr *addr, char *buf)) {
+ LIBC_CRASH_ON_NULLPTR(addr);
+ LIBC_CRASH_ON_NULLPTR(buf);
+ return net::ether_ntoa_r(*addr,
+ cpp::span<char>(buf, net::ETHER_ADDR_STR_LEN));
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/netinet/ether/ether_ntoa_r.h b/libc/src/netinet/ether/ether_ntoa_r.h
new file mode 100644
index 00000000000000..19af032485019d
--- /dev/null
+++ b/libc/src/netinet/ether/ether_ntoa_r.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 ether_ntoa_r.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NETINET_ETHER_ETHER_NTOA_R_H
+#define LLVM_LIBC_SRC_NETINET_ETHER_ETHER_NTOA_R_H
+
+#include "hdr/types/struct_ether_addr.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+char *ether_ntoa_r(const struct ether_addr *addr, char *buf);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NETINET_ETHER_ETHER_NTOA_R_H
diff --git a/libc/src/netinet/ether/ether_utils.h b/libc/src/netinet/ether/ether_utils.h
new file mode 100644
index 00000000000000..da906c87e6e97b
--- /dev/null
+++ b/libc/src/netinet/ether/ether_utils.h
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 utilities for Ethernet address manipulation.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_NETINET_ETHER_ETHER_UTILS_H
+#define LLVM_LIBC_SRC_NETINET_ETHER_ETHER_UTILS_H
+
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_ether_addr.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/common.h"
+#include "src/__support/ctype_utils.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace net {
+
+/// Maximum length of an Ethernet address string "xx:xx:xx:xx:xx:xx\0".
+inline constexpr size_t ETHER_ADDR_STR_LEN = 18;
+
+/// Formats \p addr into \p buf (which must be at least ETHER_ADDR_STR_LEN
+/// bytes) as a colon-separated lowercase hexadecimal string and returns
+/// `buf.data()`.
+LIBC_INLINE char *ether_ntoa_r(const struct ether_addr &addr,
+ cpp::span<char> buf) {
+ size_t pos = 0;
+ for (size_t i = 0; i < 6; ++i) {
+ uint8_t val = addr.ether_addr_octet[i];
+ if (val >= 0x10)
+ buf[pos++] = internal::int_to_b36_char(val >> 4);
+ buf[pos++] = internal::int_to_b36_char(val & 0xf);
+ buf[pos++] = i < 5 ? ':' : '\0';
+ }
+ return buf.data();
+}
+
+} // namespace net
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_NETINET_ETHER_ETHER_UTILS_H
diff --git a/libc/test/src/netinet/CMakeLists.txt b/libc/test/src/netinet/CMakeLists.txt
index 68499c648cd622..79382b73d0427b 100644
--- a/libc/test/src/netinet/CMakeLists.txt
+++ b/libc/test/src/netinet/CMakeLists.txt
@@ -1,5 +1,7 @@
add_custom_target(libc_netinet_unittests)
+add_subdirectory(ether)
+
add_libc_test(
in_test
SUITE
diff --git a/libc/test/src/netinet/ether/CMakeLists.txt b/libc/test/src/netinet/ether/CMakeLists.txt
new file mode 100644
index 00000000000000..66cd925e384161
--- /dev/null
+++ b/libc/test/src/netinet/ether/CMakeLists.txt
@@ -0,0 +1,23 @@
+add_custom_target(libc_netinet_ether_unittests)
+
+add_libc_test(
+ ether_ntoa_test
+ SUITE
+ libc_netinet_ether_unittests
+ SRCS
+ ether_ntoa_test.cpp
+ DEPENDS
+ libc.hdr.types.struct_ether_addr
+ libc.src.netinet.ether.ether_ntoa
+)
+
+add_libc_test(
+ ether_ntoa_r_test
+ SUITE
+ libc_netinet_ether_unittests
+ SRCS
+ ether_ntoa_r_test.cpp
+ DEPENDS
+ libc.hdr.types.struct_ether_addr
+ libc.src.netinet.ether.ether_ntoa_r
+)
diff --git a/libc/test/src/netinet/ether/ether_ntoa_r_test.cpp b/libc/test/src/netinet/ether/ether_ntoa_r_test.cpp
new file mode 100644
index 00000000000000..1e3851e9f4343d
--- /dev/null
+++ b/libc/test/src/netinet/ether/ether_ntoa_r_test.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 ether_ntoa_r.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/types/struct_ether_addr.h"
+#include "src/netinet/ether/ether_ntoa_r.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcEtherNtoaRTest, BasicConversion) {
+ char buf[18];
+
+ struct ether_addr zeroes = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+ EXPECT_EQ(buf, LIBC_NAMESPACE::ether_ntoa_r(&zeroes, buf));
+ EXPECT_STREQ("0:0:0:0:0:0", buf);
+
+ struct ether_addr broadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
+ EXPECT_EQ(buf, LIBC_NAMESPACE::ether_ntoa_r(&broadcast, buf));
+ EXPECT_STREQ("ff:ff:ff:ff:ff:ff", buf);
+
+ struct ether_addr mixed1 = {{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}};
+ EXPECT_EQ(buf, LIBC_NAMESPACE::ether_ntoa_r(&mixed1, buf));
+ EXPECT_STREQ("1:23:45:67:89:ab", buf);
+
+ struct ether_addr mixed2 = {{0xcd, 0xef, 0x0a, 0x10, 0x00, 0x9f}};
+ EXPECT_EQ(buf, LIBC_NAMESPACE::ether_ntoa_r(&mixed2, buf));
+ EXPECT_STREQ("cd:ef:a:10:0:9f", buf);
+}
diff --git a/libc/test/src/netinet/ether/ether_ntoa_test.cpp b/libc/test/src/netinet/ether/ether_ntoa_test.cpp
new file mode 100644
index 00000000000000..1176d0b3cbcc68
--- /dev/null
+++ b/libc/test/src/netinet/ether/ether_ntoa_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 ether_ntoa.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/types/struct_ether_addr.h"
+#include "src/netinet/ether/ether_ntoa.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcEtherNtoaTest, BasicConversion) {
+ struct ether_addr zeroes = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+ EXPECT_STREQ("0:0:0:0:0:0", LIBC_NAMESPACE::ether_ntoa(&zeroes));
+
+ struct ether_addr broadcast = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
+ EXPECT_STREQ("ff:ff:ff:ff:ff:ff", LIBC_NAMESPACE::ether_ntoa(&broadcast));
+
+ struct ether_addr mixed1 = {{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}};
+ EXPECT_STREQ("1:23:45:67:89:ab", LIBC_NAMESPACE::ether_ntoa(&mixed1));
+
+ struct ether_addr mixed2 = {{0xcd, 0xef, 0x0a, 0x10, 0x00, 0x9f}};
+ EXPECT_STREQ("cd:ef:a:10:0:9f", LIBC_NAMESPACE::ether_ntoa(&mixed2));
+}
+
+TEST(LlvmLibcEtherNtoaTest, BufferReuseAndOverwrite) {
+ struct ether_addr addr1 = {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
+ char *ptr1 = LIBC_NAMESPACE::ether_ntoa(&addr1);
+ EXPECT_STREQ("11:22:33:44:55:66", ptr1);
+
+ struct ether_addr addr2 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}};
+ char *ptr2 = LIBC_NAMESPACE::ether_ntoa(&addr2);
+ EXPECT_EQ(ptr1, ptr2);
+ EXPECT_STREQ("1:2:3:4:5:6", ptr1);
+ EXPECT_STREQ("1:2:3:4:5:6", ptr2);
+}
>From c17c37d0e772e95582259fc9070acd07363c22c0 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Wed, 21 Oct 2026 09:11:34 +0000
Subject: [PATCH 2/2] fixes
---
libc/hdr/types/CMakeLists.txt | 1 -
libc/include/netinet/ether.yaml | 1 -
2 files changed, 2 deletions(-)
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index fdd0ca67da3396..4c65ebc1393795 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -794,7 +794,6 @@ add_proxy_header_library(
struct_ether_addr.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.struct_ether_addr
- libc.include.net_ethernet
)
add_proxy_header_library(
diff --git a/libc/include/netinet/ether.yaml b/libc/include/netinet/ether.yaml
index f838b51c556ffb..99a65a781c11b9 100644
--- a/libc/include/netinet/ether.yaml
+++ b/libc/include/netinet/ether.yaml
@@ -1,7 +1,6 @@
header: netinet/ether.h
standards:
- bsd
- - gnu
macros: []
types: []
enums: []
More information about the libc-commits
mailing list