Libinfo-517.tar.gz
[apple/libinfo.git] / lookup.subproj / si_getaddrinfo.c
1 /*
2 * Copyright (c) 2008-2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <netdb.h>
25 #include <sys/types.h>
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdint.h>
29 #include <sys/socket.h>
30 #include <net/if.h>
31 #include <netinet/in.h>
32 #include <network/sa_compare.h>
33 #include <network/nat64.h>
34 #include <network/path_evaluation.h>
35 #include <arpa/inet.h>
36 #include <ifaddrs.h>
37 #include <net/if.h>
38 #include <string.h>
39 #include <sys/param.h>
40 #include <notify.h>
41 #include <notify_keys.h>
42 #include <pthread.h>
43 #include <TargetConditionals.h>
44 #include "netdb_async.h"
45 #include "si_module.h"
46
47 #define SOCK_UNSPEC 0
48 #define IPPROTO_UNSPEC 0
49
50 #define IPV6_ADDR_LEN 16
51 #define IPV4_ADDR_LEN 4
52
53 #define WANT_NOTHING 0
54 #define WANT_A4_ONLY 1
55 #define WANT_A6_ONLY 2
56 #define WANT_A6_PLUS_MAPPED_A4 3
57 #define WANT_A6_OR_MAPPED_A4_IF_NO_A6 4
58
59 #define V6TO4_PREFIX_16 0x2002
60
61 static int net_config_token = -1;
62 static uint32_t net_v4_count = 0;
63 static uint32_t net_v6_count = 0; // includes 6to4 addresses
64 static pthread_mutex_t net_config_mutex = PTHREAD_MUTEX_INITIALIZER;
65
66 // Libc SPI
67 int _inet_aton_check(const char *cp, struct in_addr *addr, int strict);
68
69 typedef struct {
70 struct hostent host;
71 int alias_count;
72 int addr_count;
73 uint64_t ttl;
74 } build_hostent_t;
75
76 __private_extern__ int
77 si_inet_config(uint32_t *inet4, uint32_t *inet6)
78 {
79 int status, checkit;
80 struct ifaddrs *ifa, *ifap;
81
82 pthread_mutex_lock(&net_config_mutex);
83
84 checkit = 1;
85
86 if (net_config_token < 0)
87 {
88 status = notify_register_check(kNotifySCNetworkChange, &net_config_token);
89 if (status != 0) net_config_token = -1;
90 }
91
92 if (net_config_token >= 0)
93 {
94 status = notify_check(net_config_token, &checkit);
95 if (status != 0) checkit = 1;
96 }
97
98 status = 0;
99
100 if (checkit != 0)
101 {
102 if (getifaddrs(&ifa) < 0)
103 {
104 status = -1;
105 }
106 else
107 {
108 net_v4_count = 0;
109 net_v6_count = 0;
110
111 for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next)
112 {
113 if (ifap->ifa_addr == NULL) continue;
114 if ((ifap->ifa_flags & IFF_UP) == 0) continue;
115
116 if (ifap->ifa_addr->sa_family == AF_INET)
117 {
118 net_v4_count++;
119 }
120 else if (ifap->ifa_addr->sa_family == AF_INET6)
121 {
122 net_v6_count++;
123 }
124 }
125 freeifaddrs(ifa);
126 }
127
128 }
129
130 if (inet4 != NULL) *inet4 = net_v4_count;
131 if (inet6 != NULL) *inet6 = net_v6_count;
132
133 pthread_mutex_unlock(&net_config_mutex);
134
135 return status;
136 }
137
138 void
139 freeaddrinfo(struct addrinfo *a)
140 {
141 struct addrinfo *next;
142
143 while (a != NULL)
144 {
145 next = a->ai_next;
146 if (a->ai_addr != NULL) free(a->ai_addr);
147 if (a->ai_canonname != NULL) free(a->ai_canonname);
148 free(a);
149 a = next;
150 }
151 }
152
153 const char *
154 gai_strerror(int32_t err)
155 {
156 switch (err)
157 {
158 case EAI_ADDRFAMILY: return "Address family for nodename not supported";
159 case EAI_AGAIN: return "Temporary failure in name resolution";
160 case EAI_BADFLAGS: return "Invalid value for ai_flags";
161 case EAI_FAIL: return "Non-recoverable failure in name resolution";
162 case EAI_FAMILY: return "ai_family not supported";
163 case EAI_MEMORY: return "Memory allocation failure";
164 case EAI_NODATA: return "No address associated with nodename";
165 case EAI_NONAME: return "nodename nor servname provided, or not known";
166 case EAI_SERVICE: return "servname not supported for ai_socktype";
167 case EAI_SOCKTYPE: return "ai_socktype not supported";
168 case EAI_SYSTEM: return "System error";
169 case EAI_BADHINTS: return "Bad hints";
170 case EAI_PROTOCOL: return "ai_protocol not supported";
171 case EAI_OVERFLOW: return "argument buffer overflow";
172 }
173
174 return "Unknown error";
175 }
176
177 /*
178 * getnameinfo
179 *
180 * We handle some "trival" cases locally. If the caller passes
181 * NI_NUMERICHOST (only), then this call turns into a getservbyport
182 * to get the service name + inet_pton() to create a host string.
183 * If the caller passes NI_NUMERICSERV (only), then we zero out the port
184 * number, complete the getnameinfo, and use printf() to create a service
185 * string. If the caller specifies both NI_NUMERICHOST and NI_NUMERICSERV,
186 * we inet_ntop() and printf() and return the results.
187 */
188 si_item_t *
189 si_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, const char *interface, uint32_t *err)
190 {
191 si_item_t *out = NULL;
192 const struct sockaddr *lookup_sa;
193 struct sockaddr_in s4;
194 struct in_addr a4;
195 struct in6_addr a6;
196 const uint64_t unused = 0;
197 void *addr = NULL;
198 char *host = NULL;
199 char *serv = NULL;
200 uint32_t ifnum = 0;
201 uint16_t port = 0;
202
203 int do_host_lookup = ((flags & NI_NUMERICHOST) == 0);
204 int do_serv_lookup = ((flags & NI_NUMERICSERV) == 0);
205
206 /* check input */
207 if ((si == NULL) || (sa == NULL))
208 {
209 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
210 return NULL;
211 }
212
213 if (err != NULL) *err = SI_STATUS_NO_ERROR;
214
215 lookup_sa = sa;
216
217 if (sa->sa_family == AF_INET)
218 {
219 struct sockaddr_in *s4 = (struct sockaddr_in *)sa;
220 memcpy(&a4, &s4->sin_addr, sizeof(a4));
221 port = s4->sin_port;
222 addr = &a4;
223 }
224 else if (sa->sa_family == AF_INET6)
225 {
226 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)sa;
227 memcpy(&a6, &s6->sin6_addr, sizeof(a6));
228 port = s6->sin6_port;
229
230 /* Look for scope id in IPv6 Link Local, Multicast Node Local, and Multicast Link Local */
231 if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&s6->sin6_addr))
232 {
233 ifnum = ntohs(a6.__u6_addr.__u6_addr16[1]);
234 if (ifnum == 0)
235 {
236 ifnum = s6->sin6_scope_id;
237 a6.__u6_addr.__u6_addr16[1] = htons(ifnum);
238 }
239
240 if ((ifnum != s6->sin6_scope_id) && (s6->sin6_scope_id != 0))
241 {
242 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
243 return NULL;
244 }
245 }
246
247 /* v4 mapped and compat addresses are converted to plain v4 */
248 if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr))
249 {
250 memcpy(&a4, &s6->sin6_addr.s6_addr[12], sizeof(a4));
251 addr = &a4;
252 memset(&s4, 0, sizeof(s4));
253 s4.sin_len = sizeof(s4);
254 s4.sin_family = AF_INET;
255 s4.sin_port = port;
256 memcpy(&s4.sin_addr, &a4, sizeof(s4.sin_addr));
257 lookup_sa = (const struct sockaddr *)&s4;
258 }
259 else
260 {
261 addr = &a6;
262 }
263 }
264 else
265 {
266 if (err != NULL) *err = SI_STATUS_EAI_FAMILY;
267 return NULL;
268 }
269
270 if (do_host_lookup == 1)
271 {
272 si_item_t *item = si_host_byaddr(si, addr, lookup_sa->sa_family, interface, NULL);
273 if (item != NULL)
274 {
275 struct hostent *h;
276 h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
277 if (h->h_name == NULL)
278 {
279 si_item_release(item);
280 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
281 return NULL;
282 }
283
284 host = strdup(h->h_name);
285 si_item_release(item);
286 if (host == NULL)
287 {
288 if (err != NULL) *err = SI_STATUS_EAI_MEMORY;
289 return NULL;
290 }
291 }
292 }
293
294 if ((do_serv_lookup == 1) && (port != 0))
295 {
296 si_item_t *item = si_service_byport(si, port, NULL);
297 if (item != NULL)
298 {
299 struct servent *s;
300 s = (struct servent *)((uintptr_t)item + sizeof(si_item_t));
301 if (s->s_name == NULL)
302 {
303 si_item_release(item);
304 free(host);
305 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
306 return NULL;
307 }
308
309 serv = strdup(s->s_name);
310 si_item_release(item);
311 if (serv == NULL)
312 {
313 free(host);
314 if (err != NULL) *err = SI_STATUS_EAI_MEMORY;
315 return NULL;
316 }
317 }
318 }
319
320 /*
321 * Return numeric host name for NI_NUMERICHOST or if lookup failed, but not
322 * if NI_NAMEREQD is specified (so that we later fail with EAI_NONAME).
323 */
324 if ((host == NULL) && ((flags & NI_NAMEREQD) == 0))
325 {
326 char tmp[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1];
327 tmp[0] = '\0';
328 if (sa->sa_family == AF_INET)
329 {
330 char buf[INET_ADDRSTRLEN];
331 if (inet_ntop(AF_INET, &a4, buf, sizeof(buf)) != 0)
332 {
333 host = strdup(buf);
334 }
335 }
336 else if (sa->sa_family == AF_INET6)
337 {
338 char buf[INET6_ADDRSTRLEN];
339
340 /* zero the embedded scope ID */
341 if (ifnum != 0)
342 {
343 a6.__u6_addr.__u6_addr16[1] = 0;
344 }
345
346 if (inet_ntop(AF_INET6, &a6, buf, sizeof(buf)) != 0)
347 {
348 if (ifnum != 0)
349 {
350 char ifname[IF_NAMESIZE];
351 if (if_indextoname(ifnum, ifname) != NULL)
352 {
353 asprintf(&host, "%s%%%s", buf, ifname);
354 }
355 else
356 {
357 /* ENXIO */
358 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
359 free(serv);
360 return NULL;
361 }
362 }
363 else
364 {
365 host = strdup(buf);
366 }
367 }
368 }
369 }
370
371 /* Return numeric service name for NI_NUMERICSERV or if lookup failed. */
372 if (serv == NULL)
373 {
374 asprintf(&serv, "%hu", ntohs(port));
375 }
376
377 if ((host == NULL) || (serv == NULL))
378 {
379 if (err != NULL)
380 {
381 if ((flags & NI_NAMEREQD) != 0)
382 {
383 *err = SI_STATUS_EAI_NONAME;
384 }
385 else
386 {
387 *err = SI_STATUS_EAI_MEMORY;
388 }
389 }
390 }
391 else
392 {
393 out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_NAMEINFO, 1, unused, unused, host, serv);
394 }
395
396 free(host);
397 free(serv);
398 return out;
399 }
400
401 static int
402 _gai_numericserv(const char *serv, uint16_t *port)
403 {
404 int numeric;
405 char *endptr;
406 long num;
407
408 numeric = 0;
409
410 if (serv == NULL)
411 {
412 if (port) *port = 0;
413 numeric = 1;
414 }
415 else
416 {
417 num = strtol(serv, &endptr, 10);
418 if ((serv[0] != '\0') && (*endptr == '\0') && (num >= 0) && (num <= UINT16_MAX))
419 {
420 numeric = 1;
421 if (port != NULL) *port = (uint16_t)num;
422 }
423 }
424
425 return numeric;
426 }
427
428 int
429 _gai_serv_to_port(const char *serv, uint32_t proto, uint16_t *port)
430 {
431 si_item_t *item;
432 struct servent *s;
433 const char *protoname = NULL;
434
435 if (_gai_numericserv(serv, port)) return 0;
436
437 if (proto == IPPROTO_UDP) protoname = "udp";
438 if (proto == IPPROTO_TCP) protoname = "tcp";
439
440 item = si_service_byname(si_search(), serv, protoname);
441 if (item == NULL) return -1;
442
443 s = (struct servent *)((uintptr_t)item + sizeof(si_item_t));
444 if (port) *port = ntohs(s->s_port);
445 si_item_release(item);
446
447 return 0;
448 }
449
450 si_item_t *
451 si_addrinfo_v4(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr *addr, uint16_t iface, const char *cname)
452 {
453 socket_data_t sockdata;
454 struct sockaddr_in *sa;
455 int32_t len, v32;
456 uint64_t unused;
457
458 unused = 0;
459 len = sizeof(struct sockaddr_in);
460 memset(&sockdata, 0, sizeof(socket_data_t));
461 sa = (struct sockaddr_in *)&sockdata;
462
463 sa->sin_len = len;
464 sa->sin_family = AF_INET;
465 sa->sin_port = htons(port);
466 memcpy(&sa->sin_addr, addr, sizeof(sa->sin_addr));
467
468 /* Kludge: Jam the interface number into sin_zero (4 bytes). */
469 v32 = iface;
470 memmove(sa->sin_zero, &v32, sizeof(uint32_t));
471
472 return (si_item_t *)LI_ils_create("L448844444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET, sock, proto, len, sockdata, cname);
473 }
474
475 si_item_t *
476 si_addrinfo_v4_mapped(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr *addr, uint16_t iface, const char *cname)
477 {
478 socket_data_t sockdata;
479 struct sockaddr_in6 *sa;
480 int32_t len;
481 uint64_t unused;
482
483 unused = 0;
484 len = sizeof(struct sockaddr_in6);
485 memset(&sockdata, 0, sizeof(socket_data_t));
486 sa = (struct sockaddr_in6 *)&sockdata;
487
488 sa->sin6_len = len;
489 sa->sin6_family = AF_INET6;
490 sa->sin6_port = htons(port);
491 memset(&(sa->sin6_addr.__u6_addr.__u6_addr8[10]), 0xff, 2);
492 memcpy(&(sa->sin6_addr.__u6_addr.__u6_addr8[12]), addr, sizeof(struct in_addr));
493
494 /* sin6_scope_id is in host byte order */
495 sa->sin6_scope_id = iface;
496
497 return (si_item_t *)LI_ils_create("L448844444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET6, sock, proto, len, sockdata, cname);
498 }
499
500
501 si_item_t *
502 si_addrinfo_v6(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr *addr, uint16_t iface, const char *cname)
503 {
504 socket_data_t sockdata;
505 struct sockaddr_in6 *sa;
506 int32_t len;
507 uint64_t unused;
508
509 unused = 0;
510 len = sizeof(struct sockaddr_in6);
511 memset(&sockdata, 0, sizeof(socket_data_t));
512 sa = (struct sockaddr_in6 *)&sockdata;
513
514 sa->sin6_len = len;
515 sa->sin6_family = AF_INET6;
516 sa->sin6_port = htons(port);
517 memcpy(&sa->sin6_addr, addr, sizeof(sa->sin6_addr));
518
519 /* sin6_scope_id is in host byte order */
520 sa->sin6_scope_id = iface;
521
522 if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
523 {
524 /* check for embedded scopeid */
525 uint16_t esid = ntohs(sa->sin6_addr.__u6_addr.__u6_addr16[1]);
526 if (esid != 0)
527 {
528 sa->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
529 if (iface == 0) sa->sin6_scope_id = esid;
530 }
531 }
532
533 return (si_item_t *)LI_ils_create("L448844444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET6, sock, proto, len, sockdata, cname);
534 }
535
536 si_list_t *
537 si_addrinfo_list(si_mod_t *si, uint32_t flags, int socktype, int proto, struct in_addr *a4, struct in6_addr *a6, int port, int scopeid, const char *cname4, const char *cname6)
538 {
539 int do_map = 0;
540 si_item_t *item = NULL;
541 si_list_t *out4 = NULL, *out6 = NULL;
542
543 if ((flags & AI_V4MAPPED) && ((flags & AI_ALL) || (a6 == NULL))) do_map = 1;
544
545 if (a6 != NULL)
546 {
547 if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP))
548 {
549 item = si_addrinfo_v6(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a6, scopeid, cname6);
550 out6 = si_list_add(out6, item);
551 si_item_release(item);
552 }
553
554 if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP))
555 {
556 item = si_addrinfo_v6(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a6, scopeid, cname6);
557 out6 = si_list_add(out6, item);
558 si_item_release(item);
559 }
560
561 if (proto == IPPROTO_ICMPV6)
562 {
563 item = si_addrinfo_v6(si, 0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, scopeid, cname6);
564 out6 = si_list_add(out6, item);
565 si_item_release(item);
566 }
567 }
568
569 if (a4 != NULL)
570 {
571 if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP))
572 {
573 if (do_map == 0)
574 {
575 item = si_addrinfo_v4(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, cname4);
576 out4 = si_list_add(out4, item);
577 }
578 else
579 {
580 item = si_addrinfo_v4_mapped(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, cname4);
581 out6 = si_list_add(out6, item);
582 }
583
584 si_item_release(item);
585 }
586
587 if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP))
588 {
589 if (do_map == 0)
590 {
591 item = si_addrinfo_v4(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, cname4);
592 out4 = si_list_add(out4, item);
593 }
594 else
595 {
596 item = si_addrinfo_v4_mapped(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, cname4);
597 out6 = si_list_add(out6, item);
598 }
599
600 si_item_release(item);
601 }
602
603 if (proto == IPPROTO_ICMP)
604 {
605 if (do_map == 0)
606 {
607 item = si_addrinfo_v4(si, 0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, cname4);
608 out4 = si_list_add(out4, item);
609 }
610 else
611 {
612 item = si_addrinfo_v4_mapped(si, 0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, cname4);
613 out6 = si_list_add(out6, item);
614 }
615
616 si_item_release(item);
617 }
618 }
619
620 out6 = si_list_concat(out6, out4);
621 si_list_release(out4);
622
623 return out6;
624 }
625
626 /*
627 * _gai_numerichost
628 * Determines whether the given host name is a numeric IPv4 or IPv6 address,
629 * based on the address family input value. If the input addres family is
630 * unspecified, a more specific value will be provided on output if possible.
631 * Returns 1 if host name is numeric or 0 if not, or -1 on error.
632 */
633 static int
634 _gai_numerichost(const char* nodename, uint32_t *family, int flags, struct in_addr *a4, struct in6_addr *a6, int *scope)
635 {
636 int numerichost, passive;
637
638 numerichost = 0;
639
640 if (nodename == NULL)
641 {
642 /* return loopback or passive addresses */
643 passive = (flags & AI_PASSIVE);
644
645 if (((*family == AF_UNSPEC) || (*family == AF_INET)) || ((*family == AF_INET6) && (flags & AI_V4MAPPED) && (flags & AI_ALL)))
646 {
647 if (passive) a4->s_addr = 0;
648 else a4->s_addr = htonl(INADDR_LOOPBACK);
649 }
650
651 if ((*family == AF_UNSPEC) || (*family == AF_INET6))
652 {
653 memset(a6, 0, sizeof(*a6));
654 if (!passive) a6->__u6_addr.__u6_addr32[3] = htonl(1);
655 }
656
657 numerichost = 1;
658 }
659 else
660 {
661 /*
662 * numeric IPv4 host valid for AF_UNSPEC and AF_INET
663 * also valid for AF_INET6 with AI_V4MAPPED
664 */
665 numerichost = inet_pton(AF_INET, nodename, a4);
666 if (numerichost == 0)
667 {
668 /* inet_pton doesn't allow "a", "a.b", or "a.b.c" forms, so we re-check */
669 numerichost = _inet_aton_check(nodename, a4, 1);
670 }
671
672 if (numerichost == 1)
673 {
674 if (*family == AF_UNSPEC)
675 {
676 *family = AF_INET;
677 }
678 else if (*family == AF_INET6)
679 {
680 if (flags & AI_V4MAPPED)
681 {
682 memset(a6, 0, sizeof(struct in6_addr));
683 memset(&(a6->__u6_addr.__u6_addr8[10]), 0xff, 2);
684 memcpy(&(a6->__u6_addr.__u6_addr8[12]), a4, sizeof(struct in_addr));
685 }
686 else
687 {
688 numerichost = -1;
689 }
690 }
691
692 return numerichost;
693 }
694
695 /* numeric IPv6 host valid for AF_UNSPEC and AF_INET6 */
696 numerichost = inet_pton(AF_INET6, nodename, a6);
697 if (numerichost == 1)
698 {
699 /* check for scope/zone id */
700 char *p = strrchr(nodename, SCOPE_DELIMITER);
701 if (p != NULL)
702 {
703 int i, d;
704 char *x;
705
706 p++;
707 d = 1;
708 for (x = p; (*x != '\0') && (d == 1); x++)
709 {
710 i = *x;
711 d = isdigit(i);
712 }
713
714 if (d == 1) *scope = atoi(p);
715 else *scope = if_nametoindex(p);
716 }
717
718 if (*family == AF_UNSPEC) *family = AF_INET6;
719 else if (*family == AF_INET) numerichost = -1;
720
721 return numerichost;
722 }
723 }
724
725 return numerichost;
726 }
727
728 /* si_addrinfo_list_from_hostent
729 * Returns an addrinfo list from IPv4 and IPv6 hostent entries
730 */
731 si_list_t *
732 si_addrinfo_list_from_hostent(si_mod_t *si, uint32_t flags, uint32_t socktype, uint32_t proto, uint16_t port, uint16_t scope, const struct hostent *h4, const struct hostent *h6)
733 {
734 int i;
735 si_list_t *out = NULL;
736 si_list_t *list;
737
738 if ((h6 != NULL) && (h6->h_addr_list != NULL))
739 {
740 for (i = 0; h6->h_addr_list[i] != NULL; i++)
741 {
742 struct in6_addr a6;
743 memcpy(&a6, h6->h_addr_list[i], h6->h_length);
744 list = si_addrinfo_list(si, flags, socktype, proto, NULL, &a6, port, scope, NULL, h6->h_name);
745 out = si_list_concat(out, list);
746 si_list_release(list);
747 }
748 }
749
750 if ((h4 != NULL) && (h4->h_addr_list != NULL))
751 {
752 for (i = 0; h4->h_addr_list[i] != NULL; i++)
753 {
754 struct in_addr a4;
755 memcpy(&a4, h4->h_addr_list[i], h4->h_length);
756 list = si_addrinfo_list(si, flags, socktype, proto, &a4, NULL, port, 0, h4->h_name, NULL);
757 out = si_list_concat(out, list);
758 si_list_release(list);
759 }
760 }
761
762 return out;
763 }
764
765 int
766 _gai_addr_sort(const void *a, const void *b)
767 {
768 si_item_t **item_a, **item_b;
769 si_addrinfo_t *p, *q;
770 struct sockaddr *sp, *sq;
771
772 item_a = (si_item_t **)a;
773 item_b = (si_item_t **)b;
774
775 p = (si_addrinfo_t *)((uintptr_t)*item_a + sizeof(si_item_t));
776 q = (si_addrinfo_t *)((uintptr_t)*item_b + sizeof(si_item_t));
777
778 sp = (struct sockaddr *)p->ai_addr.x;
779 sq = (struct sockaddr *)q->ai_addr.x;
780
781 /*
782 * sa_dst_compare(A,B) returns -1 if A is less desirable than B,
783 * 0 if they are equally desirable, and 1 if A is more desirable.
784 * qsort() expects the inverse, so we swap sp and sq.
785 */
786 return sa_dst_compare(sq, sp, 0);
787 }
788
789 static si_list_t *
790 _gai_sort_list(si_list_t *in, uint32_t flags)
791 {
792 si_list_t *out;
793 int filter_mapped;
794 uint32_t i;
795 uint32_t v4mapped_count = 0;
796 uint32_t v6_count = 0;
797 si_addrinfo_t *a;
798
799 if (in == NULL) return NULL;
800
801 for (i = 0; i < in->count; i++)
802 {
803 a = (si_addrinfo_t *)((uintptr_t)in->entry[i] + sizeof(si_item_t));
804 if (a->ai_family == AF_INET6)
805 {
806 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)a->ai_addr.x;
807 if (IN6_IS_ADDR_V4MAPPED(&(s6->sin6_addr))) v4mapped_count++;
808 else v6_count++;
809 }
810 }
811
812 filter_mapped = 1;
813 if ((flags & AI_V4MAPPED) && ((v6_count == 0) || (flags & AI_ALL))) filter_mapped = 0;
814
815 out = in;
816
817 if ((filter_mapped == 1) && (v4mapped_count > 0))
818 {
819 i = in->count - v4mapped_count;
820 if (i == 0) return NULL;
821
822 out = (si_list_t *)calloc(1, sizeof(si_list_t));
823 if (out == NULL) return in;
824
825 out->count = i;
826 out->refcount = in->refcount;
827
828 out->entry = (si_item_t **)calloc(out->count, sizeof(si_item_t *));
829 if (out->entry == NULL)
830 {
831 free(out);
832 return in;
833 }
834
835 out->curr = 0;
836
837 for (i = 0; i < in->count; i++)
838 {
839 a = (si_addrinfo_t *)((uintptr_t)in->entry[i] + sizeof(si_item_t));
840 if (a->ai_family == AF_INET6)
841 {
842 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)a->ai_addr.x;
843 if (IN6_IS_ADDR_V4MAPPED(&(s6->sin6_addr)))
844 {
845 si_item_release(in->entry[i]);
846 continue;
847 }
848 }
849
850 out->entry[out->curr++] = in->entry[i];
851 }
852
853 out->curr = 0;
854
855 free(in->entry);
856 free(in);
857 }
858
859 qsort(&out->entry[0], out->count, sizeof(si_item_t *), _gai_addr_sort);
860 return out;
861 }
862
863 /* _gai_simple
864 * Simple lookup via gethostbyname2(3) mechanism.
865 */
866 si_list_t *
867 _gai_simple(si_mod_t *si, const void *nodeptr, const void *servptr, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err)
868 {
869 si_item_t *h4_item = NULL, *h6_item = NULL;
870 struct hostent *h4 = NULL, *h6 = NULL;
871 si_list_t *out = NULL;
872 uint16_t port;
873
874 if ((flags & AI_NUMERICSERV) != 0)
875 {
876 if (servptr == NULL)
877 {
878 if (err) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
879 return NULL;
880 }
881 port = *(uint16_t*)servptr;
882 }
883 else
884 {
885 if (_gai_serv_to_port(servptr, proto, &port) != 0)
886 {
887 if (err) *err = SI_STATUS_EAI_NONAME;
888 return NULL;
889 }
890 }
891
892 if ((flags & AI_NUMERICHOST) != 0)
893 {
894 if (family == AF_INET)
895 {
896 h4_item = si_host_byaddr(si, nodeptr, AF_INET, interface, NULL);
897 }
898 else if (family == AF_INET6)
899 {
900 h6_item = si_host_byaddr(si, nodeptr, AF_INET6, interface, NULL);
901 }
902 }
903 else
904 {
905 if ((family == AF_INET) || (family == AF_UNSPEC))
906 {
907 h4_item = si_host_byname(si, nodeptr, AF_INET, interface, NULL);
908 }
909
910 if ((family == AF_INET6) || (family == AF_UNSPEC))
911 {
912 h6_item = si_host_byname(si, nodeptr, AF_INET6, interface, NULL);
913 }
914 }
915
916 if (h4_item != NULL)
917 {
918 h4 = (struct hostent *)((uintptr_t)h4_item + sizeof(si_item_t));
919 }
920
921 if (h6_item != NULL)
922 {
923 h6 = (struct hostent *)((uintptr_t)h6_item + sizeof(si_item_t));
924 }
925
926 out = si_addrinfo_list_from_hostent(si, flags, socktype, proto, port, 0, h4, h6);
927 si_item_release(h4_item);
928 si_item_release(h6_item);
929
930 return _gai_sort_list(out, flags);
931 }
932
933 si_list_t *
934 si_srv_byname(si_mod_t *si, const char *qname, const char *interface, uint32_t *err)
935 {
936 if (si == NULL) return 0;
937 if (si->vtable->sim_srv_byname == NULL) return 0;
938
939 return si->vtable->sim_srv_byname(si, qname, interface, err);
940 }
941
942 int
943 si_wants_addrinfo(si_mod_t *si)
944 {
945 if (si == NULL) return 0;
946 if (si->vtable->sim_addrinfo == NULL) return 0;
947 if (si->vtable->sim_wants_addrinfo == NULL) return 0;
948
949 return si->vtable->sim_wants_addrinfo(si);
950 }
951
952 static si_list_t *
953 _gai_srv(si_mod_t *si, const char *node, const char *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err)
954 {
955 int i;
956 char *qname;
957 si_srv_t *srv;
958 si_item_t *item;
959
960 si_list_t *list = NULL;
961 si_list_t *result = NULL;
962
963 /* Minimum SRV priority is zero. Start below that. */
964 int lastprio = -1;
965 int currprio;
966
967 if (node == NULL || serv == NULL) return NULL;
968
969 asprintf(&qname, "%s.%s", serv, node);
970 list = si_srv_byname(si, qname, interface, err);
971 free(qname);
972
973 /* Iterate the SRV records starting at lowest priority and attempt to
974 * lookup the target host name. Returns the first successful lookup.
975 * It's an O(n^2) algorithm but data sets are small (less than 100) and
976 * sorting overhead is dwarfed by network I/O for each element.
977 */
978 while (list != NULL && result == NULL)
979 {
980 /* Find the next lowest priority level. */
981 /* Maximum SRV priority is UINT16_MAX. Start above that. */
982 currprio = INT_MAX;
983
984 for (i = 0; i < list->count; ++i)
985 {
986 item = list->entry[i];
987 srv = (si_srv_t *)((uintptr_t)item + sizeof(si_item_t));
988
989 if (srv->priority > lastprio && srv->priority < currprio)
990 {
991 currprio = srv->priority;
992 }
993 }
994
995 if (currprio == INT_MAX)
996 {
997 /* All priorities have been evaluated. Done. */
998 break;
999 }
1000 else
1001 {
1002 lastprio = currprio;
1003 }
1004
1005 /* Lookup hosts at the current priority level. Return first match. */
1006 for (i = 0; i < list->count; ++i)
1007 {
1008 item = list->entry[i];
1009 srv = (si_srv_t *)((uintptr_t)item + sizeof(si_item_t));
1010
1011 if (srv->priority == currprio)
1012 {
1013 /* So that _gai_simple expects an integer service. */
1014 flags |= AI_NUMERICSERV;
1015
1016 result = _gai_simple(si, srv->target, &srv->port, family, socktype, proto, flags, interface, err);
1017 if (result)
1018 {
1019 break;
1020 }
1021 }
1022 }
1023 }
1024
1025 if (list != NULL)
1026 {
1027 si_list_release(list);
1028 }
1029
1030 return result;
1031 }
1032
1033 static si_list_t *
1034 _gai_nat64_synthesis(si_mod_t *si, const char *node, const void *servptr, int numericserv,
1035 uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface)
1036 {
1037 if (NULL == node)
1038 {
1039 return NULL;
1040 }
1041
1042 /* validate AI_NUMERICHOST */
1043 if ((flags & AI_NUMERICHOST) != 0)
1044 {
1045 return NULL;
1046 }
1047
1048 /* validate family */
1049 if ((AF_UNSPEC != family) && (AF_INET6 != family))
1050 {
1051 return NULL;
1052 }
1053
1054 /* validate that node is an IPv4 address */
1055 struct in_addr a4;
1056 if (1 != inet_pton(AF_INET, node, &a4))
1057 {
1058 return NULL;
1059 }
1060
1061 /* validate that IPv4 address is eligible for NAT64 synthesis */
1062 #if defined(NW_NAT64_API_VERSION) && NW_NAT64_API_VERSION >= 2
1063 if (!nw_nat64_can_v4_address_be_synthesized(&a4)) {
1064 return NULL;
1065 }
1066 #endif // NW_NAT64_API_VERSION
1067
1068 /* validate that there is at least an IPv6 address configured */
1069 uint32_t num_inet6 = 0;
1070 if ((si_inet_config(NULL, &num_inet6) < 0) || (0 == num_inet6))
1071 {
1072 return NULL;
1073 }
1074
1075 /* validate interface name and convert to index */
1076 uint32_t ifindex = 0;
1077 if (NULL != interface)
1078 {
1079 ifindex = if_nametoindex(interface);
1080 if (0 == ifindex)
1081 {
1082 return NULL;
1083 }
1084 }
1085
1086 /* validate serv and convert to port */
1087 uint16_t port = 0;
1088 if (0 == numericserv)
1089 {
1090 if (_gai_serv_to_port((const char *)servptr, proto, &port) != 0)
1091 {
1092 return NULL;
1093 }
1094 else
1095 {
1096 flags |= AI_NUMERICSERV;
1097 }
1098 }
1099 else if (NULL != servptr)
1100 {
1101 port = *((const uint16_t *)servptr);
1102 }
1103
1104 /* query NAT64 prefixes */
1105 nw_nat64_prefix_t *prefixes = NULL;
1106 const int32_t num_prefixes = nw_nat64_copy_prefixes(&ifindex, &prefixes);
1107 if ((num_prefixes <= 0) || (NULL == prefixes))
1108 {
1109 return NULL;
1110 }
1111
1112 /* add every address to results */
1113 si_list_t *out_list = NULL;
1114 for (int32_t i = 0; i < num_prefixes; i++)
1115 {
1116 struct in6_addr a6;
1117 if (!nw_nat64_synthesize_v6(&prefixes[i], &a4, &a6))
1118 {
1119 continue;
1120 }
1121 si_list_t *temp_list = si_addrinfo_list(si, flags, socktype, proto, NULL, &a6, port, 0, NULL, NULL);
1122 if (NULL == temp_list)
1123 {
1124 continue;
1125 }
1126 if (NULL != out_list)
1127 {
1128 out_list = si_list_concat(out_list, temp_list);
1129 si_list_release(temp_list);
1130 }
1131 else
1132 {
1133 out_list = temp_list;
1134 }
1135 }
1136
1137 free(prefixes);
1138
1139 /* return to standard code path if no NAT64 addresses could be synthesized */
1140 if (NULL == out_list)
1141 {
1142 return NULL;
1143 }
1144
1145 /* add IPv4 addresses and IPv4-mapped IPv6 addresses if appropriate */
1146 if (((AF_UNSPEC == family) && ((flags & AI_ADDRCONFIG) == 0)) ||
1147 ((AF_INET6 == family) && ((flags & AI_ALL) != 0) && ((flags & AI_V4MAPPED) != 0)))
1148 {
1149 si_list_t *list4 = si_addrinfo_list(si, flags, socktype, proto, &a4, NULL, port, 0, NULL, NULL);
1150 if (NULL != list4)
1151 {
1152 out_list = si_list_concat(out_list, list4);
1153 si_list_release(list4);
1154 }
1155 }
1156
1157 return _gai_sort_list(out_list, flags);
1158 }
1159
1160 static si_list_t *
1161 _gai_nat64_second_pass(si_list_t *out, si_mod_t *si, const char *serv, uint32_t family, uint32_t socktype,
1162 uint32_t proto, uint32_t flags, const char *interface)
1163 {
1164 if (out == NULL || out->count == 0)
1165 {
1166 return NULL;
1167 }
1168
1169 /* validate AI_NUMERICHOST */
1170 if ((flags & AI_NUMERICHOST) != 0)
1171 {
1172 return NULL;
1173 }
1174
1175 /* validate family */
1176 if ((AF_UNSPEC != family) && (AF_INET6 != family))
1177 {
1178 return NULL;
1179 }
1180
1181 /* skip if we already have an IPv6 address (unless it is v4-mapped) */
1182 for (uint32_t i = 0; i < out->count; i++)
1183 {
1184 si_addrinfo_t *a = (si_addrinfo_t *)((uintptr_t)out->entry[i] + sizeof(si_item_t));
1185 if (a->ai_family == AF_INET6)
1186 {
1187 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)a->ai_addr.x;
1188 if (!IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr))
1189 {
1190 return NULL;
1191 }
1192 }
1193 }
1194
1195 si_list_t *out_list = NULL;
1196 const uint32_t flags2 = flags & (~(AI_V4MAPPED | AI_V4MAPPED_CFG));
1197
1198 for (uint32_t i = 0; i < out->count; i++)
1199 {
1200 si_addrinfo_t *a = (si_addrinfo_t *)((uintptr_t)out->entry[i] + sizeof(si_item_t));
1201 struct in_addr *addr4 = NULL;
1202 if (a->ai_family == AF_INET)
1203 {
1204 addr4 = &((struct sockaddr_in *)a->ai_addr.x)->sin_addr;
1205 }
1206 else if (a->ai_family == AF_INET6)
1207 {
1208 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)a->ai_addr.x;
1209 addr4 = (struct in_addr *)&(s6->sin6_addr.__u6_addr.__u6_addr32[3]);
1210 }
1211 else
1212 {
1213 continue;
1214 }
1215
1216 /* validate that IPv4 address is eligible for NAT64 synthesis */
1217 #if defined(NW_NAT64_API_VERSION) && NW_NAT64_API_VERSION >= 2
1218 if (!nw_nat64_can_v4_address_be_synthesized(addr4))
1219 {
1220 continue;
1221 }
1222 #endif // NW_NAT64_API_VERSION
1223
1224 char v4_str[INET_ADDRSTRLEN] = {0};
1225 if (NULL == inet_ntop(AF_INET, addr4, v4_str, sizeof(v4_str)))
1226 {
1227 continue;
1228 }
1229
1230 /* skip if we have a path (route) to this address as it might go through a VPN */
1231 nw_endpoint_t endpoint = nw_endpoint_create_address((struct sockaddr *)a->ai_addr.x);
1232 if (endpoint == NULL)
1233 {
1234 continue;
1235 }
1236 nw_path_evaluator_t evaluator = nw_path_create_evaluator_for_endpoint(endpoint, NULL);
1237 network_release(endpoint);
1238 if (evaluator == NULL)
1239 {
1240 continue;
1241 }
1242 nw_path_t path = nw_path_evaluator_copy_path(evaluator);
1243 network_release(evaluator);
1244 if (path == NULL)
1245 {
1246 continue;
1247 }
1248 const nw_path_status_t status = nw_path_get_status(path);
1249 network_release(path);
1250 if (status != nw_path_status_unsatisfied)
1251 {
1252 continue;
1253 }
1254
1255 uint32_t err = SI_STATUS_NO_ERROR;
1256 si_list_t *temp_list = si_addrinfo(si, v4_str, serv, AF_INET6, socktype, proto, flags2, interface, &err);
1257 if (NULL == temp_list)
1258 {
1259 continue;
1260 }
1261 if (err != SI_STATUS_NO_ERROR)
1262 {
1263 si_list_release(temp_list);
1264 continue;
1265 }
1266 if (NULL != out_list)
1267 {
1268 out_list = si_list_concat(out_list, temp_list);
1269 si_list_release(temp_list);
1270 }
1271 else
1272 {
1273 out_list = temp_list;
1274 }
1275 }
1276 return out_list;
1277 }
1278
1279 si_list_t *
1280 si_addrinfo(si_mod_t *si, const char *node, const char *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err)
1281 {
1282 const uint32_t family_ori = family, flags_ori = flags;
1283 int numerichost, numericserv = 0;
1284 int scope = 0;
1285 const void *nodeptr = NULL, *servptr = NULL;
1286 uint16_t port;
1287 struct in_addr a4, *p4;
1288 struct in6_addr a6, *p6;
1289 const char *cname;
1290 si_list_t *out;
1291
1292 if (err != NULL) *err = SI_STATUS_NO_ERROR;
1293
1294 if (si == NULL)
1295 {
1296 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
1297 return NULL;
1298 }
1299
1300 /* treat empty strings as NULL */
1301 if ((node != NULL) && (node[0] == '\0')) node = NULL;
1302 if ((serv != NULL) && (serv[0] == '\0')) serv = NULL;
1303
1304 /* make sure we have a query */
1305 if ((node == NULL) && (serv == NULL))
1306 {
1307 if (err != NULL) *err = SI_STATUS_EAI_NONAME;
1308 return NULL;
1309 }
1310
1311 /* verify family is supported */
1312 switch (family)
1313 {
1314 case AF_UNSPEC:
1315 case AF_INET:
1316 case AF_INET6:
1317 break;
1318 default:
1319 if (err != NULL) *err = SI_STATUS_EAI_FAMILY;
1320 return NULL;
1321 }
1322
1323 /* verify socket type is supported */
1324 switch (socktype)
1325 {
1326 case SOCK_UNSPEC:
1327 case SOCK_RAW:
1328 case SOCK_DGRAM:
1329 case SOCK_STREAM:
1330 break;
1331 default:
1332 if (err != NULL) *err = SI_STATUS_EAI_BADHINTS;
1333 return NULL;
1334 }
1335
1336 /* verify protocol is supported */
1337 switch (proto)
1338 {
1339 case IPPROTO_UNSPEC:
1340 case IPPROTO_UDP:
1341 case IPPROTO_TCP:
1342 case IPPROTO_ICMP:
1343 case IPPROTO_ICMPV6:
1344 break;
1345 default:
1346 if (err != NULL) *err = SI_STATUS_EAI_BADHINTS;
1347 return NULL;
1348 }
1349
1350 /* verify socket type compatible with protocol */
1351 if (((socktype == SOCK_DGRAM) && (proto != IPPROTO_UNSPEC) && (proto != IPPROTO_UDP)) || ((socktype == SOCK_STREAM) && (proto != IPPROTO_UNSPEC) && (proto != IPPROTO_TCP)))
1352 {
1353 if (err != NULL) *err = SI_STATUS_EAI_BADHINTS;
1354 return NULL;
1355 }
1356
1357 /* replace AI_V4MAPPED_CFG with AI_V4MAPPED */
1358 if ((flags & AI_V4MAPPED_CFG) != 0)
1359 {
1360 flags = (flags & ~AI_V4MAPPED_CFG) | AI_V4MAPPED;
1361 }
1362
1363 /* check AI_V4MAPPED and AI_ALL */
1364 if (family != AF_INET6)
1365 {
1366 /* unset AI_V4MAPPED and AI_ALL unless family is AF_INET6 */
1367 flags &= ~(AI_V4MAPPED | AI_ALL);
1368 }
1369 else if ((flags & AI_V4MAPPED) == 0)
1370 {
1371 /* unset AI_ALL unless family is AF_INET6 and AI_V4MAPPED is set */
1372 flags &= ~AI_ALL;
1373 }
1374
1375 memset(&a4, 0, sizeof(struct in_addr));
1376 memset(&a6, 0, sizeof(struct in6_addr));
1377
1378 /* determine the protocol if possible */
1379 if ((proto == IPPROTO_UNSPEC) && (socktype == SOCK_DGRAM)) proto = IPPROTO_UDP;
1380 if ((proto == IPPROTO_UNSPEC) && (socktype == SOCK_STREAM)) proto = IPPROTO_TCP;
1381
1382 port = 0;
1383
1384 if ((flags & AI_SRV) != 0)
1385 {
1386 /* AI_SRV SPI */
1387 out = _gai_srv(si, node, serv, family, socktype, proto, flags, interface, err);
1388 return _gai_sort_list(out, flags);
1389 }
1390 else
1391 {
1392 /* Usual service lookup */
1393 numericserv = _gai_numericserv(serv, &port);
1394 }
1395
1396 if ((flags & AI_NUMERICSERV) && (numericserv == 0))
1397 {
1398 /* FreeBSD returns SI_STATUS_EAI_SERVICE */
1399 if (err != NULL) *err = SI_STATUS_EAI_NONAME;
1400 return NULL;
1401 }
1402
1403 if ((serv != NULL) && (strcmp(serv, "0") != 0))
1404 {
1405 if (numericserv == 1)
1406 {
1407 flags |= AI_NUMERICSERV;
1408 servptr = &port;
1409 }
1410 else
1411 {
1412 servptr = serv;
1413 }
1414 }
1415
1416 /* NAT64 IPv6 address synthesis support */
1417 si_list_t *nat64_list = _gai_nat64_synthesis(si, node, servptr, numericserv, family, socktype, proto, flags, interface);
1418 if (NULL != nat64_list)
1419 {
1420 return nat64_list;
1421 }
1422
1423 numerichost = _gai_numerichost(node, &family, flags, &a4, &a6, &scope);
1424 if ((numerichost == -1) || ((flags & AI_NUMERICHOST) && (numerichost == 0)))
1425 {
1426 if (err != NULL) *err = SI_STATUS_EAI_NONAME;
1427 return NULL;
1428 }
1429
1430 if (numerichost == 1)
1431 {
1432 flags |= AI_NUMERICHOST;
1433 if (family == AF_INET)
1434 {
1435 nodeptr = &a4;
1436 }
1437 else if (family == AF_INET6)
1438 {
1439 nodeptr = &a6;
1440 }
1441 }
1442 else
1443 {
1444 nodeptr = node;
1445 }
1446
1447 if ((numerichost == 1) && (numericserv == 0))
1448 {
1449 /* only service lookup needed. convert to port and perform a trivial getaddrinfo */
1450 if (_gai_serv_to_port(serv, proto, &port) != 0)
1451 {
1452 if (err != NULL) *err = SI_STATUS_EAI_NONAME;
1453 return NULL;
1454 }
1455 else
1456 {
1457 flags |= AI_NUMERICSERV;
1458 servptr = &port;
1459 numericserv = 1;
1460 }
1461 }
1462
1463 if ((numerichost == 1) && (numericserv == 1))
1464 {
1465 p4 = &a4;
1466 p6 = &a6;
1467 cname = NULL;
1468
1469 if (family == AF_INET) p6 = NULL;
1470 if (family == AF_INET6) p4 = NULL;
1471 if (node == NULL) cname = "localhost";
1472
1473 /* allow nodename to be a mapped IPv4 address, e.g. "::ffff:10.0.0.1" */
1474 if (p6 != NULL) flags |= AI_V4MAPPED;
1475
1476 /* handle trivial questions */
1477 out = si_addrinfo_list(si, flags, socktype, proto, p4, p6, port, scope, cname, cname);
1478 return _gai_sort_list(out, flags);
1479 }
1480 else if (si_wants_addrinfo(si))
1481 {
1482 /* or let the current module handle the host lookups intelligently */
1483 out = si->vtable->sim_addrinfo(si, nodeptr, servptr, family, socktype, proto, flags, interface, err);
1484
1485 /* run a second NAT64 pass in case a hostname was resolved over VPN to an IPv4 address
1486 and it needs to be synthesized in order to be used on IPv6-only cellular */
1487 si_list_t *nat64_list2 = _gai_nat64_second_pass(out, si, serv, family_ori, socktype,
1488 proto, flags_ori, interface);
1489 if (nat64_list2 != NULL)
1490 {
1491 out = si_list_concat(out, nat64_list2);
1492 }
1493
1494 return _gai_sort_list(out, flags);
1495 }
1496
1497 /* fall back to a default path */
1498 out = _gai_simple(si, nodeptr, servptr, family, socktype, proto, flags, interface, err);
1499 return _gai_sort_list(out, flags);
1500 }
1501
1502 static struct addrinfo *
1503 si_item_to_addrinfo(si_item_t *item)
1504 {
1505 si_addrinfo_t *a;
1506 struct addrinfo *out;
1507
1508 if (item == NULL) return NULL;
1509
1510 a = (si_addrinfo_t *)((uintptr_t)item + sizeof(si_item_t));
1511
1512 out = (struct addrinfo *)calloc(1, sizeof(struct addrinfo));
1513 if (out == NULL) return NULL;
1514
1515 out->ai_flags = a->ai_flags;
1516 out->ai_family = a->ai_family;
1517 out->ai_socktype = a->ai_socktype;
1518 out->ai_protocol = a->ai_protocol;
1519 out->ai_addrlen = a->ai_addrlen;
1520
1521 out->ai_addr = (struct sockaddr *)calloc(1, out->ai_addrlen);
1522 if (out->ai_addr == NULL)
1523 {
1524 free(out);
1525 return NULL;
1526 }
1527
1528 memcpy(out->ai_addr, a->ai_addr.x, out->ai_addrlen);
1529
1530 if (a->ai_canonname != NULL)
1531 {
1532 out->ai_canonname = strdup(a->ai_canonname);
1533 if (out->ai_canonname == NULL)
1534 {
1535 free(out);
1536 return NULL;
1537 }
1538 }
1539
1540 return out;
1541 }
1542
1543 struct addrinfo *
1544 si_list_to_addrinfo(si_list_t *list)
1545 {
1546 struct addrinfo *tail, *out;
1547 int i;
1548
1549 if (list == NULL) return NULL;
1550 if (list->count == 0) return NULL;
1551
1552 i = list->count - 1;
1553
1554 out = si_item_to_addrinfo(list->entry[i]);
1555 tail = out;
1556
1557 for (i--; i >= 0; i--)
1558 {
1559 out = si_item_to_addrinfo(list->entry[i]);
1560 if (out == NULL)
1561 {
1562 freeaddrinfo(tail);
1563 return NULL;
1564 }
1565
1566 out->ai_next = tail;
1567 tail = out;
1568 }
1569
1570 return out;
1571 }
1572
1573 /* getipnodebyname */
1574
1575 static si_item_t *
1576 make_hostent(si_mod_t *si, const char *name, struct in_addr addr)
1577 {
1578 char *addrs[2];
1579 char *aliases[1];
1580 uint64_t unused;
1581
1582 if (name == NULL) return NULL;
1583
1584 unused = 0;
1585
1586 addrs[0] = (char *)&(addr.s_addr);
1587 addrs[1] = NULL;
1588 aliases[0] = NULL;
1589
1590 return (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, unused, unused, name, aliases, AF_INET, IPV4_ADDR_LEN, addrs);
1591 }
1592
1593 static si_item_t *
1594 make_hostent6(si_mod_t *si, const char *name, struct in6_addr addr)
1595 {
1596 char *addrs[2];
1597 char *aliases[1];
1598 uint64_t unused;
1599
1600 if (name == NULL) return NULL;
1601
1602 unused = 0;
1603
1604 addrs[0] = (char *)&(addr.__u6_addr.__u6_addr32[0]);
1605 addrs[1] = NULL;
1606 aliases[0] = NULL;
1607
1608 return (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, name, aliases, AF_INET6, IPV6_ADDR_LEN, addrs);
1609 }
1610
1611 static char *
1612 lower_case(const char *s)
1613 {
1614 int i;
1615 char *t;
1616
1617 if (s == NULL) return NULL;
1618
1619 t = malloc(strlen(s) + 1);
1620 if (t == NULL) return NULL;
1621
1622 for (i = 0; s[i] != '\0'; i++)
1623 {
1624 if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32;
1625 else t[i] = s[i];
1626 }
1627
1628 t[i] = '\0';
1629
1630 return t;
1631 }
1632
1633 static int
1634 merge_alias(const char *name, build_hostent_t *h)
1635 {
1636 int i;
1637
1638 if (name == NULL) return 0;
1639 if (h == NULL) return 0;
1640 if (h->host.h_name == NULL) return 0;
1641
1642 if ((h->host.h_name != NULL) && (string_equal(name, h->host.h_name))) return 0;
1643
1644 for (i = 0; i < h->alias_count; i++)
1645 {
1646 if (string_equal(name, h->host.h_aliases[i])) return 0;
1647 }
1648
1649 if (h->alias_count == 0) h->host.h_aliases = (char **)calloc(2, sizeof(char *));
1650 else h->host.h_aliases = (char **)reallocf(h->host.h_aliases, (h->alias_count + 2) * sizeof(char *));
1651
1652 if (h->host.h_aliases == NULL)
1653 {
1654 h->alias_count = 0;
1655 return -1;
1656 }
1657
1658 h->host.h_aliases[h->alias_count] = lower_case(name);
1659 h->alias_count++;
1660 h->host.h_aliases[h->alias_count] = NULL;
1661
1662 return 0;
1663 }
1664
1665 static int
1666 append_addr(const char *addr, uint32_t len, build_hostent_t *h)
1667 {
1668 if (addr == NULL) return 0;
1669 if (h == NULL) return 0;
1670
1671 if (h->addr_count == 0) h->host.h_addr_list = (char **)calloc(2, sizeof(char *));
1672 else h->host.h_addr_list = (char **)reallocf(h->host.h_addr_list, (h->addr_count + 2) * sizeof(char *));
1673
1674 if (h->host.h_addr_list == NULL)
1675 {
1676 h->addr_count = 0;
1677 return -1;
1678 }
1679
1680 h->host.h_addr_list[h->addr_count] = malloc(len);
1681 if (h->host.h_addr_list[h->addr_count] == NULL) return -1;
1682
1683 memcpy(h->host.h_addr_list[h->addr_count], addr, len);
1684 h->addr_count++;
1685 h->host.h_addr_list[h->addr_count] = NULL;
1686
1687 return 0;
1688 }
1689
1690 static void
1691 free_build_hostent(build_hostent_t *h)
1692 {
1693 uint32_t i;
1694 char **aliases;
1695
1696 if (h == NULL) return;
1697
1698 if (h->host.h_name != NULL) free(h->host.h_name);
1699 h->host.h_name = NULL;
1700
1701 aliases = h->host.h_aliases;
1702 if (aliases != NULL)
1703 {
1704 while (*aliases != NULL) free(*aliases++);
1705 free(h->host.h_aliases);
1706 }
1707
1708 h->host.h_aliases = NULL;
1709
1710 if (h->host.h_addr_list != NULL)
1711 {
1712 for (i = 0; h->host.h_addr_list[i] != NULL; i++) free(h->host.h_addr_list[i]);
1713 free(h->host.h_addr_list);
1714 }
1715
1716 h->host.h_addr_list = NULL;
1717 free(h);
1718 }
1719
1720 si_item_t *
1721 si_ipnode_byname(si_mod_t *si, const char *name, int family, int flags, const char *interface, uint32_t *err)
1722 {
1723 int i, status, want;
1724 uint32_t if4, if6;
1725 struct in_addr addr4;
1726 struct in6_addr addr6;
1727 si_item_t *item4, *item6;
1728 build_hostent_t *out;
1729 struct hostent *h;
1730 uint64_t unused;
1731
1732 memset(&addr4, 0, sizeof(struct in_addr));
1733 memset(&addr6, 0, sizeof(struct in6_addr));
1734
1735 if (err != NULL) *err = 0;
1736
1737 if (family == AF_INET)
1738 {
1739 status = inet_aton(name, &addr4);
1740 if (status == 1)
1741 {
1742 /* create a host entry */
1743 item4 = make_hostent(si, name, addr4);
1744 if (item4 == NULL)
1745 {
1746 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1747 return NULL;
1748 }
1749
1750 return item4;
1751 }
1752 }
1753 else if (family == AF_INET6)
1754 {
1755 status = inet_pton(family, name, &addr6);
1756 if (status == 1)
1757 {
1758 /* create a host entry */
1759 item6 = make_hostent6(si, name, addr6);
1760 if (item6 == NULL)
1761 {
1762 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1763 return NULL;
1764 }
1765
1766 return item6;
1767 }
1768
1769 status = inet_aton(name, &addr4);
1770 if (status == 1)
1771 {
1772 if (!(flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)))
1773 {
1774 if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
1775 return NULL;
1776 }
1777
1778 addr6.__u6_addr.__u6_addr32[0] = 0x00000000;
1779 addr6.__u6_addr.__u6_addr32[1] = 0x00000000;
1780 addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
1781 memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr4.s_addr), IPV4_ADDR_LEN);
1782
1783 /* create a host entry */
1784 item6 = make_hostent6(si, name, addr6);
1785 if (item6 == NULL)
1786 {
1787 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1788 return NULL;
1789 }
1790
1791 return item6;
1792 }
1793 }
1794 else
1795 {
1796 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1797 return NULL;
1798 }
1799
1800 /*
1801 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
1802 */
1803
1804 if4 = 0;
1805 if6 = 0;
1806
1807 if (flags & AI_ADDRCONFIG)
1808 {
1809 if (si_inet_config(&if4, &if6) < 0)
1810 {
1811 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1812 return NULL;
1813 }
1814
1815 /* Bail out if there are no interfaces */
1816 if ((if4 == 0) && (if6 == 0))
1817 {
1818 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1819 return NULL;
1820 }
1821 }
1822
1823 /*
1824 * Figure out what we want.
1825 * If user asked for AF_INET, we only want V4 addresses.
1826 */
1827 want = WANT_A4_ONLY;
1828
1829 if (family == AF_INET)
1830 {
1831 if ((flags & AI_ADDRCONFIG) && (if4 == 0))
1832 {
1833 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1834 return NULL;
1835 }
1836 }
1837 else if (family == AF_INET6)
1838 {
1839 /* family == AF_INET6 */
1840 want = WANT_A6_ONLY;
1841
1842 if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG))
1843 {
1844 if (flags & AI_ALL)
1845 {
1846 want = WANT_A6_PLUS_MAPPED_A4;
1847 }
1848 else
1849 {
1850 want = WANT_A6_OR_MAPPED_A4_IF_NO_A6;
1851 }
1852 }
1853 else
1854 {
1855 if ((flags & AI_ADDRCONFIG) && (if6 == 0))
1856 {
1857 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1858 return NULL;
1859 }
1860 }
1861 }
1862 else
1863 {
1864 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1865 return NULL;
1866 }
1867
1868 item6 = NULL;
1869 item4 = NULL;
1870
1871 /* fetch IPv6 data if required */
1872 if ((want == WANT_A6_ONLY) || (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) || (want == WANT_A6_PLUS_MAPPED_A4))
1873 {
1874 item6 = si_host_byname(si, name, AF_INET6, interface, (uint32_t *)err);
1875 }
1876
1877 /* fetch IPv4 data if required */
1878 if ((want == WANT_A4_ONLY) || (want == WANT_A6_PLUS_MAPPED_A4) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (item6 == NULL)))
1879 {
1880 item4 = si_host_byname(si, name, AF_INET, interface, (uint32_t *)err);
1881 }
1882
1883 if (want == WANT_A4_ONLY)
1884 {
1885 si_item_release(item6);
1886 if ((item4 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
1887 return item4;
1888 }
1889
1890 if (want == WANT_A6_ONLY)
1891 {
1892 si_item_release(item4);
1893 if ((item6 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
1894 return item6;
1895 }
1896
1897 if ((item6 == NULL) && (item4 == NULL))
1898 {
1899 if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
1900 return NULL;
1901 }
1902
1903 /* output item will have IPv6 + mapped IPv4 addresses */
1904
1905 out = (build_hostent_t *)calloc(1, sizeof(build_hostent_t));
1906 if (out == NULL)
1907 {
1908 si_item_release(item4);
1909 si_item_release(item6);
1910 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
1911 return NULL;
1912 }
1913
1914 if (item4 != NULL)
1915 {
1916 h = (struct hostent *)((uintptr_t)item4 + sizeof(si_item_t));
1917
1918 out->host.h_name = lower_case(h->h_name);
1919
1920 if (h->h_aliases != NULL)
1921 {
1922 for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out);
1923 }
1924
1925 for (i = 0; h->h_addr_list[i] != 0; i++)
1926 {
1927 addr6.__u6_addr.__u6_addr32[0] = 0x00000000;
1928 addr6.__u6_addr.__u6_addr32[1] = 0x00000000;
1929 addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
1930 memmove(&(addr6.__u6_addr.__u6_addr32[3]), h->h_addr_list[i], IPV4_ADDR_LEN);
1931 append_addr((const char *)&addr6, IPV6_ADDR_LEN, out);
1932 }
1933 }
1934
1935 if (item6 != NULL)
1936 {
1937 h = (struct hostent *)((uintptr_t)item6 + sizeof(si_item_t));
1938
1939 if (out->host.h_name == NULL) out->host.h_name = lower_case(h->h_name);
1940
1941 if (h->h_aliases != NULL)
1942 {
1943 for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out);
1944 }
1945
1946 for (i = 0; h->h_addr_list[i] != 0; i++) append_addr(h->h_addr_list[i], IPV6_ADDR_LEN, out);
1947 }
1948
1949 si_item_release(item4);
1950 si_item_release(item6);
1951
1952 unused = 0;
1953
1954 item6 = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, out->host.h_name, out->host.h_aliases, AF_INET6, IPV6_ADDR_LEN, out->host.h_addr_list);
1955
1956 free_build_hostent(out);
1957
1958 return item6;
1959 }