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

source code of glibc/nss/getaddrinfo.c