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