]>
Commit | Line | Data |
---|---|---|
78fc21a1 ZJS |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | ||
bd005277 ZJS |
3 | #include <arpa/inet.h> |
4 | #include <netinet/in.h> | |
5 | #include <sys/socket.h> | |
6 | ||
78fc21a1 | 7 | #include "fd-util.h" |
bd005277 | 8 | #include "fileio.h" |
78fc21a1 ZJS |
9 | #include "fs-util.h" |
10 | #include "log.h" | |
11 | #include "resolved-etc-hosts.h" | |
bd005277 | 12 | #include "strv.h" |
f68a2622 | 13 | #include "tests.h" |
e4de7287 | 14 | #include "tmpfile-util.h" |
78fc21a1 ZJS |
15 | |
16 | static void test_parse_etc_hosts_system(void) { | |
17 | _cleanup_fclose_ FILE *f = NULL; | |
18 | ||
c65f788b ZJS |
19 | log_info("/* %s */", __func__); |
20 | ||
7612719e | 21 | f = fopen("/etc/hosts", "re"); |
78fc21a1 | 22 | if (!f) { |
487e3324 | 23 | assert_se(errno == ENOENT); |
78fc21a1 ZJS |
24 | return; |
25 | } | |
26 | ||
27 | _cleanup_(etc_hosts_free) EtcHosts hosts = {}; | |
28 | assert_se(etc_hosts_parse(&hosts, f) == 0); | |
29 | } | |
30 | ||
bd005277 ZJS |
31 | #define address_equal_4(_addr, _address) \ |
32 | ((_addr)->family == AF_INET && \ | |
33 | !memcmp(&(_addr)->address.in, &(struct in_addr) { .s_addr = (_address) }, 4)) | |
34 | ||
35 | #define address_equal_6(_addr, ...) \ | |
36 | ((_addr)->family == AF_INET6 && \ | |
37 | !memcmp(&(_addr)->address.in6, &(struct in6_addr) { .s6_addr = __VA_ARGS__}, 16) ) | |
38 | ||
c65f788b | 39 | static void test_parse_etc_hosts(void) { |
78fc21a1 ZJS |
40 | _cleanup_(unlink_tempfilep) char |
41 | t[] = "/tmp/test-resolved-etc-hosts.XXXXXX"; | |
42 | ||
c65f788b ZJS |
43 | log_info("/* %s */", __func__); |
44 | ||
78fc21a1 ZJS |
45 | int fd; |
46 | _cleanup_fclose_ FILE *f; | |
bd005277 | 47 | const char *s; |
78fc21a1 | 48 | |
c65f788b ZJS |
49 | fd = mkostemp_safe(t); |
50 | assert_se(fd >= 0); | |
51 | ||
52 | f = fdopen(fd, "r+"); | |
53 | assert_se(f); | |
bd005277 ZJS |
54 | fputs("1.2.3.4 some.where\n" |
55 | "1.2.3.5 some.where\n" | |
56 | "1.2.3.6 dash dash-dash.where-dash\n" | |
57 | "1.2.3.7 bad-dash- -bad-dash -bad-dash.bad-\n" | |
58 | "1.2.3.8\n" | |
59 | "1.2.3.9 before.comment # within.comment\n" | |
60 | "1.2.3.10 before.comment#within.comment2\n" | |
61 | "1.2.3.11 before.comment# within.comment3\n" | |
62 | "1.2.3.12 before.comment#\n" | |
63 | "1.2.3 short.address\n" | |
64 | "1.2.3.4.5 long.address\n" | |
65 | "1::2::3 multi.colon\n" | |
66 | ||
67 | "::0 some.where some.other\n" | |
68 | "0.0.0.0 black.listed\n" | |
69 | "::5\t\t\t \tsome.where\tsome.other foobar.foo.foo\t\t\t\n" | |
70 | " \n", f); | |
71 | assert_se(fflush_and_check(f) >= 0); | |
c65f788b | 72 | rewind(f); |
78fc21a1 ZJS |
73 | |
74 | _cleanup_(etc_hosts_free) EtcHosts hosts = {}; | |
75 | assert_se(etc_hosts_parse(&hosts, f) == 0); | |
76 | ||
78fc21a1 ZJS |
77 | EtcHostsItemByName *bn; |
78 | assert_se(bn = hashmap_get(hosts.by_name, "some.where")); | |
79 | assert_se(bn->n_addresses == 3); | |
80 | assert_se(bn->n_allocated >= 3); | |
bd005277 ZJS |
81 | assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.4"))); |
82 | assert_se(address_equal_4(bn->addresses[1], inet_addr("1.2.3.5"))); | |
83 | assert_se(address_equal_6(bn->addresses[2], {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5})); | |
78fc21a1 | 84 | |
bd005277 ZJS |
85 | assert_se(bn = hashmap_get(hosts.by_name, "dash")); |
86 | assert_se(bn->n_addresses == 1); | |
87 | assert_se(bn->n_allocated >= 1); | |
88 | assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.6"))); | |
89 | ||
90 | assert_se(bn = hashmap_get(hosts.by_name, "dash-dash.where-dash")); | |
91 | assert_se(bn->n_addresses == 1); | |
92 | assert_se(bn->n_allocated >= 1); | |
93 | assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.6"))); | |
94 | ||
7470cc4c ZJS |
95 | /* See https://tools.ietf.org/html/rfc1035#section-2.3.1 */ |
96 | FOREACH_STRING(s, "bad-dash-", "-bad-dash", "-bad-dash.bad-") | |
97 | assert_se(!hashmap_get(hosts.by_name, s)); | |
78fc21a1 | 98 | |
bd005277 ZJS |
99 | assert_se(bn = hashmap_get(hosts.by_name, "before.comment")); |
100 | assert_se(bn->n_addresses == 4); | |
101 | assert_se(bn->n_allocated >= 4); | |
102 | assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.9"))); | |
103 | assert_se(address_equal_4(bn->addresses[1], inet_addr("1.2.3.10"))); | |
104 | assert_se(address_equal_4(bn->addresses[2], inet_addr("1.2.3.11"))); | |
105 | assert_se(address_equal_4(bn->addresses[3], inet_addr("1.2.3.12"))); | |
106 | ||
107 | assert(!hashmap_get(hosts.by_name, "within.comment")); | |
108 | assert(!hashmap_get(hosts.by_name, "within.comment2")); | |
109 | assert(!hashmap_get(hosts.by_name, "within.comment3")); | |
110 | assert(!hashmap_get(hosts.by_name, "#")); | |
111 | ||
112 | assert(!hashmap_get(hosts.by_name, "short.address")); | |
113 | assert(!hashmap_get(hosts.by_name, "long.address")); | |
114 | assert(!hashmap_get(hosts.by_name, "multi.colon")); | |
115 | assert_se(!set_contains(hosts.no_address, "short.address")); | |
116 | assert_se(!set_contains(hosts.no_address, "long.address")); | |
117 | assert_se(!set_contains(hosts.no_address, "multi.colon")); | |
78fc21a1 ZJS |
118 | |
119 | assert_se(bn = hashmap_get(hosts.by_name, "some.other")); | |
120 | assert_se(bn->n_addresses == 1); | |
121 | assert_se(bn->n_allocated >= 1); | |
bd005277 | 122 | assert_se(address_equal_6(bn->addresses[0], {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5})); |
fd373593 ZJS |
123 | |
124 | assert_se( set_contains(hosts.no_address, "some.where")); | |
125 | assert_se( set_contains(hosts.no_address, "some.other")); | |
126 | assert_se( set_contains(hosts.no_address, "black.listed")); | |
127 | assert_se(!set_contains(hosts.no_address, "foobar.foo.foo")); | |
78fc21a1 ZJS |
128 | } |
129 | ||
c65f788b ZJS |
130 | static void test_parse_file(const char *fname) { |
131 | _cleanup_(etc_hosts_free) EtcHosts hosts = {}; | |
132 | _cleanup_fclose_ FILE *f; | |
133 | ||
134 | log_info("/* %s(\"%s\") */", __func__, fname); | |
135 | ||
136 | assert_se(f = fopen(fname, "re")); | |
137 | assert_se(etc_hosts_parse(&hosts, f) == 0); | |
138 | } | |
139 | ||
78fc21a1 | 140 | int main(int argc, char **argv) { |
f68a2622 | 141 | test_setup_logging(LOG_DEBUG); |
78fc21a1 | 142 | |
c65f788b | 143 | if (argc == 1) { |
78fc21a1 | 144 | test_parse_etc_hosts_system(); |
c65f788b ZJS |
145 | test_parse_etc_hosts(); |
146 | } else | |
147 | test_parse_file(argv[1]); | |
78fc21a1 ZJS |
148 | |
149 | return 0; | |
150 | } |