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