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