Skip to content

Commit 9774e2d

Browse files
committed
[libc] implement inet_aton
1 parent 825de78 commit 9774e2d

File tree

9 files changed

+216
-1
lines changed

9 files changed

+216
-1
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ if(LLVM_LIBC_FULL_BUILD)
945945
# arpa/inet.h entrypoints
946946
libc.src.arpa.inet.htonl
947947
libc.src.arpa.inet.htons
948+
libc.src.arpa.inet.inet_aton
948949
libc.src.arpa.inet.ntohl
949950
libc.src.arpa.inet.ntohs
950951

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ if(LLVM_LIBC_FULL_BUILD)
10771077
# arpa/inet.h entrypoints
10781078
libc.src.arpa.inet.htonl
10791079
libc.src.arpa.inet.htons
1080+
libc.src.arpa.inet.inet_aton
10801081
libc.src.arpa.inet.ntohl
10811082
libc.src.arpa.inet.ntohs
10821083

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,7 @@ if(LLVM_LIBC_FULL_BUILD)
11131113
# arpa/inet.h entrypoints
11141114
libc.src.arpa.inet.htonl
11151115
libc.src.arpa.inet.htons
1116+
libc.src.arpa.inet.inet_aton
11161117
libc.src.arpa.inet.ntohl
11171118
libc.src.arpa.inet.ntohs
11181119

libc/include/arpa/inet.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
header: arpa/inet.h
22
header_template: inet.h.def
33
macros: []
4-
types: []
4+
types:
5+
- type_name: in_addr
56
enums: []
67
objects: []
78
functions:
@@ -17,6 +18,13 @@ functions:
1718
return_type: uint16_t
1819
arguments:
1920
- type: uint16_t
21+
- name: inet_aton
22+
standards:
23+
- POSIX
24+
return_type: int
25+
arguments:
26+
- type: const char *
27+
- type: in_addr *
2028
- name: ntohl
2129
standards:
2230
- POSIX

libc/src/arpa/inet/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ add_entrypoint_object(
2222
libc.src.__support.common
2323
)
2424

25+
add_entrypoint_object(
26+
inet_aton
27+
SRCS
28+
inet_aton.cpp
29+
HDRS
30+
inet_aton.h
31+
DEPENDS
32+
libc.include.arpa_inet
33+
libc.include.llvm-libc-types.in_addr
34+
libc.src.__support.common
35+
libc.src.__support.str_to_integer
36+
libc.src.arpa.inet.htonl
37+
)
38+
2539
add_entrypoint_object(
2640
ntohl
2741
SRCS

libc/src/arpa/inet/inet_aton.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===-- Implementation of inet_aton function ------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/arpa/inet/inet_aton.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/str_to_integer.h"
12+
#include "src/arpa/inet/htonl.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
LLVM_LIBC_FUNCTION(int, inet_aton, (const char *cp, in_addr *inp)) {
17+
unsigned long parts[4] = {0};
18+
int dot_num = 0;
19+
20+
for (; dot_num < 4; ++dot_num) {
21+
auto result = internal::strtointeger<unsigned long>(cp, 0);
22+
parts[dot_num] = result;
23+
24+
if (result.has_error() || result.parsed_len == 0)
25+
return 0;
26+
char next_char = *(cp + result.parsed_len);
27+
if (next_char != '.' && next_char != '\0')
28+
return 0;
29+
else if (next_char == '\0')
30+
break;
31+
else
32+
cp += (result.parsed_len + 1);
33+
}
34+
35+
unsigned long result = 0;
36+
if (dot_num == 0) {
37+
if (parts[0] > 0xffffffff)
38+
return 0;
39+
result = parts[0];
40+
} else if (dot_num == 1) {
41+
if (parts[0] > 0xff || parts[1] > 0xffffff)
42+
return 0;
43+
result = (parts[0] << 24) | parts[1];
44+
} else if (dot_num == 2) {
45+
if (parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xffff)
46+
return 0;
47+
result = (parts[0] << 24) | (parts[1] << 16) | parts[2];
48+
} else if (dot_num == 3) {
49+
if (parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff ||
50+
parts[3] > 0xff)
51+
return 0;
52+
result = (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3];
53+
} else {
54+
return 0;
55+
}
56+
57+
if (inp)
58+
inp->s_addr = LIBC_NAMESPACE::htonl(static_cast<uint32_t>(result));
59+
60+
return 1;
61+
}
62+
63+
} // namespace LIBC_NAMESPACE_DECL

libc/src/arpa/inet/inet_aton.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header of inet_aton ----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_ARPA_INET_INET_ATON_H
10+
#define LLVM_LIBC_SRC_ARPA_INET_INET_ATON_H
11+
12+
#include "include/llvm-libc-types/in_addr.h"
13+
#include "src/__support/macros/config.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
int inet_aton(const char *cp, in_addr *inp);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_ARPA_INET_INET_ATON_H

