[libc-commits] [libc] [libc] Implement IPv6 (AF_INET6) support in inet_pton (PR #226550)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Tue Sep 29 05:17:22 PDT 2026


================
@@ -67,6 +69,109 @@ namespace net {
   return true;
 }
 
+[[nodiscard]] bool str_to_ipv6(cpp::string_view src, struct in6_addr &dst) {
+  if (src.empty())
+    return false;
+
+  bool has_double_colon = false;
+  FixedVector<uint16_t, 8> parts[2];
+  size_t part_idx = 0;
+
+  if (src.starts_with("::")) {
+    has_double_colon = true;
+    part_idx = 1;
+    src.remove_prefix(2);
+    if (src.empty()) {
+      inline_bzero(&dst.s6_addr, 16);
+      return true;
+    }
+    if (src.starts_with(':'))
+      return false;
+  } else if (src.starts_with(':')) {
+    return false;
+  }
+
+  while (!src.empty()) {
+    if (src.starts_with("::")) {
+      if (has_double_colon)
+        return false;
+      has_double_colon = true;
+      part_idx = 1;
+      src.remove_prefix(2);
+      if (src.empty())
+        break;
+      if (src.starts_with(':'))
+        return false;
+    } else if (src.starts_with(':')) {
+      src.remove_prefix(1);
+      if (src.empty() || src.starts_with(':'))
+        return false;
+    }
+
+    // Check if the current component is an embedded IPv4 address.
+    // In IPv6, an embedded IPv4 address can only appear at the very end.
+    size_t colon_pos = src.find_first_of(':');
+    cpp::string_view token =
+        (colon_pos == cpp::string_view::npos) ? src : src.substr(0, colon_pos);
+
+    if (token.find_first_of('.') != cpp::string_view::npos) {
+      if (colon_pos != cpp::string_view::npos)
+        return false;
+
+      struct in_addr in4;
+      if (!str_to_ipv4(src, in4))
+        return false;
+
+      uint16_t v4_words[2];
+      inline_memcpy(v4_words, &in4.s_addr, sizeof(v4_words));
+      if (!parts[part_idx].push_back(v4_words[0]) ||
+          !parts[part_idx].push_back(v4_words[1]))
+        return false;
+
+      src = cpp::string_view();
+      break;
+    }
+
+    if (internal::isspace(src[0]) || src[0] == '+' || src[0] == '-' ||
+        src.starts_with("0x") || src.starts_with("0X"))
+      return false;
+
+    auto result = internal::strtointeger<uint16_t>(src.data(), 16, src.size());
+    if (result.has_error() || result.parsed_len == 0 || result.parsed_len > 4)
+      return false;
+
+    if (!parts[part_idx].push_back(Endian::to_big_endian(result.value)))
+      return false;
+
+    src.remove_prefix(static_cast<size_t>(result.parsed_len));
+    if (!src.empty() && src[0] != ':')
+      return false;
+  }
+
+  if (has_double_colon) {
+    if (parts[0].size() + parts[1].size() >= 8)
----------------
labath wrote:

Let's make a named constant for 8 (something like `NUM_COMPONENTS`)

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


More information about the libc-commits mailing list