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