| //===-- 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<unsigned long>(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<uint32_t>(result)); | |
| return 1; | |
| } | |
| } // namespace LIBC_NAMESPACE_DECL |