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