File: | build-scan/../src/resolve/resolved-etc-hosts.c |
Warning: | line 166, column 16 Potential leak of memory pointed to by 'item' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include "fd-util.h" | |||
4 | #include "fileio.h" | |||
5 | #include "hostname-util.h" | |||
6 | #include "resolved-etc-hosts.h" | |||
7 | #include "resolved-dns-synthesize.h" | |||
8 | #include "string-util.h" | |||
9 | #include "strv.h" | |||
10 | #include "time-util.h" | |||
11 | ||||
12 | /* Recheck /etc/hosts at most once every 2s */ | |||
13 | #define ETC_HOSTS_RECHECK_USEC(2*((usec_t) 1000000ULL)) (2*USEC_PER_SEC((usec_t) 1000000ULL)) | |||
14 | ||||
15 | typedef struct EtcHostsItem { | |||
16 | int family; | |||
17 | union in_addr_union address; | |||
18 | ||||
19 | char **names; | |||
20 | } EtcHostsItem; | |||
21 | ||||
22 | typedef struct EtcHostsItemByName { | |||
23 | char *name; | |||
24 | ||||
25 | EtcHostsItem **items; | |||
26 | size_t n_items, n_allocated; | |||
27 | } EtcHostsItemByName; | |||
28 | ||||
29 | void manager_etc_hosts_flush(Manager *m) { | |||
30 | EtcHostsItem *item; | |||
31 | EtcHostsItemByName *bn; | |||
32 | ||||
33 | while ((item = set_steal_first(m->etc_hosts_by_address))) { | |||
34 | strv_free(item->names); | |||
35 | free(item); | |||
36 | } | |||
37 | ||||
38 | while ((bn = hashmap_steal_first(m->etc_hosts_by_name))) { | |||
39 | free(bn->name); | |||
40 | free(bn->items); | |||
41 | free(bn); | |||
42 | } | |||
43 | ||||
44 | m->etc_hosts_by_address = set_free(m->etc_hosts_by_address); | |||
45 | m->etc_hosts_by_name = hashmap_free(m->etc_hosts_by_name); | |||
46 | ||||
47 | m->etc_hosts_mtime = USEC_INFINITY((usec_t) -1); | |||
48 | } | |||
49 | ||||
50 | static void etc_hosts_item_hash_func(const void *p, struct siphash *state) { | |||
51 | const EtcHostsItem *item = p; | |||
52 | ||||
53 | siphash24_compress(&item->family, sizeof(item->family), state); | |||
54 | ||||
55 | if (item->family == AF_INET2) | |||
56 | siphash24_compress(&item->address.in, sizeof(item->address.in), state); | |||
57 | else if (item->family == AF_INET610) | |||
58 | siphash24_compress(&item->address.in6, sizeof(item->address.in6), state); | |||
59 | } | |||
60 | ||||
61 | static int etc_hosts_item_compare_func(const void *a, const void *b) { | |||
62 | const EtcHostsItem *x = a, *y = b; | |||
63 | ||||
64 | if (x->family != y->family) | |||
65 | return x->family - y->family; | |||
66 | ||||
67 | if (x->family == AF_INET2) | |||
68 | return memcmp(&x->address.in.s_addr, &y->address.in.s_addr, sizeof(struct in_addr)); | |||
69 | ||||
70 | if (x->family == AF_INET610) | |||
71 | return memcmp(&x->address.in6.s6_addr__in6_u.__u6_addr8, &y->address.in6.s6_addr__in6_u.__u6_addr8, sizeof(struct in6_addr)); | |||
72 | ||||
73 | return trivial_compare_func(a, b); | |||
74 | } | |||
75 | ||||
76 | static const struct hash_ops etc_hosts_item_ops = { | |||
77 | .hash = etc_hosts_item_hash_func, | |||
78 | .compare = etc_hosts_item_compare_func, | |||
79 | }; | |||
80 | ||||
81 | static int add_item(Manager *m, int family, const union in_addr_union *address, char **names) { | |||
82 | ||||
83 | EtcHostsItem key = { | |||
84 | .family = family, | |||
85 | .address = *address, | |||
86 | }; | |||
87 | EtcHostsItem *item; | |||
88 | char **n; | |||
89 | int r; | |||
90 | ||||
91 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-etc-hosts.c" , 91, __PRETTY_FUNCTION__); } while (0); | |||
92 | assert(address)do { if ((__builtin_expect(!!(!(address)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("address"), "../src/resolve/resolved-etc-hosts.c" , 92, __PRETTY_FUNCTION__); } while (0); | |||
93 | ||||
94 | r = in_addr_is_null(family, address); | |||
95 | if (r < 0) | |||
96 | return r; | |||
97 | if (r > 0) | |||
98 | /* This is an 0.0.0.0 or :: item, which we assume means that we shall map the specified hostname to | |||
99 | * nothing. */ | |||
100 | item = NULL((void*)0); | |||
101 | else { | |||
102 | /* If this is a normal address, then, simply add entry mapping it to the specified names */ | |||
103 | ||||
104 | item = set_get(m->etc_hosts_by_address, &key); | |||
105 | if (item) { | |||
106 | r = strv_extend_strv(&item->names, names, true1); | |||
107 | if (r < 0) | |||
108 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 108, __func__); | |||
109 | } else { | |||
110 | ||||
111 | r = set_ensure_allocated(&m->etc_hosts_by_address, &etc_hosts_item_ops)internal_set_ensure_allocated(&m->etc_hosts_by_address , &etc_hosts_item_ops ); | |||
112 | if (r < 0) | |||
113 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 113, __func__); | |||
114 | ||||
115 | item = new0(EtcHostsItem, 1)((EtcHostsItem*) calloc((1), sizeof(EtcHostsItem))); | |||
116 | if (!item) | |||
117 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 117, __func__); | |||
118 | ||||
119 | item->family = family; | |||
120 | item->address = *address; | |||
121 | item->names = names; | |||
122 | ||||
123 | r = set_put(m->etc_hosts_by_address, item); | |||
124 | if (r < 0) { | |||
125 | free(item); | |||
126 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 126, __func__); | |||
127 | } | |||
128 | } | |||
129 | } | |||
130 | ||||
131 | STRV_FOREACH(n, names)for ((n) = (names); (n) && *(n); (n)++) { | |||
132 | EtcHostsItemByName *bn; | |||
133 | ||||
134 | bn = hashmap_get(m->etc_hosts_by_name, *n); | |||
135 | if (!bn) { | |||
136 | r = hashmap_ensure_allocated(&m->etc_hosts_by_name, &dns_name_hash_ops)internal_hashmap_ensure_allocated(&m->etc_hosts_by_name , &dns_name_hash_ops ); | |||
137 | if (r < 0) | |||
138 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 138, __func__); | |||
139 | ||||
140 | bn = new0(EtcHostsItemByName, 1)((EtcHostsItemByName*) calloc((1), sizeof(EtcHostsItemByName) )); | |||
141 | if (!bn) | |||
142 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 142, __func__); | |||
143 | ||||
144 | bn->name = strdup(*n); | |||
145 | if (!bn->name) { | |||
146 | free(bn); | |||
147 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 147, __func__); | |||
148 | } | |||
149 | ||||
150 | r = hashmap_put(m->etc_hosts_by_name, bn->name, bn); | |||
151 | if (r < 0) { | |||
152 | free(bn->name); | |||
153 | free(bn); | |||
154 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 154, __func__); | |||
155 | } | |||
156 | } | |||
157 | ||||
158 | if (item) { | |||
159 | if (!GREEDY_REALLOC(bn->items, bn->n_allocated, bn->n_items+1)greedy_realloc((void**) &(bn->items), &(bn->n_allocated ), (bn->n_items+1), sizeof((bn->items)[0]))) | |||
160 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 160, __func__); | |||
161 | ||||
162 | bn->items[bn->n_items++] = item; | |||
163 | } | |||
164 | } | |||
165 | ||||
166 | return 0; | |||
| ||||
167 | } | |||
168 | ||||
169 | static int parse_line(Manager *m, unsigned nr, const char *line) { | |||
170 | _cleanup_free___attribute__((cleanup(freep))) char *address = NULL((void*)0); | |||
171 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **names = NULL((void*)0); | |||
172 | union in_addr_union in; | |||
173 | bool_Bool suppressed = false0; | |||
174 | int family, r; | |||
175 | ||||
176 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-etc-hosts.c" , 176, __PRETTY_FUNCTION__); } while (0); | |||
177 | assert(line)do { if ((__builtin_expect(!!(!(line)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("line"), "../src/resolve/resolved-etc-hosts.c" , 177, __PRETTY_FUNCTION__); } while (0); | |||
178 | ||||
179 | r = extract_first_word(&line, &address, NULL((void*)0), EXTRACT_RELAX); | |||
180 | if (r < 0) | |||
181 | return log_error_errno(r, "Couldn't extract address, in line /etc/hosts:%u.", nr)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-etc-hosts.c", 181, __func__, "Couldn't extract address, in line /etc/hosts:%u." , nr) : -abs(_e); }); | |||
182 | if (r == 0) { | |||
183 | log_error("Premature end of line, in line /etc/hosts:%u.", nr)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-etc-hosts.c", 183, __func__, "Premature end of line, in line /etc/hosts:%u." , nr) : -abs(_e); }); | |||
184 | return -EINVAL22; | |||
185 | } | |||
186 | ||||
187 | r = in_addr_from_string_auto(address, &family, &in); | |||
188 | if (r < 0) | |||
189 | return log_error_errno(r, "Address '%s' is invalid, in line /etc/hosts:%u.", address, nr)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-etc-hosts.c", 189, __func__, "Address '%s' is invalid, in line /etc/hosts:%u." , address, nr) : -abs(_e); }); | |||
190 | ||||
191 | for (;;) { | |||
192 | _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0); | |||
193 | ||||
194 | r = extract_first_word(&line, &name, NULL((void*)0), EXTRACT_RELAX); | |||
195 | if (r < 0) | |||
196 | return log_error_errno(r, "Couldn't extract host name, in line /etc/hosts:%u.", nr)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-etc-hosts.c", 196, __func__, "Couldn't extract host name, in line /etc/hosts:%u." , nr) : -abs(_e); }); | |||
197 | if (r == 0) | |||
198 | break; | |||
199 | ||||
200 | r = dns_name_is_valid(name); | |||
201 | if (r
| |||
202 | return log_error_errno(r, "Hostname %s is not valid, ignoring, in line /etc/hosts:%u.", name, nr)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-etc-hosts.c", 202, __func__, "Hostname %s is not valid, ignoring, in line /etc/hosts:%u." , name, nr) : -abs(_e); }); | |||
203 | ||||
204 | if (is_localhost(name)) { | |||
205 | /* Suppress the "localhost" line that is often seen */ | |||
206 | suppressed = true1; | |||
207 | continue; | |||
208 | } | |||
209 | ||||
210 | r = strv_push(&names, name); | |||
211 | if (r < 0) | |||
212 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-etc-hosts.c" , 212, __func__); | |||
213 | ||||
214 | name = NULL((void*)0); | |||
215 | } | |||
216 | ||||
217 | if (strv_isempty(names)) { | |||
218 | ||||
219 | if (suppressed) | |||
220 | return 0; | |||
221 | ||||
222 | log_error("Line is missing any host names, in line /etc/hosts:%u.", nr)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-etc-hosts.c", 222, __func__, "Line is missing any host names, in line /etc/hosts:%u." , nr) : -abs(_e); }); | |||
223 | return -EINVAL22; | |||
224 | } | |||
225 | ||||
226 | /* Takes possession of the names strv */ | |||
227 | r = add_item(m, family, &in, names); | |||
228 | if (r < 0) | |||
229 | return r; | |||
230 | ||||
231 | names = NULL((void*)0); | |||
232 | return r; | |||
233 | } | |||
234 | ||||
235 | int manager_etc_hosts_read(Manager *m) { | |||
236 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
237 | char line[LINE_MAX2048]; | |||
238 | struct stat st; | |||
239 | usec_t ts; | |||
240 | unsigned nr = 0; | |||
241 | int r; | |||
242 | ||||
243 | assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &ts) >= 0)do { if ((__builtin_expect(!!(!(sd_event_now(m->event, clock_boottime_or_monotonic (), &ts) >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("sd_event_now(m->event, clock_boottime_or_monotonic(), &ts) >= 0" ), "../src/resolve/resolved-etc-hosts.c", 243, __PRETTY_FUNCTION__ ); } while (0); | |||
244 | ||||
245 | /* See if we checked /etc/hosts recently already */ | |||
246 | if (m->etc_hosts_last != USEC_INFINITY((usec_t) -1) && m->etc_hosts_last + ETC_HOSTS_RECHECK_USEC(2*((usec_t) 1000000ULL)) > ts) | |||
247 | return 0; | |||
248 | ||||
249 | m->etc_hosts_last = ts; | |||
250 | ||||
251 | if (m->etc_hosts_mtime != USEC_INFINITY((usec_t) -1)) { | |||
252 | if (stat("/etc/hosts", &st) < 0) { | |||
253 | if (errno(*__errno_location ()) == ENOENT2) { | |||
254 | r = 0; | |||
255 | goto clear; | |||
256 | } | |||
257 | ||||
258 | return log_error_errno(errno, "Failed to stat /etc/hosts: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/resolve/resolved-etc-hosts.c", 258 , __func__, "Failed to stat /etc/hosts: %m") : -abs(_e); }); | |||
259 | } | |||
260 | ||||
261 | /* Did the mtime change? If not, there's no point in re-reading the file. */ | |||
262 | if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime) | |||
263 | return 0; | |||
264 | } | |||
265 | ||||
266 | f = fopen("/etc/hosts", "re"); | |||
267 | if (!f) { | |||
268 | if (errno(*__errno_location ()) == ENOENT2) { | |||
269 | r = 0; | |||
270 | goto clear; | |||
271 | } | |||
272 | ||||
273 | return log_error_errno(errno, "Failed to open /etc/hosts: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/resolve/resolved-etc-hosts.c", 273 , __func__, "Failed to open /etc/hosts: %m") : -abs(_e); }); | |||
274 | } | |||
275 | ||||
276 | /* Take the timestamp at the beginning of processing, so that any changes made later are read on the next | |||
277 | * invocation */ | |||
278 | r = fstat(fileno(f), &st); | |||
279 | if (r < 0) | |||
280 | return log_error_errno(errno, "Failed to fstat() /etc/hosts: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/resolve/resolved-etc-hosts.c", 280 , __func__, "Failed to fstat() /etc/hosts: %m") : -abs(_e); } ); | |||
281 | ||||
282 | manager_etc_hosts_flush(m); | |||
283 | ||||
284 | FOREACH_LINE(line, f, return log_error_errno(errno, "Failed to read /etc/hosts: %m"))for (;;) if (!fgets(line, sizeof(line), f)) { if (ferror(f)) { return ({ int _level = ((3)), _e = (((*__errno_location ())) ), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm ) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/resolve/resolved-etc-hosts.c" , 284, __func__, "Failed to read /etc/hosts: %m") : -abs(_e); }); } break; } else { | |||
285 | char *l; | |||
286 | ||||
287 | nr++; | |||
288 | ||||
289 | l = strstrip(line); | |||
290 | if (isempty(l)) | |||
291 | continue; | |||
292 | if (l[0] == '#') | |||
293 | continue; | |||
294 | ||||
295 | r = parse_line(m, nr, l); | |||
296 | if (r == -ENOMEM12) /* On OOM we abandon the half-built-up structure. All other errors we ignore and proceed */ | |||
297 | goto clear; | |||
298 | } | |||
299 | ||||
300 | m->etc_hosts_mtime = timespec_load(&st.st_mtim); | |||
301 | m->etc_hosts_last = ts; | |||
302 | ||||
303 | return 1; | |||
304 | ||||
305 | clear: | |||
306 | manager_etc_hosts_flush(m); | |||
307 | return r; | |||
308 | } | |||
309 | ||||
310 | int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) { | |||
311 | bool_Bool found_a = false0, found_aaaa = false0; | |||
312 | EtcHostsItemByName *bn; | |||
313 | EtcHostsItem k = {}; | |||
314 | DnsResourceKey *t; | |||
315 | const char *name; | |||
316 | unsigned i; | |||
317 | int r; | |||
318 | ||||
319 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-etc-hosts.c" , 319, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
320 | assert(q)do { if ((__builtin_expect(!!(!(q)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("q"), "../src/resolve/resolved-etc-hosts.c" , 320, __PRETTY_FUNCTION__); } while (0); | |||
321 | assert(answer)do { if ((__builtin_expect(!!(!(answer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("answer"), "../src/resolve/resolved-etc-hosts.c" , 321, __PRETTY_FUNCTION__); } while (0); | |||
322 | ||||
323 | r = manager_etc_hosts_read(m); | |||
324 | if (r < 0) | |||
325 | return r; | |||
326 | ||||
327 | name = dns_question_first_name(q); | |||
328 | if (!name) | |||
329 | return 0; | |||
330 | ||||
331 | r = dns_name_address(name, &k.family, &k.address); | |||
332 | if (r > 0) { | |||
333 | EtcHostsItem *item; | |||
334 | DnsResourceKey *found_ptr = NULL((void*)0); | |||
335 | ||||
336 | item = set_get(m->etc_hosts_by_address, &k); | |||
337 | if (!item) | |||
338 | return 0; | |||
339 | ||||
340 | /* We have an address in /etc/hosts that matches the queried name. Let's return successful. Actual data | |||
341 | * we'll only return if the request was for PTR. */ | |||
342 | ||||
343 | DNS_QUESTION_FOREACH(t, q)for (size_t __unique_prefix_i7 = ({ (t) = ((q) && (q) ->n_keys > 0) ? (q)->keys[0] : ((void*)0); 0; }); (q ) && (__unique_prefix_i7 < (q)->n_keys); __unique_prefix_i7 ++, (t) = (__unique_prefix_i7 < (q)->n_keys ? (q)->keys [__unique_prefix_i7] : ((void*)0))) { | |||
344 | if (!IN_SET(t->type, DNS_TYPE_PTR, DNS_TYPE_ANY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_PTR, DNS_TYPE_ANY})/sizeof(int) ]; switch(t->type) { case DNS_TYPE_PTR: case DNS_TYPE_ANY: _found = 1; break; default: break; } _found; })) | |||
345 | continue; | |||
346 | if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_CLASS_IN, DNS_CLASS_ANY})/sizeof(int )]; switch(t->class) { case DNS_CLASS_IN: case DNS_CLASS_ANY : _found = 1; break; default: break; } _found; })) | |||
347 | continue; | |||
348 | ||||
349 | r = dns_name_equal(dns_resource_key_name(t), name); | |||
350 | if (r < 0) | |||
351 | return r; | |||
352 | if (r > 0) { | |||
353 | found_ptr = t; | |||
354 | break; | |||
355 | } | |||
356 | } | |||
357 | ||||
358 | if (found_ptr) { | |||
359 | char **n; | |||
360 | ||||
361 | r = dns_answer_reserve(answer, strv_length(item->names)); | |||
362 | if (r < 0) | |||
363 | return r; | |||
364 | ||||
365 | STRV_FOREACH(n, item->names)for ((n) = (item->names); (n) && *(n); (n)++) { | |||
366 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *rr = NULL((void*)0); | |||
367 | ||||
368 | rr = dns_resource_record_new(found_ptr); | |||
369 | if (!rr) | |||
370 | return -ENOMEM12; | |||
371 | ||||
372 | rr->ptr.name = strdup(*n); | |||
373 | if (!rr->ptr.name) | |||
374 | return -ENOMEM12; | |||
375 | ||||
376 | r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED); | |||
377 | if (r < 0) | |||
378 | return r; | |||
379 | } | |||
380 | } | |||
381 | ||||
382 | return 1; | |||
383 | } | |||
384 | ||||
385 | bn = hashmap_get(m->etc_hosts_by_name, name); | |||
386 | if (!bn) | |||
387 | return 0; | |||
388 | ||||
389 | r = dns_answer_reserve(answer, bn->n_items); | |||
390 | if (r < 0) | |||
391 | return r; | |||
392 | ||||
393 | DNS_QUESTION_FOREACH(t, q)for (size_t __unique_prefix_i8 = ({ (t) = ((q) && (q) ->n_keys > 0) ? (q)->keys[0] : ((void*)0); 0; }); (q ) && (__unique_prefix_i8 < (q)->n_keys); __unique_prefix_i8 ++, (t) = (__unique_prefix_i8 < (q)->n_keys ? (q)->keys [__unique_prefix_i8] : ((void*)0))) { | |||
394 | if (!IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_ANY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_ANY} )/sizeof(int)]; switch(t->type) { case DNS_TYPE_A: case DNS_TYPE_AAAA : case DNS_TYPE_ANY: _found = 1; break; default: break; } _found ; })) | |||
395 | continue; | |||
396 | if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_CLASS_IN, DNS_CLASS_ANY})/sizeof(int )]; switch(t->class) { case DNS_CLASS_IN: case DNS_CLASS_ANY : _found = 1; break; default: break; } _found; })) | |||
397 | continue; | |||
398 | ||||
399 | r = dns_name_equal(dns_resource_key_name(t), name); | |||
400 | if (r < 0) | |||
401 | return r; | |||
402 | if (r == 0) | |||
403 | continue; | |||
404 | ||||
405 | if (IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_ANY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_A, DNS_TYPE_ANY})/sizeof(int)]; switch(t->type) { case DNS_TYPE_A: case DNS_TYPE_ANY: _found = 1; break; default: break; } _found; })) | |||
406 | found_a = true1; | |||
407 | if (IN_SET(t->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_AAAA, DNS_TYPE_ANY})/sizeof(int )]; switch(t->type) { case DNS_TYPE_AAAA: case DNS_TYPE_ANY : _found = 1; break; default: break; } _found; })) | |||
408 | found_aaaa = true1; | |||
409 | ||||
410 | if (found_a && found_aaaa) | |||
411 | break; | |||
412 | } | |||
413 | ||||
414 | for (i = 0; i < bn->n_items; i++) { | |||
415 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *rr = NULL((void*)0); | |||
416 | ||||
417 | if ((!found_a && bn->items[i]->family == AF_INET2) || | |||
418 | (!found_aaaa && bn->items[i]->family == AF_INET610)) | |||
419 | continue; | |||
420 | ||||
421 | r = dns_resource_record_new_address(&rr, bn->items[i]->family, &bn->items[i]->address, bn->name); | |||
422 | if (r < 0) | |||
423 | return r; | |||
424 | ||||
425 | r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED); | |||
426 | if (r < 0) | |||
427 | return r; | |||
428 | } | |||
429 | ||||
430 | return found_a || found_aaaa; | |||
431 | } |