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