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