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