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