//===-- Implementation of inet_aton function ------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "src/arpa/inet/inet_aton.h" #include "src/__support/common.h" #include "src/__support/endian_internal.h" #include "src/__support/str_to_integer.h" namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(int, inet_aton, (const char *cp, in_addr *inp)) { constexpr int IPV4_MAX_DOT_NUM = 3; unsigned long parts[IPV4_MAX_DOT_NUM + 1] = {0}; int dot_num = 0; for (; dot_num <= IPV4_MAX_DOT_NUM; ++dot_num) { auto result = internal::strtointeger(cp, 0); parts[dot_num] = result; if (result.has_error() || result.parsed_len == 0) return 0; char next_char = *(cp + result.parsed_len); if (next_char != '.' && next_char != '\0') return 0; else if (next_char == '\0') break; else cp += (result.parsed_len + 1); } if (dot_num > IPV4_MAX_DOT_NUM) return 0; // converts the Internet host address cp from the IPv4 numbers-and-dots // notation (a[.b[.c[.d]]]) into binary form (in network byte order) unsigned long result = 0; for (int i = 0; i <= dot_num; ++i) { unsigned long max_part = i == dot_num ? (0xffffffffUL >> (8 * dot_num)) : 0xffUL; if (parts[i] > max_part) return 0; int shift = i == dot_num ? 0 : 8 * (IPV4_MAX_DOT_NUM - i); result |= parts[i] << shift; } if (inp) inp->s_addr = Endian::to_big_endian(static_cast(result)); return 1; } } // namespace LIBC_NAMESPACE_DECL