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