1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include <netinet/in.h>
6 #include <sys/socket.h>
12 #include "resolved-etc-hosts.h"
15 #include "tmpfile-util.h"
17 TEST(parse_etc_hosts_system
) {
18 _cleanup_fclose_
FILE *f
= NULL
;
20 f
= fopen("/etc/hosts", "re");
22 assert_se(errno
== ENOENT
);
26 _cleanup_(etc_hosts_clear
) EtcHosts hosts
= {};
27 assert_se(etc_hosts_parse(&hosts
, f
) == 0);
30 #define in_addr_4(_address_str) \
31 (&(struct in_addr_data) { .family = AF_INET, .address.in = { .s_addr = inet_addr(_address_str) } })
33 #define in_addr_6(...) \
34 (&(struct in_addr_data) { .family = AF_INET6, .address.in6 = { .s6_addr = __VA_ARGS__ } })
36 #define has_4(_set, _address_str) \
37 set_contains(_set, in_addr_4(_address_str))
39 #define has_6(_set, ...) \
40 set_contains(_set, in_addr_6(__VA_ARGS__))
42 TEST(parse_etc_hosts
) {
43 _cleanup_(unlink_tempfilep
) char
44 t
[] = "/tmp/test-resolved-etc-hosts.XXXXXX";
47 _cleanup_fclose_
FILE *f
= NULL
;
49 fd
= mkostemp_safe(t
);
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"
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"
67 "::0 some.where some.other\n"
68 "0.0.0.0 deny.listed\n"
69 "::5\t\t\t \tsome.where\tsome.other foobar.foo.foo\t\t\t\n"
71 assert_se(fflush_and_check(f
) >= 0);
74 _cleanup_(etc_hosts_clear
) EtcHosts hosts
= {};
75 assert_se(etc_hosts_parse(&hosts
, f
) == 0);
77 EtcHostsItemByName
*bn
;
78 assert_se(bn
= hashmap_get(hosts
.by_name
, "some.where"));
79 assert_se(set_size(bn
->addresses
) == 3);
80 assert_se(has_4(bn
->addresses
, "1.2.3.4"));
81 assert_se(has_4(bn
->addresses
, "1.2.3.5"));
82 assert_se(has_6(bn
->addresses
, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}));
84 assert_se(bn
= hashmap_get(hosts
.by_name
, "dash"));
85 assert_se(set_size(bn
->addresses
) == 1);
86 assert_se(has_4(bn
->addresses
, "1.2.3.6"));
88 assert_se(bn
= hashmap_get(hosts
.by_name
, "dash-dash.where-dash"));
89 assert_se(set_size(bn
->addresses
) == 1);
90 assert_se(has_4(bn
->addresses
, "1.2.3.6"));
92 /* See https://tools.ietf.org/html/rfc1035#section-2.3.1 */
93 FOREACH_STRING(s
, "bad-dash-", "-bad-dash", "-bad-dash.bad-")
94 assert_se(!hashmap_get(hosts
.by_name
, s
));
96 assert_se(bn
= hashmap_get(hosts
.by_name
, "before.comment"));
97 assert_se(set_size(bn
->addresses
) == 4);
98 assert_se(has_4(bn
->addresses
, "1.2.3.9"));
99 assert_se(has_4(bn
->addresses
, "1.2.3.10"));
100 assert_se(has_4(bn
->addresses
, "1.2.3.11"));
101 assert_se(has_4(bn
->addresses
, "1.2.3.12"));
103 assert_se(!hashmap_get(hosts
.by_name
, "within.comment"));
104 assert_se(!hashmap_get(hosts
.by_name
, "within.comment2"));
105 assert_se(!hashmap_get(hosts
.by_name
, "within.comment3"));
106 assert_se(!hashmap_get(hosts
.by_name
, "#"));
108 assert_se(!hashmap_get(hosts
.by_name
, "short.address"));
109 assert_se(!hashmap_get(hosts
.by_name
, "long.address"));
110 assert_se(!hashmap_get(hosts
.by_name
, "multi.colon"));
111 assert_se(!set_contains(hosts
.no_address
, "short.address"));
112 assert_se(!set_contains(hosts
.no_address
, "long.address"));
113 assert_se(!set_contains(hosts
.no_address
, "multi.colon"));
115 assert_se(bn
= hashmap_get(hosts
.by_name
, "some.other"));
116 assert_se(set_size(bn
->addresses
) == 1);
117 assert_se(has_6(bn
->addresses
, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}));
119 EtcHostsItemByAddress
*ba
;
120 assert_se(ba
= hashmap_get(hosts
.by_address
, in_addr_4("1.2.3.6")));
121 assert_se(set_size(ba
->names
) == 2);
122 assert_se(set_contains(ba
->names
, "dash"));
123 assert_se(set_contains(ba
->names
, "dash-dash.where-dash"));
124 assert_se(streq(ba
->canonical_name
, "dash"));
126 assert_se(ba
= hashmap_get(hosts
.by_address
, in_addr_6({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5})));
127 assert_se(set_size(ba
->names
) == 3);
128 assert_se(set_contains(ba
->names
, "some.where"));
129 assert_se(set_contains(ba
->names
, "some.other"));
130 assert_se(set_contains(ba
->names
, "foobar.foo.foo"));
131 assert_se(streq(ba
->canonical_name
, "some.where"));
133 assert_se( set_contains(hosts
.no_address
, "some.where"));
134 assert_se( set_contains(hosts
.no_address
, "some.other"));
135 assert_se( set_contains(hosts
.no_address
, "deny.listed"));
136 assert_se(!set_contains(hosts
.no_address
, "foobar.foo.foo"));
139 static void test_parse_file_one(const char *fname
) {
140 _cleanup_(etc_hosts_clear
) EtcHosts hosts
= {};
141 _cleanup_fclose_
FILE *f
= NULL
;
143 log_info("/* %s(\"%s\") */", __func__
, fname
);
145 assert_se(f
= fopen(fname
, "re"));
146 assert_se(etc_hosts_parse(&hosts
, f
) == 0);
150 for (int i
= 1; i
< saved_argc
; i
++)
151 test_parse_file_one(saved_argv
[i
]);
154 DEFINE_TEST_MAIN(LOG_DEBUG
);