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