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