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
1868static bool
1869add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp,
1870 char *val1, char *val2, char **pos)
1871{
1872 struct in6_addr prefix;
1873 unsigned long int bits;
1874 unsigned long int val;
1875 char *endp;
1876
1877 bits = 128;
1878 __set_errno (0);
1879 char *cp = strchr (val1, '/');
1880 if (cp != NULL)
1881 *cp++ = '\0';
1882 *pos = cp;
1883 if (inet_pton (AF_INET6, val1, &prefix)
1884 && (cp == NULL
1885 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1886 || errno != ERANGE)
1887 && *endp == '\0'
1888 && bits <= 128
1889 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1890 || errno != ERANGE)
1891 && *endp == '\0'
1892 && val <= INT_MAX)
1893 {
1894 struct prefixlist *newp = malloc (size: sizeof (*newp));
1895 if (newp == NULL)
1896 return false;
1897
1898 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
1899 newp->entry.bits = bits;
1900 newp->entry.val = val;
1901 newp->next = *listp;
1902 *listp = newp;
1903 ++*lenp;
1904 *nullbitsp |= bits == 0;
1905 }
1906 return true;
1907}
1908
1909static bool
1910add_scopelist (struct scopelist **listp, size_t *lenp, bool *nullbitsp,
1911 const struct in6_addr *prefixp, unsigned long int bits,
1912 unsigned long int val)
1913{
1914 struct scopelist *newp = malloc (size: sizeof (*newp));
1915 if (newp == NULL)
1916 return false;
1917
1918 newp->entry.netmask = htonl (bits != 96 ? (0xffffffff << (128 - bits)) : 0);
1919 newp->entry.addr32 = (prefixp->s6_addr32[3] & newp->entry.netmask);
1920 newp->entry.scope = val;
1921 newp->next = *listp;
1922 *listp = newp;
1923 ++*lenp;
1924 *nullbitsp |= bits == 96;
1925
1926 return true;
1927}
1928
1929static void
1930gaiconf_init (void)
1931{
1932 struct prefixlist *labellist = NULL;
1933 size_t nlabellist = 0;
1934 bool labellist_nullbits = false;
1935 struct prefixlist *precedencelist = NULL;
1936 size_t nprecedencelist = 0;
1937 bool precedencelist_nullbits = false;
1938 struct scopelist *scopelist = NULL;
1939 size_t nscopelist = 0;
1940 bool scopelist_nullbits = false;
1941
1942 FILE *fp = fopen (GAICONF_FNAME, "rce");
1943 if (fp == NULL)
1944 goto no_file;
1945
1946 struct __stat64_t64 st;
1947 if (__fstat64_time64 (fileno (fp), &st) != 0)
1948 {
1949 fclose (fp);
1950 goto no_file;
1951 }
1952
1953 char *line = NULL;
1954 size_t linelen = 0;
1955
1956 __fsetlocking (fp, FSETLOCKING_BYCALLER);
1957
1958 while (!feof_unlocked (fp))
1959 {
1960 ssize_t n = __getline (lineptr: &line, n: &linelen, stream: fp);
1961 if (n <= 0)
1962 break;
1963
1964 /* Handle comments. No escaping possible so this is easy. */
1965 char *cp = strchr (line, '#');
1966 if (cp != NULL)
1967 *cp = '\0';
1968
1969 cp = line;
1970 while (isspace (*cp))
1971 ++cp;
1972
1973 char *cmd = cp;
1974 while (*cp != '\0' && !isspace (*cp))
1975 ++cp;
1976 size_t cmdlen = cp - cmd;
1977
1978 if (*cp != '\0')
1979 *cp++ = '\0';
1980 while (isspace (*cp))
1981 ++cp;
1982
1983 char *val1 = cp;
1984 while (*cp != '\0' && !isspace (*cp))
1985 ++cp;
1986 size_t val1len = cp - cmd;
1987
1988 /* We always need at least two values. */
1989 if (val1len == 0)
1990 continue;
1991
1992 if (*cp != '\0')
1993 *cp++ = '\0';
1994 while (isspace (*cp))
1995 ++cp;
1996
1997 char *val2 = cp;
1998 while (*cp != '\0' && !isspace (*cp))
1999 ++cp;
2000
2001 /* Ignore the rest of the line. */
2002 *cp = '\0';
2003
2004 switch (cmdlen)
2005 {
2006 case 5:
2007 if (strcmp (cmd, "label") == 0)
2008 {
2009 if (!add_prefixlist (listp: &labellist, lenp: &nlabellist,
2010 nullbitsp: &labellist_nullbits, val1, val2, pos: &cp))
2011 {
2012 free (ptr: line);
2013 fclose (fp);
2014 goto no_file;
2015 }
2016 }
2017 break;
2018
2019 case 6:
2020 if (strcmp (cmd, "reload") == 0)
2021 {
2022 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2023 if (gaiconf_reload_flag)
2024 gaiconf_reload_flag_ever_set = 1;
2025 }
2026 break;
2027
2028 case 7:
2029 if (strcmp (cmd, "scopev4") == 0)
2030 {
2031 struct in6_addr prefix;
2032 unsigned long int bits;
2033 unsigned long int val;
2034 char *endp;
2035
2036 bits = 32;
2037 __set_errno (0);
2038 cp = strchr (val1, '/');
2039 if (cp != NULL)
2040 *cp++ = '\0';
2041 if (inet_pton (AF_INET6, val1, &prefix))
2042 {
2043 bits = 128;
2044 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2045 && (cp == NULL
2046 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2047 || errno != ERANGE)
2048 && *endp == '\0'
2049 && bits >= 96
2050 && bits <= 128
2051 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2052 || errno != ERANGE)
2053 && *endp == '\0'
2054 && val <= INT_MAX)
2055 {
2056 if (!add_scopelist (listp: &scopelist, lenp: &nscopelist,
2057 nullbitsp: &scopelist_nullbits, prefixp: &prefix,
2058 bits, val))
2059 {
2060 free (ptr: line);
2061 fclose (fp);
2062 goto no_file;
2063 }
2064 }
2065 }
2066 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2067 && (cp == NULL
2068 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2069 || errno != ERANGE)
2070 && *endp == '\0'
2071 && bits <= 32
2072 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2073 || errno != ERANGE)
2074 && *endp == '\0'
2075 && val <= INT_MAX)
2076 {
2077 if (!add_scopelist (listp: &scopelist, lenp: &nscopelist,
2078 nullbitsp: &scopelist_nullbits, prefixp: &prefix,
2079 bits: bits + 96, val))
2080 {
2081 free (ptr: line);
2082 fclose (fp);
2083 goto no_file;
2084 }
2085 }
2086 }
2087 break;
2088
2089 case 10:
2090 if (strcmp (cmd, "precedence") == 0)
2091 {
2092 if (!add_prefixlist (listp: &precedencelist, lenp: &nprecedencelist,
2093 nullbitsp: &precedencelist_nullbits, val1, val2,
2094 pos: &cp))
2095 {
2096 free (ptr: line);
2097 fclose (fp);
2098 goto no_file;
2099 }
2100 }
2101 break;
2102 }
2103 }
2104
2105 free (ptr: line);
2106
2107 fclose (fp);
2108
2109 /* Create the array for the labels. */
2110 struct prefixentry *new_labels;
2111 if (nlabellist > 0)
2112 {
2113 if (!labellist_nullbits)
2114 ++nlabellist;
2115 new_labels = malloc (size: nlabellist * sizeof (*new_labels));
2116 if (new_labels == NULL)
2117 goto no_file;
2118
2119 int i = nlabellist;
2120 if (!labellist_nullbits)
2121 {
2122 --i;
2123 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2124 new_labels[i].bits = 0;
2125 new_labels[i].val = 1;
2126 }
2127
2128 struct prefixlist *l = labellist;
2129 while (i-- > 0)
2130 {
2131 new_labels[i] = l->entry;
2132 l = l->next;
2133 }
2134 free_prefixlist (list: labellist);
2135 labellist = NULL;
2136
2137 /* Sort the entries so that the most specific ones are at
2138 the beginning. */
2139 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2140 }
2141 else
2142 new_labels = (struct prefixentry *) default_labels;
2143
2144 struct prefixentry *new_precedence;
2145 if (nprecedencelist > 0)
2146 {
2147 if (!precedencelist_nullbits)
2148 ++nprecedencelist;
2149 new_precedence = malloc (size: nprecedencelist * sizeof (*new_precedence));
2150 if (new_precedence == NULL)
2151 {
2152 if (new_labels != default_labels)
2153 free (ptr: new_labels);
2154 goto no_file;
2155 }
2156
2157 int i = nprecedencelist;
2158 if (!precedencelist_nullbits)
2159 {
2160 --i;
2161 memset (&new_precedence[i].prefix, '\0',
2162 sizeof (struct in6_addr));
2163 new_precedence[i].bits = 0;
2164 new_precedence[i].val = 40;
2165 }
2166
2167 struct prefixlist *l = precedencelist;
2168 while (i-- > 0)
2169 {
2170 new_precedence[i] = l->entry;
2171 l = l->next;
2172 }
2173 free_prefixlist (list: precedencelist);
2174 precedencelist = NULL;
2175
2176 /* Sort the entries so that the most specific ones are at
2177 the beginning. */
2178 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2179 prefixcmp);
2180 }
2181 else
2182 new_precedence = (struct prefixentry *) default_precedence;
2183
2184 struct scopeentry *new_scopes;
2185 if (nscopelist > 0)
2186 {
2187 if (!scopelist_nullbits)
2188 ++nscopelist;
2189 new_scopes = malloc (size: nscopelist * sizeof (*new_scopes));
2190 if (new_scopes == NULL)
2191 {
2192 if (new_labels != default_labels)
2193 free (ptr: new_labels);
2194 if (new_precedence != default_precedence)
2195 free (ptr: new_precedence);
2196 goto no_file;
2197 }
2198
2199 int i = nscopelist;
2200 if (!scopelist_nullbits)
2201 {
2202 --i;
2203 new_scopes[i].addr32 = 0;
2204 new_scopes[i].netmask = 0;
2205 new_scopes[i].scope = 14;
2206 }
2207
2208 struct scopelist *l = scopelist;
2209 while (i-- > 0)
2210 {
2211 new_scopes[i] = l->entry;
2212 l = l->next;
2213 }
2214 free_scopelist (list: scopelist);
2215
2216 /* Sort the entries so that the most specific ones are at
2217 the beginning. */
2218 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2219 scopecmp);
2220 }
2221 else
2222 new_scopes = (struct scopeentry *) default_scopes;
2223
2224 /* Now we are ready to replace the values. */
2225 const struct prefixentry *old = labels;
2226 labels = new_labels;
2227 if (old != default_labels)
2228 free (ptr: (void *) old);
2229
2230 old = precedence;
2231 precedence = new_precedence;
2232 if (old != default_precedence)
2233 free (ptr: (void *) old);
2234
2235 const struct scopeentry *oldscope = scopes;
2236 scopes = new_scopes;
2237 if (oldscope != default_scopes)
2238 free (ptr: (void *) oldscope);
2239
2240 save_gaiconf_mtime (st: &st);
2241 return;
2242
2243no_file:
2244 free_prefixlist (list: labellist);
2245 free_prefixlist (list: precedencelist);
2246 free_scopelist (list: scopelist);
2247
2248 /* If we previously read the file but it is gone now, free the old data and
2249 use the builtin one. Leave the reload flag alone. */
2250 __libc_getaddrinfo_freemem ();
2251}
2252
2253
2254static void
2255gaiconf_reload (void)
2256{
2257 struct __stat64_t64 st;
2258 if (__stat64_time64 (GAICONF_FNAME, &st) != 0
2259 || !check_gaiconf_mtime (st: &st))
2260 gaiconf_init ();
2261}
2262
2263static bool
2264try_connect (int *fdp, int *afp, struct sockaddr_in6 *source_addrp,
2265 const struct sockaddr *addr, socklen_t addrlen, int family)
2266{
2267 int fd = *fdp;
2268 int af = *afp;
2269 socklen_t sl = sizeof (*source_addrp);
2270
2271 while (true)
2272 {
2273 if (fd != -1 && __connect (fd, addr, addrlen) == 0
2274 && __getsockname (fd: fd, addr: (struct sockaddr *) source_addrp, len: &sl) == 0)
2275 return true;
2276
2277 if (errno == EAFNOSUPPORT && af == AF_INET6 && family == AF_INET)
2278 {
2279 /* This could mean IPv6 sockets are IPv6-only. */
2280 if (fd != -1)
2281 __close_nocancel_nostatus (fd);
2282 *afp = af = AF_INET;
2283 *fdp = fd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC,
2284 IPPROTO_IP);
2285 continue;
2286 }
2287
2288 return false;
2289 }
2290
2291 __builtin_unreachable ();
2292}
2293
2294int
2295getaddrinfo (const char *name, const char *service,
2296 const struct addrinfo *hints, struct addrinfo **pai)
2297{
2298 int i = 0, last_i = 0;
2299 int nresults = 0;
2300 struct addrinfo *p = NULL;
2301 struct gaih_service gaih_service, *pservice;
2302 struct addrinfo local_hints;
2303
2304 if (name != NULL && name[0] == '*' && name[1] == 0)
2305 name = NULL;
2306
2307 if (service != NULL && service[0] == '*' && service[1] == 0)
2308 service = NULL;
2309
2310 if (name == NULL && service == NULL)
2311 return EAI_NONAME;
2312
2313 if (hints == NULL)
2314 hints = &default_hints;
2315
2316 if (hints->ai_flags
2317 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2318 |AI_IDN|AI_CANONIDN|DEPRECATED_AI_IDN
2319 |AI_NUMERICSERV|AI_ALL))
2320 return EAI_BADFLAGS;
2321
2322 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2323 return EAI_BADFLAGS;
2324
2325 if (hints->ai_family != AF_UNSPEC && hints->ai_family != AF_INET
2326 && hints->ai_family != AF_INET6)
2327 return EAI_FAMILY;
2328
2329 struct in6addrinfo *in6ai = NULL;
2330 size_t in6ailen = 0;
2331 bool seen_ipv4 = false;
2332 bool seen_ipv6 = false;
2333 bool check_pf_called = false;
2334
2335 if (hints->ai_flags & AI_ADDRCONFIG)
2336 {
2337 /* We might need information about what interfaces are available.
2338 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2339 cannot cache the results since new interfaces could be added at
2340 any time. */
2341 __check_pf (seen_ipv4: &seen_ipv4, seen_ipv6: &seen_ipv6, in6ai: &in6ai, in6ailen: &in6ailen);
2342 check_pf_called = true;
2343
2344 /* Now make a decision on what we return, if anything. */
2345 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2346 {
2347 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2348 narrow down the search. */
2349 if (seen_ipv4 != seen_ipv6)
2350 {
2351 local_hints = *hints;
2352 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2353 hints = &local_hints;
2354 }
2355 }
2356 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2357 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2358 {
2359 /* We cannot possibly return a valid answer. */
2360 __free_in6ai (in6ai);
2361 return EAI_NONAME;
2362 }
2363 }
2364
2365 if (service && service[0])
2366 {
2367 char *c;
2368 gaih_service.name = service;
2369 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2370 if (*c != '\0')
2371 {
2372 if (hints->ai_flags & AI_NUMERICSERV)
2373 {
2374 __free_in6ai (in6ai);
2375 return EAI_NONAME;
2376 }
2377
2378 gaih_service.num = -1;
2379 }
2380
2381 pservice = &gaih_service;
2382 }
2383 else
2384 pservice = NULL;
2385
2386 struct addrinfo **end = &p;
2387 unsigned int naddrs = 0;
2388 struct scratch_buffer tmpbuf;
2389
2390 scratch_buffer_init (buffer: &tmpbuf);
2391 last_i = gaih_inet (name, service: pservice, req: hints, pai: end, naddrs: &naddrs, tmpbuf: &tmpbuf);
2392 scratch_buffer_free (buffer: &tmpbuf);
2393
2394 if (last_i != 0)
2395 {
2396 freeaddrinfo (p);
2397 __free_in6ai (in6ai);
2398
2399 return -last_i;
2400 }
2401
2402 while (*end)
2403 {
2404 end = &((*end)->ai_next);
2405 ++nresults;
2406 }
2407
2408 if (naddrs > 1)
2409 {
2410 /* Read the config file. */
2411 __libc_once_define (static, once);
2412 __typeof (once) old_once = once;
2413 __libc_once (once, gaiconf_init);
2414 /* Sort results according to RFC 3484. */
2415 struct sort_result *results;
2416 size_t *order;
2417 struct addrinfo *q;
2418 struct addrinfo *last = NULL;
2419 char *canonname = NULL;
2420 struct scratch_buffer buf;
2421 scratch_buffer_init (buffer: &buf);
2422
2423 if (!scratch_buffer_set_array_size (buffer: &buf, nelem: nresults,
2424 size: sizeof (*results) + sizeof (size_t)))
2425 {
2426 __free_in6ai (in6ai);
2427 return EAI_MEMORY;
2428 }
2429 results = buf.data;
2430
2431 order = (size_t *) (results + nresults);
2432
2433 /* Now we definitely need the interface information. */
2434 if (! check_pf_called)
2435 __check_pf (seen_ipv4: &seen_ipv4, seen_ipv6: &seen_ipv6, in6ai: &in6ai, in6ailen: &in6ailen);
2436
2437 /* If we have information about deprecated and temporary addresses
2438 sort the array now. */
2439 if (in6ai != NULL)
2440 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2441
2442 int fd = -1;
2443 int af = AF_UNSPEC;
2444
2445 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2446 {
2447 results[i].dest_addr = q;
2448 results[i].native = -1;
2449 order[i] = i;
2450
2451 /* If we just looked up the address for a different
2452 protocol, reuse the result. */
2453 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2454 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2455 {
2456 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2457 results[i - 1].source_addr_len);
2458 results[i].source_addr_len = results[i - 1].source_addr_len;
2459 results[i].got_source_addr = results[i - 1].got_source_addr;
2460 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2461 results[i].prefixlen = results[i - 1].prefixlen;
2462 results[i].index = results[i - 1].index;
2463 }
2464 else
2465 {
2466 results[i].got_source_addr = false;
2467 results[i].source_addr_flags = 0;
2468 results[i].prefixlen = 0;
2469 results[i].index = 0xffffffffu;
2470
2471 /* We overwrite the type with SOCK_DGRAM since we do not
2472 want connect() to connect to the other side. If we
2473 cannot determine the source address remember this
2474 fact. */
2475 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2476 {
2477 if (fd != -1)
2478 __close_nocancel_nostatus (fd);
2479 af = q->ai_family;
2480 fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP);
2481 }
2482 else
2483 {
2484 /* Reset the connection. */
2485 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2486 __connect (fd, &sa, sizeof (sa));
2487 }
2488
2489 if (try_connect (fdp: &fd, afp: &af, source_addrp: &results[i].source_addr, addr: q->ai_addr,
2490 addrlen: q->ai_addrlen, family: q->ai_family))
2491 {
2492 results[i].source_addr_len = sizeof (results[i].source_addr);
2493 results[i].got_source_addr = true;
2494
2495 if (in6ai != NULL)
2496 {
2497 /* See whether the source address is on the list of
2498 deprecated or temporary addresses. */
2499 struct in6addrinfo tmp;
2500
2501 if (q->ai_family == AF_INET && af == AF_INET)
2502 {
2503 struct sockaddr_in *sinp
2504 = (struct sockaddr_in *) &results[i].source_addr;
2505 tmp.addr[0] = 0;
2506 tmp.addr[1] = 0;
2507 tmp.addr[2] = htonl (0xffff);
2508 /* Special case for lo interface, the source address
2509 being possibly different than the interface
2510 address. */
2511 if ((ntohl(sinp->sin_addr.s_addr) & 0xff000000)
2512 == 0x7f000000)
2513 tmp.addr[3] = htonl(0x7f000001);
2514 else
2515 tmp.addr[3] = sinp->sin_addr.s_addr;
2516 }
2517 else
2518 {
2519 struct sockaddr_in6 *sin6p
2520 = (struct sockaddr_in6 *) &results[i].source_addr;
2521 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2522 }
2523
2524 struct in6addrinfo *found
2525 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2526 in6aicmp);
2527 if (found != NULL)
2528 {
2529 results[i].source_addr_flags = found->flags;
2530 results[i].prefixlen = found->prefixlen;
2531 results[i].index = found->index;
2532 }
2533 }
2534
2535 if (q->ai_family == AF_INET && af == AF_INET6)
2536 {
2537 /* We have to convert the address. The socket is
2538 IPv6 and the request is for IPv4. */
2539 struct sockaddr_in6 *sin6
2540 = (struct sockaddr_in6 *) &results[i].source_addr;
2541 struct sockaddr_in *sin
2542 = (struct sockaddr_in *) &results[i].source_addr;
2543 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2544 sin->sin_family = AF_INET;
2545 /* We do not have to initialize sin_port since this
2546 fields has the same position and size in the IPv6
2547 structure. */
2548 assert (offsetof (struct sockaddr_in, sin_port)
2549 == offsetof (struct sockaddr_in6, sin6_port));
2550 assert (sizeof (sin->sin_port)
2551 == sizeof (sin6->sin6_port));
2552 memcpy (&sin->sin_addr,
2553 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2554 results[i].source_addr_len = sizeof (struct sockaddr_in);
2555 }
2556 }
2557 else
2558 /* Just make sure that if we have to process the same
2559 address again we do not copy any memory. */
2560 results[i].source_addr_len = 0;
2561 }
2562
2563 /* Remember the canonical name. */
2564 if (q->ai_canonname != NULL)
2565 {
2566 assert (canonname == NULL);
2567 canonname = q->ai_canonname;
2568 q->ai_canonname = NULL;
2569 }
2570 }
2571
2572 if (fd != -1)
2573 __close_nocancel_nostatus (fd);
2574
2575 /* We got all the source addresses we can get, now sort using
2576 the information. */
2577 struct sort_result_combo src
2578 = { .results = results, .nresults = nresults };
2579 if (__glibc_unlikely (gaiconf_reload_flag_ever_set))
2580 {
2581 __libc_lock_define_initialized (static, lock);
2582
2583 __libc_lock_lock (lock);
2584 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2585 gaiconf_reload ();
2586 __qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2587 __libc_lock_unlock (lock);
2588 }
2589 else
2590 __qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2591
2592 /* Queue the results up as they come out of sorting. */
2593 q = p = results[order[0]].dest_addr;
2594 for (i = 1; i < nresults; ++i)
2595 q = q->ai_next = results[order[i]].dest_addr;
2596 q->ai_next = NULL;
2597
2598 /* Fill in the canonical name into the new first entry. */
2599 p->ai_canonname = canonname;
2600
2601 scratch_buffer_free (buffer: &buf);
2602 }
2603
2604 __free_in6ai (in6ai);
2605
2606 if (p)
2607 {
2608 *pai = p;
2609 return 0;
2610 }
2611
2612 return last_i ? -last_i : EAI_NONAME;
2613}
2614libc_hidden_def (getaddrinfo)
2615
2616nss_interface_function (getaddrinfo)
2617
2618void
2619freeaddrinfo (struct addrinfo *ai)
2620{
2621 struct addrinfo *p;
2622
2623 while (ai != NULL)
2624 {
2625 p = ai;
2626 ai = ai->ai_next;
2627 free (ptr: p->ai_canonname);
2628 free (ptr: p);
2629 }
2630}
2631libc_hidden_def (freeaddrinfo)
2632

source code of glibc/nss/getaddrinfo.c