[libc-commits] [libc] f05c112 - [libc] Implement ether_ntoa and ether_ntoa_r (#233876)

via libc-commits libc-commits at lists.llvm.org
Wed Oct 21 09:50:16 PDT 2026


Author: Pavel Labath
Date: 2026-10-21T18:50:10+02:00
New Revision: f05c112b2e455f62378de6d298b6798648a66941

URL: https://github.com/llvm/llvm-project/commit/f05c112b2e455f62378de6d298b6798648a66941
DIFF: https://github.com/llvm/llvm-project/commit/f05c112b2e455f62378de6d298b6798648a66941.diff

LOG: [libc] Implement ether_ntoa and ether_ntoa_r (#233876)

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

Added: 
    libc/hdr/types/struct_ether_addr.h
    libc/include/llvm-libc-types/struct_ether_addr.h
    libc/include/net/ethernet.yaml
    libc/include/netinet/ether.yaml
    libc/src/netinet/ether/CMakeLists.txt
    libc/src/netinet/ether/ether_ntoa.cpp
    libc/src/netinet/ether/ether_ntoa.h
    libc/src/netinet/ether/ether_ntoa_r.cpp
    libc/src/netinet/ether/ether_ntoa_r.h
    libc/src/netinet/ether/ether_utils.h
    libc/test/src/netinet/ether/CMakeLists.txt
    libc/test/src/netinet/ether/ether_ntoa_r_test.cpp
    libc/test/src/netinet/ether/ether_ntoa_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/aarch64/headers.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/riscv/headers.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/config/linux/x86_64/headers.txt
    libc/hdr/types/CMakeLists.txt
    libc/include/CMakeLists.txt
    libc/include/llvm-libc-types/CMakeLists.txt
    libc/src/netinet/CMakeLists.txt
    libc/test/src/netinet/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 0a708ef004c1f9..f0bd53429a398d 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1164,6 +1164,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 e9a7dc064434d3..820d1e35c139b5 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 bc5efd2e335e7e..c3d26abf4c254d 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 8a8999ee12f39f..2b501ea3e9a22d 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 82b487b435da20..e17228ae37a8ef 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 b726c097eb8a5c..1d6819fb813c33 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..4c65ebc1393795 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -788,6 +788,14 @@ 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
+)
+
 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 9a2dd0e9d488ad..0130ba1d72e0e1 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -1144,6 +1144,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
@@ -1158,6 +1167,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..99a65a781c11b9
--- /dev/null
+++ b/libc/include/netinet/ether.yaml
@@ -0,0 +1,21 @@
+header: netinet/ether.h
+standards:
+  - bsd
+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);
+}


        


More information about the libc-commits mailing list