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

source code of glibc/sysdeps/posix/getaddrinfo.c