libc/test/src/arpa/inet/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ add_libc_unittest(
2626
libc.src.arpa.inet.ntohs
2727
)
2828

29+
add_libc_unittest(
30+
inet_aton
31+
SUITE
32+
libc_arpa_inet_unittests
33+
SRCS
34+
inet_aton_test.cpp
35+
CXX_STANDARD
36+
20
37+
DEPENDS
38+
libc.src.arpa.inet.htonl
39+
libc.src.arpa.inet.inet_aton
40+
)
41+
2942
add_libc_unittest(
3043
ntohl
3144
SUITE
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//===-- Unittests for inet_aton -------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/arpa/inet/htonl.h"
10+
#include "src/arpa/inet/inet_aton.h"
11+
#include "test/UnitTest/Test.h"
12+
13+
namespace LIBC_NAMESPACE_DECL {
14+
15+
TEST(LlvmLibcInetAton, ValidTest) {
16+
in_addr a;
17+
18+
// a.b.c.d
19+
a.s_addr = 0;
20+
ASSERT_EQ(1, inet_aton("127.1.2.4", &a));
21+
ASSERT_EQ(htonl(0x7f010204), a.s_addr);
22+
23+
// a.b.c
24+
a.s_addr = 0;
25+
ASSERT_EQ(1, inet_aton("127.1.4", &a));
26+
ASSERT_EQ(htonl(0x7f010004), a.s_addr);
27+
28+
// a.b
29+
a.s_addr = 0;
30+
ASSERT_EQ(1, inet_aton("127.1", &a));
31+
ASSERT_EQ(htonl(0x7f000001), a.s_addr);
32+
33+
// a
34+
a.s_addr = 0;
35+
ASSERT_EQ(1, inet_aton("0x7f000001", &a));
36+
ASSERT_EQ(htonl(0x7f000001), a.s_addr);
37+
38+
// Hex (0x) and mixed-case hex digits.
39+
a.s_addr = 0;
40+
ASSERT_EQ(1, inet_aton("0xFf.0.0.1", &a));
41+
ASSERT_EQ(htonl(0xff000001), a.s_addr);
42+
43+
// Hex (0X) and mixed-case hex digits.
44+
a.s_addr = 0;
45+
ASSERT_EQ(1, inet_aton("0XfF.0.0.1", &a));
46+
ASSERT_EQ(htonl(0xff000001), a.s_addr);
47+
48+
// Octal.
49+
a.s_addr = 0;
50+
ASSERT_EQ(1, inet_aton("0177.0.0.1", &a));
51+
ASSERT_EQ(htonl(0x7f000001), a.s_addr);
52+
53+
a.s_addr = 0;
54+
ASSERT_EQ(1, inet_aton("036", &a));
55+
ASSERT_EQ(htonl(036U), a.s_addr);
56+
}
57+
58+
TEST(LlvmLibcInetAton, InvalidTest) {
59+
ASSERT_EQ(0, inet_aton("", nullptr)); // Empty.
60+
ASSERT_EQ(0, inet_aton("x", nullptr)); // Leading junk.
61+
ASSERT_EQ(0, inet_aton("127.0.0.1x", nullptr)); // Trailing junk.
62+
ASSERT_EQ(0, inet_aton("09.0.0.1", nullptr)); // Invalid octal.
63+
ASSERT_EQ(0, inet_aton("0xg.0.0.1", nullptr)); // Invalid hex.
64+
65+
ASSERT_EQ(0, inet_aton("1.2.3.4.5", nullptr)); // Too many dots.
66+
ASSERT_EQ(0, inet_aton("1.2.3.4.", nullptr)); // Trailing dot.
67+
68+
// Out of range a.b.c.d form.
69+
ASSERT_EQ(0, inet_aton("999.0.0.1", nullptr));
70+
ASSERT_EQ(0, inet_aton("0.999.0.1", nullptr));
71+
ASSERT_EQ(0, inet_aton("0.0.999.1", nullptr));
72+
ASSERT_EQ(0, inet_aton("0.0.0.999", nullptr));
73+
74+
// Out of range a.b.c form.
75+
ASSERT_EQ(0, inet_aton("256.0.0", nullptr));
76+
ASSERT_EQ(0, inet_aton("0.256.0", nullptr));
77+
ASSERT_EQ(0, inet_aton("0.0.0x10000", nullptr));
78+
79+
// Out of range a.b form.
80+
ASSERT_EQ(0, inet_aton("256.0", nullptr));
81+
ASSERT_EQ(0, inet_aton("0.0x1000000", nullptr));
82+
83+
// Out of range a form.
84+
ASSERT_EQ(0, inet_aton("0x100000000", nullptr));
85+
86+
// 64-bit overflow.
87+
ASSERT_EQ(0, inet_aton("0x10000000000000000", nullptr));
88+
89+
// Out of range octal.
90+
ASSERT_EQ(0, inet_aton("0400.0.0.1", nullptr));
91+
}
92+
93+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)