]> git.ipfire.org Git - thirdparty/glibc.git/blame - nss/getaddrinfo.c
Move getaddrinfo from 'posix' into 'nss'
[thirdparty/glibc.git] / nss / getaddrinfo.c
CommitLineData
cd065b68 1/* Host and service name lookups using Name Service Switch modules.
6d7e8eda 2 Copyright (C) 1996-2023 Free Software Foundation, Inc.
cd065b68
FW
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
cd065b68 18
46ec036d
UD
19/* The Inner Net License, Version 2.00
20
21 The author(s) grant permission for redistribution and use in source and
22binary forms, with or without modification, of the software and documentation
23provided that the following conditions are met:
24
250. If you receive a version of the software that is specifically labelled
26 as not being for redistribution (check the version message and/or README),
27 you are not permitted to redistribute that version of the software in any
28 way or form.
291. All terms of the all other applicable copyrights and licenses must be
30 followed.
312. Redistributions of source code must retain the authors' copyright
32 notice(s), this list of conditions, and the following disclaimer.
333. Redistributions in binary form must reproduce the authors' copyright
34 notice(s), this list of conditions, and the following disclaimer in the
35 documentation and/or other materials provided with the distribution.
aeb25823 364. [The copyright holder has authorized the removal of this clause.]
46ec036d
UD
375. Neither the name(s) of the author(s) nor the names of its contributors
38 may be used to endorse or promote products derived from this software
39 without specific prior written permission.
40
41THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
42EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
45DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
48ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51
52 If these license terms cause you a real problem, contact the author. */
53
54/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
55
c0bc5f7b 56#include <assert.h>
77dd4c3b 57#include <ctype.h>
c0bc5f7b 58#include <errno.h>
925c3c5c 59#include <ifaddrs.h>
c0bc5f7b 60#include <netdb.h>
1eb946b9 61#include <nss.h>
b76e0659 62#include <resolv/resolv-internal.h>
352f4ff9 63#include <resolv/resolv_context.h>
f24dca48 64#include <stdbool.h>
c0bc5f7b 65#include <stdio.h>
77dd4c3b 66#include <stdio_ext.h>
46ec036d 67#include <stdlib.h>
c0bc5f7b 68#include <string.h>
e054f494 69#include <stdint.h>
c0bc5f7b 70#include <arpa/inet.h>
77dd4c3b 71#include <net/if.h>
a334319f 72#include <netinet/in.h>
77dd4c3b
UD
73#include <sys/socket.h>
74#include <sys/stat.h>
c0bc5f7b
UD
75#include <sys/types.h>
76#include <sys/un.h>
77#include <sys/utsname.h>
77dd4c3b 78#include <unistd.h>
218d76e0 79#include <nsswitch.h>
ec999b8e 80#include <libc-lock.h>
5ddb5bf5 81#include <not-cancel.h>
d19687d6 82#include <nscd/nscd-client.h>
62417d7e 83#include <nscd/nscd_proto.h>
cd065b68 84#include <scratch_buffer.h>
80d8cb91 85#include <inet/net-internal.h>
1fb05e3d 86
7f9f1ecb
FW
87/* Former AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES
88 flags, now ignored. */
89#define DEPRECATED_AI_IDN 0x300
e2fd3cbe 90
7fc03cf3
JM
91#if IS_IN (libc)
92# define feof_unlocked(fp) __feof_unlocked (fp)
93#endif
94
40a55d20
UD
95struct gaih_service
96 {
97 const char *name;
98 int num;
99 };
46ec036d 100
40a55d20
UD
101struct gaih_servtuple
102 {
40a55d20
UD
103 int socktype;
104 int protocol;
105 int port;
8d6cf99f 106 bool set;
40a55d20 107 };
46ec036d 108
46ec036d 109
40a55d20
UD
110struct gaih_typeproto
111 {
112 int socktype;
113 int protocol;
372bfcac
UD
114 uint8_t protoflag;
115 bool defaultflag;
116 char name[8];
40a55d20 117 };
46ec036d 118
26dea461
SP
119struct gaih_result
120{
121 struct gaih_addrtuple *at;
122 char *canon;
973fe93a 123 char *h_name;
b44389cb 124 bool free_at;
e7e5315b 125 bool got_ipv6;
26dea461
SP
126};
127
f3ac48d0
UD
128/* Values for `protoflag'. */
129#define GAI_PROTO_NOSERVICE 1
85599e53 130#define GAI_PROTO_PROTOANY 2
f3ac48d0 131
3e2d61a3 132static const struct gaih_typeproto gaih_inet_typeproto[] =
40a55d20 133{
372bfcac
UD
134 { 0, 0, 0, false, "" },
135 { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
136 { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
137#if defined SOCK_DCCP && defined IPPROTO_DCCP
138 { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
139#endif
140#ifdef IPPROTO_UDPLITE
141 { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
18a74157
UD
142#endif
143#ifdef IPPROTO_SCTP
144 { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
145 { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
372bfcac
UD
146#endif
147 { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
148 { 0, 0, 0, false, "" }
46ec036d
UD
149};
150
3e2d61a3 151static const struct addrinfo default_hints =
925c3c5c
UD
152 {
153 .ai_flags = AI_DEFAULT,
154 .ai_family = PF_UNSPEC,
155 .ai_socktype = 0,
156 .ai_protocol = 0,
157 .ai_addrlen = 0,
158 .ai_addr = NULL,
159 .ai_canonname = NULL,
160 .ai_next = NULL
161 };
40a55d20 162
906cecbe
SP
163static void
164gaih_result_reset (struct gaih_result *res)
165{
166 if (res->free_at)
167 free (res->at);
168 free (res->canon);
973fe93a 169 free (res->h_name);
906cecbe
SP
170 memset (res, 0, sizeof (*res));
171}
40a55d20 172
40a55d20 173static int
3e2d61a3 174gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
cd065b68
FW
175 const struct addrinfo *req, struct gaih_servtuple *st,
176 struct scratch_buffer *tmpbuf)
46ec036d
UD
177{
178 struct servent *s;
993b3242 179 struct servent ts;
40a55d20
UD
180 int r;
181
182 do
993b3242 183 {
cd065b68
FW
184 r = __getservbyname_r (servicename, tp->name, &ts,
185 tmpbuf->data, tmpbuf->length, &s);
a0bf6ac7 186 if (r != 0 || s == NULL)
993b3242 187 {
a0bf6ac7 188 if (r == ERANGE)
cd065b68
FW
189 {
190 if (!scratch_buffer_grow (tmpbuf))
191 return -EAI_MEMORY;
192 }
40a55d20 193 else
639a0ef8 194 return -EAI_SERVICE;
993b3242
UD
195 }
196 }
40a55d20 197 while (r);
993b3242 198
238ae1eb 199 st->socktype = tp->socktype;
85599e53
UD
200 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
201 ? req->ai_protocol : tp->protocol);
238ae1eb 202 st->port = s->s_port;
8d6cf99f 203 st->set = true;
46ec036d
UD
204
205 return 0;
206}
207
973fe93a
SP
208/* Convert struct hostent to a list of struct gaih_addrtuple objects. The new
209 addresses are appended to the tuple array in RES. */
4ab2ab03 210static bool
906cecbe
SP
211convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
212 struct hostent *h, struct gaih_result *res)
4ab2ab03 213{
4ab2ab03
FW
214 /* Count the number of addresses in h->h_addr_list. */
215 size_t count = 0;
216 for (char **p = h->h_addr_list; *p != NULL; ++p)
217 ++count;
218
219 /* Report no data if no addresses are available, or if the incoming
220 address size is larger than what we can store. */
221 if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
222 return true;
223
906cecbe 224 struct gaih_addrtuple *array = res->at;
30046046
SP
225 size_t old = 0;
226
227 while (array != NULL)
228 {
229 old++;
230 array = array->next;
231 }
232
906cecbe 233 array = realloc (res->at, (old + count) * sizeof (*array));
30046046 234
4ab2ab03
FW
235 if (array == NULL)
236 return false;
237
906cecbe
SP
238 res->got_ipv6 = family == AF_INET6;
239 res->at = array;
240 res->free_at = true;
30046046 241
973fe93a
SP
242 /* Duplicate h_name because it may get reclaimed when the underlying storage
243 is freed. */
244 if (res->h_name == NULL)
245 {
246 res->h_name = __strdup (h->h_name);
247 if (res->h_name == NULL)
248 return false;
249 }
250
30046046
SP
251 /* Update the next pointers on reallocation. */
252 for (size_t i = 0; i < old; i++)
253 array[i].next = array + i + 1;
254
255 array += old;
256
257 memset (array, 0, count * sizeof (*array));
258
4ab2ab03
FW
259 for (size_t i = 0; i < count; ++i)
260 {
261 if (family == AF_INET && req->ai_family == AF_INET6)
262 {
263 /* Perform address mapping. */
264 array[i].family = AF_INET6;
265 memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
266 array[i].addr[2] = htonl (0xffff);
267 }
268 else
269 {
270 array[i].family = family;
271 memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
272 }
273 array[i].next = array + i + 1;
274 }
4ab2ab03
FW
275 array[count - 1].next = NULL;
276
4ab2ab03
FW
277 return true;
278}
279
cfa3bd48
SP
280static int
281gethosts (nss_gethostbyname3_r fct, int family, const char *name,
282 const struct addrinfo *req, struct scratch_buffer *tmpbuf,
283 struct gaih_result *res, enum nss_status *statusp, int *no_datap)
284{
285 struct hostent th;
286 char *localcanon = NULL;
287 enum nss_status status;
288
289 *no_datap = 0;
290 while (1)
291 {
292 *statusp = status = DL_CALL_FCT (fct, (name, family, &th,
293 tmpbuf->data, tmpbuf->length,
294 &errno, &h_errno, NULL,
295 &localcanon));
296 if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL
297 || errno != ERANGE)
298 break;
299 if (!scratch_buffer_grow (tmpbuf))
300 return -EAI_MEMORY;
301 }
302 if (status == NSS_STATUS_NOTFOUND
303 || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
304 {
305 if (h_errno == NETDB_INTERNAL)
306 return -EAI_SYSTEM;
307 if (h_errno == TRY_AGAIN)
308 *no_datap = EAI_AGAIN;
309 else
310 *no_datap = h_errno == NO_DATA;
311 }
312 else if (status == NSS_STATUS_SUCCESS)
313 {
314 if (!convert_hostent_to_gaih_addrtuple (req, family, &th, res))
b587456c 315 return -EAI_MEMORY;
cfa3bd48
SP
316
317 if (localcanon != NULL && res->canon == NULL)
318 {
319 char *canonbuf = __strdup (localcanon);
320 if (canonbuf == NULL)
b587456c 321 return -EAI_MEMORY;
cfa3bd48
SP
322 res->canon = canonbuf;
323 }
324 }
218d76e0 325
cfa3bd48
SP
326 return 0;
327}
28977c2c 328
673cb072
FW
329/* This function is called if a canonical name is requested, but if
330 the service function did not provide it. It tries to obtain the
331 name using getcanonname_r from the same service NIP. If the name
332 cannot be canonicalized, return a copy of NAME. Return NULL on
333 memory allocation failure. The returned string is allocated on the
334 heap; the caller has to free it. */
335static char *
973fe93a 336getcanonname (nss_action_list nip, const char *hname, const char *name)
673cb072 337{
499a92df 338 nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
673cb072
FW
339 char *s = (char *) name;
340 if (cfct != NULL)
341 {
342 char buf[256];
973fe93a
SP
343 if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf), &s, &errno,
344 &h_errno)) != NSS_STATUS_SUCCESS)
673cb072
FW
345 /* If the canonical name cannot be determined, use the passed
346 string. */
347 s = (char *) name;
348 }
3bf7bab8 349 return __strdup (s);
673cb072 350}
3af48b5b 351
d01411f6
SP
352/* Process looked up canonical name and if necessary, decode to IDNA. Result
353 is a new string written to CANONP and the earlier string is freed. */
354
355static int
356process_canonname (const struct addrinfo *req, const char *orig_name,
26dea461 357 struct gaih_result *res)
d01411f6 358{
26dea461 359 char *canon = res->canon;
d01411f6
SP
360
361 if ((req->ai_flags & AI_CANONNAME) != 0)
362 {
363 bool do_idn = req->ai_flags & AI_CANONIDN;
364 if (do_idn)
365 {
366 char *out;
367 int rc = __idna_from_dns_encoding (canon ?: orig_name, &out);
368 if (rc == 0)
369 {
370 free (canon);
371 canon = out;
372 }
373 else if (rc == EAI_IDN_ENCODE)
374 /* Use the punycode name as a fallback. */
375 do_idn = false;
376 else
377 return -rc;
378 }
379 if (!do_idn && canon == NULL && (canon = __strdup (orig_name)) == NULL)
380 return -EAI_MEMORY;
381 }
382
26dea461 383 res->canon = canon;
d01411f6
SP
384 return 0;
385}
386
40a55d20 387static int
8d6cf99f
SP
388get_servtuples (const struct gaih_service *service, const struct addrinfo *req,
389 struct gaih_servtuple *st, struct scratch_buffer *tmpbuf)
46ec036d 390{
8d6cf99f 391 int i;
3e2d61a3 392 const struct gaih_typeproto *tp = gaih_inet_typeproto;
46ec036d 393
40a55d20
UD
394 if (req->ai_protocol || req->ai_socktype)
395 {
f3ac48d0
UD
396 ++tp;
397
4b1fef84 398 while (tp->name[0]
3a47453d
UD
399 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
400 || (req->ai_protocol != 0
85599e53 401 && !(tp->protoflag & GAI_PROTO_PROTOANY)
3a47453d 402 && req->ai_protocol != tp->protocol)))
f3ac48d0
UD
403 ++tp;
404
4b1fef84 405 if (! tp->name[0])
6e4c40ba
UD
406 {
407 if (req->ai_socktype)
639a0ef8 408 return -EAI_SOCKTYPE;
6e4c40ba 409 else
639a0ef8 410 return -EAI_SERVICE;
6e4c40ba 411 }
40a55d20
UD
412 }
413
8d6cf99f
SP
414 if (service != NULL && (tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
415 return -EAI_SERVICE;
416
417 if (service == NULL || service->num >= 0)
40a55d20 418 {
8d6cf99f 419 int port = service != NULL ? htons (service->num) : 0;
f3ac48d0 420
8d6cf99f 421 if (req->ai_socktype || req->ai_protocol)
40a55d20 422 {
8d6cf99f
SP
423 st[0].socktype = tp->socktype;
424 st[0].protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
425 ? req->ai_protocol : tp->protocol);
426 st[0].port = port;
427 st[0].set = true;
3a47453d 428
8d6cf99f
SP
429 return 0;
430 }
3a47453d 431
8d6cf99f
SP
432 /* Neither socket type nor protocol is set. Return all socket types
433 we know about. */
434 for (i = 0, ++tp; tp->name[0]; ++tp)
435 if (tp->defaultflag)
436 {
437 st[i].socktype = tp->socktype;
438 st[i].protocol = tp->protocol;
439 st[i].port = port;
440 st[i++].set = true;
441 }
84a4fd33 442
8d6cf99f
SP
443 return 0;
444 }
238ae1eb 445
8d6cf99f
SP
446 if (tp->name[0])
447 return gaih_inet_serv (service->name, tp, req, st, tmpbuf);
238ae1eb 448
8d6cf99f 449 for (i = 0, tp++; tp->name[0]; tp++)
84a4fd33 450 {
8d6cf99f
SP
451 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
452 continue;
29546dd9 453
8d6cf99f
SP
454 if (req->ai_socktype != 0
455 && req->ai_socktype != tp->socktype)
456 continue;
457 if (req->ai_protocol != 0
458 && !(tp->protoflag & GAI_PROTO_PROTOANY)
459 && req->ai_protocol != tp->protocol)
460 continue;
372bfcac 461
8d6cf99f
SP
462 if (gaih_inet_serv (service->name,
463 tp, req, &st[i], tmpbuf) != 0)
464 continue;
372bfcac 465
8d6cf99f 466 i++;
84a4fd33 467 }
40a55d20 468
8d6cf99f
SP
469 if (!st[0].set)
470 return -EAI_SERVICE;
471
472 return 0;
473}
474
e7e5315b
SP
475#ifdef USE_NSCD
476/* Query addresses from nscd cache, returning a non-zero value on error.
477 RES members have the lookup result; RES->AT is NULL if there were no errors
478 but also no results. */
479
480static int
481get_nscd_addresses (const char *name, const struct addrinfo *req,
482 struct gaih_result *res)
483{
484 if (__nss_not_use_nscd_hosts > 0
485 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
486 __nss_not_use_nscd_hosts = 0;
487
488 res->at = NULL;
489
490 if (__nss_not_use_nscd_hosts || __nss_database_custom[NSS_DBSIDX_hosts])
491 return 0;
492
493 /* Try to use nscd. */
494 struct nscd_ai_result *air = NULL;
495 int err = __nscd_getai (name, &air, &h_errno);
496
497 if (__glibc_unlikely (air == NULL))
498 {
499 /* The database contains a negative entry. */
500 if (err == 0)
501 return -EAI_NONAME;
502 if (__nss_not_use_nscd_hosts == 0)
503 {
504 if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
505 return -EAI_MEMORY;
506 if (h_errno == TRY_AGAIN)
507 return -EAI_AGAIN;
508 return -EAI_SYSTEM;
509 }
510 return 0;
511 }
512
513 /* Transform into gaih_addrtuple list. */
514 int result = 0;
515 char *addrs = air->addrs;
516
517 struct gaih_addrtuple *addrfree = calloc (air->naddrs, sizeof (*addrfree));
518 struct gaih_addrtuple *at = calloc (air->naddrs, sizeof (*at));
519 if (at == NULL)
520 {
521 result = -EAI_MEMORY;
522 goto out;
523 }
524
525 res->free_at = true;
526
527 int count = 0;
528 for (int i = 0; i < air->naddrs; ++i)
529 {
530 socklen_t size = (air->family[i] == AF_INET
531 ? INADDRSZ : IN6ADDRSZ);
532
533 if (!((air->family[i] == AF_INET
534 && req->ai_family == AF_INET6
535 && (req->ai_flags & AI_V4MAPPED) != 0)
536 || req->ai_family == AF_UNSPEC
537 || air->family[i] == req->ai_family))
538 {
539 /* Skip over non-matching result. */
540 addrs += size;
541 continue;
542 }
543
544 if (air->family[i] == AF_INET && req->ai_family == AF_INET6
545 && (req->ai_flags & AI_V4MAPPED))
546 {
547 at[count].family = AF_INET6;
548 at[count].addr[3] = *(uint32_t *) addrs;
549 at[count].addr[2] = htonl (0xffff);
550 }
551 else if (req->ai_family == AF_UNSPEC
c9226c03 552 || air->family[i] == req->ai_family)
e7e5315b 553 {
c9226c03 554 at[count].family = air->family[i];
e7e5315b 555 memcpy (at[count].addr, addrs, size);
c9226c03 556 if (air->family[i] == AF_INET6)
e7e5315b
SP
557 res->got_ipv6 = true;
558 }
559 at[count].next = at + count + 1;
560 count++;
561 addrs += size;
562 }
563
564 if ((req->ai_flags & AI_CANONNAME) && air->canon != NULL)
565 {
566 char *canonbuf = __strdup (air->canon);
567 if (canonbuf == NULL)
568 {
569 result = -EAI_MEMORY;
570 goto out;
571 }
572 res->canon = canonbuf;
573 }
574
575 if (count == 0)
576 {
577 result = -EAI_NONAME;
578 goto out;
579 }
580
581 at[count - 1].next = NULL;
582
583 res->at = at;
584
585out:
586 free (air);
587 if (result != 0)
588 {
589 free (at);
590 res->free_at = false;
591 }
592
593 return result;
594}
595#endif
596
906cecbe
SP
597static int
598get_nss_addresses (const char *name, const struct addrinfo *req,
599 struct scratch_buffer *tmpbuf, struct gaih_result *res)
600{
601 int no_data = 0;
602 int no_inet6_data = 0;
603 nss_action_list nip;
604 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
605 enum nss_status status = NSS_STATUS_UNAVAIL;
606 int no_more;
607 struct resolv_context *res_ctx = NULL;
608 bool do_merge = false;
609 int result = 0;
610
611 no_more = !__nss_database_get (nss_database_hosts, &nip);
612
613 /* If we are looking for both IPv4 and IPv6 address we don't
614 want the lookup functions to automatically promote IPv4
615 addresses to IPv6 addresses, so we use the no_inet6
616 function variant. */
617 res_ctx = __resolv_context_get ();
618 if (res_ctx == NULL)
619 no_more = 1;
620
621 while (!no_more)
622 {
623 /* Always start afresh; continue should discard previous results
624 and the hosts database does not support merge. */
625 gaih_result_reset (res);
626
627 if (do_merge)
628 {
629 __set_h_errno (NETDB_INTERNAL);
630 __set_errno (EBUSY);
631 break;
632 }
633
634 no_data = 0;
635 nss_gethostbyname4_r *fct4 = NULL;
636
637 /* gethostbyname4_r sends out parallel A and AAAA queries and
638 is thus only suitable for PF_UNSPEC. */
639 if (req->ai_family == PF_UNSPEC)
640 fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
641
642 if (fct4 != NULL)
643 {
644 while (1)
645 {
646 status = DL_CALL_FCT (fct4, (name, &res->at,
647 tmpbuf->data, tmpbuf->length,
648 &errno, &h_errno,
649 NULL));
650 if (status == NSS_STATUS_SUCCESS)
651 break;
652 /* gethostbyname4_r may write into AT, so reset it. */
653 res->at = NULL;
654 if (status != NSS_STATUS_TRYAGAIN
655 || errno != ERANGE || h_errno != NETDB_INTERNAL)
656 {
657 if (h_errno == TRY_AGAIN)
658 no_data = EAI_AGAIN;
659 else
660 no_data = h_errno == NO_DATA;
661 break;
662 }
663
664 if (!scratch_buffer_grow (tmpbuf))
665 {
666 __resolv_context_put (res_ctx);
667 result = -EAI_MEMORY;
668 goto out;
669 }
670 }
671
672 if (status == NSS_STATUS_SUCCESS)
673 {
674 assert (!no_data);
675 no_data = 1;
676
677 if ((req->ai_flags & AI_CANONNAME) != 0 && res->canon == NULL)
678 {
679 char *canonbuf = __strdup (res->at->name);
680 if (canonbuf == NULL)
681 {
682 __resolv_context_put (res_ctx);
683 result = -EAI_MEMORY;
684 goto out;
685 }
686 res->canon = canonbuf;
687 }
688
689 struct gaih_addrtuple **pat = &res->at;
690
691 while (*pat != NULL)
692 {
693 if ((*pat)->family == AF_INET
694 && req->ai_family == AF_INET6
695 && (req->ai_flags & AI_V4MAPPED) != 0)
696 {
697 uint32_t *pataddr = (*pat)->addr;
698 (*pat)->family = AF_INET6;
699 pataddr[3] = pataddr[0];
700 pataddr[2] = htonl (0xffff);
701 pataddr[1] = 0;
702 pataddr[0] = 0;
703 pat = &((*pat)->next);
704 no_data = 0;
705 }
706 else if (req->ai_family == AF_UNSPEC
707 || (*pat)->family == req->ai_family)
708 {
709 pat = &((*pat)->next);
710
711 no_data = 0;
712 if (req->ai_family == AF_INET6)
713 res->got_ipv6 = true;
714 }
715 else
716 *pat = ((*pat)->next);
717 }
718 }
719
720 no_inet6_data = no_data;
721 }
722 else
723 {
724 nss_gethostbyname3_r *fct = NULL;
725 if (req->ai_flags & AI_CANONNAME)
726 /* No need to use this function if we do not look for
727 the canonical name. The function does not exist in
728 all NSS modules and therefore the lookup would
729 often fail. */
730 fct = __nss_lookup_function (nip, "gethostbyname3_r");
731 if (fct == NULL)
732 /* We are cheating here. The gethostbyname2_r
733 function does not have the same interface as
734 gethostbyname3_r but the extra arguments the
735 latter takes are added at the end. So the
736 gethostbyname2_r code will just ignore them. */
737 fct = __nss_lookup_function (nip, "gethostbyname2_r");
738
739 if (fct != NULL)
740 {
741 if (req->ai_family == AF_INET6
742 || req->ai_family == AF_UNSPEC)
743 {
cfa3bd48
SP
744 if ((result = gethosts (fct, AF_INET6, name, req, tmpbuf,
745 res, &status, &no_data)) != 0)
746 {
747 __resolv_context_put (res_ctx);
748 goto out;
749 }
906cecbe
SP
750 no_inet6_data = no_data;
751 inet6_status = status;
752 }
753 if (req->ai_family == AF_INET
754 || req->ai_family == AF_UNSPEC
755 || (req->ai_family == AF_INET6
756 && (req->ai_flags & AI_V4MAPPED)
757 /* Avoid generating the mapped addresses if we
758 know we are not going to need them. */
759 && ((req->ai_flags & AI_ALL) || !res->got_ipv6)))
760 {
cfa3bd48
SP
761 if ((result = gethosts (fct, AF_INET, name, req, tmpbuf,
762 res, &status, &no_data)) != 0)
763 {
764 __resolv_context_put (res_ctx);
765 goto out;
766 }
906cecbe
SP
767
768 if (req->ai_family == AF_INET)
769 {
770 no_inet6_data = no_data;
771 inet6_status = status;
772 }
773 }
774
775 /* If we found one address for AF_INET or AF_INET6,
776 don't continue the search. */
777 if (inet6_status == NSS_STATUS_SUCCESS
778 || status == NSS_STATUS_SUCCESS)
779 {
780 if ((req->ai_flags & AI_CANONNAME) != 0
781 && res->canon == NULL)
782 {
973fe93a 783 char *canonbuf = getcanonname (nip, res->h_name, name);
906cecbe
SP
784 if (canonbuf == NULL)
785 {
786 __resolv_context_put (res_ctx);
787 result = -EAI_MEMORY;
788 goto out;
789 }
790 res->canon = canonbuf;
791 }
792 status = NSS_STATUS_SUCCESS;
793 }
794 else
795 {
796 /* We can have different states for AF_INET and
797 AF_INET6. Try to find a useful one for both. */
798 if (inet6_status == NSS_STATUS_TRYAGAIN)
799 status = NSS_STATUS_TRYAGAIN;
800 else if (status == NSS_STATUS_UNAVAIL
801 && inet6_status != NSS_STATUS_UNAVAIL)
802 status = inet6_status;
803 }
804 }
805 else
806 {
807 /* Could not locate any of the lookup functions.
808 The NSS lookup code does not consistently set
809 errno, so we need to supply our own error
810 code here. The root cause could either be a
811 resource allocation failure, or a missing
812 service function in the DSO (so it should not
813 be listed in /etc/nsswitch.conf). Assume the
814 former, and return EBUSY. */
815 status = NSS_STATUS_UNAVAIL;
816 __set_h_errno (NETDB_INTERNAL);
817 __set_errno (EBUSY);
818 }
819 }
820
821 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
822 break;
823
824 /* The hosts database does not support MERGE. */
825 if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
826 do_merge = true;
827
828 nip++;
829 if (nip->module == NULL)
830 no_more = -1;
831 }
832
833 __resolv_context_put (res_ctx);
834
835 /* If we have a failure which sets errno, report it using
836 EAI_SYSTEM. */
837 if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
838 && h_errno == NETDB_INTERNAL)
839 {
840 result = -EAI_SYSTEM;
841 goto out;
842 }
843
844 if (no_data != 0 && no_inet6_data != 0)
845 {
846 /* If both requests timed out report this. */
847 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
848 result = -EAI_AGAIN;
849 else
850 /* We made requests but they turned out no data. The name
851 is known, though. */
852 result = -EAI_NODATA;
853 }
854
855out:
856 if (result != 0)
857 gaih_result_reset (res);
858 return result;
859}
860
26dea461
SP
861/* Convert numeric addresses to binary into RES. On failure, RES->AT is set to
862 NULL and an error code is returned. If AI_NUMERIC_HOST is not requested and
863 the function cannot determine a result, RES->AT is set to NULL and 0
864 returned. */
865
866static int
867text_to_binary_address (const char *name, const struct addrinfo *req,
868 struct gaih_result *res)
869{
870 struct gaih_addrtuple *at = res->at;
871 int result = 0;
872
873 assert (at != NULL);
874
875 memset (at->addr, 0, sizeof (at->addr));
876 if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
877 {
878 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
879 at->family = AF_INET;
880 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
881 {
882 at->addr[3] = at->addr[0];
883 at->addr[2] = htonl (0xffff);
884 at->addr[1] = 0;
885 at->addr[0] = 0;
886 at->family = AF_INET6;
887 }
888 else
889 {
890 result = -EAI_ADDRFAMILY;
891 goto out;
892 }
893
894 if (req->ai_flags & AI_CANONNAME)
895 {
896 char *canonbuf = __strdup (name);
897 if (canonbuf == NULL)
898 {
899 result = -EAI_MEMORY;
900 goto out;
901 }
902 res->canon = canonbuf;
903 }
904 return 0;
905 }
906
907 char *scope_delim = strchr (name, SCOPE_DELIMITER);
908 int e;
909
910 if (scope_delim == NULL)
911 e = inet_pton (AF_INET6, name, at->addr);
912 else
913 e = __inet_pton_length (AF_INET6, name, scope_delim - name, at->addr);
914
915 if (e > 0)
916 {
917 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
918 at->family = AF_INET6;
919 else if (req->ai_family == AF_INET
920 && IN6_IS_ADDR_V4MAPPED (at->addr))
921 {
922 at->addr[0] = at->addr[3];
923 at->family = AF_INET;
924 }
925 else
926 {
927 result = -EAI_ADDRFAMILY;
928 goto out;
929 }
930
931 if (scope_delim != NULL
932 && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
933 scope_delim + 1, &at->scopeid) != 0)
934 {
935 result = -EAI_NONAME;
936 goto out;
937 }
938
939 if (req->ai_flags & AI_CANONNAME)
940 {
941 char *canonbuf = __strdup (name);
942 if (canonbuf == NULL)
943 {
944 result = -EAI_MEMORY;
945 goto out;
946 }
947 res->canon = canonbuf;
948 }
949 return 0;
950 }
951
952 if ((req->ai_flags & AI_NUMERICHOST))
953 result = -EAI_NONAME;
954
955out:
956 res->at = NULL;
957 return result;
958}
959
b44389cb
SP
960/* If possible, call the simple, old functions, which do not support IPv6 scope
961 ids, nor retrieving the canonical name. */
962
963static int
964try_simple_gethostbyname (const char *name, const struct addrinfo *req,
965 struct scratch_buffer *tmpbuf,
966 struct gaih_result *res)
967{
968 res->at = NULL;
969
970 if (req->ai_family != AF_INET || (req->ai_flags & AI_CANONNAME) != 0)
971 return 0;
972
973 int rc;
974 struct hostent th;
975 struct hostent *h;
976
977 while (1)
978 {
979 rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf->data,
980 tmpbuf->length, &h, &h_errno);
981 if (rc != ERANGE || h_errno != NETDB_INTERNAL)
982 break;
983 if (!scratch_buffer_grow (tmpbuf))
984 return -EAI_MEMORY;
985 }
986
987 if (rc == 0)
988 {
989 if (h != NULL)
990 {
991 /* We found data, convert it. RES->AT from the conversion will
992 either be an allocated block or NULL, both of which are safe to
993 pass to free (). */
906cecbe 994 if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, res))
b44389cb
SP
995 return -EAI_MEMORY;
996
997 res->free_at = true;
998 return 0;
999 }
1000 if (h_errno == NO_DATA)
1001 return -EAI_NODATA;
1002
1003 return -EAI_NONAME;
1004 }
1005
1006 if (h_errno == NETDB_INTERNAL)
1007 return -EAI_SYSTEM;
1008 if (h_errno == TRY_AGAIN)
1009 return -EAI_AGAIN;
1010
1011 /* We made requests but they turned out no data.
1012 The name is known, though. */
1013 return -EAI_NODATA;
1014}
1015
657472b2
SP
1016/* Add local address information into RES. RES->AT is assumed to have enough
1017 space for two tuples and is zeroed out. */
1018
1019static void
1020get_local_addresses (const struct addrinfo *req, struct gaih_result *res)
1021{
1022 struct gaih_addrtuple *atr = res->at;
1023 if (req->ai_family == AF_UNSPEC)
1024 res->at->next = res->at + 1;
1025
1026 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1027 {
1028 res->at->family = AF_INET6;
1029 if ((req->ai_flags & AI_PASSIVE) == 0)
1030 memcpy (res->at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1031 atr = res->at->next;
1032 }
1033
1034 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1035 {
1036 atr->family = AF_INET;
1037 if ((req->ai_flags & AI_PASSIVE) == 0)
1038 atr->addr[0] = htonl (INADDR_LOOPBACK);
1039 }
1040}
1041
ac4653ef
SP
1042/* Generate results in PAI and its count in NADDRS. Return 0 on success or an
1043 error code on failure. */
1044
1045static int
1046generate_addrinfo (const struct addrinfo *req, struct gaih_result *res,
1047 const struct gaih_servtuple *st, struct addrinfo **pai,
1048 unsigned int *naddrs)
1049{
1050 size_t socklen;
1051 sa_family_t family;
1052
1053 /* Buffer is the size of an unformatted IPv6 address in printable format. */
1054 for (struct gaih_addrtuple *at = res->at; at != NULL; at = at->next)
1055 {
1056 family = at->family;
1057 if (family == AF_INET6)
1058 {
1059 socklen = sizeof (struct sockaddr_in6);
1060
1061 /* If we looked up IPv4 mapped address discard them here if
1062 the caller isn't interested in all address and we have
1063 found at least one IPv6 address. */
1064 if (res->got_ipv6
1065 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1066 && IN6_IS_ADDR_V4MAPPED (at->addr))
1067 continue;
1068 }
1069 else
1070 socklen = sizeof (struct sockaddr_in);
1071
1072 for (int i = 0; st[i].set; i++)
1073 {
1074 struct addrinfo *ai;
1075 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1076 if (ai == NULL)
1077 return -EAI_MEMORY;
1078
1079 ai->ai_flags = req->ai_flags;
1080 ai->ai_family = family;
1081 ai->ai_socktype = st[i].socktype;
1082 ai->ai_protocol = st[i].protocol;
1083 ai->ai_addrlen = socklen;
1084 ai->ai_addr = (void *) (ai + 1);
1085
1086 /* We only add the canonical name once. */
1087 ai->ai_canonname = res->canon;
1088 res->canon = NULL;
1089
1090#ifdef _HAVE_SA_LEN
1091 ai->ai_addr->sa_len = socklen;
1092#endif /* _HAVE_SA_LEN */
1093 ai->ai_addr->sa_family = family;
1094
1095 /* In case of an allocation error the list must be NULL
1096 terminated. */
1097 ai->ai_next = NULL;
1098
1099 if (family == AF_INET6)
1100 {
1101 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) ai->ai_addr;
1102 sin6p->sin6_port = st[i].port;
1103 sin6p->sin6_flowinfo = 0;
1104 memcpy (&sin6p->sin6_addr, at->addr, sizeof (struct in6_addr));
1105 sin6p->sin6_scope_id = at->scopeid;
1106 }
1107 else
1108 {
1109 struct sockaddr_in *sinp = (struct sockaddr_in *) ai->ai_addr;
1110 sinp->sin_port = st[i].port;
1111 memcpy (&sinp->sin_addr, at->addr, sizeof (struct in_addr));
1112 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1113 }
1114
1115 pai = &(ai->ai_next);
1116 }
1117
1118 ++*naddrs;
1119 }
1120 return 0;
1121}
1122
8d6cf99f
SP
1123static int
1124gaih_inet (const char *name, const struct gaih_service *service,
1125 const struct addrinfo *req, struct addrinfo **pai,
1126 unsigned int *naddrs, struct scratch_buffer *tmpbuf)
1127{
1128 struct gaih_servtuple st[sizeof (gaih_inet_typeproto)
1129 / sizeof (struct gaih_typeproto)] = {0};
1130
8d6cf99f
SP
1131 const char *orig_name = name;
1132
8d6cf99f
SP
1133 int rc;
1134 if ((rc = get_servtuples (service, req, st, tmpbuf)) != 0)
1135 return rc;
1136
34a9094f 1137 bool malloc_name = false;
34a9094f 1138 struct gaih_addrtuple *addrmem = NULL;
34a9094f 1139 int result = 0;
cd065b68 1140
26dea461 1141 struct gaih_result res = {0};
657472b2
SP
1142 struct gaih_addrtuple local_at[2] = {0};
1143
1144 res.at = local_at;
1145
1146 if (__glibc_unlikely (name == NULL))
40a55d20 1147 {
657472b2
SP
1148 get_local_addresses (req, &res);
1149 goto process_list;
1150 }
e2fd3cbe 1151
657472b2
SP
1152 if (req->ai_flags & AI_IDN)
1153 {
1154 char *out;
1155 result = __idna_to_dns_encoding (name, &out);
1156 if (result != 0)
1157 return -result;
1158 name = out;
1159 malloc_name = true;
1160 }
26dea461 1161
657472b2
SP
1162 if ((result = text_to_binary_address (name, req, &res)) != 0)
1163 goto free_and_return;
1164 else if (res.at != NULL)
1165 goto process_list;
26dea461 1166
657472b2
SP
1167 if ((result = try_simple_gethostbyname (name, req, tmpbuf, &res)) != 0)
1168 goto free_and_return;
1169 else if (res.at != NULL)
1170 goto process_list;
b44389cb 1171
e7e5315b 1172#ifdef USE_NSCD
657472b2
SP
1173 if ((result = get_nscd_addresses (name, req, &res)) != 0)
1174 goto free_and_return;
1175 else if (res.at != NULL)
1176 goto process_list;
e7e5315b
SP
1177#endif
1178
657472b2
SP
1179 if ((result = get_nss_addresses (name, req, tmpbuf, &res)) != 0)
1180 goto free_and_return;
1181 else if (res.at != NULL)
1182 goto process_list;
40a55d20 1183
657472b2
SP
1184 /* None of the lookups worked, so name not found. */
1185 result = -EAI_NONAME;
1186 goto free_and_return;
1fb05e3d 1187
906cecbe 1188process_list:
ac4653ef
SP
1189 /* Set up the canonical name if we need it. */
1190 if ((result = process_canonname (req, orig_name, &res)) != 0)
1191 goto free_and_return;
01abbc0f 1192
ac4653ef 1193 result = generate_addrinfo (req, &res, st, pai, naddrs);
34a9094f 1194
ac4653ef 1195free_and_return:
34a9094f
UD
1196 if (malloc_name)
1197 free ((char *) name);
46ce8881 1198 free (addrmem);
ec6b95c3 1199 gaih_result_reset (&res);
34a9094f
UD
1200
1201 return result;
46ec036d
UD
1202}
1203
46ec036d 1204
5ddb5bf5
UD
1205struct sort_result
1206{
1207 struct addrinfo *dest_addr;
0efd1956
UD
1208 /* Using sockaddr_storage is for now overkill. We only support IPv4
1209 and IPv6 so far. If this changes at some point we can adjust the
1210 type here. */
1211 struct sockaddr_in6 source_addr;
d19687d6 1212 uint8_t source_addr_len;
5ddb5bf5 1213 bool got_source_addr;
3af48b5b 1214 uint8_t source_addr_flags;
6f3914d5 1215 uint8_t prefixlen;
773e79b3
UD
1216 uint32_t index;
1217 int32_t native;
1218};
1219
1220struct sort_result_combo
1221{
1222 struct sort_result *results;
1223 int nresults;
5ddb5bf5
UD
1224};
1225
1226
ee72b971
UD
1227#if __BYTE_ORDER == __BIG_ENDIAN
1228# define htonl_c(n) n
1229#else
1230# define htonl_c(n) __bswap_constant_32 (n)
1231#endif
1232
1233static const struct scopeentry
1234{
1235 union
1236 {
1237 char addr[4];
1238 uint32_t addr32;
1239 };
1240 uint32_t netmask;
1241 int32_t scope;
1242} default_scopes[] =
1243 {
1244 /* Link-local addresses: scope 2. */
1245 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1246 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
ee72b971
UD
1247 /* Default: scope 14. */
1248 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1249 };
1250
1251/* The label table. */
1252static const struct scopeentry *scopes;
1253
1254
5ddb5bf5 1255static int
0efd1956 1256get_scope (const struct sockaddr_in6 *in6)
5ddb5bf5
UD
1257{
1258 int scope;
0efd1956 1259 if (in6->sin6_family == PF_INET6)
5ddb5bf5 1260 {
5ddb5bf5
UD
1261 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1262 {
5fab5544
UD
1263 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1264 /* RFC 4291 2.5.3 says that the loopback address is to be
1265 treated like a link-local address. */
1266 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
5ddb5bf5
UD
1267 scope = 2;
1268 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1269 scope = 5;
1270 else
1271 /* XXX Is this the correct default behavior? */
1272 scope = 14;
1273 }
1274 else
1275 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1276 }
0efd1956 1277 else if (in6->sin6_family == PF_INET)
5ddb5bf5 1278 {
0efd1956 1279 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
ee72b971
UD
1280
1281 size_t cnt = 0;
1282 while (1)
1283 {
1284 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1285 == scopes[cnt].addr32)
1286 return scopes[cnt].scope;
1287
1288 ++cnt;
1289 }
1290 /* NOTREACHED */
5ddb5bf5
UD
1291 }
1292 else
1293 /* XXX What is a good default? */
1294 scope = 15;
1295
1296 return scope;
1297}
1298
1299
77dd4c3b 1300struct prefixentry
5ddb5bf5
UD
1301{
1302 struct in6_addr prefix;
1303 unsigned int bits;
1304 int val;
77dd4c3b
UD
1305};
1306
1307
1308/* The label table. */
1309static const struct prefixentry *labels;
1310
1311/* Default labels. */
1312static const struct prefixentry default_labels[] =
5ddb5bf5
UD
1313 {
1314 /* See RFC 3484 for the details. */
6107639e
UD
1315 { { .__in6_u
1316 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1318 }, 128, 0 },
1319 { { .__in6_u
1320 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1322 }, 16, 2 },
1323 { { .__in6_u
1324 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1326 }, 96, 3 },
1327 { { .__in6_u
1328 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1329 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1330 }, 96, 4 },
6e2a7825
UD
1331 /* The next two entries differ from RFC 3484. We need to treat
1332 IPv6 site-local addresses special because they are never NATed,
1333 unlike site-locale IPv4 addresses. If this would not happen, on
1334 machines which have only IPv4 and IPv6 site-local addresses, the
1335 sorting would prefer the IPv6 site-local addresses, causing
1336 unnecessary delays when trying to connect to a global IPv6 address
1337 through a site-local IPv6 address. */
6107639e
UD
1338 { { .__in6_u
1339 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1341 }, 10, 5 },
1342 { { .__in6_u
1343 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1345 }, 7, 6 },
f4a79765 1346 /* Additional rule for Teredo tunnels. */
6107639e
UD
1347 { { .__in6_u
1348 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1350 }, 32, 7 },
1351 { { .__in6_u
1352 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1354 }, 0, 1 }
5ddb5bf5
UD
1355 };
1356
1357
77dd4c3b
UD
1358/* The precedence table. */
1359static const struct prefixentry *precedence;
1360
1361/* The default precedences. */
1362static const struct prefixentry default_precedence[] =
5ddb5bf5
UD
1363 {
1364 /* See RFC 3484 for the details. */
6107639e
UD
1365 { { .__in6_u
1366 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1368 }, 128, 50 },
1369 { { .__in6_u
1370 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1372 }, 16, 30 },
1373 { { .__in6_u
1374 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1376 }, 96, 20 },
1377 { { .__in6_u
1378 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1380 }, 96, 10 },
1381 { { .__in6_u
1382 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1384 }, 0, 40 }
5ddb5bf5
UD
1385 };
1386
1387
1388static int
0efd1956 1389match_prefix (const struct sockaddr_in6 *in6,
77dd4c3b 1390 const struct prefixentry *list, int default_val)
5ddb5bf5
UD
1391{
1392 int idx;
1393 struct sockaddr_in6 in6_mem;
5ddb5bf5 1394
0efd1956 1395 if (in6->sin6_family == PF_INET)
5ddb5bf5 1396 {
0efd1956 1397 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
5ddb5bf5 1398
5846c4e2 1399 /* Construct a V4-to-6 mapped address. */
5ddb5bf5
UD
1400 in6_mem.sin6_family = PF_INET6;
1401 in6_mem.sin6_port = in->sin_port;
1402 in6_mem.sin6_flowinfo = 0;
5846c4e2
UD
1403 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1404 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1405 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1406 in6_mem.sin6_scope_id = 0;
5ddb5bf5
UD
1407
1408 in6 = &in6_mem;
1409 }
0efd1956 1410 else if (in6->sin6_family != PF_INET6)
5ddb5bf5
UD
1411 return default_val;
1412
1413 for (idx = 0; ; ++idx)
1414 {
1415 unsigned int bits = list[idx].bits;
d4ed7561
UD
1416 const uint8_t *mask = list[idx].prefix.s6_addr;
1417 const uint8_t *val = in6->sin6_addr.s6_addr;
5ddb5bf5 1418
207cce4c 1419 while (bits >= 8)
5ddb5bf5
UD
1420 {
1421 if (*mask != *val)
1422 break;
1423
1424 ++mask;
1425 ++val;
1426 bits -= 8;
1427 }
1428
1429 if (bits < 8)
1430 {
d9a3ae7f 1431 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
5ddb5bf5
UD
1432 /* Match! */
1433 break;
1434 }
1435 }
1436
1437 return list[idx].val;
1438}
1439
1440
1441static int
0efd1956 1442get_label (const struct sockaddr_in6 *in6)
5ddb5bf5
UD
1443{
1444 /* XXX What is a good default value? */
0efd1956 1445 return match_prefix (in6, labels, INT_MAX);
5ddb5bf5
UD
1446}
1447
1448
1449static int
0efd1956 1450get_precedence (const struct sockaddr_in6 *in6)
5ddb5bf5
UD
1451{
1452 /* XXX What is a good default value? */
0efd1956 1453 return match_prefix (in6, precedence, 0);
5ddb5bf5
UD
1454}
1455
1456
c6bad06a
UD
1457/* Find last bit set in a word. */
1458static int
1459fls (uint32_t a)
1460{
1461 uint32_t mask;
6f3914d5 1462 int n;
c6bad06a
UD
1463 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1464 if ((a & mask) != 0)
1465 break;
1466 return n;
1467}
1468
1469
5ddb5bf5 1470static int
773e79b3 1471rfc3484_sort (const void *p1, const void *p2, void *arg)
5ddb5bf5 1472{
0efd1956
UD
1473 const size_t idx1 = *(const size_t *) p1;
1474 const size_t idx2 = *(const size_t *) p2;
773e79b3 1475 struct sort_result_combo *src = (struct sort_result_combo *) arg;
0efd1956
UD
1476 struct sort_result *a1 = &src->results[idx1];
1477 struct sort_result *a2 = &src->results[idx2];
5ddb5bf5
UD
1478
1479 /* Rule 1: Avoid unusable destinations.
1480 We have the got_source_addr flag set if the destination is reachable. */
1481 if (a1->got_source_addr && ! a2->got_source_addr)
1482 return -1;
1483 if (! a1->got_source_addr && a2->got_source_addr)
1484 return 1;
1485
1486
1487 /* Rule 2: Prefer matching scope. Only interesting if both
1488 destination addresses are IPv6. */
1489 int a1_dst_scope
0efd1956 1490 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
5ddb5bf5
UD
1491
1492 int a2_dst_scope
0efd1956 1493 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
5ddb5bf5
UD
1494
1495 if (a1->got_source_addr)
1496 {
1497 int a1_src_scope = get_scope (&a1->source_addr);
1498 int a2_src_scope = get_scope (&a2->source_addr);
1499
1500 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1501 return -1;
1502 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1503 return 1;
1504 }
1505
1506
3af48b5b
UD
1507 /* Rule 3: Avoid deprecated addresses. */
1508 if (a1->got_source_addr)
1509 {
1510 if (!(a1->source_addr_flags & in6ai_deprecated)
1511 && (a2->source_addr_flags & in6ai_deprecated))
1512 return -1;
1513 if ((a1->source_addr_flags & in6ai_deprecated)
1514 && !(a2->source_addr_flags & in6ai_deprecated))
1515 return 1;
1516 }
5ddb5bf5 1517
457b559e
UD
1518 /* Rule 4: Prefer home addresses. */
1519 if (a1->got_source_addr)
1520 {
1521 if (!(a1->source_addr_flags & in6ai_homeaddress)
1522 && (a2->source_addr_flags & in6ai_homeaddress))
4a85a8ee 1523 return 1;
457b559e
UD
1524 if ((a1->source_addr_flags & in6ai_homeaddress)
1525 && !(a2->source_addr_flags & in6ai_homeaddress))
4a85a8ee 1526 return -1;
457b559e 1527 }
5ddb5bf5
UD
1528
1529 /* Rule 5: Prefer matching label. */
1530 if (a1->got_source_addr)
1531 {
1532 int a1_dst_label
0efd1956 1533 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
5ddb5bf5
UD
1534 int a1_src_label = get_label (&a1->source_addr);
1535
1536 int a2_dst_label
0efd1956 1537 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
5ddb5bf5
UD
1538 int a2_src_label = get_label (&a2->source_addr);
1539
1540 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1541 return -1;
1542 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1543 return 1;
1544 }
1545
1546
1547 /* Rule 6: Prefer higher precedence. */
1548 int a1_prec
0efd1956 1549 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
5ddb5bf5 1550 int a2_prec
0efd1956 1551 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
5ddb5bf5
UD
1552
1553 if (a1_prec > a2_prec)
1554 return -1;
1555 if (a1_prec < a2_prec)
1556 return 1;
1557
1558
3af48b5b
UD
1559 /* Rule 7: Prefer native transport. */
1560 if (a1->got_source_addr)
1561 {
773e79b3
UD
1562 /* The same interface index means the same interface which means
1563 there is no difference in transport. This should catch many
1564 (most?) cases. */
1565 if (a1->index != a2->index)
1566 {
49029a66
UD
1567 int a1_native = a1->native;
1568 int a2_native = a2->native;
1569
1570 if (a1_native == -1 || a2_native == -1)
773e79b3 1571 {
49029a66
UD
1572 uint32_t a1_index;
1573 if (a1_native == -1)
1574 {
1575 /* If we do not have the information use 'native' as
1576 the default. */
1577 a1_native = 0;
1578 a1_index = a1->index;
1579 }
1580 else
1581 a1_index = 0xffffffffu;
1582
1583 uint32_t a2_index;
1584 if (a2_native == -1)
1585 {
1586 /* If we do not have the information use 'native' as
1587 the default. */
1588 a2_native = 0;
1589 a2_index = a2->index;
1590 }
1591 else
1592 a2_index = 0xffffffffu;
1593
1594 __check_native (a1_index, &a1_native, a2_index, &a2_native);
773e79b3
UD
1595
1596 /* Fill in the results in all the records. */
1597 for (int i = 0; i < src->nresults; ++i)
894f3f10 1598 if (a1_index != -1 && src->results[i].index == a1_index)
49029a66
UD
1599 {
1600 assert (src->results[i].native == -1
1601 || src->results[i].native == a1_native);
773e79b3 1602 src->results[i].native = a1_native;
49029a66 1603 }
894f3f10 1604 else if (a2_index != -1 && src->results[i].index == a2_index)
49029a66
UD
1605 {
1606 assert (src->results[i].native == -1
1607 || src->results[i].native == a2_native);
773e79b3 1608 src->results[i].native = a2_native;
49029a66 1609 }
773e79b3 1610 }
3af48b5b 1611
49029a66 1612 if (a1_native && !a2_native)
773e79b3 1613 return -1;
49029a66 1614 if (!a1_native && a2_native)
773e79b3
UD
1615 return 1;
1616 }
3af48b5b 1617 }
5ddb5bf5
UD
1618
1619
1620 /* Rule 8: Prefer smaller scope. */
1621 if (a1_dst_scope < a2_dst_scope)
1622 return -1;
1623 if (a1_dst_scope > a2_dst_scope)
1624 return 1;
1625
1626
1627 /* Rule 9: Use longest matching prefix. */
1628 if (a1->got_source_addr
1629 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1630 {
1631 int bit1 = 0;
1632 int bit2 = 0;
1633
1634 if (a1->dest_addr->ai_family == PF_INET)
1635 {
0efd1956
UD
1636 assert (a1->source_addr.sin6_family == PF_INET);
1637 assert (a2->source_addr.sin6_family == PF_INET);
5ddb5bf5 1638
6f3914d5
UD
1639 /* Outside of subnets, as defined by the network masks,
1640 common address prefixes for IPv4 addresses make no sense.
1641 So, define a non-zero value only if source and
1642 destination address are on the same subnet. */
1643 struct sockaddr_in *in1_dst
1644 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1645 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1646 struct sockaddr_in *in1_src
1647 = (struct sockaddr_in *) &a1->source_addr;
1648 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1649 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1650
1651 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1652 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1653
1654 struct sockaddr_in *in2_dst
1655 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1656 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1657 struct sockaddr_in *in2_src
1658 = (struct sockaddr_in *) &a2->source_addr;
1659 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1660 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1661
1662 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1663 bit2 = fls (in2_dst_addr ^ in2_src_addr);
5ddb5bf5
UD
1664 }
1665 else if (a1->dest_addr->ai_family == PF_INET6)
1666 {
0efd1956
UD
1667 assert (a1->source_addr.sin6_family == PF_INET6);
1668 assert (a2->source_addr.sin6_family == PF_INET6);
5ddb5bf5
UD
1669
1670 struct sockaddr_in6 *in1_dst;
1671 struct sockaddr_in6 *in1_src;
1672 struct sockaddr_in6 *in2_dst;
1673 struct sockaddr_in6 *in2_src;
1674
1675 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1676 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1677 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1678 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1679
1680 int i;
1681 for (i = 0; i < 4; ++i)
1682 if (in1_dst->sin6_addr.s6_addr32[i]
1683 != in1_src->sin6_addr.s6_addr32[i]
1684 || (in2_dst->sin6_addr.s6_addr32[i]
1685 != in2_src->sin6_addr.s6_addr32[i]))
1686 break;
1687
1688 if (i < 4)
1689 {
c6bad06a
UD
1690 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1691 ^ in1_src->sin6_addr.s6_addr32[i]));
1692 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1693 ^ in2_src->sin6_addr.s6_addr32[i]));
5ddb5bf5
UD
1694 }
1695 }
1696
1697 if (bit1 > bit2)
1698 return -1;
1699 if (bit1 < bit2)
1700 return 1;
1701 }
1702
1703
6f55ed88
UD
1704 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1705 compare with the value indicating the order in which the entries
1706 have been received from the services. NB: no two entries can have
1707 the same order so the test will never return zero. */
0efd1956 1708 return idx1 < idx2 ? -1 : 1;
5ddb5bf5
UD
1709}
1710
1711
3af48b5b
UD
1712static int
1713in6aicmp (const void *p1, const void *p2)
1714{
1715 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1716 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1717
1718 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1719}
1720
1721
77dd4c3b
UD
1722/* Name of the config file for RFC 3484 sorting (for now). */
1723#define GAICONF_FNAME "/etc/gai.conf"
1724
1725
fc4837e5 1726/* Non-zero if we are supposed to reload the config file automatically
77dd4c3b
UD
1727 whenever it changed. */
1728static int gaiconf_reload_flag;
1729
fc4837e5
UD
1730/* Non-zero if gaiconf_reload_flag was ever set to true. */
1731static int gaiconf_reload_flag_ever_set;
1732
77dd4c3b 1733/* Last modification time. */
a0844057
RM
1734#ifdef _STATBUF_ST_NSEC
1735
52a5fe70 1736static struct __timespec64 gaiconf_mtime;
77dd4c3b 1737
a0844057 1738static inline void
52a5fe70 1739save_gaiconf_mtime (const struct __stat64_t64 *st)
a0844057 1740{
30adcf5a
AZ
1741 gaiconf_mtime = (struct __timespec64) { st->st_mtim.tv_sec,
1742 st->st_mtim.tv_nsec };
a0844057
RM
1743}
1744
1745static inline bool
52a5fe70 1746check_gaiconf_mtime (const struct __stat64_t64 *st)
a0844057
RM
1747{
1748 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1749 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1750}
1751
1752#else
1753
1754static time_t gaiconf_mtime;
1755
1756static inline void
52a5fe70 1757save_gaiconf_mtime (const struct __stat64_t64 *st)
a0844057
RM
1758{
1759 gaiconf_mtime = st->st_mtime;
1760}
1761
1762static inline bool
52a5fe70 1763check_gaiconf_mtime (const struct __stat64_t64 *st)
a0844057 1764{
fbc723bb 1765 return st->st_mtime == gaiconf_mtime;
a0844057
RM
1766}
1767
1768#endif
1769
77dd4c3b 1770
88677348
AZN
1771void
1772__libc_getaddrinfo_freemem (void)
77dd4c3b
UD
1773{
1774 if (labels != default_labels)
1775 {
1776 const struct prefixentry *old = labels;
1777 labels = default_labels;
1778 free ((void *) old);
1779 }
1780
1781 if (precedence != default_precedence)
1782 {
1783 const struct prefixentry *old = precedence;
1784 precedence = default_precedence;
1785 free ((void *) old);
1786 }
ee72b971
UD
1787
1788 if (scopes != default_scopes)
1789 {
1790 const struct scopeentry *old = scopes;
1791 scopes = default_scopes;
1792 free ((void *) old);
1793 }
77dd4c3b
UD
1794}
1795
1796
1797struct prefixlist
1798{
1799 struct prefixentry entry;
1800 struct prefixlist *next;
1801};
1802
1803
ee72b971
UD
1804struct scopelist
1805{
1806 struct scopeentry entry;
1807 struct scopelist *next;
1808};
1809
1810
77dd4c3b
UD
1811static void
1812free_prefixlist (struct prefixlist *list)
1813{
1814 while (list != NULL)
1815 {
1816 struct prefixlist *oldp = list;
1817 list = list->next;
1818 free (oldp);
1819 }
1820}
1821
1822
ee72b971
UD
1823static void
1824free_scopelist (struct scopelist *list)
1825{
1826 while (list != NULL)
1827 {
1828 struct scopelist *oldp = list;
1829 list = list->next;
1830 free (oldp);
1831 }
1832}
1833
1834
77dd4c3b
UD
1835static int
1836prefixcmp (const void *p1, const void *p2)
1837{
1838 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1839 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1840
1841 if (e1->bits < e2->bits)
1842 return 1;
1843 if (e1->bits == e2->bits)
1844 return 0;
1845 return -1;
1846}
1847
1848
ee72b971
UD
1849static int
1850scopecmp (const void *p1, const void *p2)
1851{
1852 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1853 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1854
1855 if (e1->netmask > e2->netmask)
1856 return -1;
1857 if (e1->netmask == e2->netmask)
1858 return 0;
1859 return 1;
1860}
1861
06890c7b
SP
1862static bool
1863add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp,
1864 char *val1, char *val2, char **pos)
1865{
1866 struct in6_addr prefix;
1867 unsigned long int bits;
1868 unsigned long int val;
1869 char *endp;
1870
1871 bits = 128;
1872 __set_errno (0);
1873 char *cp = strchr (val1, '/');
1874 if (cp != NULL)
1875 *cp++ = '\0';
1876 *pos = cp;
1877 if (inet_pton (AF_INET6, val1, &prefix)
1878 && (cp == NULL
1879 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1880 || errno != ERANGE)
1881 && *endp == '\0'
1882 && bits <= 128
1883 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1884 || errno != ERANGE)
1885 && *endp == '\0'
1886 && val <= INT_MAX)
1887 {
1888 struct prefixlist *newp = malloc (sizeof (*newp));
1889 if (newp == NULL)
1890 return false;
1891
1892 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
1893 newp->entry.bits = bits;
1894 newp->entry.val = val;
1895 newp->next = *listp;
1896 *listp = newp;
1897 ++*lenp;
1898 *nullbitsp |= bits == 0;
1899 }
1900 return true;
1901}
1902
1903static bool
1904add_scopelist (struct scopelist **listp, size_t *lenp, bool *nullbitsp,
1905 const struct in6_addr *prefixp, unsigned long int bits,
1906 unsigned long int val)
1907{
1908 struct scopelist *newp = malloc (sizeof (*newp));
1909 if (newp == NULL)
1910 return false;
1911
1912 newp->entry.netmask = htonl (bits != 96 ? (0xffffffff << (128 - bits)) : 0);
1913 newp->entry.addr32 = (prefixp->s6_addr32[3] & newp->entry.netmask);
1914 newp->entry.scope = val;
1915 newp->next = *listp;
1916 *listp = newp;
1917 ++*lenp;
1918 *nullbitsp |= bits == 96;
1919
1920 return true;
1921}
ee72b971 1922
77dd4c3b
UD
1923static void
1924gaiconf_init (void)
1925{
1926 struct prefixlist *labellist = NULL;
1927 size_t nlabellist = 0;
1928 bool labellist_nullbits = false;
1929 struct prefixlist *precedencelist = NULL;
1930 size_t nprecedencelist = 0;
1931 bool precedencelist_nullbits = false;
ee72b971
UD
1932 struct scopelist *scopelist = NULL;
1933 size_t nscopelist = 0;
1934 bool scopelist_nullbits = false;
77dd4c3b 1935
312be3f9 1936 FILE *fp = fopen (GAICONF_FNAME, "rce");
bc0d18d8
SP
1937 if (fp == NULL)
1938 goto no_file;
1939
1940 struct __stat64_t64 st;
1941 if (__fstat64_time64 (fileno (fp), &st) != 0)
77dd4c3b 1942 {
bc0d18d8
SP
1943 fclose (fp);
1944 goto no_file;
1945 }
77dd4c3b 1946
bc0d18d8
SP
1947 char *line = NULL;
1948 size_t linelen = 0;
77dd4c3b 1949
bc0d18d8 1950 __fsetlocking (fp, FSETLOCKING_BYCALLER);
77dd4c3b 1951
bc0d18d8
SP
1952 while (!feof_unlocked (fp))
1953 {
1954 ssize_t n = __getline (&line, &linelen, fp);
1955 if (n <= 0)
1956 break;
77dd4c3b 1957
bc0d18d8
SP
1958 /* Handle comments. No escaping possible so this is easy. */
1959 char *cp = strchr (line, '#');
1960 if (cp != NULL)
1961 *cp = '\0';
77dd4c3b 1962
bc0d18d8
SP
1963 cp = line;
1964 while (isspace (*cp))
1965 ++cp;
77dd4c3b 1966
bc0d18d8
SP
1967 char *cmd = cp;
1968 while (*cp != '\0' && !isspace (*cp))
1969 ++cp;
1970 size_t cmdlen = cp - cmd;
77dd4c3b 1971
bc0d18d8
SP
1972 if (*cp != '\0')
1973 *cp++ = '\0';
1974 while (isspace (*cp))
1975 ++cp;
77dd4c3b 1976
bc0d18d8
SP
1977 char *val1 = cp;
1978 while (*cp != '\0' && !isspace (*cp))
1979 ++cp;
1980 size_t val1len = cp - cmd;
77dd4c3b 1981
bc0d18d8
SP
1982 /* We always need at least two values. */
1983 if (val1len == 0)
1984 continue;
77dd4c3b 1985
bc0d18d8
SP
1986 if (*cp != '\0')
1987 *cp++ = '\0';
1988 while (isspace (*cp))
1989 ++cp;
77dd4c3b 1990
bc0d18d8
SP
1991 char *val2 = cp;
1992 while (*cp != '\0' && !isspace (*cp))
1993 ++cp;
77dd4c3b 1994
bc0d18d8
SP
1995 /* Ignore the rest of the line. */
1996 *cp = '\0';
77dd4c3b 1997
bc0d18d8
SP
1998 switch (cmdlen)
1999 {
2000 case 5:
2001 if (strcmp (cmd, "label") == 0)
77dd4c3b 2002 {
bc0d18d8
SP
2003 if (!add_prefixlist (&labellist, &nlabellist,
2004 &labellist_nullbits, val1, val2, &cp))
77dd4c3b 2005 {
bc0d18d8
SP
2006 free (line);
2007 fclose (fp);
2008 goto no_file;
77dd4c3b 2009 }
bc0d18d8
SP
2010 }
2011 break;
77dd4c3b 2012
bc0d18d8
SP
2013 case 6:
2014 if (strcmp (cmd, "reload") == 0)
2015 {
2016 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2017 if (gaiconf_reload_flag)
2018 gaiconf_reload_flag_ever_set = 1;
2019 }
2020 break;
77dd4c3b 2021
bc0d18d8
SP
2022 case 7:
2023 if (strcmp (cmd, "scopev4") == 0)
2024 {
2025 struct in6_addr prefix;
2026 unsigned long int bits;
2027 unsigned long int val;
2028 char *endp;
2029
2030 bits = 32;
2031 __set_errno (0);
2032 cp = strchr (val1, '/');
2033 if (cp != NULL)
2034 *cp++ = '\0';
2035 if (inet_pton (AF_INET6, val1, &prefix))
ee72b971 2036 {
bc0d18d8
SP
2037 bits = 128;
2038 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2039 && (cp == NULL
2040 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2041 || errno != ERANGE)
2042 && *endp == '\0'
2043 && bits >= 96
2044 && bits <= 128
2045 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2046 || errno != ERANGE)
2047 && *endp == '\0'
2048 && val <= INT_MAX)
ee72b971 2049 {
06890c7b
SP
2050 if (!add_scopelist (&scopelist, &nscopelist,
2051 &scopelist_nullbits, &prefix,
bc0d18d8 2052 bits, val))
06890c7b
SP
2053 {
2054 free (line);
2055 fclose (fp);
2056 goto no_file;
2057 }
ee72b971
UD
2058 }
2059 }
bc0d18d8
SP
2060 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2061 && (cp == NULL
2062 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2063 || errno != ERANGE)
2064 && *endp == '\0'
2065 && bits <= 32
2066 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2067 || errno != ERANGE)
2068 && *endp == '\0'
2069 && val <= INT_MAX)
77dd4c3b 2070 {
bc0d18d8
SP
2071 if (!add_scopelist (&scopelist, &nscopelist,
2072 &scopelist_nullbits, &prefix,
2073 bits + 96, val))
06890c7b
SP
2074 {
2075 free (line);
2076 fclose (fp);
2077 goto no_file;
2078 }
77dd4c3b 2079 }
77dd4c3b 2080 }
bc0d18d8 2081 break;
77dd4c3b 2082
bc0d18d8
SP
2083 case 10:
2084 if (strcmp (cmd, "precedence") == 0)
77dd4c3b 2085 {
bc0d18d8
SP
2086 if (!add_prefixlist (&precedencelist, &nprecedencelist,
2087 &precedencelist_nullbits, val1, val2,
2088 &cp))
2089 {
2090 free (line);
2091 fclose (fp);
2092 goto no_file;
2093 }
77dd4c3b 2094 }
bc0d18d8 2095 break;
77dd4c3b 2096 }
bc0d18d8 2097 }
77dd4c3b 2098
bc0d18d8 2099 free (line);
77dd4c3b 2100
bc0d18d8 2101 fclose (fp);
77dd4c3b 2102
bc0d18d8
SP
2103 /* Create the array for the labels. */
2104 struct prefixentry *new_labels;
2105 if (nlabellist > 0)
2106 {
2107 if (!labellist_nullbits)
2108 ++nlabellist;
2109 new_labels = malloc (nlabellist * sizeof (*new_labels));
2110 if (new_labels == NULL)
2111 goto no_file;
2112
2113 int i = nlabellist;
2114 if (!labellist_nullbits)
2115 {
2116 --i;
2117 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2118 new_labels[i].bits = 0;
2119 new_labels[i].val = 1;
77dd4c3b 2120 }
77dd4c3b 2121
bc0d18d8
SP
2122 struct prefixlist *l = labellist;
2123 while (i-- > 0)
ee72b971 2124 {
bc0d18d8
SP
2125 new_labels[i] = l->entry;
2126 l = l->next;
2127 }
2128 free_prefixlist (labellist);
2129 labellist = NULL;
ee72b971 2130
bc0d18d8
SP
2131 /* Sort the entries so that the most specific ones are at
2132 the beginning. */
2133 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2134 }
2135 else
2136 new_labels = (struct prefixentry *) default_labels;
ee72b971 2137
bc0d18d8
SP
2138 struct prefixentry *new_precedence;
2139 if (nprecedencelist > 0)
2140 {
2141 if (!precedencelist_nullbits)
2142 ++nprecedencelist;
2143 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2144 if (new_precedence == NULL)
2145 {
2146 if (new_labels != default_labels)
2147 free (new_labels);
2148 goto no_file;
ee72b971 2149 }
77dd4c3b 2150
bc0d18d8
SP
2151 int i = nprecedencelist;
2152 if (!precedencelist_nullbits)
2153 {
2154 --i;
2155 memset (&new_precedence[i].prefix, '\0',
2156 sizeof (struct in6_addr));
2157 new_precedence[i].bits = 0;
2158 new_precedence[i].val = 40;
2159 }
77dd4c3b 2160
bc0d18d8
SP
2161 struct prefixlist *l = precedencelist;
2162 while (i-- > 0)
2163 {
2164 new_precedence[i] = l->entry;
2165 l = l->next;
2166 }
2167 free_prefixlist (precedencelist);
2168 precedencelist = NULL;
ee72b971 2169
bc0d18d8
SP
2170 /* Sort the entries so that the most specific ones are at
2171 the beginning. */
2172 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2173 prefixcmp);
77dd4c3b
UD
2174 }
2175 else
bc0d18d8
SP
2176 new_precedence = (struct prefixentry *) default_precedence;
2177
2178 struct scopeentry *new_scopes;
2179 if (nscopelist > 0)
77dd4c3b 2180 {
bc0d18d8
SP
2181 if (!scopelist_nullbits)
2182 ++nscopelist;
2183 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2184 if (new_scopes == NULL)
2185 {
2186 if (new_labels != default_labels)
2187 free (new_labels);
2188 if (new_precedence != default_precedence)
2189 free (new_precedence);
2190 goto no_file;
2191 }
2192
2193 int i = nscopelist;
2194 if (!scopelist_nullbits)
2195 {
2196 --i;
2197 new_scopes[i].addr32 = 0;
2198 new_scopes[i].netmask = 0;
2199 new_scopes[i].scope = 14;
2200 }
2201
2202 struct scopelist *l = scopelist;
2203 while (i-- > 0)
2204 {
2205 new_scopes[i] = l->entry;
2206 l = l->next;
2207 }
ee72b971 2208 free_scopelist (scopelist);
77dd4c3b 2209
bc0d18d8
SP
2210 /* Sort the entries so that the most specific ones are at
2211 the beginning. */
2212 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2213 scopecmp);
77dd4c3b 2214 }
bc0d18d8
SP
2215 else
2216 new_scopes = (struct scopeentry *) default_scopes;
2217
2218 /* Now we are ready to replace the values. */
2219 const struct prefixentry *old = labels;
2220 labels = new_labels;
2221 if (old != default_labels)
2222 free ((void *) old);
2223
2224 old = precedence;
2225 precedence = new_precedence;
2226 if (old != default_precedence)
2227 free ((void *) old);
2228
2229 const struct scopeentry *oldscope = scopes;
2230 scopes = new_scopes;
2231 if (oldscope != default_scopes)
2232 free ((void *) oldscope);
2233
2234 save_gaiconf_mtime (&st);
2235 return;
2236
2237no_file:
2238 free_prefixlist (labellist);
2239 free_prefixlist (precedencelist);
2240 free_scopelist (scopelist);
2241
2242 /* If we previously read the file but it is gone now, free the old data and
2243 use the builtin one. Leave the reload flag alone. */
88677348 2244 __libc_getaddrinfo_freemem ();
77dd4c3b
UD
2245}
2246
2247
2248static void
2249gaiconf_reload (void)
2250{
52a5fe70
AZ
2251 struct __stat64_t64 st;
2252 if (__stat64_time64 (GAICONF_FNAME, &st) != 0
a0844057 2253 || !check_gaiconf_mtime (&st))
77dd4c3b
UD
2254 gaiconf_init ();
2255}
2256
d3f2c2c8
SP
2257static bool
2258try_connect (int *fdp, int *afp, struct sockaddr_in6 *source_addrp,
2259 const struct sockaddr *addr, socklen_t addrlen, int family)
2260{
2261 int fd = *fdp;
2262 int af = *afp;
2263 socklen_t sl = sizeof (*source_addrp);
2264
2265 while (true)
2266 {
2267 if (fd != -1 && __connect (fd, addr, addrlen) == 0
2268 && __getsockname (fd, (struct sockaddr *) source_addrp, &sl) == 0)
2269 return true;
2270
2271 if (errno == EAFNOSUPPORT && af == AF_INET6 && family == AF_INET)
2272 {
2273 /* This could mean IPv6 sockets are IPv6-only. */
2274 if (fd != -1)
2275 __close_nocancel_nostatus (fd);
2276 *afp = af = AF_INET;
2277 *fdp = fd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC,
2278 IPPROTO_IP);
2279 continue;
2280 }
2281
2282 return false;
2283 }
2284
2285 __builtin_unreachable ();
2286}
77dd4c3b 2287
40a55d20
UD
2288int
2289getaddrinfo (const char *name, const char *service,
2290 const struct addrinfo *hints, struct addrinfo **pai)
46ec036d 2291{
786dcb62 2292 int i = 0, last_i = 0;
5ddb5bf5 2293 int nresults = 0;
786dcb62 2294 struct addrinfo *p = NULL;
46ec036d 2295 struct gaih_service gaih_service, *pservice;
925c3c5c 2296 struct addrinfo local_hints;
46ec036d 2297
40a55d20 2298 if (name != NULL && name[0] == '*' && name[1] == 0)
1fb05e3d
UD
2299 name = NULL;
2300
40a55d20 2301 if (service != NULL && service[0] == '*' && service[1] == 0)
1fb05e3d
UD
2302 service = NULL;
2303
40a55d20 2304 if (name == NULL && service == NULL)
46ec036d
UD
2305 return EAI_NONAME;
2306
40a55d20
UD
2307 if (hints == NULL)
2308 hints = &default_hints;
46ec036d 2309
925c3c5c
UD
2310 if (hints->ai_flags
2311 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
7f9f1ecb 2312 |AI_IDN|AI_CANONIDN|DEPRECATED_AI_IDN
c1d98085 2313 |AI_NUMERICSERV|AI_ALL))
46ec036d
UD
2314 return EAI_BADFLAGS;
2315
06877a37 2316 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
46ec036d
UD
2317 return EAI_BADFLAGS;
2318
c1de872c
TR
2319 if (hints->ai_family != AF_UNSPEC && hints->ai_family != AF_INET
2320 && hints->ai_family != AF_INET6)
2321 return EAI_FAMILY;
2322
cf6ada44 2323 struct in6addrinfo *in6ai = NULL;
e53f0f51 2324 size_t in6ailen = 0;
3af48b5b
UD
2325 bool seen_ipv4 = false;
2326 bool seen_ipv6 = false;
fa3fc0fe 2327 bool check_pf_called = false;
e53f0f51 2328
925c3c5c
UD
2329 if (hints->ai_flags & AI_ADDRCONFIG)
2330 {
fa3fc0fe
UD
2331 /* We might need information about what interfaces are available.
2332 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2333 cannot cache the results since new interfaces could be added at
2334 any time. */
2335 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2336 check_pf_called = true;
2337
925c3c5c 2338 /* Now make a decision on what we return, if anything. */
c1d98085 2339 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
925c3c5c
UD
2340 {
2341 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2342 narrow down the search. */
cceb038a 2343 if (seen_ipv4 != seen_ipv6)
925c3c5c
UD
2344 {
2345 local_hints = *hints;
2346 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2347 hints = &local_hints;
2348 }
2349 }
2350 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2351 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
3af48b5b
UD
2352 {
2353 /* We cannot possibly return a valid answer. */
3a2c0242 2354 __free_in6ai (in6ai);
3af48b5b
UD
2355 return EAI_NONAME;
2356 }
925c3c5c
UD
2357 }
2358
40a55d20
UD
2359 if (service && service[0])
2360 {
2361 char *c;
2362 gaih_service.name = service;
2363 gaih_service.num = strtoul (gaih_service.name, &c, 10);
c1d98085
UD
2364 if (*c != '\0')
2365 {
2366 if (hints->ai_flags & AI_NUMERICSERV)
3af48b5b 2367 {
3a2c0242 2368 __free_in6ai (in6ai);
3af48b5b
UD
2369 return EAI_NONAME;
2370 }
c1d98085
UD
2371
2372 gaih_service.num = -1;
2373 }
ca225a41 2374
40a55d20
UD
2375 pservice = &gaih_service;
2376 }
2377 else
46ec036d
UD
2378 pservice = NULL;
2379
d0a1ae94 2380 struct addrinfo **end = &p;
01abbc0f 2381 unsigned int naddrs = 0;
c1de872c 2382 struct scratch_buffer tmpbuf;
cd065b68 2383
c1de872c
TR
2384 scratch_buffer_init (&tmpbuf);
2385 last_i = gaih_inet (name, pservice, hints, end, &naddrs, &tmpbuf);
2386 scratch_buffer_free (&tmpbuf);
786dcb62 2387
c1de872c 2388 if (last_i != 0)
786dcb62 2389 {
c1de872c 2390 freeaddrinfo (p);
3a2c0242 2391 __free_in6ai (in6ai);
c1de872c
TR
2392
2393 return -last_i;
2394 }
2395
2396 while (*end)
2397 {
2398 end = &((*end)->ai_next);
2399 ++nresults;
786dcb62 2400 }
46ec036d 2401
01abbc0f 2402 if (naddrs > 1)
5ddb5bf5 2403 {
77dd4c3b
UD
2404 /* Read the config file. */
2405 __libc_once_define (static, once);
2406 __typeof (once) old_once = once;
2407 __libc_once (once, gaiconf_init);
5ddb5bf5 2408 /* Sort results according to RFC 3484. */
1cef1b19
AS
2409 struct sort_result *results;
2410 size_t *order;
5ddb5bf5 2411 struct addrinfo *q;
d19687d6 2412 struct addrinfo *last = NULL;
c7fa647a 2413 char *canonname = NULL;
955a47a4
JST
2414 struct scratch_buffer buf;
2415 scratch_buffer_init (&buf);
1cef1b19 2416
955a47a4
JST
2417 if (!scratch_buffer_set_array_size (&buf, nresults,
2418 sizeof (*results) + sizeof (size_t)))
1cef1b19 2419 {
955a47a4
JST
2420 __free_in6ai (in6ai);
2421 return EAI_MEMORY;
1cef1b19 2422 }
955a47a4
JST
2423 results = buf.data;
2424
1cef1b19 2425 order = (size_t *) (results + nresults);
5ddb5bf5 2426
fa3fc0fe
UD
2427 /* Now we definitely need the interface information. */
2428 if (! check_pf_called)
2429 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2430
773e79b3 2431 /* If we have information about deprecated and temporary addresses
3af48b5b
UD
2432 sort the array now. */
2433 if (in6ai != NULL)
2434 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2435
e1db0493
UD
2436 int fd = -1;
2437 int af = AF_UNSPEC;
2438
d19687d6 2439 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
5ddb5bf5
UD
2440 {
2441 results[i].dest_addr = q;
773e79b3 2442 results[i].native = -1;
0efd1956 2443 order[i] = i;
5ddb5bf5 2444
007a3ddc 2445 /* If we just looked up the address for a different
d19687d6
UD
2446 protocol, reuse the result. */
2447 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2448 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
5ddb5bf5 2449 {
d19687d6
UD
2450 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2451 results[i - 1].source_addr_len);
2452 results[i].source_addr_len = results[i - 1].source_addr_len;
2453 results[i].got_source_addr = results[i - 1].got_source_addr;
3af48b5b 2454 results[i].source_addr_flags = results[i - 1].source_addr_flags;
6f3914d5 2455 results[i].prefixlen = results[i - 1].prefixlen;
773e79b3 2456 results[i].index = results[i - 1].index;
d19687d6
UD
2457 }
2458 else
2459 {
6f3914d5 2460 results[i].got_source_addr = false;
3af48b5b 2461 results[i].source_addr_flags = 0;
6f3914d5 2462 results[i].prefixlen = 0;
773e79b3 2463 results[i].index = 0xffffffffu;
3af48b5b 2464
007a3ddc
UD
2465 /* We overwrite the type with SOCK_DGRAM since we do not
2466 want connect() to connect to the other side. If we
2467 cannot determine the source address remember this
2468 fact. */
e1db0493
UD
2469 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2470 {
2471 if (fd != -1)
c181840c 2472 __close_nocancel_nostatus (fd);
e1db0493 2473 af = q->ai_family;
2f83a729 2474 fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP);
e1db0493
UD
2475 }
2476 else
2477 {
2478 /* Reset the connection. */
2479 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2480 __connect (fd, &sa, sizeof (sa));
2481 }
2482
d3f2c2c8
SP
2483 if (try_connect (&fd, &af, &results[i].source_addr, q->ai_addr,
2484 q->ai_addrlen, q->ai_family))
d19687d6 2485 {
d3f2c2c8 2486 results[i].source_addr_len = sizeof (results[i].source_addr);
007a3ddc 2487 results[i].got_source_addr = true;
3af48b5b 2488
6f3914d5 2489 if (in6ai != NULL)
3af48b5b 2490 {
e1db0493 2491 /* See whether the source address is on the list of
11bf311e 2492 deprecated or temporary addresses. */
3af48b5b 2493 struct in6addrinfo tmp;
6f3914d5
UD
2494
2495 if (q->ai_family == AF_INET && af == AF_INET)
2496 {
2497 struct sockaddr_in *sinp
2498 = (struct sockaddr_in *) &results[i].source_addr;
2499 tmp.addr[0] = 0;
2500 tmp.addr[1] = 0;
2501 tmp.addr[2] = htonl (0xffff);
894f3f10
AM
2502 /* Special case for lo interface, the source address
2503 being possibly different than the interface
2504 address. */
2505 if ((ntohl(sinp->sin_addr.s_addr) & 0xff000000)
2506 == 0x7f000000)
2507 tmp.addr[3] = htonl(0x7f000001);
2508 else
2509 tmp.addr[3] = sinp->sin_addr.s_addr;
6f3914d5
UD
2510 }
2511 else
2512 {
2513 struct sockaddr_in6 *sin6p
2514 = (struct sockaddr_in6 *) &results[i].source_addr;
2515 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2516 }
3af48b5b
UD
2517
2518 struct in6addrinfo *found
2519 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2520 in6aicmp);
2521 if (found != NULL)
6f3914d5
UD
2522 {
2523 results[i].source_addr_flags = found->flags;
2524 results[i].prefixlen = found->prefixlen;
773e79b3 2525 results[i].index = found->index;
6f3914d5 2526 }
3af48b5b 2527 }
6f3914d5
UD
2528
2529 if (q->ai_family == AF_INET && af == AF_INET6)
e1db0493
UD
2530 {
2531 /* We have to convert the address. The socket is
2532 IPv6 and the request is for IPv4. */
2533 struct sockaddr_in6 *sin6
2534 = (struct sockaddr_in6 *) &results[i].source_addr;
2535 struct sockaddr_in *sin
2536 = (struct sockaddr_in *) &results[i].source_addr;
2537 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
6f3914d5
UD
2538 sin->sin_family = AF_INET;
2539 /* We do not have to initialize sin_port since this
2540 fields has the same position and size in the IPv6
2541 structure. */
2542 assert (offsetof (struct sockaddr_in, sin_port)
2543 == offsetof (struct sockaddr_in6, sin6_port));
2544 assert (sizeof (sin->sin_port)
2545 == sizeof (sin6->sin6_port));
e1db0493
UD
2546 memcpy (&sin->sin_addr,
2547 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
6f3914d5 2548 results[i].source_addr_len = sizeof (struct sockaddr_in);
e1db0493 2549 }
d19687d6 2550 }
007a3ddc
UD
2551 else
2552 /* Just make sure that if we have to process the same
2553 address again we do not copy any memory. */
2554 results[i].source_addr_len = 0;
5ddb5bf5 2555 }
c7fa647a
UD
2556
2557 /* Remember the canonical name. */
2558 if (q->ai_canonname != NULL)
2559 {
2560 assert (canonname == NULL);
2561 canonname = q->ai_canonname;
2562 q->ai_canonname = NULL;
2563 }
5ddb5bf5
UD
2564 }
2565
e1db0493 2566 if (fd != -1)
c181840c 2567 __close_nocancel_nostatus (fd);
e1db0493 2568
5ddb5bf5
UD
2569 /* We got all the source addresses we can get, now sort using
2570 the information. */
773e79b3
UD
2571 struct sort_result_combo src
2572 = { .results = results, .nresults = nresults };
a1ffb40e 2573 if (__glibc_unlikely (gaiconf_reload_flag_ever_set))
fc4837e5
UD
2574 {
2575 __libc_lock_define_initialized (static, lock);
2576
2577 __libc_lock_lock (lock);
be971a2b 2578 if (__libc_once_get (old_once) && gaiconf_reload_flag)
fc4837e5 2579 gaiconf_reload ();
bef8fd60 2580 __qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
fc4837e5
UD
2581 __libc_lock_unlock (lock);
2582 }
2583 else
bef8fd60 2584 __qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
5ddb5bf5
UD
2585
2586 /* Queue the results up as they come out of sorting. */
0efd1956 2587 q = p = results[order[0]].dest_addr;
5ddb5bf5 2588 for (i = 1; i < nresults; ++i)
0efd1956 2589 q = q->ai_next = results[order[i]].dest_addr;
5ddb5bf5 2590 q->ai_next = NULL;
c7fa647a
UD
2591
2592 /* Fill in the canonical name into the new first entry. */
2593 p->ai_canonname = canonname;
1cef1b19 2594
955a47a4 2595 scratch_buffer_free (&buf);
5ddb5bf5
UD
2596 }
2597
3a2c0242 2598 __free_in6ai (in6ai);
3af48b5b 2599
40a55d20
UD
2600 if (p)
2601 {
2602 *pai = p;
2603 return 0;
2604 }
46ec036d 2605
639a0ef8 2606 return last_i ? -last_i : EAI_NONAME;
46ec036d 2607}
9b0b40d3 2608libc_hidden_def (getaddrinfo)
46ec036d 2609
01767843 2610nss_interface_function (getaddrinfo)
2f7f7bc6 2611
40a55d20
UD
2612void
2613freeaddrinfo (struct addrinfo *ai)
46ec036d
UD
2614{
2615 struct addrinfo *p;
2616
40a55d20
UD
2617 while (ai != NULL)
2618 {
2619 p = ai;
2620 ai = ai->ai_next;
b9343764 2621 free (p->ai_canonname);
40a55d20
UD
2622 free (p);
2623 }
46ec036d 2624}
9b0b40d3 2625libc_hidden_def (freeaddrinfo)