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