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