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