]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/posix/getaddrinfo.c
* sysdeps/posix/getaddrinfo.c (struct sort_result): Add
[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 <resolv.h>
44 #include <stdbool.h>
45 #include <stdio.h>
46 #include <stdio_ext.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <arpa/inet.h>
50 #include <net/if.h>
51 #include <netinet/in.h>
52 #include <sys/socket.h>
53 #include <sys/stat.h>
54 #include <sys/types.h>
55 #include <sys/un.h>
56 #include <sys/utsname.h>
57 #include <unistd.h>
58 #include <nsswitch.h>
59 #include <bits/libc-lock.h>
60 #include <not-cancel.h>
61 #include <nscd/nscd-client.h>
62 #include <nscd/nscd_proto.h>
63
64 #ifdef HAVE_NETLINK_ROUTE
65 # include <kernel-features.h>
66 #endif
67
68 #ifdef HAVE_LIBIDN
69 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
70 extern int __idna_to_unicode_lzlz (const char *input, char **output,
71 int flags);
72 # include <libidn/idna.h>
73 #endif
74
75 #define GAIH_OKIFUNSPEC 0x0100
76 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
77
78 #ifndef UNIX_PATH_MAX
79 # define UNIX_PATH_MAX 108
80 #endif
81
82 struct gaih_service
83 {
84 const char *name;
85 int num;
86 };
87
88 struct gaih_servtuple
89 {
90 struct gaih_servtuple *next;
91 int socktype;
92 int protocol;
93 int port;
94 };
95
96 static const struct gaih_servtuple nullserv;
97
98 struct gaih_addrtuple
99 {
100 struct gaih_addrtuple *next;
101 char *name;
102 int family;
103 uint32_t addr[4];
104 uint32_t scopeid;
105 };
106
107 struct gaih_typeproto
108 {
109 int socktype;
110 int protocol;
111 char name[4];
112 int protoflag;
113 };
114
115 /* Values for `protoflag'. */
116 #define GAI_PROTO_NOSERVICE 1
117 #define GAI_PROTO_PROTOANY 2
118
119 static const struct gaih_typeproto gaih_inet_typeproto[] =
120 {
121 { 0, 0, "", 0 },
122 { SOCK_STREAM, IPPROTO_TCP, "tcp", 0 },
123 { SOCK_DGRAM, IPPROTO_UDP, "udp", 0 },
124 { SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
125 { 0, 0, "", 0 }
126 };
127
128 struct gaih
129 {
130 int family;
131 int (*gaih)(const char *name, const struct gaih_service *service,
132 const struct addrinfo *req, struct addrinfo **pai,
133 unsigned int *naddrs);
134 };
135
136 static const struct addrinfo default_hints =
137 {
138 .ai_flags = AI_DEFAULT,
139 .ai_family = PF_UNSPEC,
140 .ai_socktype = 0,
141 .ai_protocol = 0,
142 .ai_addrlen = 0,
143 .ai_addr = NULL,
144 .ai_canonname = NULL,
145 .ai_next = NULL
146 };
147
148
149 static int
150 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
151 const struct addrinfo *req, struct gaih_servtuple *st)
152 {
153 struct servent *s;
154 size_t tmpbuflen = 1024;
155 struct servent ts;
156 char *tmpbuf;
157 int r;
158
159 do
160 {
161 tmpbuf = __alloca (tmpbuflen);
162
163 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
164 &s);
165 if (r != 0 || s == NULL)
166 {
167 if (r == ERANGE)
168 tmpbuflen *= 2;
169 else
170 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
171 }
172 }
173 while (r);
174
175 st->next = NULL;
176 st->socktype = tp->socktype;
177 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
178 ? req->ai_protocol : tp->protocol);
179 st->port = s->s_port;
180
181 return 0;
182 }
183
184 #define gethosts(_family, _type) \
185 { \
186 int i; \
187 int herrno; \
188 struct hostent th; \
189 struct hostent *h; \
190 char *localcanon = NULL; \
191 no_data = 0; \
192 while (1) { \
193 rc = 0; \
194 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
195 &rc, &herrno, NULL, &localcanon)); \
196 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
197 break; \
198 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
199 } \
200 if (status == NSS_STATUS_SUCCESS && rc == 0) \
201 h = &th; \
202 else \
203 h = NULL; \
204 if (rc != 0) \
205 { \
206 if (herrno == NETDB_INTERNAL) \
207 { \
208 __set_h_errno (herrno); \
209 return -EAI_SYSTEM; \
210 } \
211 if (herrno == TRY_AGAIN) \
212 no_data = EAI_AGAIN; \
213 else \
214 no_data = herrno == NO_DATA; \
215 } \
216 else if (h != NULL) \
217 { \
218 for (i = 0; h->h_addr_list[i]; i++) \
219 { \
220 if (*pat == NULL) \
221 { \
222 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
223 (*pat)->scopeid = 0; \
224 } \
225 uint32_t *addr = (*pat)->addr; \
226 (*pat)->next = NULL; \
227 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
228 if (_family == AF_INET && req->ai_family == AF_INET6) \
229 { \
230 (*pat)->family = AF_INET6; \
231 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
232 addr[2] = htonl (0xffff); \
233 addr[1] = 0; \
234 addr[0] = 0; \
235 } \
236 else \
237 { \
238 (*pat)->family = _family; \
239 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
240 } \
241 pat = &((*pat)->next); \
242 } \
243 \
244 if (localcanon != NULL && canon == NULL) \
245 canon = strdupa (localcanon); \
246 \
247 if (_family == AF_INET6 && i > 0) \
248 got_ipv6 = true; \
249 } \
250 }
251
252
253 typedef enum nss_status (*nss_gethostbyname3_r)
254 (const char *name, int af, struct hostent *host,
255 char *buffer, size_t buflen, int *errnop,
256 int *h_errnop, int32_t *ttlp, char **canonp);
257 typedef enum nss_status (*nss_getcanonname_r)
258 (const char *name, char *buffer, size_t buflen, char **result,
259 int *errnop, int *h_errnop);
260 extern service_user *__nss_hosts_database attribute_hidden;
261
262
263 static int
264 gaih_inet (const char *name, const struct gaih_service *service,
265 const struct addrinfo *req, struct addrinfo **pai,
266 unsigned int *naddrs)
267 {
268 const struct gaih_typeproto *tp = gaih_inet_typeproto;
269 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
270 struct gaih_addrtuple *at = NULL;
271 int rc;
272 bool got_ipv6 = false;
273 const char *canon = NULL;
274 const char *orig_name = name;
275
276 if (req->ai_protocol || req->ai_socktype)
277 {
278 ++tp;
279
280 while (tp->name[0]
281 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
282 || (req->ai_protocol != 0
283 && !(tp->protoflag & GAI_PROTO_PROTOANY)
284 && req->ai_protocol != tp->protocol)))
285 ++tp;
286
287 if (! tp->name[0])
288 {
289 if (req->ai_socktype)
290 return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
291 else
292 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
293 }
294 }
295
296 int port = 0;
297 if (service != NULL)
298 {
299 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
300 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
301
302 if (service->num < 0)
303 {
304 if (tp->name[0])
305 {
306 st = (struct gaih_servtuple *)
307 __alloca (sizeof (struct gaih_servtuple));
308
309 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
310 return rc;
311 }
312 else
313 {
314 struct gaih_servtuple **pst = &st;
315 for (tp++; tp->name[0]; tp++)
316 {
317 struct gaih_servtuple *newp;
318
319 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
320 continue;
321
322 if (req->ai_socktype != 0
323 && req->ai_socktype != tp->socktype)
324 continue;
325 if (req->ai_protocol != 0
326 && !(tp->protoflag & GAI_PROTO_PROTOANY)
327 && req->ai_protocol != tp->protocol)
328 continue;
329
330 newp = (struct gaih_servtuple *)
331 __alloca (sizeof (struct gaih_servtuple));
332
333 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
334 {
335 if (rc & GAIH_OKIFUNSPEC)
336 continue;
337 return rc;
338 }
339
340 *pst = newp;
341 pst = &(newp->next);
342 }
343 if (st == (struct gaih_servtuple *) &nullserv)
344 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
345 }
346 }
347 else
348 {
349 port = htons (service->num);
350 goto got_port;
351 }
352 }
353 else
354 {
355 got_port:
356
357 if (req->ai_socktype || req->ai_protocol)
358 {
359 st = __alloca (sizeof (struct gaih_servtuple));
360 st->next = NULL;
361 st->socktype = tp->socktype;
362 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
363 ? req->ai_protocol : tp->protocol);
364 st->port = port;
365 }
366 else
367 {
368 /* Neither socket type nor protocol is set. Return all socket types
369 we know about. */
370 struct gaih_servtuple **lastp = &st;
371 for (++tp; tp->name[0]; ++tp)
372 {
373 struct gaih_servtuple *newp;
374
375 newp = __alloca (sizeof (struct gaih_servtuple));
376 newp->next = NULL;
377 newp->socktype = tp->socktype;
378 newp->protocol = tp->protocol;
379 newp->port = port;
380
381 *lastp = newp;
382 lastp = &newp->next;
383 }
384 }
385 }
386
387 if (name != NULL)
388 {
389 at = __alloca (sizeof (struct gaih_addrtuple));
390
391 at->family = AF_UNSPEC;
392 at->scopeid = 0;
393 at->next = NULL;
394
395 #ifdef HAVE_LIBIDN
396 if (req->ai_flags & AI_IDN)
397 {
398 int idn_flags = 0;
399 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
400 idn_flags |= IDNA_ALLOW_UNASSIGNED;
401 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
402 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
403
404 char *p = NULL;
405 rc = __idna_to_ascii_lz (name, &p, idn_flags);
406 if (rc != IDNA_SUCCESS)
407 {
408 if (rc == IDNA_MALLOC_ERROR)
409 return -EAI_MEMORY;
410 if (rc == IDNA_DLOPEN_ERROR)
411 return -EAI_SYSTEM;
412 return -EAI_IDN_ENCODE;
413 }
414 /* In case the output string is the same as the input string
415 no new string has been allocated. */
416 if (p != name)
417 {
418 name = strdupa (p);
419 free (p);
420 }
421 }
422 #endif
423
424 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
425 {
426 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
427 at->family = AF_INET;
428 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
429 {
430 at->addr[3] = at->addr[0];
431 at->addr[2] = htonl (0xffff);
432 at->addr[1] = 0;
433 at->addr[0] = 0;
434 at->family = AF_INET6;
435 }
436 else
437 return -EAI_ADDRFAMILY;
438
439 if (req->ai_flags & AI_CANONNAME)
440 canon = name;
441 }
442 else if (at->family == AF_UNSPEC)
443 {
444 char *namebuf = (char *) name;
445 char *scope_delim = strchr (name, SCOPE_DELIMITER);
446
447 if (__builtin_expect (scope_delim != NULL, 0))
448 {
449 namebuf = alloca (scope_delim - name + 1);
450 *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
451 }
452
453 if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
454 {
455 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
456 at->family = AF_INET6;
457 else if (req->ai_family == AF_INET
458 && IN6_IS_ADDR_V4MAPPED (at->addr))
459 {
460 at->addr[0] = at->addr[3];
461 at->family = AF_INET;
462 }
463 else
464 return -EAI_ADDRFAMILY;
465
466 if (scope_delim != NULL)
467 {
468 int try_numericscope = 0;
469 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
470 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
471 {
472 at->scopeid = if_nametoindex (scope_delim + 1);
473 if (at->scopeid == 0)
474 try_numericscope = 1;
475 }
476 else
477 try_numericscope = 1;
478
479 if (try_numericscope != 0)
480 {
481 char *end;
482 assert (sizeof (uint32_t) <= sizeof (unsigned long));
483 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
484 10);
485 if (*end != '\0')
486 return GAIH_OKIFUNSPEC | -EAI_NONAME;
487 }
488 }
489
490 if (req->ai_flags & AI_CANONNAME)
491 canon = name;
492 }
493 }
494
495 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
496 {
497 struct gaih_addrtuple **pat = &at;
498 int no_data = 0;
499 int no_inet6_data = 0;
500 service_user *nip = NULL;
501 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
502 enum nss_status status = NSS_STATUS_UNAVAIL;
503 int no_more;
504 int old_res_options;
505
506 /* If we do not have to look for IPv4 and IPv6 together, use
507 the simple, old functions. */
508 if (req->ai_family == AF_INET
509 || (req->ai_family == AF_INET6
510 && ((req->ai_flags & AI_V4MAPPED) == 0
511 || (req->ai_flags & AI_ALL) == 0)))
512 {
513 int family = req->ai_family;
514 size_t tmpbuflen = 512;
515 char *tmpbuf = alloca (tmpbuflen);
516 int rc;
517 struct hostent th;
518 struct hostent *h;
519 int herrno;
520
521 simple_again:
522 while (1)
523 {
524 rc = __gethostbyname2_r (name, family, &th, tmpbuf,
525 tmpbuflen, &h, &herrno);
526 if (rc != ERANGE || herrno != NETDB_INTERNAL)
527 break;
528 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
529 }
530
531 if (rc == 0)
532 {
533 if (h == NULL)
534 {
535 if (req->ai_family == AF_INET6
536 && (req->ai_flags & AI_V4MAPPED)
537 && family == AF_INET6)
538 {
539 /* Try again, this time looking for IPv4
540 addresses. */
541 family = AF_INET;
542 goto simple_again;
543 }
544 }
545 else
546 {
547 /* We found data, now convert it into the list. */
548 for (int i = 0; h->h_addr_list[i]; ++i)
549 {
550 if (*pat == NULL)
551 {
552 *pat = __alloca (sizeof (struct gaih_addrtuple));
553 (*pat)->scopeid = 0;
554 }
555 (*pat)->next = NULL;
556 (*pat)->family = req->ai_family;
557 if (family == req->ai_family)
558 memcpy ((*pat)->addr, h->h_addr_list[i],
559 h->h_length);
560 else
561 {
562 uint32_t *addr = (uint32_t *) (*pat)->addr;
563 addr[3] = *(uint32_t *) h->h_addr_list[i];
564 addr[2] = htonl (0xffff);
565 addr[1] = 0;
566 addr[0] = 0;
567 }
568 pat = &((*pat)->next);
569 }
570 }
571 }
572 else
573 {
574 if (herrno == NETDB_INTERNAL)
575 {
576 __set_h_errno (herrno);
577 return -EAI_SYSTEM;
578 }
579 if (herrno == TRY_AGAIN)
580 {
581 return -EAI_AGAIN;
582 }
583 /* We made requests but they turned out no data.
584 The name is known, though. */
585 return GAIH_OKIFUNSPEC | -EAI_NODATA;
586 }
587
588 goto process_list;
589 }
590
591 #ifdef USE_NSCD
592 if (__nss_not_use_nscd_hosts > 0
593 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
594 __nss_not_use_nscd_hosts = 0;
595
596 if (!__nss_not_use_nscd_hosts)
597 {
598 /* Try to use nscd. */
599 struct nscd_ai_result *air = NULL;
600 int herrno;
601 int err = __nscd_getai (name, &air, &herrno);
602 if (air != NULL)
603 {
604 /* Transform into gaih_addrtuple list. */
605 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
606 char *addrs = air->addrs;
607
608 for (int i = 0; i < air->naddrs; ++i)
609 {
610 socklen_t size = (air->family[i] == AF_INET
611 ? INADDRSZ : IN6ADDRSZ);
612 if (*pat == NULL)
613 {
614 *pat = __alloca (sizeof (struct gaih_addrtuple));
615 (*pat)->scopeid = 0;
616 }
617 uint32_t *pataddr = (*pat)->addr;
618 (*pat)->next = NULL;
619 if (added_canon || air->canon == NULL)
620 (*pat)->name = NULL;
621 else
622 canon = (*pat)->name = strdupa (air->canon);
623
624 if (air->family[i] == AF_INET
625 && req->ai_family == AF_INET6
626 && (req->ai_flags & AI_V4MAPPED))
627 {
628 (*pat)->family = AF_INET6;
629 pataddr[3] = *(uint32_t *) addrs;
630 pataddr[2] = htonl (0xffff);
631 pataddr[1] = 0;
632 pataddr[0] = 0;
633 pat = &((*pat)->next);
634 added_canon = true;
635 }
636 else if (req->ai_family == AF_UNSPEC
637 || air->family[i] == req->ai_family)
638 {
639 (*pat)->family = air->family[i];
640 memcpy (pataddr, addrs, size);
641 pat = &((*pat)->next);
642 added_canon = true;
643 if (air->family[i] == AF_INET6)
644 got_ipv6 = true;
645 }
646 addrs += size;
647 }
648
649 free (air);
650
651 if (at->family == AF_UNSPEC)
652 return GAIH_OKIFUNSPEC | -EAI_NONAME;
653
654 goto process_list;
655 }
656 else if (err != 0 && __nss_not_use_nscd_hosts == 0)
657 {
658 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
659 return -EAI_MEMORY;
660 if (herrno == TRY_AGAIN)
661 return -EAI_AGAIN;
662 return -EAI_SYSTEM;
663 }
664 }
665 #endif
666
667 if (__nss_hosts_database != NULL)
668 {
669 no_more = 0;
670 nip = __nss_hosts_database;
671 }
672 else
673 no_more = __nss_database_lookup ("hosts", NULL,
674 "dns [!UNAVAIL=return] files",
675 &nip);
676
677 if (__res_maybe_init (&_res, 0) == -1)
678 no_more = 1;
679
680 /* If we are looking for both IPv4 and IPv6 address we don't
681 want the lookup functions to automatically promote IPv4
682 addresses to IPv6 addresses. Currently this is decided
683 by setting the RES_USE_INET6 bit in _res.options. */
684 old_res_options = _res.options;
685 _res.options &= ~RES_USE_INET6;
686
687 size_t tmpbuflen = 512;
688 char *tmpbuf = alloca (tmpbuflen);
689
690 while (!no_more)
691 {
692 nss_gethostbyname3_r fct = NULL;
693 if (req->ai_flags & AI_CANONNAME)
694 /* No need to use this function if we do not look for
695 the canonical name. The function does not exist in
696 all NSS modules and therefore the lookup would
697 often fail. */
698 fct = __nss_lookup_function (nip, "gethostbyname3_r");
699 if (fct == NULL)
700 /* We are cheating here. The gethostbyname2_r function does
701 not have the same interface as gethostbyname3_r but the
702 extra arguments the latter takes are added at the end.
703 So the gethostbyname2_r code will just ignore them. */
704 fct = __nss_lookup_function (nip, "gethostbyname2_r");
705
706 if (fct != NULL)
707 {
708 if (req->ai_family == AF_INET6
709 || req->ai_family == AF_UNSPEC)
710 {
711 gethosts (AF_INET6, struct in6_addr);
712 no_inet6_data = no_data;
713 inet6_status = status;
714 }
715 if (req->ai_family == AF_INET
716 || req->ai_family == AF_UNSPEC
717 || (req->ai_family == AF_INET6
718 && (req->ai_flags & AI_V4MAPPED)
719 /* Avoid generating the mapped addresses if we
720 know we are not going to need them. */
721 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
722 {
723 gethosts (AF_INET, struct in_addr);
724
725 if (req->ai_family == AF_INET)
726 {
727 no_inet6_data = no_data;
728 inet6_status = status;
729 }
730 }
731
732 /* If we found one address for AF_INET or AF_INET6,
733 don't continue the search. */
734 if (inet6_status == NSS_STATUS_SUCCESS
735 || status == NSS_STATUS_SUCCESS)
736 {
737 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
738 {
739 /* If we need the canonical name, get it
740 from the same service as the result. */
741 nss_getcanonname_r cfct;
742 int herrno;
743
744 cfct = __nss_lookup_function (nip, "getcanonname_r");
745 if (cfct != NULL)
746 {
747 const size_t max_fqdn_len = 256;
748 char *buf = alloca (max_fqdn_len);
749 char *s;
750
751 if (DL_CALL_FCT (cfct, (at->name ?: name, buf,
752 max_fqdn_len, &s, &rc,
753 &herrno))
754 == NSS_STATUS_SUCCESS)
755 canon = s;
756 else
757 /* Set to name now to avoid using
758 gethostbyaddr. */
759 canon = name;
760 }
761 }
762
763 break;
764 }
765
766 /* We can have different states for AF_INET and
767 AF_INET6. Try to find a useful one for both. */
768 if (inet6_status == NSS_STATUS_TRYAGAIN)
769 status = NSS_STATUS_TRYAGAIN;
770 else if (status == NSS_STATUS_UNAVAIL
771 && inet6_status != NSS_STATUS_UNAVAIL)
772 status = inet6_status;
773 }
774
775 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
776 break;
777
778 if (nip->next == NULL)
779 no_more = -1;
780 else
781 nip = nip->next;
782 }
783
784 _res.options = old_res_options;
785
786 if (no_data != 0 && no_inet6_data != 0)
787 {
788 /* If both requests timed out report this. */
789 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
790 return -EAI_AGAIN;
791
792 /* We made requests but they turned out no data. The name
793 is known, though. */
794 return GAIH_OKIFUNSPEC | -EAI_NODATA;
795 }
796 }
797
798 process_list:
799 if (at->family == AF_UNSPEC)
800 return GAIH_OKIFUNSPEC | -EAI_NONAME;
801 }
802 else
803 {
804 struct gaih_addrtuple *atr;
805 atr = at = __alloca (sizeof (struct gaih_addrtuple));
806 memset (at, '\0', sizeof (struct gaih_addrtuple));
807
808 if (req->ai_family == AF_UNSPEC)
809 {
810 at->next = __alloca (sizeof (struct gaih_addrtuple));
811 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
812 }
813
814 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
815 {
816 at->family = AF_INET6;
817 if ((req->ai_flags & AI_PASSIVE) == 0)
818 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
819 atr = at->next;
820 }
821
822 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
823 {
824 atr->family = AF_INET;
825 if ((req->ai_flags & AI_PASSIVE) == 0)
826 atr->addr[0] = htonl (INADDR_LOOPBACK);
827 }
828 }
829
830 if (pai == NULL)
831 return 0;
832
833 {
834 struct gaih_servtuple *st2;
835 struct gaih_addrtuple *at2 = at;
836 size_t socklen;
837 sa_family_t family;
838
839 /*
840 buffer is the size of an unformatted IPv6 address in printable format.
841 */
842 while (at2 != NULL)
843 {
844 /* Only the first entry gets the canonical name. */
845 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
846 {
847 if (canon == NULL)
848 {
849 struct hostent *h = NULL;
850 int herrno;
851 struct hostent th;
852 size_t tmpbuflen = 512;
853 char *tmpbuf = NULL;
854
855 do
856 {
857 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
858 rc = __gethostbyaddr_r (at2->addr,
859 ((at2->family == AF_INET6)
860 ? sizeof (struct in6_addr)
861 : sizeof (struct in_addr)),
862 at2->family, &th, tmpbuf,
863 tmpbuflen, &h, &herrno);
864 }
865 while (rc == ERANGE && herrno == NETDB_INTERNAL);
866
867 if (rc != 0 && herrno == NETDB_INTERNAL)
868 {
869 __set_h_errno (herrno);
870 return -EAI_SYSTEM;
871 }
872
873 if (h != NULL)
874 canon = h->h_name;
875 else
876 {
877 assert (orig_name != NULL);
878 /* If the canonical name cannot be determined, use
879 the passed in string. */
880 canon = orig_name;
881 }
882 }
883
884 #ifdef HAVE_LIBIDN
885 if (req->ai_flags & AI_CANONIDN)
886 {
887 int idn_flags = 0;
888 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
889 idn_flags |= IDNA_ALLOW_UNASSIGNED;
890 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
891 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
892
893 char *out;
894 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
895 if (rc != IDNA_SUCCESS)
896 {
897 if (rc == IDNA_MALLOC_ERROR)
898 return -EAI_MEMORY;
899 if (rc == IDNA_DLOPEN_ERROR)
900 return -EAI_SYSTEM;
901 return -EAI_IDN_ENCODE;
902 }
903 /* In case the output string is the same as the input
904 string no new string has been allocated. Otherwise
905 make a copy. */
906 if (out == canon)
907 goto make_copy;
908 }
909 else
910 #endif
911 {
912 #ifdef HAVE_LIBIDN
913 make_copy:
914 #endif
915 canon = strdup (canon);
916 if (canon == NULL)
917 return -EAI_MEMORY;
918 }
919 }
920
921 family = at2->family;
922 if (family == AF_INET6)
923 {
924 socklen = sizeof (struct sockaddr_in6);
925
926 /* If we looked up IPv4 mapped address discard them here if
927 the caller isn't interested in all address and we have
928 found at least one IPv6 address. */
929 if (got_ipv6
930 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
931 && IN6_IS_ADDR_V4MAPPED (at2->addr))
932 goto ignore;
933 }
934 else
935 socklen = sizeof (struct sockaddr_in);
936
937 for (st2 = st; st2 != NULL; st2 = st2->next)
938 {
939 struct addrinfo *ai;
940 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
941 if (ai == NULL)
942 {
943 free ((char *) canon);
944 return -EAI_MEMORY;
945 }
946
947 ai->ai_flags = req->ai_flags;
948 ai->ai_family = family;
949 ai->ai_socktype = st2->socktype;
950 ai->ai_protocol = st2->protocol;
951 ai->ai_addrlen = socklen;
952 ai->ai_addr = (void *) (ai + 1);
953
954 /* We only add the canonical name once. */
955 ai->ai_canonname = (char *) canon;
956 canon = NULL;
957
958 #ifdef _HAVE_SA_LEN
959 ai->ai_addr->sa_len = socklen;
960 #endif /* _HAVE_SA_LEN */
961 ai->ai_addr->sa_family = family;
962
963 /* In case of an allocation error the list must be NULL
964 terminated. */
965 ai->ai_next = NULL;
966
967 if (family == AF_INET6)
968 {
969 struct sockaddr_in6 *sin6p =
970 (struct sockaddr_in6 *) ai->ai_addr;
971
972 sin6p->sin6_port = st2->port;
973 sin6p->sin6_flowinfo = 0;
974 memcpy (&sin6p->sin6_addr,
975 at2->addr, sizeof (struct in6_addr));
976 sin6p->sin6_scope_id = at2->scopeid;
977 }
978 else
979 {
980 struct sockaddr_in *sinp =
981 (struct sockaddr_in *) ai->ai_addr;
982 sinp->sin_port = st2->port;
983 memcpy (&sinp->sin_addr,
984 at2->addr, sizeof (struct in_addr));
985 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
986 }
987
988 pai = &(ai->ai_next);
989 }
990
991 ++*naddrs;
992
993 ignore:
994 at2 = at2->next;
995 }
996 }
997 return 0;
998 }
999
1000
1001 struct sort_result
1002 {
1003 struct addrinfo *dest_addr;
1004 struct sockaddr_storage source_addr;
1005 size_t service_order;
1006 uint8_t source_addr_len;
1007 bool got_source_addr;
1008 uint8_t source_addr_flags;
1009 };
1010
1011
1012 static int
1013 get_scope (const struct sockaddr_storage *ss)
1014 {
1015 int scope;
1016 if (ss->ss_family == PF_INET6)
1017 {
1018 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
1019
1020 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1021 {
1022 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
1023 scope = 2;
1024 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1025 scope = 5;
1026 else
1027 /* XXX Is this the correct default behavior? */
1028 scope = 14;
1029 }
1030 else
1031 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1032 }
1033 else if (ss->ss_family == PF_INET)
1034 {
1035 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1036 const uint8_t *addr = (const uint8_t *) &in->sin_addr;
1037
1038 /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1039 169.254/16 and 127/8 are link-local. */
1040 if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
1041 scope = 2;
1042 else if (addr[0] == 10 || (addr[0] == 172 && (addr[1] & 0xf0) == 16)
1043 || (addr[0] == 192 && addr[1] == 168))
1044 scope = 5;
1045 else
1046 scope = 14;
1047 }
1048 else
1049 /* XXX What is a good default? */
1050 scope = 15;
1051
1052 return scope;
1053 }
1054
1055
1056 struct prefixentry
1057 {
1058 struct in6_addr prefix;
1059 unsigned int bits;
1060 int val;
1061 };
1062
1063
1064 /* The label table. */
1065 static const struct prefixentry *labels;
1066
1067 /* Default labels. */
1068 static const struct prefixentry default_labels[] =
1069 {
1070 /* See RFC 3484 for the details. */
1071 { { .in6_u
1072 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
1074 128, 0 },
1075 { { .in6_u
1076 = { .u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1078 16, 2 },
1079 { { .in6_u
1080 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1082 96, 3 },
1083 { { .in6_u
1084 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1085 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
1086 96, 4 },
1087 /* The next two entries differ from RFC 3484. We need to treat
1088 IPv6 site-local addresses special because they are never NATed,
1089 unlike site-locale IPv4 addresses. If this would not happen, on
1090 machines which have only IPv4 and IPv6 site-local addresses, the
1091 sorting would prefer the IPv6 site-local addresses, causing
1092 unnecessary delays when trying to connect to a global IPv6 address
1093 through a site-local IPv6 address. */
1094 { { .in6_u
1095 = { .u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1097 10, 5 },
1098 { { .in6_u
1099 = { .u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1101 7, 6 },
1102 { { .in6_u
1103 = { .u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1105 32, 7 },
1106 { { .in6_u
1107 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1109 0, 1 }
1110 };
1111
1112
1113 /* The precedence table. */
1114 static const struct prefixentry *precedence;
1115
1116 /* The default precedences. */
1117 static const struct prefixentry default_precedence[] =
1118 {
1119 /* See RFC 3484 for the details. */
1120 { { .in6_u
1121 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
1123 128, 50 },
1124 { { .in6_u
1125 = { .u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1127 16, 30 },
1128 { { .in6_u
1129 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1131 96, 20 },
1132 { { .in6_u
1133 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } },
1135 96, 10 },
1136 { { .in6_u
1137 = { .u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } },
1139 0, 40 }
1140 };
1141
1142
1143 static int
1144 match_prefix (const struct sockaddr_storage *ss,
1145 const struct prefixentry *list, int default_val)
1146 {
1147 int idx;
1148 struct sockaddr_in6 in6_mem;
1149 const struct sockaddr_in6 *in6;
1150
1151 if (ss->ss_family == PF_INET6)
1152 in6 = (const struct sockaddr_in6 *) ss;
1153 else if (ss->ss_family == PF_INET)
1154 {
1155 const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1156
1157 /* Convert to IPv6 address. */
1158 in6_mem.sin6_family = PF_INET6;
1159 in6_mem.sin6_port = in->sin_port;
1160 in6_mem.sin6_flowinfo = 0;
1161 if (in->sin_addr.s_addr == htonl (0x7f000001))
1162 in6_mem.sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
1163 else
1164 {
1165 /* Construct a V4-to-6 mapped address. */
1166 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1167 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1168 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1169 in6_mem.sin6_scope_id = 0;
1170 }
1171
1172 in6 = &in6_mem;
1173 }
1174 else
1175 return default_val;
1176
1177 for (idx = 0; ; ++idx)
1178 {
1179 unsigned int bits = list[idx].bits;
1180 const uint8_t *mask = list[idx].prefix.s6_addr;
1181 const uint8_t *val = in6->sin6_addr.s6_addr;
1182
1183 while (bits >= 8)
1184 {
1185 if (*mask != *val)
1186 break;
1187
1188 ++mask;
1189 ++val;
1190 bits -= 8;
1191 }
1192
1193 if (bits < 8)
1194 {
1195 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1196 /* Match! */
1197 break;
1198 }
1199 }
1200
1201 return list[idx].val;
1202 }
1203
1204
1205 static int
1206 get_label (const struct sockaddr_storage *ss)
1207 {
1208 /* XXX What is a good default value? */
1209 return match_prefix (ss, labels, INT_MAX);
1210 }
1211
1212
1213 static int
1214 get_precedence (const struct sockaddr_storage *ss)
1215 {
1216 /* XXX What is a good default value? */
1217 return match_prefix (ss, precedence, 0);
1218 }
1219
1220
1221 /* Find last bit set in a word. */
1222 static int
1223 fls (uint32_t a)
1224 {
1225 uint32_t mask;
1226 int n = 0;
1227 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1228 if ((a & mask) != 0)
1229 break;
1230 return n;
1231 }
1232
1233
1234 static int
1235 rfc3484_sort (const void *p1, const void *p2)
1236 {
1237 const struct sort_result *a1 = (const struct sort_result *) p1;
1238 const struct sort_result *a2 = (const struct sort_result *) p2;
1239
1240 /* Rule 1: Avoid unusable destinations.
1241 We have the got_source_addr flag set if the destination is reachable. */
1242 if (a1->got_source_addr && ! a2->got_source_addr)
1243 return -1;
1244 if (! a1->got_source_addr && a2->got_source_addr)
1245 return 1;
1246
1247
1248 /* Rule 2: Prefer matching scope. Only interesting if both
1249 destination addresses are IPv6. */
1250 int a1_dst_scope
1251 = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1252
1253 int a2_dst_scope
1254 = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1255
1256 if (a1->got_source_addr)
1257 {
1258 int a1_src_scope = get_scope (&a1->source_addr);
1259 int a2_src_scope = get_scope (&a2->source_addr);
1260
1261 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1262 return -1;
1263 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1264 return 1;
1265 }
1266
1267
1268 /* Rule 3: Avoid deprecated addresses. */
1269 if (a1->got_source_addr)
1270 {
1271 if (!(a1->source_addr_flags & in6ai_deprecated)
1272 && (a2->source_addr_flags & in6ai_deprecated))
1273 return -1;
1274 if ((a1->source_addr_flags & in6ai_deprecated)
1275 && !(a2->source_addr_flags & in6ai_deprecated))
1276 return 1;
1277 }
1278
1279 /* Rule 4: Prefer home addresses. */
1280 if (a1->got_source_addr)
1281 {
1282 if (!(a1->source_addr_flags & in6ai_homeaddress)
1283 && (a2->source_addr_flags & in6ai_homeaddress))
1284 return 1;
1285 if ((a1->source_addr_flags & in6ai_homeaddress)
1286 && !(a2->source_addr_flags & in6ai_homeaddress))
1287 return -1;
1288 }
1289
1290 /* Rule 5: Prefer matching label. */
1291 if (a1->got_source_addr)
1292 {
1293 int a1_dst_label
1294 = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1295 int a1_src_label = get_label (&a1->source_addr);
1296
1297 int a2_dst_label
1298 = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1299 int a2_src_label = get_label (&a2->source_addr);
1300
1301 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1302 return -1;
1303 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1304 return 1;
1305 }
1306
1307
1308 /* Rule 6: Prefer higher precedence. */
1309 int a1_prec
1310 = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1311 int a2_prec
1312 = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1313
1314 if (a1_prec > a2_prec)
1315 return -1;
1316 if (a1_prec < a2_prec)
1317 return 1;
1318
1319
1320 /* Rule 7: Prefer native transport. */
1321 if (a1->got_source_addr)
1322 {
1323 if (!(a1->source_addr_flags & in6ai_temporary)
1324 && (a2->source_addr_flags & in6ai_temporary))
1325 return -1;
1326 if ((a1->source_addr_flags & in6ai_temporary)
1327 && !(a2->source_addr_flags & in6ai_temporary))
1328 return 1;
1329
1330 /* XXX Do we need to check anything beside temporary addresses? */
1331 }
1332
1333
1334 /* Rule 8: Prefer smaller scope. */
1335 if (a1_dst_scope < a2_dst_scope)
1336 return -1;
1337 if (a1_dst_scope > a2_dst_scope)
1338 return 1;
1339
1340
1341 /* Rule 9: Use longest matching prefix. */
1342 if (a1->got_source_addr
1343 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1344 {
1345 int bit1 = 0;
1346 int bit2 = 0;
1347
1348 if (a1->dest_addr->ai_family == PF_INET)
1349 {
1350 assert (a1->source_addr.ss_family == PF_INET);
1351 assert (a2->source_addr.ss_family == PF_INET);
1352
1353 struct sockaddr_in *in1_dst;
1354 struct sockaddr_in *in1_src;
1355 struct sockaddr_in *in2_dst;
1356 struct sockaddr_in *in2_src;
1357
1358 in1_dst = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1359 in1_src = (struct sockaddr_in *) &a1->source_addr;
1360 in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1361 in2_src = (struct sockaddr_in *) &a2->source_addr;
1362
1363 bit1 = fls (ntohl (in1_dst->sin_addr.s_addr
1364 ^ in1_src->sin_addr.s_addr));
1365 bit2 = fls (ntohl (in2_dst->sin_addr.s_addr
1366 ^ in2_src->sin_addr.s_addr));
1367 }
1368 else if (a1->dest_addr->ai_family == PF_INET6)
1369 {
1370 assert (a1->source_addr.ss_family == PF_INET6);
1371 assert (a2->source_addr.ss_family == PF_INET6);
1372
1373 struct sockaddr_in6 *in1_dst;
1374 struct sockaddr_in6 *in1_src;
1375 struct sockaddr_in6 *in2_dst;
1376 struct sockaddr_in6 *in2_src;
1377
1378 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1379 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1380 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1381 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1382
1383 int i;
1384 for (i = 0; i < 4; ++i)
1385 if (in1_dst->sin6_addr.s6_addr32[i]
1386 != in1_src->sin6_addr.s6_addr32[i]
1387 || (in2_dst->sin6_addr.s6_addr32[i]
1388 != in2_src->sin6_addr.s6_addr32[i]))
1389 break;
1390
1391 if (i < 4)
1392 {
1393 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1394 ^ in1_src->sin6_addr.s6_addr32[i]));
1395 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1396 ^ in2_src->sin6_addr.s6_addr32[i]));
1397 }
1398 }
1399
1400 if (bit1 > bit2)
1401 return -1;
1402 if (bit1 < bit2)
1403 return 1;
1404 }
1405
1406
1407 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1408 compare with the value indicating the order in which the entries
1409 have been received from the services. NB: no two entries can have
1410 the same order so the test will never return zero. */
1411 return a1->service_order < a2->service_order ? -1 : 1;
1412 }
1413
1414
1415 static int
1416 in6aicmp (const void *p1, const void *p2)
1417 {
1418 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1419 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1420
1421 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1422 }
1423
1424
1425 /* Name of the config file for RFC 3484 sorting (for now). */
1426 #define GAICONF_FNAME "/etc/gai.conf"
1427
1428
1429 /* Nozero if we are supposed to reload the config file automatically
1430 whenever it changed. */
1431 static int gaiconf_reload_flag;
1432
1433 /* Last modification time. */
1434 static struct timespec gaiconf_mtime;
1435
1436
1437 libc_freeres_fn(fini)
1438 {
1439 if (labels != default_labels)
1440 {
1441 const struct prefixentry *old = labels;
1442 labels = default_labels;
1443 free ((void *) old);
1444 }
1445
1446 if (precedence != default_precedence)
1447 {
1448 const struct prefixentry *old = precedence;
1449 precedence = default_precedence;
1450 free ((void *) old);
1451 }
1452 }
1453
1454
1455 struct prefixlist
1456 {
1457 struct prefixentry entry;
1458 struct prefixlist *next;
1459 };
1460
1461
1462 static void
1463 free_prefixlist (struct prefixlist *list)
1464 {
1465 while (list != NULL)
1466 {
1467 struct prefixlist *oldp = list;
1468 list = list->next;
1469 free (oldp);
1470 }
1471 }
1472
1473
1474 static int
1475 prefixcmp (const void *p1, const void *p2)
1476 {
1477 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1478 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1479
1480 if (e1->bits < e2->bits)
1481 return 1;
1482 if (e1->bits == e2->bits)
1483 return 0;
1484 return -1;
1485 }
1486
1487
1488 static void
1489 gaiconf_init (void)
1490 {
1491 struct prefixlist *labellist = NULL;
1492 size_t nlabellist = 0;
1493 bool labellist_nullbits = false;
1494 struct prefixlist *precedencelist = NULL;
1495 size_t nprecedencelist = 0;
1496 bool precedencelist_nullbits = false;
1497
1498 FILE *fp = fopen (GAICONF_FNAME, "rc");
1499 if (fp != NULL)
1500 {
1501 struct stat64 st;
1502 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
1503 {
1504 fclose (fp);
1505 goto no_file;
1506 }
1507
1508 char *line = NULL;
1509 size_t linelen = 0;
1510
1511 __fsetlocking (fp, FSETLOCKING_BYCALLER);
1512
1513 while (!feof_unlocked (fp))
1514 {
1515 ssize_t n = __getline (&line, &linelen, fp);
1516 if (n <= 0)
1517 break;
1518
1519 /* Handle comments. No escaping possible so this is easy. */
1520 char *cp = strchr (line, '#');
1521 if (cp != NULL)
1522 *cp = '\0';
1523
1524 cp = line;
1525 while (isspace (*cp))
1526 ++cp;
1527
1528 char *cmd = cp;
1529 while (*cp != '\0' && !isspace (*cp))
1530 ++cp;
1531 size_t cmdlen = cp - cmd;
1532
1533 if (*cp != '\0')
1534 *cp++ = '\0';
1535 while (isspace (*cp))
1536 ++cp;
1537
1538 char *val1 = cp;
1539 while (*cp != '\0' && !isspace (*cp))
1540 ++cp;
1541 size_t val1len = cp - cmd;
1542
1543 /* We always need at least two values. */
1544 if (val1len == 0)
1545 continue;
1546
1547 if (*cp != '\0')
1548 *cp++ = '\0';
1549 while (isspace (*cp))
1550 ++cp;
1551
1552 char *val2 = cp;
1553 while (*cp != '\0' && !isspace (*cp))
1554 ++cp;
1555
1556 /* Ignore the rest of the line. */
1557 *cp = '\0';
1558
1559 struct prefixlist **listp;
1560 size_t *lenp;
1561 bool *nullbitsp;
1562 switch (cmdlen)
1563 {
1564 case 5:
1565 if (strcmp (cmd, "label") == 0)
1566 {
1567 struct in6_addr prefix;
1568 unsigned long int bits;
1569 unsigned long int val;
1570 char *endp;
1571
1572 listp = &labellist;
1573 lenp = &nlabellist;
1574 nullbitsp = &labellist_nullbits;
1575
1576 new_elem:
1577 bits = 128;
1578 __set_errno (0);
1579 cp = strchr (val1, '/');
1580 if (cp != NULL)
1581 *cp++ = '\0';
1582 if (inet_pton (AF_INET6, val1, &prefix)
1583 && (cp == NULL
1584 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1585 || errno != ERANGE)
1586 && *endp == '\0'
1587 && bits <= INT_MAX
1588 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1589 || errno != ERANGE)
1590 && *endp == '\0'
1591 && val <= INT_MAX)
1592 {
1593 struct prefixlist *newp = malloc (sizeof (*newp));
1594 if (newp == NULL)
1595 {
1596 free (line);
1597 fclose (fp);
1598 goto no_file;
1599 }
1600
1601 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
1602 newp->entry.bits = bits;
1603 newp->entry.val = val;
1604 newp->next = *listp;
1605 *listp = newp;
1606 ++*lenp;
1607 *nullbitsp |= bits == 0;
1608 }
1609 }
1610 break;
1611
1612 case 6:
1613 if (strcmp (cmd, "reload") == 0)
1614 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
1615 break;
1616
1617 case 10:
1618 if (strcmp (cmd, "precedence") == 0)
1619 {
1620 listp = &precedencelist;
1621 lenp = &nprecedencelist;
1622 nullbitsp = &precedencelist_nullbits;
1623 goto new_elem;
1624 }
1625 break;
1626 }
1627 }
1628
1629 free (line);
1630
1631 fclose (fp);
1632
1633 /* Create the array for the labels. */
1634 struct prefixentry *new_labels;
1635 if (nlabellist > 0)
1636 {
1637 if (!labellist_nullbits)
1638 ++nlabellist;
1639 new_labels = malloc (nlabellist * sizeof (*new_labels));
1640 if (new_labels == NULL)
1641 goto no_file;
1642
1643 int i = nlabellist;
1644 if (!labellist_nullbits)
1645 {
1646 --i;
1647 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
1648 new_labels[i].bits = 0;
1649 new_labels[i].val = 1;
1650 }
1651
1652 struct prefixlist *l = labellist;
1653 while (i-- > 0)
1654 {
1655 new_labels[i] = l->entry;
1656 l = l->next;
1657 }
1658 free_prefixlist (labellist);
1659
1660 /* Sort the entries so that the most specific ones are at
1661 the beginning. */
1662 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
1663 }
1664 else
1665 new_labels = (struct prefixentry *) default_labels;
1666
1667 struct prefixentry *new_precedence;
1668 if (nprecedencelist > 0)
1669 {
1670 if (!precedencelist_nullbits)
1671 ++nprecedencelist;
1672 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
1673 if (new_precedence == NULL)
1674 {
1675 if (new_labels != default_labels)
1676 free (new_labels);
1677 goto no_file;
1678 }
1679
1680 int i = nprecedencelist;
1681 if (!precedencelist_nullbits)
1682 {
1683 --i;
1684 memset (&new_precedence[i].prefix, '\0',
1685 sizeof (struct in6_addr));
1686 new_precedence[i].bits = 0;
1687 new_precedence[i].val = 40;
1688 }
1689
1690 struct prefixlist *l = precedencelist;
1691 while (i-- > 0)
1692 {
1693 new_precedence[i] = l->entry;
1694 l = l->next;
1695 }
1696 free_prefixlist (precedencelist);
1697
1698 /* Sort the entries so that the most specific ones are at
1699 the beginning. */
1700 qsort (new_precedence, nprecedencelist, sizeof (*new_labels),
1701 prefixcmp);
1702 }
1703 else
1704 new_precedence = (struct prefixentry *) default_precedence;
1705
1706 /* Now we are ready to replace the values. */
1707 const struct prefixentry *old = labels;
1708 labels = new_labels;
1709 if (old != default_labels)
1710 free ((void *) old);
1711
1712 old = precedence;
1713 precedence = new_precedence;
1714 if (old != default_precedence)
1715 free ((void *) old);
1716
1717 gaiconf_mtime = st.st_mtim;
1718 }
1719 else
1720 {
1721 no_file:
1722 free_prefixlist (labellist);
1723 free_prefixlist (precedencelist);
1724
1725 /* If we previously read the file but it is gone now, free the
1726 old data and use the builtin one. Leave the reload flag
1727 alone. */
1728 fini ();
1729 }
1730 }
1731
1732
1733 static void
1734 gaiconf_reload (void)
1735 {
1736 struct stat64 st;
1737 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
1738 || memcmp (&st.st_mtim, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
1739 gaiconf_init ();
1740 }
1741
1742
1743 #if HAVE_NETLINK_ROUTE
1744 # if __ASSUME_NETLINK_SUPPORT == 0
1745 /* Defined in ifaddrs.c. */
1746 extern int __no_netlink_support attribute_hidden;
1747 # else
1748 # define __no_netlink_support 0
1749 # endif
1750 #endif
1751
1752
1753 int
1754 getaddrinfo (const char *name, const char *service,
1755 const struct addrinfo *hints, struct addrinfo **pai)
1756 {
1757 int i = 0, last_i = 0;
1758 int nresults = 0;
1759 struct addrinfo *p = NULL;
1760 struct gaih_service gaih_service, *pservice;
1761 struct addrinfo local_hints;
1762
1763 if (name != NULL && name[0] == '*' && name[1] == 0)
1764 name = NULL;
1765
1766 if (service != NULL && service[0] == '*' && service[1] == 0)
1767 service = NULL;
1768
1769 if (name == NULL && service == NULL)
1770 return EAI_NONAME;
1771
1772 if (hints == NULL)
1773 hints = &default_hints;
1774
1775 if (hints->ai_flags
1776 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
1777 #ifdef HAVE_LIBIDN
1778 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
1779 |AI_IDN_USE_STD3_ASCII_RULES
1780 #endif
1781 |AI_NUMERICSERV|AI_ALL))
1782 return EAI_BADFLAGS;
1783
1784 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
1785 return EAI_BADFLAGS;
1786
1787 struct in6addrinfo *in6ai = NULL;
1788 size_t in6ailen = 0;
1789 bool seen_ipv4 = false;
1790 bool seen_ipv6 = false;
1791 #ifdef HAVE_NETLINK_ROUTE
1792 int sockfd = -1;
1793 pid_t nl_pid;
1794 #endif
1795 /* We might need information about what kind of interfaces are available.
1796 But even if AI_ADDRCONFIG is not used, if the user requested IPv6
1797 addresses we have to know whether an address is deprecated or
1798 temporary. */
1799 if ((hints->ai_flags & AI_ADDRCONFIG) || hints->ai_family == PF_UNSPEC
1800 || hints->ai_family == PF_INET6)
1801 {
1802 /* Determine whether we have IPv4 or IPv6 interfaces or both. We
1803 cannot cache the results since new interfaces could be added at
1804 any time. */
1805 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
1806 #ifdef HAVE_NETLINK_ROUTE
1807 if (! __no_netlink_support)
1808 {
1809 sockfd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1810
1811 struct sockaddr_nl nladdr;
1812 memset (&nladdr, '\0', sizeof (nladdr));
1813 nladdr.nl_family = AF_NETLINK;
1814
1815 socklen_t addr_len = sizeof (nladdr);
1816
1817 if (sockfd >= 0
1818 && __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) == 0
1819 && __getsockname (sockfd, (struct sockaddr *) &nladdr,
1820 &addr_len) == 0
1821 && make_request (sockfd, nladdr.nl_pid, &seen_ipv4, &seen_ipv6,
1822 in6ai, in6ailen) == 0)
1823 {
1824 /* It worked. */
1825 nl_pid = nladdr.nl_pid;
1826 goto got_netlink_socket;
1827 }
1828
1829 if (sockfd >= 0)
1830 close_not_cancel_no_status (sockfd);
1831
1832 #if __ASSUME_NETLINK_SUPPORT == 0
1833 /* Remember that there is no netlink support. */
1834 if (errno != EMFILE && errno != ENFILE)
1835 __no_netlink_support = 1;
1836 #else
1837 else
1838 {
1839 if (errno != EMFILE && errno != ENFILE)
1840 sockfd = -2;
1841
1842 /* We cannot determine what interfaces are available. Be
1843 pessimistic. */
1844 seen_ipv4 = true;
1845 seen_ipv6 = true;
1846 return;
1847 }
1848 #endif
1849 }
1850 #endif
1851 }
1852
1853 #ifdef HAVE_NETLINK_ROUTE
1854 got_netlink_socket:
1855 #endif
1856 if (hints->ai_flags & AI_ADDRCONFIG)
1857 {
1858 /* Now make a decision on what we return, if anything. */
1859 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
1860 {
1861 /* If we haven't seen both IPv4 and IPv6 interfaces we can
1862 narrow down the search. */
1863 if (! seen_ipv4 || ! seen_ipv6)
1864 {
1865 local_hints = *hints;
1866 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
1867 hints = &local_hints;
1868 }
1869 }
1870 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
1871 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
1872 {
1873 /* We cannot possibly return a valid answer. */
1874 free (in6ai);
1875 return EAI_NONAME;
1876 }
1877 }
1878
1879 if (service && service[0])
1880 {
1881 char *c;
1882 gaih_service.name = service;
1883 gaih_service.num = strtoul (gaih_service.name, &c, 10);
1884 if (*c != '\0')
1885 {
1886 if (hints->ai_flags & AI_NUMERICSERV)
1887 {
1888 free (in6ai);
1889 return EAI_NONAME;
1890 }
1891
1892 gaih_service.num = -1;
1893 }
1894
1895 pservice = &gaih_service;
1896 }
1897 else
1898 pservice = NULL;
1899
1900 struct addrinfo **end;
1901 if (pai)
1902 end = &p;
1903 else
1904 end = NULL;
1905
1906 unsigned int naddrs = 0;
1907 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
1908 || hints->ai_family == AF_INET6)
1909 {
1910 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
1911 if (last_i != 0)
1912 {
1913 freeaddrinfo (p);
1914 free (in6ai);
1915
1916 return -(last_i & GAIH_EAI);
1917 }
1918 if (end)
1919 while (*end)
1920 {
1921 end = &((*end)->ai_next);
1922 ++nresults;
1923 }
1924 }
1925 else
1926 {
1927 free (in6ai);
1928 return EAI_FAMILY;
1929 }
1930
1931 if (naddrs > 1)
1932 {
1933 /* Read the config file. */
1934 __libc_once_define (static, once);
1935 __typeof (once) old_once = once;
1936 __libc_once (once, gaiconf_init);
1937 if (old_once && gaiconf_reload_flag)
1938 gaiconf_reload ();
1939
1940 /* Sort results according to RFC 3484. */
1941 struct sort_result results[nresults];
1942 struct addrinfo *q;
1943 struct addrinfo *last = NULL;
1944 char *canonname = NULL;
1945
1946 /* If we have information about deprecated and temporary address
1947 sort the array now. */
1948 if (in6ai != NULL)
1949 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
1950
1951 int fd = -1;
1952 int af = AF_UNSPEC;
1953
1954 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
1955 {
1956 results[i].dest_addr = q;
1957 results[i].got_source_addr = false;
1958 results[i].service_order = i;
1959
1960 /* If we just looked up the address for a different
1961 protocol, reuse the result. */
1962 if (last != NULL && last->ai_addrlen == q->ai_addrlen
1963 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
1964 {
1965 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
1966 results[i - 1].source_addr_len);
1967 results[i].source_addr_len = results[i - 1].source_addr_len;
1968 results[i].got_source_addr = results[i - 1].got_source_addr;
1969 results[i].source_addr_flags = results[i - 1].source_addr_flags;
1970 }
1971 else
1972 {
1973 results[i].source_addr_flags = 0;
1974
1975 /* We overwrite the type with SOCK_DGRAM since we do not
1976 want connect() to connect to the other side. If we
1977 cannot determine the source address remember this
1978 fact. */
1979 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
1980 {
1981 if (fd != -1)
1982 close_retry:
1983 close_not_cancel_no_status (fd);
1984 af = q->ai_family;
1985 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
1986 }
1987 else
1988 {
1989 /* Reset the connection. */
1990 struct sockaddr sa = { .sa_family = AF_UNSPEC };
1991 __connect (fd, &sa, sizeof (sa));
1992 }
1993
1994 socklen_t sl = sizeof (results[i].source_addr);
1995 if (fd != -1
1996 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
1997 && __getsockname (fd,
1998 (struct sockaddr *) &results[i].source_addr,
1999 &sl) == 0)
2000 {
2001 results[i].source_addr_len = sl;
2002 results[i].got_source_addr = true;
2003
2004 if (q->ai_family == AF_INET6 && in6ai != NULL)
2005 {
2006 /* See whether the source address is on the list of
2007 deprecated or temporary addresses. */
2008 struct in6addrinfo tmp;
2009 struct sockaddr_in6 *sin6p
2010 = (struct sockaddr_in6 *) &results[i].source_addr;
2011 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2012
2013 struct in6addrinfo *found
2014 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2015 in6aicmp);
2016 if (found != NULL)
2017 results[i].source_addr_flags = found->flags;
2018 }
2019 else if (q->ai_family == AF_INET && af == AF_INET6)
2020 {
2021 /* We have to convert the address. The socket is
2022 IPv6 and the request is for IPv4. */
2023 struct sockaddr_in6 *sin6
2024 = (struct sockaddr_in6 *) &results[i].source_addr;
2025 struct sockaddr_in *sin
2026 = (struct sockaddr_in *) &results[i].source_addr;
2027 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2028 memcpy (&sin->sin_addr,
2029 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2030 results[i].source_addr_len = INADDRSZ;
2031 sin->sin_family = AF_INET;
2032 }
2033 }
2034 else if (errno == EAFNOSUPPORT && af == AF_INET6
2035 && q->ai_family == AF_INET)
2036 /* This could mean IPv6 sockets are IPv6-only. */
2037 goto close_retry;
2038 else
2039 /* Just make sure that if we have to process the same
2040 address again we do not copy any memory. */
2041 results[i].source_addr_len = 0;
2042 }
2043
2044 /* Remember the canonical name. */
2045 if (q->ai_canonname != NULL)
2046 {
2047 assert (canonname == NULL);
2048 canonname = q->ai_canonname;
2049 q->ai_canonname = NULL;
2050 }
2051 }
2052
2053 if (fd != -1)
2054 close_not_cancel_no_status (fd);
2055
2056 /* We got all the source addresses we can get, now sort using
2057 the information. */
2058 qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
2059
2060 /* Queue the results up as they come out of sorting. */
2061 q = p = results[0].dest_addr;
2062 for (i = 1; i < nresults; ++i)
2063 q = q->ai_next = results[i].dest_addr;
2064 q->ai_next = NULL;
2065
2066 /* Fill in the canonical name into the new first entry. */
2067 p->ai_canonname = canonname;
2068 }
2069
2070 free (in6ai);
2071
2072 if (p)
2073 {
2074 *pai = p;
2075 return 0;
2076 }
2077
2078 if (pai == NULL && last_i == 0)
2079 return 0;
2080
2081 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2082 }
2083 libc_hidden_def (getaddrinfo)
2084
2085 static_link_warning (getaddrinfo)
2086
2087 void
2088 freeaddrinfo (struct addrinfo *ai)
2089 {
2090 struct addrinfo *p;
2091
2092 while (ai != NULL)
2093 {
2094 p = ai;
2095 ai = ai->ai_next;
2096 free (p->ai_canonname);
2097 free (p);
2098 }
2099 }
2100 libc_hidden_def (freeaddrinfo)