]> git.saurik.com Git - apple/libinfo.git/blob - lookup.subproj/libinfo.c
Libinfo-542.40.3.tar.gz
[apple/libinfo.git] / lookup.subproj / libinfo.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 <stdlib.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <netdb.h>
32 #include <asl.h>
33 #include <printerdb.h>
34 #include <sys/param.h>
35 #include <sys/syscall.h>
36 #include <pthread.h>
37 #include <arpa/inet.h>
38 #include <netinet/if_ether.h>
39 #include "si_module.h"
40 #include "libinfo.h"
41 #include <thread_data.h>
42 #include <sys/kauth.h>
43 #include "netdb_async.h"
44 #include <dispatch/dispatch.h>
45 #include <mach-o/dyld_priv.h>
46 #include <sys/stat.h>
47
48 #define SOCK_UNSPEC 0
49 #define IPPROTO_UNSPEC 0
50 #define IPV6_ADDR_LEN 16
51 #define IPV4_ADDR_LEN 4
52
53 #define SYSTEM_UID_LIMIT 500
54
55 /* kernel syscalls */
56 extern int __initgroups(u_int gidsetsize, gid_t *gidset, int gmuid);
57
58 /* SPI from long ago */
59 int _proto_stayopen;
60
61 extern struct addrinfo *si_list_to_addrinfo(si_list_t *list);
62 extern int getnameinfo_link(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
63 __private_extern__ void search_set_flags(si_mod_t *si, const char *name, uint32_t flag);
64
65 /*
66 * Impedence matching for async calls.
67 *
68 * This layer holds on to the caller's callback and context in this
69 * structure, which gets passed to the si_module async routines along
70 * with a callbac in this layer. When this layer gets a callback,
71 * it can save the item or list in thread-specific memory and then
72 * invoke the caller's callback with the appropriate data type.
73 */
74
75 typedef struct
76 {
77 void *orig_callback;
78 void *orig_context;
79 uint32_t cat;
80 int32_t key_offset;
81 } si_context_t;
82
83 si_mod_t *
84 si_search_file(void)
85 {
86 static si_mod_t *search = NULL;
87
88 if (search == NULL) search = si_module_with_name("file");
89
90 return search;
91 }
92
93 LIBINFO_EXPORT
94 si_mod_t *
95 si_search(void)
96 {
97 static si_mod_t *search = NULL;
98
99 if (search == NULL) search = si_module_with_name("search");
100
101 return search;
102 }
103
104 LIBINFO_EXPORT
105 void
106 si_search_module_set_flags(const char *name, uint32_t flag)
107 {
108 search_set_flags(si_search(), name, flag);
109 }
110
111 static void
112 si_libinfo_general_callback(si_item_t *item, uint32_t status, void *ctx)
113 {
114 si_context_t *sictx;
115 union
116 {
117 char *x;
118 struct passwd *u;
119 struct group *g;
120 struct grouplist_s *l;
121 struct hostent *h;
122 struct netent *n;
123 struct servent *s;
124 struct protoent *p;
125 struct rpcent *r;
126 struct fstab *f;
127 } res;
128
129 if (ctx == NULL) return;
130
131 sictx = (si_context_t *)ctx;
132
133 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
134 {
135 free(sictx);
136 si_item_release(item);
137 return;
138 }
139
140 if (sictx->key_offset >= 0)
141 {
142 LI_set_thread_item(sictx->cat + sictx->key_offset, item);
143 }
144
145 res.x = NULL;
146 if (item != NULL) res.x = (char*)((uintptr_t)item + sizeof(si_item_t));
147
148 switch (sictx->cat)
149 {
150 case CATEGORY_USER:
151 {
152 ((si_user_async_callback)(sictx->orig_callback))(res.u, sictx->orig_context);
153 break;
154 }
155 case CATEGORY_GROUP:
156 {
157 ((si_group_async_callback)(sictx->orig_callback))(res.g, sictx->orig_context);
158 break;
159 }
160 case CATEGORY_GROUPLIST:
161 {
162 ((si_grouplist_async_callback)(sictx->orig_callback))(res.l, sictx->orig_context);
163 break;
164 }
165 case CATEGORY_HOST_IPV4:
166 case CATEGORY_HOST_IPV6:
167 {
168 ((si_host_async_callback)(sictx->orig_callback))(res.h, sictx->orig_context);
169 break;
170 }
171 case CATEGORY_NETWORK:
172 {
173 ((si_network_async_callback)(sictx->orig_callback))(res.n, sictx->orig_context);
174 break;
175 }
176 case CATEGORY_SERVICE:
177 {
178 ((si_service_async_callback)(sictx->orig_callback))(res.s, sictx->orig_context);
179 break;
180 }
181 case CATEGORY_PROTOCOL:
182 {
183 ((si_protocol_async_callback)(sictx->orig_callback))(res.p, sictx->orig_context);
184 break;
185 }
186 case CATEGORY_RPC:
187 {
188 ((si_rpc_async_callback)(sictx->orig_callback))(res.r, sictx->orig_context);
189 break;
190 }
191 case CATEGORY_FS:
192 {
193 ((si_fs_async_callback)(sictx->orig_callback))(res.f, sictx->orig_context);
194 break;
195 }
196 }
197
198 free(sictx);
199 }
200
201 /* USER */
202
203 LIBINFO_EXPORT
204 struct passwd *
205 getpwnam(const char *name)
206 {
207 si_item_t *item;
208
209 #ifdef CALL_TRACE
210 fprintf(stderr, "-> %s %s\n", __func__, name);
211 #endif
212 item = si_user_byname(si_search(), name);
213 LI_set_thread_item(CATEGORY_USER + 100, item);
214
215 if (item == NULL) return NULL;
216 return (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
217 }
218
219 mach_port_t
220 getpwnam_async_call(const char *name, si_user_async_callback callback, void *context)
221 {
222 si_context_t *sictx;
223
224 #ifdef CALL_TRACE
225 fprintf(stderr, ">> %s %s\n", __func__, name);
226 #endif
227
228 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
229 if (sictx == NULL) return MACH_PORT_NULL;
230
231 sictx->orig_callback = callback;
232 sictx->orig_context = context;
233 sictx->cat = CATEGORY_USER;
234 sictx->key_offset = 100;
235
236 return si_async_call(si_search(), SI_CALL_USER_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
237 }
238
239 void
240 getpwnam_async_handle_reply(mach_msg_header_t *msg)
241 {
242 #ifdef CALL_TRACE
243 fprintf(stderr, "<< %s\n", __func__);
244 #endif
245
246 si_async_handle_reply(msg);
247 }
248
249 LIBINFO_EXPORT
250 struct passwd *
251 getpwuid(uid_t uid)
252 {
253 si_item_t *item = NULL;
254
255 #ifdef CALL_TRACE
256 fprintf(stderr, "-> %s %d\n", __func__, uid);
257 #endif
258
259 // Search the file module first for all system uids
260 // (ie, uid value < 500) since they should all be
261 // in the /etc/*passwd file.
262 if (uid < SYSTEM_UID_LIMIT)
263 item = si_user_byuid(si_search_file(), uid);
264
265 if (item == NULL)
266 item = si_user_byuid(si_search(), uid);
267 LI_set_thread_item(CATEGORY_USER + 200, item);
268
269 if (item == NULL) return NULL;
270 return (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
271 }
272
273 mach_port_t
274 getpwuid_async_call(uid_t uid, si_user_async_callback callback, void *context)
275 {
276 si_context_t *sictx;
277
278 #ifdef CALL_TRACE
279 fprintf(stderr, ">> %s %d\n", __func__, uid);
280 #endif
281
282 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
283 if (sictx == NULL) return MACH_PORT_NULL;
284
285 sictx->orig_callback = callback;
286 sictx->orig_context = context;
287 sictx->cat = CATEGORY_USER;
288 sictx->key_offset = 200;
289
290 // Search the file module first for all system uids
291 // (ie, uid value < 500) since they should all be
292 // in the /etc/*passwd file.
293 if (uid < SYSTEM_UID_LIMIT)
294 {
295 si_item_t *item = si_user_byuid(si_search_file(), uid);
296 if (item)
297 {
298 si_item_release(item);
299 return si_async_call(si_search_file(), SI_CALL_USER_BYUID, NULL, NULL, NULL, (uint32_t)uid, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
300 }
301 }
302
303 return si_async_call(si_search(), SI_CALL_USER_BYUID, NULL, NULL, NULL, (uint32_t)uid, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
304 }
305
306 void
307 getpwuid_async_handle_reply(mach_msg_header_t *msg)
308 {
309 #ifdef CALL_TRACE
310 fprintf(stderr, "<< %s\n", __func__);
311 #endif
312
313 si_async_handle_reply(msg);
314 }
315
316 LIBINFO_EXPORT
317 struct passwd *
318 getpwuuid(uuid_t uuid)
319 {
320 si_item_t *item;
321
322 #ifdef CALL_TRACE
323 uuid_string_t uuidstr;
324 uuid_unparse_upper(uuid, uuidstr);
325 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
326 #endif
327
328 item = si_user_byuuid(si_search(), uuid);
329 LI_set_thread_item(CATEGORY_USER + 300, item);
330
331 if (item == NULL) return NULL;
332 return (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
333 }
334
335 LIBINFO_EXPORT
336 void
337 setpwent(void)
338 {
339 #ifdef CALL_TRACE
340 fprintf(stderr, "-- %s\n", __func__);
341 #endif
342
343 LI_set_thread_list(CATEGORY_USER, NULL);
344 }
345
346 LIBINFO_EXPORT
347 struct passwd *
348 getpwent(void)
349 {
350 si_list_t *list;
351 si_item_t *item;
352
353 #ifdef CALL_TRACE
354 fprintf(stderr, "-> %s\n", __func__);
355 #endif
356
357 list = LI_get_thread_list(CATEGORY_USER);
358 if (list == NULL)
359 {
360 list = si_user_all(si_search());
361 LI_set_thread_list(CATEGORY_USER, list);
362 }
363
364 item = si_list_next(list);
365 if (item == NULL) return NULL;
366
367 return (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
368 }
369
370 LIBINFO_EXPORT
371 void
372 endpwent(void)
373 {
374 #ifdef CALL_TRACE
375 fprintf(stderr, "-- %s\n", __func__);
376 #endif
377
378 LI_set_thread_list(CATEGORY_USER, NULL);
379 }
380
381 LIBINFO_EXPORT
382 int
383 setpassent(int ignored)
384 {
385 si_list_t *list;
386
387 #ifdef CALL_TRACE
388 fprintf(stderr, "-> %s\n", __func__);
389 #endif
390
391 list = LI_get_thread_list(CATEGORY_USER);
392 si_list_reset(list);
393
394 if (list == NULL) return 0;
395 return 1;
396 }
397
398 /* GROUP */
399
400 LIBINFO_EXPORT
401 struct group *
402 getgrnam(const char *name)
403 {
404 si_item_t *item;
405
406 #ifdef CALL_TRACE
407 fprintf(stderr, "-> %s %s\n", __func__, name);
408 #endif
409
410 item = si_group_byname(si_search(), name);
411 LI_set_thread_item(CATEGORY_GROUP + 100, item);
412
413 if (item == NULL) return NULL;
414 return (struct group *)((uintptr_t)item + sizeof(si_item_t));
415 }
416
417 mach_port_t
418 getgrnam_async_call(const char *name, si_group_async_callback callback, void *context)
419 {
420 si_context_t *sictx;
421
422 #ifdef CALL_TRACE
423 fprintf(stderr, ">> %s %s\n", __func__, name);
424 #endif
425
426 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
427 if (sictx == NULL) return MACH_PORT_NULL;
428
429 sictx->orig_callback = callback;
430 sictx->orig_context = context;
431 sictx->cat = CATEGORY_GROUP;
432 sictx->key_offset = 100;
433
434 return si_async_call(si_search(), SI_CALL_GROUP_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
435 }
436
437 void
438 getgrnam_async_handle_reply(mach_msg_header_t *msg)
439 {
440 #ifdef CALL_TRACE
441 fprintf(stderr, "<< %s\n", __func__);
442 #endif
443
444 si_async_handle_reply(msg);
445 }
446
447 LIBINFO_EXPORT
448 struct group *
449 getgrgid(gid_t gid)
450 {
451 si_item_t *item;
452
453 #ifdef CALL_TRACE
454 fprintf(stderr, "-> %s %d\n", __func__, gid);
455 #endif
456
457 item = si_group_bygid(si_search(), gid);
458 LI_set_thread_item(CATEGORY_GROUP + 200, item);
459
460 if (item == NULL) return NULL;
461 return (struct group *)((uintptr_t)item + sizeof(si_item_t));
462 }
463
464 mach_port_t
465 getgrgid_async_call(gid_t gid, si_group_async_callback callback, void *context)
466 {
467 si_context_t *sictx;
468
469 #ifdef CALL_TRACE
470 fprintf(stderr, ">> %s %d\n", __func__, gid);
471 #endif
472
473 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
474 if (sictx == NULL) return MACH_PORT_NULL;
475
476 sictx->orig_callback = callback;
477 sictx->orig_context = context;
478 sictx->cat = CATEGORY_GROUP;
479 sictx->key_offset = 200;
480
481 return si_async_call(si_search(), SI_CALL_GROUP_BYGID, NULL, NULL, NULL, (uint32_t)gid, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
482 }
483
484 void
485 getgruid_async_handle_reply(mach_msg_header_t *msg)
486 {
487 #ifdef CALL_TRACE
488 fprintf(stderr, "<< %s\n", __func__);
489 #endif
490
491 si_async_handle_reply(msg);
492 }
493
494 LIBINFO_EXPORT
495 struct group *
496 getgruuid(uuid_t uuid)
497 {
498 si_item_t *item;
499
500 #ifdef CALL_TRACE
501 uuid_string_t uuidstr;
502 uuid_unparse_upper(uuid, uuidstr);
503 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
504 #endif
505
506 item = si_group_byuuid(si_search(), uuid);
507 LI_set_thread_item(CATEGORY_GROUP + 300, item);
508
509 if (item == NULL) return NULL;
510 return (struct group *)((uintptr_t)item + sizeof(si_item_t));
511 }
512
513 LIBINFO_EXPORT
514 void
515 setgrent(void)
516 {
517 #ifdef CALL_TRACE
518 fprintf(stderr, "-- %s\n", __func__);
519 #endif
520
521 LI_set_thread_list(CATEGORY_GROUP, NULL);
522 }
523
524 LIBINFO_EXPORT
525 struct group *
526 getgrent(void)
527 {
528 si_list_t *list;
529 si_item_t *item;
530
531 #ifdef CALL_TRACE
532 fprintf(stderr, "-> %s\n", __func__);
533 #endif
534
535 list = LI_get_thread_list(CATEGORY_GROUP);
536 if (list == NULL)
537 {
538 list = si_group_all(si_search());
539 LI_set_thread_list(CATEGORY_GROUP, list);
540 }
541
542 item = si_list_next(list);
543 if (item == NULL) return NULL;
544
545 return (struct group *)((uintptr_t)item + sizeof(si_item_t));
546 }
547
548 LIBINFO_EXPORT
549 void
550 endgrent(void)
551 {
552 #ifdef CALL_TRACE
553 fprintf(stderr, "-- %s\n", __func__);
554 #endif
555
556 LI_set_thread_list(CATEGORY_GROUP, NULL);
557 }
558
559 LIBINFO_EXPORT
560 int
561 setgroupent(int ignored)
562 {
563 si_list_t *list;
564
565 #ifdef CALL_TRACE
566 fprintf(stderr, "-> %s\n", __func__);
567 #endif
568
569 list = LI_get_thread_list(CATEGORY_GROUP);
570 si_list_reset(list);
571
572 if (list == NULL) return 0;
573 return 1;
574 }
575
576 /* NETGROUP */
577 LIBINFO_EXPORT
578 int
579 innetgr(const char *group, const char *host, const char *user, const char *domain)
580 {
581 int res;
582 #ifdef CALL_TRACE
583 fprintf(stderr, "-> %s %s %s %s %s\n", __func__, group, host, user, domain);
584 #endif
585
586 res = si_in_netgroup(si_search(), group, host, user, domain);
587
588 #ifdef CALL_TRACE
589 fprintf(stderr, "<- %s %d\n", __func__, res);
590 #endif
591
592 return res;
593 }
594
595 /* N.B. there is no async innetgr */
596
597 /*
598 * setnetgrent is really more like a getXXXbyname routine than a
599 * setXXXent routine, since we are looking up a netgroup by name.
600 */
601 LIBINFO_EXPORT
602 void
603 setnetgrent(const char *name)
604 {
605 si_list_t *list;
606
607 #ifdef CALL_TRACE
608 fprintf(stderr, "-> %s %s\n", __func__, name);
609 #endif
610
611 list = si_netgroup_byname(si_search(), name);
612 LI_set_thread_list(CATEGORY_NETGROUP, list);
613 }
614
615 /* N.B. there is no async getnetgrent */
616
617 LIBINFO_EXPORT
618 int
619 getnetgrent(char **host, char **user, char **domain)
620 {
621 si_list_t *list;
622 si_item_t *item;
623 struct netgrent_s *ng;
624
625 #ifdef CALL_TRACE
626 fprintf(stderr, "-> %s\n", __func__);
627 #endif
628
629 list = LI_get_thread_list(CATEGORY_NETGROUP);
630 item = si_list_next(list);
631 if (item == NULL) return 0;
632
633 ng = (struct netgrent_s *)((uintptr_t)item + sizeof(si_item_t));
634
635 *host = ng->ng_host;
636 *user = ng->ng_user;
637 *domain = ng->ng_domain;
638
639 return 1;
640 }
641
642 LIBINFO_EXPORT
643 void
644 endnetgrent(void)
645 {
646 #ifdef CALL_TRACE
647 fprintf(stderr, "-- %s\n", __func__);
648 #endif
649
650 LI_set_thread_list(CATEGORY_NETGROUP, NULL);
651 }
652
653 #if DS_AVAILABLE
654 static void
655 _check_groups(const char *function, int32_t ngroups)
656 {
657 static dispatch_once_t once;
658
659 if (ngroups > 0 && ngroups < NGROUPS_MAX) {
660 return;
661 }
662
663 /* only log once per process */
664 dispatch_once(&once, ^(void) {
665 const char *proc_name = getprogname();
666 if (strcmp(proc_name, "id") != 0 && strcmp(proc_name, "smbd") != 0 && strcmp(proc_name, "rpcsvchost") != 0) {
667 #pragma clang diagnostic push
668 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
669 aslmsg msg = asl_new(ASL_TYPE_MSG);
670 char buffer[256];
671
672 snprintf(buffer, sizeof(buffer), "%d", (ngroups == 0 ? INT_MAX : ngroups));
673 asl_set(msg, "com.apple.message.value", buffer);
674
675 asl_set(msg, "com.apple.message.domain", "com.apple.system.libinfo");
676 asl_set(msg, "com.apple.message.result", "noop");
677 asl_set(msg, "com.apple.message.signature", function);
678
679 asl_log(NULL, msg, ASL_LEVEL_NOTICE, "%s called triggering group enumeration", function);
680
681 asl_free(msg);
682 }
683 #pragma clang diagnostic pop
684 });
685 }
686 #endif
687
688 /* GROUPLIST */
689
690 static int
691 getgrouplist_internal(const char *name, int basegid, gid_t *groups, uint32_t *ngroups)
692 {
693 int i, j, x, g, add, max;
694 si_item_t *item;
695 si_grouplist_t *gl;
696
697 /*
698 * On input, ngroups specifies the size of the groups array.
699 * On output, it is set to the number of groups that are being returned.
700 * Returns -1 if the size is too small to fit all the groups that were found.
701 */
702
703 #ifdef CALL_TRACE
704 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
705 #endif
706
707 if (name == NULL) return 0;
708 if (groups == NULL) return 0;
709 if (ngroups == NULL) return 0;
710
711 max = (*ngroups);
712 *ngroups = 0;
713 if (max <= 0) return 0;
714
715 groups[0] = basegid;
716 *ngroups = 1;
717
718 item = si_grouplist(si_search(), name, max+1);
719 LI_set_thread_item(CATEGORY_GROUPLIST, item);
720 if (item == NULL) return 0;
721
722 gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t));
723
724 x = 1;
725
726 for (i = 0; i < gl->gl_count; i++)
727 {
728 g = gl->gl_gid[i];
729 add = 1;
730 for (j = 0; j < x; j++) {
731 if (groups[j] == g) {
732 add = 0;
733 break;
734 }
735 }
736 if (add == 0) continue;
737
738 if (x >= max) return -1;
739 groups[x] = g;
740 x++;
741 *ngroups = x;
742 }
743
744 return 0;
745 }
746
747 LIBINFO_EXPORT
748 int
749 getgrouplist(const char *name, int basegid, int *groups, int *ngroups)
750 {
751 #if DS_AVAILABLE
752 _check_groups("getgrouplist", *ngroups);
753 #endif
754
755 return getgrouplist_internal(name, basegid, (gid_t *)groups, (uint32_t *)ngroups);
756 }
757
758 static void
759 merge_gid(gid_t *list, gid_t g, int32_t *count)
760 {
761 int32_t cnt;
762 int i;
763
764 cnt = (*count);
765 for (i = 0; i < cnt; i++) {
766 if (list[i] == g) return;
767 }
768
769 list[cnt] = g;
770 (*count)++;
771 }
772
773 static int32_t
774 _getgrouplist_2_internal(const char *name, gid_t basegid, gid_t **groups)
775 {
776 int32_t i, count;
777 si_item_t *item;
778 gid_t *gids;
779 si_grouplist_t *gl;
780
781 item = si_grouplist(si_search(), name, INT_MAX);
782 LI_set_thread_item(CATEGORY_GROUPLIST, item);
783 if (item == NULL) return -1;
784
785 gl = (si_grouplist_t *) ((uintptr_t) item + sizeof(si_item_t));
786
787 /*
788 * we can allocate enough up-front, we'll only use what we need
789 * we add one to the count that was found in case the basegid is not there
790 */
791 gids = calloc(gl->gl_count + 1, sizeof(gid_t));
792 if (gids == NULL) return -1;
793
794 count = 0;
795 merge_gid(gids, basegid, &count);
796 if (gl->gl_gid != NULL) {
797 for (i = 0; i < gl->gl_count; i++) {
798 merge_gid(gids, gl->gl_gid[i], &count);
799 }
800 }
801
802 (*groups) = gids;
803
804 return count;
805 }
806
807 LIBINFO_EXPORT
808 int32_t
809 getgrouplist_2(const char *name, gid_t basegid, gid_t **groups)
810 {
811 /*
812 * Passes back a gid_t list containing all the users groups (and basegid).
813 * Caller must free the list.
814 * Returns the number of gids in the list or -1 on failure.
815 */
816
817 #ifdef CALL_TRACE
818 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
819 #endif
820
821 if (name == NULL) return 0;
822 if (groups == NULL) return 0;
823
824 #if DS_AVAILABLE
825 _check_groups("getgrouplist_2", INT_MAX);
826 #endif
827
828 return _getgrouplist_2_internal(name, basegid, groups);
829 }
830
831 LIBINFO_EXPORT
832 int32_t
833 getgroupcount(const char *name, gid_t basegid)
834 {
835 int32_t count;
836 gid_t *groups;
837
838 #ifdef CALL_TRACE
839 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
840 #endif
841
842 #if DS_AVAILABLE
843 _check_groups("getgroupcount", INT_MAX);
844 #endif
845
846 groups = NULL;
847 count = _getgrouplist_2_internal(name, basegid, &groups);
848 if (groups != NULL) free(groups);
849
850 return count;
851 }
852
853 /* XXX to do: async getgrouplist_2 */
854
855 LIBINFO_EXPORT
856 int
857 initgroups(const char *name, int basegid)
858 {
859 int status;
860 uint32_t ngroups;
861 gid_t groups[NGROUPS];
862 uid_t uid;
863 #ifdef DS_AVAILABLE
864 si_item_t *item;
865 struct passwd *p;
866 #endif
867
868 #ifdef CALL_TRACE
869 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
870 #endif
871
872 /* KAUTH_UID_NONE tells the kernel not to fetch supplementary groups from DirectoryService */
873 uid = KAUTH_UID_NONE;
874
875 #ifdef DS_AVAILABLE
876 /* get the UID for this user */
877 item = si_user_byname(si_search(), name);
878 if (item != NULL)
879 {
880 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
881 uid = p->pw_uid;
882 si_item_release(item);
883 }
884 #endif
885
886 ngroups = NGROUPS;
887
888 /*
889 * Ignore status.
890 * A failure either means that user belongs to more than NGROUPS groups
891 * or no groups at all.
892 */
893
894 (void) getgrouplist_internal(name, basegid, groups, &ngroups);
895
896 status = __initgroups(ngroups, groups, uid);
897 if (status < 0) return -1;
898
899 return 0;
900 }
901
902 /* ALIAS */
903
904 LIBINFO_EXPORT
905 struct aliasent *
906 alias_getbyname(const char *name)
907 {
908 si_item_t *item;
909
910 #ifdef CALL_TRACE
911 fprintf(stderr, "-> %s %s\n", __func__, name);
912 #endif
913
914 item = si_alias_byname(si_search(), name);
915 LI_set_thread_item(CATEGORY_ALIAS + 100, item);
916 if (item == NULL) return NULL;
917
918 return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t));
919 }
920
921 mach_port_t
922 alias_getbyname_async_call(const char *name, si_alias_async_callback callback, void *context)
923 {
924 si_context_t *sictx;
925
926 #ifdef CALL_TRACE
927 fprintf(stderr, ">> %s %s\n", __func__, name);
928 #endif
929
930 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
931 if (sictx == NULL) return MACH_PORT_NULL;
932
933 sictx->orig_callback = callback;
934 sictx->orig_context = context;
935 sictx->cat = CATEGORY_ALIAS;
936 sictx->key_offset = 100;
937
938 return si_async_call(si_search(), SI_CALL_ALIAS_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
939 }
940
941 void
942 alias_getbyname_async_handle_reply(mach_msg_header_t *msg)
943 {
944 #ifdef CALL_TRACE
945 fprintf(stderr, "<< %s\n", __func__);
946 #endif
947
948 si_async_handle_reply(msg);
949 }
950
951 LIBINFO_EXPORT
952 void
953 alias_setent(void)
954 {
955 #ifdef CALL_TRACE
956 fprintf(stderr, "-> %s\n", __func__);
957 #endif
958
959 LI_set_thread_list(CATEGORY_ALIAS, NULL);
960 }
961
962 LIBINFO_EXPORT
963 struct aliasent *
964 alias_getent(void)
965 {
966 si_list_t *list;
967 si_item_t *item;
968
969 #ifdef CALL_TRACE
970 fprintf(stderr, "-> %s\n", __func__);
971 #endif
972
973 list = LI_get_thread_list(CATEGORY_ALIAS);
974 if (list == NULL)
975 {
976 list = si_alias_all(si_search());
977 LI_set_thread_list(CATEGORY_ALIAS, list);
978 }
979
980 item = si_list_next(list);
981 if (item == NULL) return NULL;
982
983 return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t));
984 }
985
986 LIBINFO_EXPORT
987 void
988 alias_endent(void)
989 {
990 #ifdef CALL_TRACE
991 fprintf(stderr, "-- %s\n", __func__);
992 #endif
993
994 LI_set_thread_list(CATEGORY_ALIAS, NULL);
995 }
996
997 /* HOST */
998
999 LIBINFO_EXPORT
1000 void
1001 freehostent(struct hostent *h)
1002 {
1003 if (h == NULL) return;
1004
1005 si_item_t *item = (si_item_t *)((uintptr_t)h - sizeof(si_item_t));
1006 si_item_release(item);
1007 }
1008
1009 struct hostent *
1010 gethostbynameerrno(const char *name, int *err)
1011 {
1012 si_item_t *item;
1013 uint32_t status;
1014 struct in_addr addr4;
1015
1016 #ifdef CALL_TRACE
1017 fprintf(stderr, "-> %s %s\n", __func__, name);
1018 #endif
1019
1020 memset(&addr4, 0, sizeof(struct in_addr));
1021 status = SI_STATUS_NO_ERROR;
1022 item = NULL;
1023
1024 if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, NULL, &status);
1025 else item = si_host_byname(si_search(), name, AF_INET, NULL, &status);
1026
1027 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1028 if (err != NULL) *err = status;
1029
1030 LI_set_thread_item(CATEGORY_HOST + 100, item);
1031 if (item == NULL) return NULL;
1032
1033 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1034 }
1035
1036 LIBINFO_EXPORT
1037 struct hostent *
1038 gethostbyname(const char *name)
1039 {
1040 si_item_t *item;
1041 uint32_t status;
1042 struct in_addr addr4;
1043
1044 #ifdef CALL_TRACE
1045 fprintf(stderr, "-> %s %s\n", __func__, name);
1046 #endif
1047
1048 memset(&addr4, 0, sizeof(struct in_addr));
1049 status = SI_STATUS_NO_ERROR;
1050 item = NULL;
1051
1052 if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, NULL, &status);
1053 else item = si_host_byname(si_search(), name, AF_INET, NULL, &status);
1054
1055 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1056 h_errno = status;
1057
1058 LI_set_thread_item(CATEGORY_HOST + 100, item);
1059 if (item == NULL) return NULL;
1060
1061 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1062 }
1063
1064 mach_port_t
1065 gethostbyname_async_call(const char *name, si_host_async_callback callback, void *context)
1066 {
1067 si_context_t *sictx;
1068
1069 #ifdef CALL_TRACE
1070 fprintf(stderr, ">> %s %s\n", __func__, name);
1071 #endif
1072
1073 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1074 if (sictx == NULL) return MACH_PORT_NULL;
1075
1076 sictx->orig_callback = callback;
1077 sictx->orig_context = context;
1078 sictx->cat = CATEGORY_HOST;
1079 sictx->key_offset = 100;
1080
1081 return si_async_call(si_search(), SI_CALL_HOST_BYNAME, name, NULL, NULL, AF_INET, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1082 }
1083
1084 LIBINFO_EXPORT
1085 mach_port_t
1086 gethostbyname_async_start(const char *name, si_host_async_callback callback, void *context)
1087 {
1088 return gethostbyname_async_call(name, callback, context);
1089 }
1090
1091 LIBINFO_EXPORT
1092 void
1093 gethostbyname_async_cancel(mach_port_t p)
1094 {
1095 #ifdef CALL_TRACE
1096 fprintf(stderr, "-- %s\n", __func__);
1097 #endif
1098
1099 si_async_cancel(p);
1100 }
1101
1102 #if 0
1103 void
1104 gethostbyname_async_handle_reply(void *param)
1105 {
1106 mach_msg_header_t *msg;
1107
1108 #ifdef CALL_TRACE
1109 fprintf(stderr, "<< %s\n", __func__);
1110 #endif
1111
1112 msg = (mach_msg_header_t *)param;
1113 si_async_handle_reply(msg);
1114 }
1115 #endif
1116
1117 LIBINFO_EXPORT
1118 void
1119 gethostbyname_async_handleReply(void *param)
1120 {
1121 mach_msg_header_t *msg;
1122
1123 #ifdef CALL_TRACE
1124 fprintf(stderr, "<< %s\n", __func__);
1125 #endif
1126
1127 msg = (mach_msg_header_t *)param;
1128 si_async_handle_reply(msg);
1129 }
1130
1131 LIBINFO_EXPORT
1132 struct hostent *
1133 gethostbyname2(const char *name, int af)
1134 {
1135 si_item_t *item;
1136 uint32_t status;
1137 struct in_addr addr4;
1138 struct in6_addr addr6;
1139 si_mod_t *search = si_search();
1140
1141 #ifdef CALL_TRACE
1142 fprintf(stderr, "-> %s %s %d\n", __func__, name, af);
1143 #endif
1144
1145 memset(&addr4, 0, sizeof(struct in_addr));
1146 memset(&addr6, 0, sizeof(struct in6_addr));
1147 status = SI_STATUS_NO_ERROR;
1148 item = NULL;
1149
1150 if (((af == AF_INET) && (inet_aton(name, &addr4) == 1)) || ((af == AF_INET6) && (inet_pton(af, name, &addr6) == 1)))
1151 {
1152 item = si_ipnode_byname(search, name, (uint32_t)af, 0, NULL, &status);
1153 }
1154 else
1155 {
1156 item = si_host_byname(search, name, (uint32_t)af, NULL, &status);
1157 }
1158
1159 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1160 h_errno = status;
1161
1162 LI_set_thread_item(CATEGORY_HOST + 100, item);
1163 if (item == NULL) return NULL;
1164
1165 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1166 }
1167
1168 mach_port_t
1169 gethostbyname2_async_call(const char *name, int af, si_group_async_callback callback, void *context)
1170 {
1171 si_context_t *sictx;
1172
1173 #ifdef CALL_TRACE
1174 fprintf(stderr, ">> %s %s %d\n", __func__, name, af);
1175 #endif
1176
1177 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1178 if (sictx == NULL) return MACH_PORT_NULL;
1179
1180 sictx->orig_callback = callback;
1181 sictx->orig_context = context;
1182 sictx->cat = CATEGORY_HOST;
1183 sictx->key_offset = 100;
1184
1185 return si_async_call(si_search(), SI_CALL_HOST_BYNAME, name, NULL, NULL, (uint32_t)af, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1186 }
1187
1188 void
1189 gethostbyname2_async_cancel(mach_port_t p)
1190 {
1191 #ifdef CALL_TRACE
1192 fprintf(stderr, "-- %s\n", __func__);
1193 #endif
1194
1195 si_async_cancel(p);
1196 }
1197
1198 void
1199 gethostbyname2_async_handle_reply(mach_msg_header_t *msg)
1200 {
1201 #ifdef CALL_TRACE
1202 fprintf(stderr, "<< %s\n", __func__);
1203 #endif
1204
1205 si_async_handle_reply(msg);
1206 }
1207
1208 LIBINFO_EXPORT
1209 struct hostent *
1210 gethostbyaddr(const void *addr, socklen_t len, int type)
1211 {
1212 si_item_t *item;
1213 uint32_t status;
1214
1215 #ifdef CALL_TRACE
1216 fprintf(stderr, "-> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-");
1217 #endif
1218
1219 status = SI_STATUS_NO_ERROR;
1220
1221 item = si_host_byaddr(si_search(), addr, (uint32_t)type, NULL, &status);
1222 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1223 h_errno = status;
1224
1225 LI_set_thread_item(CATEGORY_HOST + 200, item);
1226 if (item == NULL) return NULL;
1227
1228 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1229 }
1230
1231 mach_port_t
1232 gethostbyaddr_async_call(const void *addr, socklen_t len, int type, si_host_async_callback callback, void *context)
1233 {
1234 si_context_t *sictx;
1235 uint32_t addrlen;
1236
1237 #ifdef CALL_TRACE
1238 fprintf(stderr, ">> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-");
1239 #endif
1240
1241 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1242 if (sictx == NULL) return MACH_PORT_NULL;
1243
1244 sictx->orig_callback = callback;
1245 sictx->orig_context = context;
1246 sictx->cat = CATEGORY_HOST;
1247 sictx->key_offset = 200;
1248
1249 /* addr is not a C string - pass length in num3 */
1250 addrlen = len;
1251 return si_async_call(si_search(), SI_CALL_HOST_BYADDR, addr, NULL, NULL, (uint32_t)type, 0, addrlen, 0, (void *)si_libinfo_general_callback, sictx);
1252 }
1253
1254 LIBINFO_EXPORT
1255 mach_port_t
1256 gethostbyaddr_async_start(const char *addr, int len, int family, si_host_async_callback callback, void *context)
1257 {
1258 socklen_t slen = len;
1259
1260 return gethostbyaddr_async_call(addr, slen, family, callback, context);
1261 }
1262
1263 LIBINFO_EXPORT
1264 void
1265 gethostbyaddr_async_cancel(mach_port_t p)
1266 {
1267 #ifdef CALL_TRACE
1268 fprintf(stderr, "-- %s\n", __func__);
1269 #endif
1270
1271 si_async_cancel(p);
1272 }
1273
1274 #if 0
1275 void
1276 gethostbyaddr_async_handle_reply(void *param)
1277 {
1278
1279 mach_msg_header_t *msg;
1280
1281 #ifdef CALL_TRACE
1282 fprintf(stderr, "<< %s\n", __func__);
1283 #endif
1284
1285 msg = (mach_msg_header_t *)param;
1286 si_async_handle_reply(msg);
1287 }
1288 #endif
1289
1290 LIBINFO_EXPORT
1291 void
1292 gethostbyaddr_async_handleReply(void *param)
1293 {
1294 mach_msg_header_t *msg;
1295
1296 #ifdef CALL_TRACE
1297 fprintf(stderr, "<< %s\n", __func__);
1298 #endif
1299
1300 msg = (mach_msg_header_t *)param;
1301 si_async_handle_reply(msg);
1302 }
1303
1304 LIBINFO_EXPORT
1305 struct hostent *
1306 getipnodebyname(const char *name, int family, int flags, int *err)
1307 {
1308 si_item_t *item;
1309 uint32_t status;
1310
1311 #ifdef CALL_TRACE
1312 fprintf(stderr, "-> %s %s %d 0x%08x\n", __func__, name, family, flags);
1313 #endif
1314
1315 status = SI_STATUS_NO_ERROR;
1316
1317 item = si_ipnode_byname(si_search(), name, family, flags, NULL, &status);
1318 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1319 if (err != NULL) *err = status;
1320
1321 if (item == NULL) return NULL;
1322
1323 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1324 }
1325
1326 #if 0
1327 mach_port_t
1328 getipnodebyname_async_call(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context)
1329 {
1330 si_context_t *sictx;
1331
1332 #ifdef CALL_TRACE
1333 fprintf(stderr, ">> %s %s %d 0x%08x\n", __func__, name, family, flags);
1334 #endif
1335
1336 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1337 if (sictx == NULL) return MACH_PORT_NULL;
1338
1339 sictx->orig_callback = callback;
1340 sictx->orig_context = context;
1341 sictx->cat = CATEGORY_HOST;
1342 sictx->key_offset = -1;
1343
1344 return si_async_call(si_search(), SI_CALL_IPNODE_BYNAME, name, NULL, NULL, (uint32_t)family, (uint32_t)flags, 0, 0, (void *)si_libinfo_general_callback, sictx);
1345 }
1346
1347 mach_port_t
1348 getipnodebyname_async_start(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context)
1349 {
1350 return getipnodebyname_async_call(name, family, flags, err, callback, context);
1351 }
1352
1353 void
1354 getipnodebyname_async_cancel(mach_port_t p)
1355 {
1356 #ifdef CALL_TRACE
1357 fprintf(stderr, "-- %s\n", __func__);
1358 #endif
1359
1360 si_async_cancel(p);
1361 }
1362
1363 void
1364 getipnodebyname_async_handle_reply(mach_msg_header_t *msg)
1365 {
1366 #ifdef CALL_TRACE
1367 fprintf(stderr, "<< %s\n", __func__);
1368 #endif
1369
1370 si_async_handle_reply(msg);
1371 }
1372
1373 void
1374 getipnodebyname_async_handleReply(mach_msg_header_t *msg)
1375 {
1376 #ifdef CALL_TRACE
1377 fprintf(stderr, "<< %s\n", __func__);
1378 #endif
1379
1380 si_async_handle_reply(msg);
1381 }
1382 #endif
1383
1384 static int
1385 is_a4_mapped(const char *s)
1386 {
1387 int i;
1388 u_int8_t c;
1389
1390 if (s == NULL) return 0;
1391
1392 for (i = 0; i < 10; i++)
1393 {
1394 c = s[i];
1395 if (c != 0x0) return 0;
1396 }
1397
1398 for (i = 10; i < 12; i++)
1399 {
1400 c = s[i];
1401 if (c != 0xff) return 0;
1402 }
1403
1404 return 1;
1405 }
1406
1407 static int
1408 is_a4_compat(const char *s)
1409 {
1410 int i;
1411 u_int8_t c;
1412
1413 if (s == NULL) return 0;
1414
1415 for (i = 0; i < 12; i++)
1416 {
1417 c = s[i];
1418 if (c != 0x0) return 0;
1419 }
1420
1421 /* Check for :: and ::1 */
1422 for (i = 13; i < 15; i++)
1423 {
1424 /* anything non-zero in these 3 bytes means it's a V4 address */
1425 c = s[i];
1426 if (c != 0x0) return 1;
1427 }
1428
1429 /* Leading 15 bytes are all zero */
1430 c = s[15];
1431 if (c == 0x0) return 0;
1432 if (c == 0x1) return 0;
1433
1434 return 1;
1435 }
1436
1437 LIBINFO_EXPORT
1438 struct hostent *
1439 getipnodebyaddr(const void *src, size_t len, int family, int *err)
1440 {
1441 si_item_t *item;
1442
1443 #ifdef CALL_TRACE
1444 fprintf(stderr, "-> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-");
1445 #endif
1446
1447 if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src)))
1448 {
1449 src += 12;
1450 len = 4;
1451 family = AF_INET;
1452 }
1453
1454 item = si_host_byaddr(si_search(), src, family, NULL, (uint32_t *)err);
1455 if (item == NULL) return NULL;
1456
1457 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1458 }
1459
1460 #if 0
1461 static void
1462 si_libinfo_ipnode_callback(si_item_t *item, uint32_t status, void *ctx)
1463 {
1464 si_context_t *sictx;
1465 struct hostent *h;
1466
1467 if (ctx == NULL) return;
1468
1469 sictx = (si_context_t *)ctx;
1470
1471 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
1472 {
1473 free(sictx);
1474 si_item_release(item);
1475 return;
1476 }
1477
1478 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1479
1480 if (item == NULL)
1481 {
1482 ((si_ipnode_async_callback)(sictx->orig_callback))(NULL, status, sictx->orig_context);
1483 return;
1484 }
1485
1486 h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1487 ((si_ipnode_async_callback)(sictx->orig_callback))(h, status, sictx->orig_context);
1488
1489 free(sictx);
1490 }
1491
1492 mach_port_t
1493 getipnodebyaddr_async_call(const void *src, socklen_t len, int family, int *err, si_ipnode_async_callback callback, void *context)
1494 {
1495 si_context_t *sictx;
1496 uint32_t srclen;
1497
1498 #ifdef CALL_TRACE
1499 fprintf(stderr, ">> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-");
1500 #endif
1501
1502 if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src)))
1503 {
1504 src += 12;
1505 len = 4;
1506 family = AF_INET;
1507 }
1508
1509 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1510 if (sictx == NULL) return MACH_PORT_NULL;
1511
1512 sictx->orig_callback = callback;
1513 sictx->orig_context = context;
1514 sictx->cat = CATEGORY_HOST;
1515 sictx->key_offset = -1;
1516
1517 /* src is not a C string - pass length in num3 */
1518 srclen = len;
1519 return si_async_call(si_search(), SI_CALL_HOST_BYADDR, src, NULL, NULL, (uint32_t)family, 0, srclen, 0, (void *)si_libinfo_ipnode_callback, sictx);
1520 }
1521
1522 mach_port_t
1523 getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, si_ipnode_async_callback callback, void *context)
1524 {
1525 socklen_t slen = len;
1526
1527 return getipnodebyaddr_async_call(addr, slen, family, error, callback, context);
1528 }
1529
1530 void
1531 getipnodebyaddr_async_cancel(mach_port_t p)
1532 {
1533 #ifdef CALL_TRACE
1534 fprintf(stderr, "-- %s\n", __func__);
1535 #endif
1536
1537 si_async_cancel(p);
1538 }
1539
1540 void
1541 getipnodebyaddr_async_handle_reply(mach_msg_header_t *msg)
1542 {
1543 #ifdef CALL_TRACE
1544 fprintf(stderr, "<< %s\n", __func__);
1545 #endif
1546
1547 si_async_handle_reply(msg);
1548 }
1549
1550 void
1551 getipnodebyaddr_async_handleReply(mach_msg_header_t *msg)
1552 {
1553 #ifdef CALL_TRACE
1554 fprintf(stderr, "<< %s\n", __func__);
1555 #endif
1556
1557 si_async_handle_reply(msg);
1558 }
1559 #endif
1560
1561 LIBINFO_EXPORT
1562 void
1563 sethostent(int ignored)
1564 {
1565 #ifdef CALL_TRACE
1566 fprintf(stderr, "-- %s\n", __func__);
1567 #endif
1568
1569 LI_set_thread_list(CATEGORY_HOST, NULL);
1570 }
1571
1572 LIBINFO_EXPORT
1573 struct hostent *
1574 gethostent(void)
1575 {
1576 si_list_t *list;
1577 si_item_t *item;
1578
1579 #ifdef CALL_TRACE
1580 fprintf(stderr, "-> %s\n", __func__);
1581 #endif
1582
1583 list = LI_get_thread_list(CATEGORY_HOST);
1584 if (list == NULL)
1585 {
1586 list = si_host_all(si_search());
1587 LI_set_thread_list(CATEGORY_HOST, list);
1588 }
1589
1590 item = si_list_next(list);
1591 if (item == NULL) return NULL;
1592
1593 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1594 }
1595
1596 LIBINFO_EXPORT
1597 void
1598 endhostent(void)
1599 {
1600 #ifdef CALL_TRACE
1601 fprintf(stderr, "-- %s\n", __func__);
1602 #endif
1603
1604 LI_set_thread_list(CATEGORY_HOST, NULL);
1605 }
1606
1607 /* MAC ADDRESS */
1608
1609 LIBINFO_EXPORT
1610 int
1611 ether_hostton(const char *name, struct ether_addr *e)
1612 {
1613 si_item_t *item;
1614 si_mac_t *mac;
1615 uint32_t t[6];
1616 int i;
1617
1618 #ifdef CALL_TRACE
1619 fprintf(stderr, "-> %s %s\n", __func__, name);
1620 #endif
1621
1622 if (name == NULL) return -1;
1623 if (e == NULL) return -1;
1624
1625 item = si_mac_byname(si_search(), name);
1626 LI_set_thread_item(CATEGORY_MAC + 100, item);
1627 if (item == NULL) return -1;
1628
1629 mac = (si_mac_t *)((uintptr_t)item + sizeof(si_item_t));
1630
1631 i = sscanf(mac->mac, " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]);
1632 if (i != 6) return -1;
1633
1634 for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i];
1635 return 0;
1636 }
1637
1638 /* XXX to do? async ether_hostton */
1639
1640 LIBINFO_EXPORT
1641 int
1642 ether_ntohost(char *name, const struct ether_addr *e)
1643 {
1644 si_item_t *item;
1645 si_mac_t *mac;
1646 uint32_t i, x[6];
1647 char str[256];
1648
1649 if (name == NULL) return -1;
1650 if (e == NULL) return -1;
1651
1652 for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i];
1653 snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]);
1654
1655 #ifdef CALL_TRACE
1656 fprintf(stderr, "-> %s %s\n", __func__, str);
1657 #endif
1658
1659 item = si_mac_bymac(si_search(), str);
1660 LI_set_thread_item(CATEGORY_MAC + 200, item);
1661 if (item == NULL) return -1;
1662
1663 mac = (si_mac_t *)((uintptr_t)item + sizeof(si_item_t));
1664
1665 memcpy(name, mac->host, strlen(mac->host) + 1);
1666 return 0;
1667 }
1668
1669 /* XXX to do? async ether_ntohost */
1670
1671 /* NETWORK */
1672
1673 LIBINFO_EXPORT
1674 struct netent *
1675 getnetbyname(const char *name)
1676 {
1677 si_item_t *item;
1678
1679 #ifdef CALL_TRACE
1680 fprintf(stderr, "-> %s %s\n", __func__, name);
1681 #endif
1682
1683 item = si_network_byname(si_search(), name);
1684 LI_set_thread_item(CATEGORY_NETWORK + 100, item);
1685 if (item == NULL) return NULL;
1686
1687 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1688 }
1689
1690 mach_port_t
1691 getnetbyname_async_call(const char *name, si_network_async_callback callback, void *context)
1692 {
1693 si_context_t *sictx;
1694
1695 #ifdef CALL_TRACE
1696 fprintf(stderr, ">> %s %s\n", __func__, name);
1697 #endif
1698
1699 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1700 if (sictx == NULL) return MACH_PORT_NULL;
1701
1702 sictx->orig_callback = callback;
1703 sictx->orig_context = context;
1704 sictx->cat = CATEGORY_NETWORK;
1705 sictx->key_offset = 100;
1706
1707 return si_async_call(si_search(), SI_CALL_NETWORK_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1708 }
1709
1710 void
1711 getnetbyname_async_handle_reply(mach_msg_header_t *msg)
1712 {
1713 #ifdef CALL_TRACE
1714 fprintf(stderr, "<< %s\n", __func__);
1715 #endif
1716
1717 si_async_handle_reply(msg);
1718 }
1719
1720 LIBINFO_EXPORT
1721 struct netent *
1722 getnetbyaddr(uint32_t net, int type)
1723 {
1724 si_item_t *item;
1725
1726 #ifdef CALL_TRACE
1727 fprintf(stderr, "-> %s 0x%08x\n", __func__, net);
1728 #endif
1729
1730 if (type != AF_INET) return NULL;
1731
1732 item = si_network_byaddr(si_search(), net);
1733 LI_set_thread_item(CATEGORY_NETWORK + 200, item);
1734 if (item == NULL) return NULL;
1735
1736 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1737 }
1738
1739 mach_port_t
1740 getnetbyaddr_async_call(uint32_t net, int type, si_group_async_callback callback, void *context)
1741 {
1742 si_context_t *sictx;
1743
1744 #ifdef CALL_TRACE
1745 fprintf(stderr, ">> %s 0x%08x\n", __func__, net);
1746 #endif
1747
1748 if (type != AF_INET) return MACH_PORT_NULL;
1749
1750 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1751 if (sictx == NULL) return MACH_PORT_NULL;
1752
1753 sictx->orig_callback = callback;
1754 sictx->orig_context = context;
1755 sictx->cat = CATEGORY_NETWORK;
1756 sictx->key_offset = 200;
1757
1758 return si_async_call(si_search(), SI_CALL_NETWORK_BYADDR, NULL, NULL, NULL, net, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1759 }
1760
1761 void
1762 getnetbyaddr_async_handle_reply(mach_msg_header_t *msg)
1763 {
1764 #ifdef CALL_TRACE
1765 fprintf(stderr, "<< %s\n", __func__);
1766 #endif
1767
1768 si_async_handle_reply(msg);
1769 }
1770
1771 LIBINFO_EXPORT
1772 void
1773 setnetent(int ignored)
1774 {
1775 #ifdef CALL_TRACE
1776 fprintf(stderr, "-- %s\n", __func__);
1777 #endif
1778
1779 LI_set_thread_list(CATEGORY_NETWORK, NULL);
1780 }
1781
1782 LIBINFO_EXPORT
1783 struct netent *
1784 getnetent(void)
1785 {
1786 si_list_t *list;
1787 si_item_t *item;
1788
1789 #ifdef CALL_TRACE
1790 fprintf(stderr, "-> %s\n", __func__);
1791 #endif
1792
1793 list = LI_get_thread_list(CATEGORY_NETWORK);
1794 if (list == NULL)
1795 {
1796 list = si_network_all(si_search());
1797 LI_set_thread_list(CATEGORY_NETWORK, list);
1798 }
1799
1800 item = si_list_next(list);
1801 if (item == NULL) return NULL;
1802
1803 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1804 }
1805
1806 LIBINFO_EXPORT
1807 void
1808 endnetent(void)
1809 {
1810 #ifdef CALL_TRACE
1811 fprintf(stderr, "-- %s\n", __func__);
1812 #endif
1813
1814 LI_set_thread_list(CATEGORY_NETWORK, NULL);
1815 }
1816
1817 /* SERVICE */
1818
1819 LIBINFO_EXPORT
1820 struct servent *
1821 getservbyname(const char *name, const char *proto)
1822 {
1823 si_item_t *item;
1824
1825 #ifdef CALL_TRACE
1826 fprintf(stderr, "-> %s %s %s\n", __func__, name, proto);
1827 #endif
1828
1829 item = si_service_byname(si_search(), name, proto);
1830 LI_set_thread_item(CATEGORY_SERVICE + 100, item);
1831 if (item == NULL) return NULL;
1832
1833 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1834 }
1835
1836 mach_port_t
1837 getservbyname_async_call(const char *name, const char *proto, si_service_async_callback callback, void *context)
1838 {
1839 si_context_t *sictx;
1840
1841 #ifdef CALL_TRACE
1842 fprintf(stderr, ">> %s %s %s\n", __func__, name, proto);
1843 #endif
1844
1845 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1846 if (sictx == NULL) return MACH_PORT_NULL;
1847
1848 sictx->orig_callback = callback;
1849 sictx->orig_context = context;
1850 sictx->cat = CATEGORY_SERVICE;
1851 sictx->key_offset = 100;
1852
1853 return si_async_call(si_search(), SI_CALL_SERVICE_BYNAME, name, proto, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1854 }
1855
1856 void
1857 getservbyname_async_handle_reply(mach_msg_header_t *msg)
1858 {
1859 #ifdef CALL_TRACE
1860 fprintf(stderr, "<< %s\n", __func__);
1861 #endif
1862
1863 si_async_handle_reply(msg);
1864 }
1865
1866 LIBINFO_EXPORT
1867 struct servent *
1868 getservbyport(int port, const char *proto)
1869 {
1870 si_item_t *item;
1871
1872 #ifdef CALL_TRACE
1873 fprintf(stderr, "-> %s %d %s\n", __func__, ntohs((uint16_t)port), proto);
1874 #endif
1875
1876 item = si_service_byport(si_search(), port, proto);
1877 LI_set_thread_item(CATEGORY_SERVICE + 200, item);
1878 if (item == NULL) return NULL;
1879
1880 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1881 }
1882
1883 mach_port_t
1884 getservbyport_async_call(int port, const char *proto, si_group_async_callback callback, void *context)
1885 {
1886 si_context_t *sictx;
1887
1888 #ifdef CALL_TRACE
1889 fprintf(stderr, ">> %s %d %s\n", __func__, port, proto);
1890 #endif
1891
1892 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1893 if (sictx == NULL) return MACH_PORT_NULL;
1894
1895 sictx->orig_callback = callback;
1896 sictx->orig_context = context;
1897 sictx->cat = CATEGORY_SERVICE;
1898 sictx->key_offset = 200;
1899
1900 return si_async_call(si_search(), SI_CALL_SERVICE_BYPORT, NULL, proto, NULL, port, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1901 }
1902
1903 void
1904 getservbyport_async_handle_reply(mach_msg_header_t *msg)
1905 {
1906 #ifdef CALL_TRACE
1907 fprintf(stderr, "<< %s\n", __func__);
1908 #endif
1909
1910 si_async_handle_reply(msg);
1911 }
1912
1913 LIBINFO_EXPORT
1914 void
1915 setservent(int ignored)
1916 {
1917 #ifdef CALL_TRACE
1918 fprintf(stderr, "-- %s\n", __func__);
1919 #endif
1920
1921 LI_set_thread_list(CATEGORY_SERVICE, NULL);
1922 }
1923
1924 LIBINFO_EXPORT
1925 struct servent *
1926 getservent(void)
1927 {
1928 si_list_t *list;
1929 si_item_t *item;
1930
1931 #ifdef CALL_TRACE
1932 fprintf(stderr, "-> %s\n", __func__);
1933 #endif
1934
1935 list = LI_get_thread_list(CATEGORY_SERVICE);
1936 if (list == NULL)
1937 {
1938 list = si_service_all(si_search());
1939 LI_set_thread_list(CATEGORY_SERVICE, list);
1940 }
1941
1942 item = si_list_next(list);
1943 if (item == NULL) return NULL;
1944
1945 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1946 }
1947
1948 LIBINFO_EXPORT
1949 void
1950 endservent(void)
1951 {
1952 #ifdef CALL_TRACE
1953 fprintf(stderr, "-- %s\n", __func__);
1954 #endif
1955
1956 LI_set_thread_list(CATEGORY_SERVICE, NULL);
1957 }
1958
1959 /* PROTOCOL */
1960
1961 LIBINFO_EXPORT
1962 struct protoent *
1963 getprotobyname(const char *name)
1964 {
1965 si_item_t *item;
1966
1967 #ifdef CALL_TRACE
1968 fprintf(stderr, "-> %s %s\n", __func__, name);
1969 #endif
1970
1971 item = si_protocol_byname(si_search(), name);
1972 LI_set_thread_item(CATEGORY_PROTOCOL + 100, item);
1973 if (item == NULL) return NULL;
1974
1975 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1976 }
1977
1978 mach_port_t
1979 getprotobyname_async_call(const char *name, si_protocol_async_callback callback, void *context)
1980 {
1981 si_context_t *sictx;
1982
1983 #ifdef CALL_TRACE
1984 fprintf(stderr, ">> %s %s\n", __func__, name);
1985 #endif
1986
1987 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1988 if (sictx == NULL) return MACH_PORT_NULL;
1989
1990 sictx->orig_callback = callback;
1991 sictx->orig_context = context;
1992 sictx->cat = CATEGORY_PROTOCOL;
1993 sictx->key_offset = 100;
1994
1995 return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1996 }
1997
1998 void
1999 getprotobyname_async_handle_reply(mach_msg_header_t *msg)
2000 {
2001 #ifdef CALL_TRACE
2002 fprintf(stderr, "<< %s\n", __func__);
2003 #endif
2004
2005 si_async_handle_reply(msg);
2006 }
2007
2008 LIBINFO_EXPORT
2009 struct protoent *
2010 getprotobynumber(int number)
2011 {
2012 si_item_t *item;
2013
2014 #ifdef CALL_TRACE
2015 fprintf(stderr, "-> %s %d\n", __func__, number);
2016 #endif
2017
2018 item = si_protocol_bynumber(si_search(), number);
2019 LI_set_thread_item(CATEGORY_PROTOCOL + 200, item);
2020 if (item == NULL) return NULL;
2021
2022 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
2023 }
2024
2025 mach_port_t
2026 getprotobynumber_async_call(int number, si_group_async_callback callback, void *context)
2027 {
2028 si_context_t *sictx;
2029
2030 #ifdef CALL_TRACE
2031 fprintf(stderr, ">> %s %d\n", __func__, number);
2032 #endif
2033
2034 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2035 if (sictx == NULL) return MACH_PORT_NULL;
2036
2037 sictx->orig_callback = callback;
2038 sictx->orig_context = context;
2039 sictx->cat = CATEGORY_PROTOCOL;
2040 sictx->key_offset = 200;
2041
2042 return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2043 }
2044
2045 void
2046 getprotobynumber_async_handle_reply(mach_msg_header_t *msg)
2047 {
2048 #ifdef CALL_TRACE
2049 fprintf(stderr, "<< %s\n", __func__);
2050 #endif
2051
2052 si_async_handle_reply(msg);
2053 }
2054
2055 LIBINFO_EXPORT
2056 void
2057 setprotoent(int ignored)
2058 {
2059 #ifdef CALL_TRACE
2060 fprintf(stderr, "-- %s\n", __func__);
2061 #endif
2062
2063 LI_set_thread_list(CATEGORY_PROTOCOL, NULL);
2064 }
2065
2066 LIBINFO_EXPORT
2067 struct protoent *
2068 getprotoent(void)
2069 {
2070 si_list_t *list;
2071 si_item_t *item;
2072
2073 #ifdef CALL_TRACE
2074 fprintf(stderr, "-> %s\n", __func__);
2075 #endif
2076
2077 list = LI_get_thread_list(CATEGORY_PROTOCOL);
2078 if (list == NULL)
2079 {
2080 list = si_protocol_all(si_search());
2081 LI_set_thread_list(CATEGORY_PROTOCOL, list);
2082 }
2083
2084 item = si_list_next(list);
2085 if (item == NULL) return NULL;
2086
2087 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
2088 }
2089
2090 LIBINFO_EXPORT
2091 void
2092 endprotoent(void)
2093 {
2094 #ifdef CALL_TRACE
2095 fprintf(stderr, "-- %s\n", __func__);
2096 #endif
2097
2098 LI_set_thread_list(CATEGORY_PROTOCOL, NULL);
2099 }
2100
2101 /* RPC */
2102
2103 LIBINFO_EXPORT
2104 struct rpcent *
2105 getrpcbyname(const char *name)
2106 {
2107 si_item_t *item;
2108
2109 #ifdef CALL_TRACE
2110 fprintf(stderr, "-> %s %s\n", __func__, name);
2111 #endif
2112
2113 item = si_rpc_byname(si_search(), name);
2114 LI_set_thread_item(CATEGORY_RPC + 100, item);
2115 if (item == NULL) return NULL;
2116
2117 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2118 }
2119
2120 mach_port_t
2121 getrpcbyname_async_call(const char *name, si_rpc_async_callback callback, void *context)
2122 {
2123 si_context_t *sictx;
2124
2125 #ifdef CALL_TRACE
2126 fprintf(stderr, ">> %s %s\n", __func__, name);
2127 #endif
2128
2129 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2130 if (sictx == NULL) return MACH_PORT_NULL;
2131
2132 sictx->orig_callback = callback;
2133 sictx->orig_context = context;
2134 sictx->cat = CATEGORY_RPC;
2135 sictx->key_offset = 100;
2136
2137 return si_async_call(si_search(), SI_CALL_RPC_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2138 }
2139
2140 void
2141 getrpcbyname_async_handle_reply(mach_msg_header_t *msg)
2142 {
2143 #ifdef CALL_TRACE
2144 fprintf(stderr, "<< %s\n", __func__);
2145 #endif
2146
2147 si_async_handle_reply(msg);
2148 }
2149
2150 LIBINFO_EXPORT
2151 struct rpcent *
2152 getrpcbynumber
2153 (
2154 #ifdef __LP64__
2155 int number
2156 #else
2157 long number
2158 #endif
2159 )
2160 {
2161 si_item_t *item;
2162
2163 #ifdef CALL_TRACE
2164 fprintf(stderr, "-> %s %ld\n", __func__, (long int)number);
2165 #endif
2166
2167 item = si_rpc_bynumber(si_search(), number);
2168 LI_set_thread_item(CATEGORY_RPC + 200, item);
2169 if (item == NULL) return NULL;
2170
2171 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2172 }
2173
2174 mach_port_t
2175 getrpcbynumber_async_call(int number, si_group_async_callback callback, void *context)
2176 {
2177 si_context_t *sictx;
2178
2179 #ifdef CALL_TRACE
2180 fprintf(stderr, ">> %s %d\n", __func__, number);
2181 #endif
2182
2183 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2184 if (sictx == NULL) return MACH_PORT_NULL;
2185
2186 sictx->orig_callback = callback;
2187 sictx->orig_context = context;
2188 sictx->cat = CATEGORY_RPC;
2189 sictx->key_offset = 200;
2190
2191 return si_async_call(si_search(), SI_CALL_RPC_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2192 }
2193
2194 void
2195 getrpcbynumber_async_handle_reply(mach_msg_header_t *msg)
2196 {
2197 #ifdef CALL_TRACE
2198 fprintf(stderr, "<< %s\n", __func__);
2199 #endif
2200
2201 si_async_handle_reply(msg);
2202 }
2203
2204 LIBINFO_EXPORT
2205 void
2206 setrpcent(int ignored)
2207 {
2208 #ifdef CALL_TRACE
2209 fprintf(stderr, "-- %s\n", __func__);
2210 #endif
2211
2212 LI_set_thread_list(CATEGORY_RPC, NULL);
2213 }
2214
2215 LIBINFO_EXPORT
2216 struct rpcent *
2217 getrpcent(void)
2218 {
2219 si_list_t *list;
2220 si_item_t *item;
2221
2222 #ifdef CALL_TRACE
2223 fprintf(stderr, "-> %s\n", __func__);
2224 #endif
2225
2226 list = LI_get_thread_list(CATEGORY_RPC);
2227 if (list == NULL)
2228 {
2229 list = si_rpc_all(si_search());
2230 LI_set_thread_list(CATEGORY_RPC, list);
2231 }
2232
2233 item = si_list_next(list);
2234 if (item == NULL) return NULL;
2235
2236 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2237 }
2238
2239 LIBINFO_EXPORT
2240 void
2241 endrpcent(void)
2242 {
2243 #ifdef CALL_TRACE
2244 fprintf(stderr, "-- %s\n", __func__);
2245 #endif
2246
2247 LI_set_thread_list(CATEGORY_RPC, NULL);
2248 }
2249
2250 /* FS */
2251
2252 LIBINFO_EXPORT
2253 struct fstab *
2254 getfsspec(const char *spec)
2255 {
2256 si_item_t *item;
2257
2258 #ifdef CALL_TRACE
2259 fprintf(stderr, "-> %s %s\n", __func__, spec);
2260 #endif
2261
2262 item = si_fs_byspec(si_search(), spec);
2263 LI_set_thread_item(CATEGORY_FS + 100, item);
2264 if (item == NULL) return NULL;
2265
2266 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2267 }
2268
2269 struct fstab *
2270 getfsbyname(const char *name)
2271 {
2272 #ifdef CALL_TRACE
2273 fprintf(stderr, "-> %s %s\n", __func__, name);
2274 #endif
2275
2276 return getfsspec(name);
2277 }
2278
2279 mach_port_t
2280 getfsspec_async_call(const char *spec, si_fs_async_callback callback, void *context)
2281 {
2282 si_context_t *sictx;
2283
2284 #ifdef CALL_TRACE
2285 fprintf(stderr, ">> %s %s\n", __func__, spec);
2286 #endif
2287
2288 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2289 if (sictx == NULL) return MACH_PORT_NULL;
2290
2291 sictx->orig_callback = callback;
2292 sictx->orig_context = context;
2293 sictx->cat = CATEGORY_FS;
2294 sictx->key_offset = 100;
2295
2296 return si_async_call(si_search(), SI_CALL_FS_BYSPEC, spec, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2297 }
2298
2299 void
2300 getfsspec_async_handle_reply(mach_msg_header_t *msg)
2301 {
2302 #ifdef CALL_TRACE
2303 fprintf(stderr, "<< %s\n", __func__);
2304 #endif
2305
2306 si_async_handle_reply(msg);
2307 }
2308
2309 LIBINFO_EXPORT
2310 struct fstab *
2311 getfsfile(const char *file)
2312 {
2313 si_item_t *item;
2314
2315 #ifdef CALL_TRACE
2316 fprintf(stderr, "-> %s %s\n", __func__, file);
2317 #endif
2318
2319 item = si_fs_byfile(si_search(), file);
2320 LI_set_thread_item(CATEGORY_FS + 200, item);
2321 if (item == NULL) return NULL;
2322
2323 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2324 }
2325
2326 mach_port_t
2327 getfsfile_async_call(const char *file, si_fs_async_callback callback, void *context)
2328 {
2329 si_context_t *sictx;
2330
2331 #ifdef CALL_TRACE
2332 fprintf(stderr, ">> %s %s\n", __func__, file);
2333 #endif
2334
2335 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2336 if (sictx == NULL) return MACH_PORT_NULL;
2337
2338 sictx->orig_callback = callback;
2339 sictx->orig_context = context;
2340 sictx->cat = CATEGORY_FS;
2341 sictx->key_offset = 200;
2342
2343 return si_async_call(si_search(), SI_CALL_FS_BYFILE, file, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2344 }
2345
2346 void
2347 getfsfile_async_handle_reply(mach_msg_header_t *msg)
2348 {
2349 #ifdef CALL_TRACE
2350 fprintf(stderr, "<< %s\n", __func__);
2351 #endif
2352
2353 si_async_handle_reply(msg);
2354 }
2355
2356 LIBINFO_EXPORT
2357 int
2358 setfsent(void)
2359 {
2360 #ifdef CALL_TRACE
2361 fprintf(stderr, "-> %s\n", __func__);
2362 #endif
2363
2364 LI_set_thread_list(CATEGORY_FS, NULL);
2365 return 1;
2366 }
2367
2368 LIBINFO_EXPORT
2369 struct fstab *
2370 getfsent(void)
2371 {
2372 si_list_t *list;
2373 si_item_t *item;
2374
2375 #ifdef CALL_TRACE
2376 fprintf(stderr, "-> %s\n", __func__);
2377 #endif
2378
2379 list = LI_get_thread_list(CATEGORY_FS);
2380 if (list == NULL)
2381 {
2382 list = si_fs_all(si_search());
2383 LI_set_thread_list(CATEGORY_FS, list);
2384 }
2385
2386 item = si_list_next(list);
2387 if (item == NULL) return NULL;
2388
2389 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2390 }
2391
2392 LIBINFO_EXPORT
2393 void
2394 endfsent(void)
2395 {
2396 #ifdef CALL_TRACE
2397 fprintf(stderr, "-- %s\n", __func__);
2398 #endif
2399
2400 LI_set_thread_list(CATEGORY_FS, NULL);
2401 }
2402
2403 /* GETADDRINFO */
2404
2405 static int
2406 _getaddrinfo_internal(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, struct addrinfo **res)
2407 {
2408 si_list_t *list;
2409 uint32_t family, socktype, protocol, flags, status;
2410 struct addrinfo *ai;
2411
2412 family = AF_UNSPEC;
2413 socktype = SOCK_UNSPEC;
2414 protocol = IPPROTO_UNSPEC;
2415 flags = 0;
2416 status = SI_STATUS_NO_ERROR;
2417
2418 if (res == NULL) return 0;
2419 *res = NULL;
2420
2421 if (hints != NULL)
2422 {
2423 family = hints->ai_family;
2424 socktype = hints->ai_socktype;
2425 protocol = hints->ai_protocol;
2426 flags = hints->ai_flags;
2427 }
2428
2429 if (flags == 0) flags = AI_DEFAULT;
2430
2431 #ifdef CALL_TRACE
2432 fprintf(stderr, "-> %s %s %s %u %u %u 0x%08x %s\n", __func__, nodename, servname, family, socktype, protocol, flags, (interface == NULL) ? "" : interface);
2433 #endif
2434
2435 list = si_addrinfo(si_search(), nodename, servname, family, socktype, protocol, flags, interface, &status);
2436 if ((status != SI_STATUS_NO_ERROR) || (list == NULL) || (list->count == 0))
2437 {
2438 si_list_release(list);
2439
2440 if (status == SI_STATUS_NO_ERROR) return EAI_NONAME;
2441 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2442 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2443 else status = status - SI_STATUS_EAI_PLUS_100;
2444 return status;
2445 }
2446
2447 *res = si_list_to_addrinfo(list);
2448 si_list_release(list);
2449 if (*res == NULL) status = EAI_MEMORY;
2450
2451 /* don't return the canonical name unless asked */
2452 if ((flags & AI_CANONNAME) == 0)
2453 {
2454 for (ai = *res; ai != NULL; ai = ai->ai_next)
2455 {
2456 free(ai->ai_canonname);
2457 ai->ai_canonname = NULL;
2458 }
2459 }
2460
2461 return status;
2462 }
2463
2464 LIBINFO_EXPORT
2465 int
2466 getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
2467 {
2468 return _getaddrinfo_internal(nodename, servname, hints, NULL, res);
2469 }
2470
2471 #ifdef CALL_TRACE
2472
2473 static char *
2474 socket_name(int sock)
2475 {
2476 static char str[16];
2477
2478 switch(sock)
2479 {
2480 case SOCK_UNSPEC: return "SOCK_UNSPEC";
2481 case SOCK_STREAM: return "SOCK_STREAM";
2482 case SOCK_DGRAM: return "SOCK_DGRAM";
2483 }
2484
2485 sprintf(str, "%d", sock);
2486 return str;
2487 }
2488
2489 static char *
2490 family_name(int pf)
2491 {
2492 static char str[16];
2493
2494 switch(pf)
2495 {
2496 case PF_UNSPEC: return "PF_UNSPEC";
2497 case PF_INET: return "PF_INET";
2498 case PF_INET6: return "PF_INET6";
2499 };
2500
2501 sprintf(str, "%d", pf);
2502 return str;
2503 }
2504
2505 static char *
2506 protocol_name(int p)
2507 {
2508 static char str[16];
2509
2510 switch(p)
2511 {
2512 case IPPROTO_UNSPEC: return "IPPROTO_UNSPEC";
2513 case IPPROTO_TCP: return "IPPROTO_TCP";
2514 case IPPROTO_UDP: return "IPPROTO_UDP";
2515 }
2516
2517 sprintf(str, "%d", p);
2518 return str;
2519 }
2520
2521 static char *
2522 _gai_inet_ntop(struct in6_addr a)
2523 {
2524 static char buf[128];
2525 char t[32];
2526 unsigned short x;
2527 char *p;
2528 int i;
2529
2530 memset(buf, 0, 128);
2531
2532 p = (char *)&a.__u6_addr.__u6_addr32;
2533 for (i = 0; i < 8; i++, x += 1)
2534 {
2535 memmove(&x, p, 2);
2536 p += 2;
2537 sprintf(t, "%hx", x);
2538 strcat(buf, t);
2539 if (i < 7) strcat(buf, ":");
2540 }
2541
2542 return buf;
2543 }
2544
2545 static void
2546 fprint_addrinfo(FILE *f, struct addrinfo *a)
2547 {
2548 int i;
2549 unsigned char v;
2550 struct sockaddr_in *s4;
2551 struct sockaddr_in6 *s6;
2552
2553 if (a == NULL) return;
2554
2555 if (a->ai_flags != 0)
2556 {
2557 fprintf(f, "flags =");
2558 if (a->ai_flags & AI_PASSIVE) fprintf(f, " AI_PASSIVE");
2559 if (a->ai_flags & AI_CANONNAME) fprintf(f, " AI_CANONNAME");
2560 if (a->ai_flags & AI_NUMERICHOST) fprintf(f, " AI_NUMERICHOST");
2561 if (a->ai_flags & AI_NUMERICSERV) fprintf(f, " AI_NUMERICSERV");
2562 fprintf(f, "\n");
2563 }
2564
2565 fprintf(f, "family = %s\n", family_name(a->ai_family));
2566 fprintf(f, "socktype = %s\n", socket_name(a->ai_socktype));
2567 fprintf(f, "protocol = %s\n", protocol_name(a->ai_protocol));
2568
2569 fprintf(f, "canonical name = ");
2570 if (a->ai_canonname == NULL) fprintf(f, "NULL\n");
2571 else fprintf(f, "\"%s\"\n", a->ai_canonname);
2572
2573 fprintf(f, "addrlen = %ld\n", (long int)a->ai_addrlen);
2574
2575 if (a->ai_addr == NULL) fprintf(f, "sockaddr = NULL\n");
2576 else
2577 {
2578 if (a->ai_family == PF_INET)
2579 {
2580 s4 = (struct sockaddr_in *)a->ai_addr;
2581
2582 fprintf(f, "sockaddr_in len = %d\n", s4->sin_len);
2583 fprintf(f, "sockaddr_in family = %s\n", family_name(s4->sin_family));
2584 fprintf(f, "sockaddr_in port = %hu\n", ntohs(s4->sin_port));
2585 fprintf(f, "sockaddr_in address = %s\n", inet_ntoa(s4->sin_addr));
2586 }
2587 else if (a->ai_family == PF_INET6)
2588 {
2589 s6 = (struct sockaddr_in6 *)a->ai_addr;
2590
2591 fprintf(f, "sockaddr_in6 len = %d\n", s6->sin6_len);
2592 fprintf(f, "sockaddr_in6 family = %s\n", family_name(s6->sin6_family));
2593 fprintf(f, "sockaddr_in6 port = %hu\n", ntohs(s6->sin6_port));
2594 fprintf(f, "sockaddr_in6 flowinfo = %d\n", s6->sin6_flowinfo);
2595 fprintf(f, "sockaddr_in6 address = %s\n", _gai_inet_ntop(s6->sin6_addr));
2596 fprintf(f, "sockaddr_in6 scope_id = %d\n", s6->sin6_scope_id);
2597 }
2598 else
2599 {
2600 fprintf(f, "sockaddr len = %d\n", a->ai_addr->sa_len);
2601 fprintf(f, "sockaddr family = %s\n", family_name(a->ai_addr->sa_family));
2602 fprintf(f, "sockaddr data = ");
2603 for (i = 0; i < a->ai_addr->sa_len - 2; i++)
2604 {
2605 v = a->ai_addr->sa_data[i];
2606 fprintf(f, "%02x", v);
2607 }
2608 fprintf(f, "\n");
2609 }
2610 }
2611
2612 if (a->ai_next != NULL)
2613 {
2614 fprintf(f, "NEXT --->\n");
2615 fprint_addrinfo(f, a->ai_next);
2616 }
2617 }
2618
2619 #endif
2620
2621 static void
2622 si_libinfo_addrinfo_callback(si_list_t *list, uint32_t status, void *ctx)
2623 {
2624 si_context_t *sictx;
2625 struct addrinfo *out;
2626
2627 if (ctx == NULL)
2628 {
2629 #ifdef CALL_TRACE
2630 fprintf(stderr, " %s error no context\n", __func__);
2631 #endif
2632 si_list_release(list);
2633 return;
2634 }
2635
2636 sictx = (si_context_t *)ctx;
2637
2638 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2639 {
2640 #ifdef CALL_TRACE
2641 fprintf(stderr, " %s error no callback\n", __func__);
2642 #endif
2643 si_list_release(list);
2644 free(sictx);
2645 return;
2646 }
2647
2648 if (status != SI_STATUS_NO_ERROR)
2649 {
2650 #ifdef CALL_TRACE
2651 fprintf(stderr, " %s original status %d\n", __func__, status);
2652 #endif
2653 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2654 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2655 else status = status - SI_STATUS_EAI_PLUS_100;
2656 }
2657
2658 if (list == NULL)
2659 {
2660 #ifdef CALL_TRACE
2661 fprintf(stderr, " %s result NULL status %d (returning EAI_NONAME)\n", __func__, status);
2662 #endif
2663 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_NONAME, NULL, sictx->orig_context);
2664 free(sictx);
2665 return;
2666 }
2667
2668 out = si_list_to_addrinfo(list);
2669 si_list_release(list);
2670 if (out == NULL)
2671 {
2672 #ifdef CALL_TRACE
2673 fprintf(stderr, " %s result conversion failed returning NULL status %d (returning EAI_MEMORY)\n", __func__, status);
2674 #endif
2675 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_MEMORY, NULL, sictx->orig_context);
2676 free(sictx);
2677 return;
2678 }
2679
2680 #ifdef CALL_TRACE
2681 fprintf(stderr, " %s %d\n", __func__, status);
2682 fprint_addrinfo(stderr, out);
2683 #endif
2684 ((si_addrinfo_async_callback)(sictx->orig_callback))(status, out, sictx->orig_context);
2685
2686 free(sictx);
2687 }
2688
2689 /* SPI */
2690 LIBINFO_EXPORT
2691 mach_port_t
2692 _getaddrinfo_interface_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, si_addrinfo_async_callback callback, void *context)
2693 {
2694 si_context_t *sictx;
2695 uint32_t family, socktype, protocol, flags;
2696
2697 family = AF_UNSPEC;
2698 socktype = SOCK_UNSPEC;
2699 protocol = IPPROTO_UNSPEC;
2700 flags = 0;
2701
2702 if (hints != NULL)
2703 {
2704 family = hints->ai_family;
2705 socktype = hints->ai_socktype;
2706 protocol = hints->ai_protocol;
2707 flags = hints->ai_flags;
2708 }
2709
2710 if (flags == 0) flags = AI_DEFAULT;
2711
2712 #ifdef CALL_TRACE
2713 fprintf(stderr, ">> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags);
2714 #endif
2715
2716 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2717 if (sictx == NULL) return MACH_PORT_NULL;
2718
2719 sictx->orig_callback = callback;
2720 sictx->orig_context = context;
2721 sictx->cat = CATEGORY_ADDRINFO;
2722 sictx->key_offset = 0;
2723
2724 return si_async_call(si_search(), SI_CALL_ADDRINFO, nodename, servname, interface, family, socktype, protocol, flags, (void *)si_libinfo_addrinfo_callback, sictx);
2725 }
2726
2727 mach_port_t
2728 getaddrinfo_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2729 {
2730 return _getaddrinfo_interface_async_call(nodename, servname, hints, NULL, callback, context);
2731 }
2732
2733 LIBINFO_EXPORT
2734 int32_t
2735 getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2736 {
2737 if (p == NULL) return EAI_SYSTEM;
2738
2739 *p = getaddrinfo_async_call(nodename, servname, hints, callback, context);
2740
2741 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2742 return 0;
2743 }
2744
2745 LIBINFO_EXPORT
2746 int32_t
2747 getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints)
2748 {
2749 return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL);
2750 }
2751
2752 LIBINFO_EXPORT
2753 int32_t
2754 getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res)
2755 {
2756 /* unsupported Leopard SPI */
2757 return EAI_SYSTEM;
2758 }
2759
2760 LIBINFO_EXPORT
2761 void
2762 getaddrinfo_async_cancel(mach_port_t p)
2763 {
2764 #ifdef CALL_TRACE
2765 fprintf(stderr, "-- %s\n", __func__);
2766 #endif
2767
2768 si_async_cancel(p);
2769 }
2770
2771 LIBINFO_EXPORT
2772 int32_t
2773 getaddrinfo_async_handle_reply(void *param)
2774 {
2775 mach_msg_header_t *msg;
2776
2777 #ifdef CALL_TRACE
2778 fprintf(stderr, "<< %s\n", __func__);
2779 #endif
2780
2781 msg = (mach_msg_header_t *)param;
2782 si_async_handle_reply(msg);
2783
2784 return 0;
2785 }
2786
2787 /* GETNAMEINFO */
2788
2789 static int
2790 _getnameinfo_interface_internal(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags, const char *interface)
2791 {
2792 si_item_t *item;
2793 si_nameinfo_t *ni;
2794 uint32_t status, len, wantn, wants;
2795
2796 #ifdef CALL_TRACE
2797 fprintf(stderr, "-> %s\n", __func__);
2798 #endif
2799
2800 status = SI_STATUS_NO_ERROR;
2801
2802 wantn = 0;
2803 if ((node != NULL) && (nodelen > 0)) wantn = 1;
2804
2805 wants = 0;
2806 if ((service != NULL) && (servicelen > 0)) wants = 1;
2807
2808 if ((wantn == 0) && (wants == 0)) return status;
2809
2810 if (wantn == 0) flags |= NI_NUMERICHOST;
2811 if (wants == 0) flags |= NI_NUMERICSERV;
2812
2813 item = si_nameinfo(si_search(), sa, flags, interface, &status);
2814 if ((status != SI_STATUS_NO_ERROR) || (item == NULL))
2815 {
2816 si_item_release(item);
2817
2818 if (status == SI_STATUS_NO_ERROR) status = EAI_NONAME;
2819 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2820 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2821 else status = status - SI_STATUS_EAI_PLUS_100;
2822 return status;
2823 }
2824
2825 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2826
2827 len = 0;
2828 if (ni->ni_node != NULL) len = strlen(ni->ni_node) + 1;
2829 if ((wantn == 1) && (len > 0))
2830 {
2831 if (len > nodelen)
2832 {
2833 si_item_release(item);
2834 return EAI_OVERFLOW;
2835 }
2836
2837 memset(node, 0, nodelen);
2838 memcpy(node, ni->ni_node, len);
2839 }
2840
2841 len = 0;
2842 if (ni->ni_serv != NULL) len = strlen(ni->ni_serv) + 1;
2843 if ((wants == 1) && (len > 0))
2844 {
2845 if (len > servicelen)
2846 {
2847 si_item_release(item);
2848 return EAI_OVERFLOW;
2849 }
2850
2851 memset(service, 0, servicelen);
2852 memcpy(service, ni->ni_serv, len);
2853 }
2854
2855 si_item_release(item);
2856 return 0;
2857 }
2858
2859 LIBINFO_EXPORT
2860 int
2861 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags)
2862 {
2863 if (sa == NULL) return EAI_FAIL;
2864
2865 if (sa->sa_family == AF_LINK) return getnameinfo_link(sa, salen, node, nodelen, service, servicelen, flags);
2866 return _getnameinfo_interface_internal(sa, salen, node, nodelen, service, servicelen, flags, NULL);
2867 }
2868
2869 static void
2870 si_libinfo_nameinfo_callback(si_item_t *item, uint32_t status, void *ctx)
2871 {
2872 si_context_t *sictx;
2873 si_nameinfo_t *ni;
2874 char *node, *serv;
2875
2876 if (ctx == NULL) return;
2877
2878 sictx = (si_context_t *)ctx;
2879
2880 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2881 {
2882 si_item_release(item);
2883 free(sictx);
2884 return;
2885 }
2886
2887 if (status != SI_STATUS_NO_ERROR)
2888 {
2889 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2890 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2891 else status = status - SI_STATUS_EAI_PLUS_100;
2892 }
2893
2894 if (item == NULL)
2895 {
2896 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, NULL, NULL, sictx->orig_context);
2897 free(sictx);
2898 return;
2899 }
2900
2901 LI_set_thread_item(CATEGORY_NAMEINFO, item);
2902
2903 node = NULL;
2904 serv = NULL;
2905
2906 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2907 if (ni->ni_node != NULL) node = strdup(ni->ni_node);
2908 if (ni->ni_serv != NULL) serv = strdup(ni->ni_serv);
2909
2910 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, node, serv, sictx->orig_context);
2911 free(sictx);
2912 }
2913
2914 /* SPI */
2915 LIBINFO_EXPORT
2916 mach_port_t
2917 _getnameinfo_interface_async_call(const struct sockaddr *sa, size_t len, int flags, const char *interface, si_nameinfo_async_callback callback, void *context)
2918 {
2919 si_context_t *sictx;
2920 uint32_t salen;
2921
2922 #ifdef CALL_TRACE
2923 fprintf(stderr, ">> %s\n", __func__);
2924 #endif
2925
2926 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2927 if (sictx == NULL) return MACH_PORT_NULL;
2928
2929 sictx->orig_callback = callback;
2930 sictx->orig_context = context;
2931 sictx->cat = CATEGORY_ADDRINFO;
2932 sictx->key_offset = 0;
2933
2934 /* sa is not a C string - pass length in num3 */
2935 salen = len;
2936 return si_async_call(si_search(), SI_CALL_NAMEINFO, (const char *)sa, NULL, interface, flags, 0, salen, 0, (void *)si_libinfo_nameinfo_callback, sictx);
2937 }
2938
2939 mach_port_t
2940 getnameinfo_async_call(const struct sockaddr *sa, size_t len, int flags, si_nameinfo_async_callback callback, void *context)
2941 {
2942 return _getnameinfo_interface_async_call(sa, len, flags, NULL, callback, context);
2943 }
2944
2945 LIBINFO_EXPORT
2946 int32_t
2947 getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, si_nameinfo_async_callback callback, void *context)
2948 {
2949 if (p == NULL) return EAI_SYSTEM;
2950 *p = getnameinfo_async_call(sa, salen, flags, callback, context);
2951
2952 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2953 return 0;
2954 }
2955
2956 LIBINFO_EXPORT
2957 int32_t
2958 getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags)
2959 {
2960 return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL);
2961 }
2962
2963 LIBINFO_EXPORT
2964 void
2965 getnameinfo_async_cancel(mach_port_t p)
2966 {
2967 #ifdef CALL_TRACE
2968 fprintf(stderr, "-- %s\n", __func__);
2969 #endif
2970
2971 si_async_cancel(p);
2972 }
2973
2974 LIBINFO_EXPORT
2975 int32_t
2976 getnameinfo_async_handle_reply(void *param)
2977 {
2978 mach_msg_header_t *msg;
2979
2980 #ifdef CALL_TRACE
2981 fprintf(stderr, "<< %s\n", __func__);
2982 #endif
2983
2984 msg = (mach_msg_header_t *)param;
2985 si_async_handle_reply(msg);
2986
2987 return 0;
2988 }
2989
2990 /* getpwXXX_r and getgrXXX_r */
2991
2992 static int
2993 copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen)
2994 {
2995 int hsize;
2996 char *bp;
2997
2998 if (in == NULL) return -1;
2999 if (out == NULL) return -1;
3000
3001 if (buffer == NULL) buflen = 0;
3002
3003 /* Calculate size of input */
3004 hsize = 0;
3005 if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1);
3006 if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1);
3007 if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1);
3008 if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1);
3009 if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1);
3010 if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1);
3011
3012 /* Check buffer space */
3013 if (hsize > buflen) return -1;
3014
3015 /* Copy result into caller's struct passwd, using buffer for memory */
3016 bp = buffer;
3017
3018 out->pw_name = NULL;
3019 if (in->pw_name != NULL)
3020 {
3021 out->pw_name = bp;
3022 hsize = strlen(in->pw_name) + 1;
3023 memmove(bp, in->pw_name, hsize);
3024 bp += hsize;
3025 }
3026
3027 out->pw_passwd = NULL;
3028 if (in->pw_passwd != NULL)
3029 {
3030 out->pw_passwd = bp;
3031 hsize = strlen(in->pw_passwd) + 1;
3032 memmove(bp, in->pw_passwd, hsize);
3033 bp += hsize;
3034 }
3035
3036 out->pw_uid = in->pw_uid;
3037
3038 out->pw_gid = in->pw_gid;
3039
3040 out->pw_change = in->pw_change;
3041
3042 out->pw_class = NULL;
3043 if (in->pw_class != NULL)
3044 {
3045 out->pw_class = bp;
3046 hsize = strlen(in->pw_class) + 1;
3047 memmove(bp, in->pw_class, hsize);
3048 bp += hsize;
3049 }
3050
3051 out->pw_gecos = NULL;
3052 if (in->pw_gecos != NULL)
3053 {
3054 out->pw_gecos = bp;
3055 hsize = strlen(in->pw_gecos) + 1;
3056 memmove(bp, in->pw_gecos, hsize);
3057 bp += hsize;
3058 }
3059
3060 out->pw_dir = NULL;
3061 if (in->pw_dir != NULL)
3062 {
3063 out->pw_dir = bp;
3064 hsize = strlen(in->pw_dir) + 1;
3065 memmove(bp, in->pw_dir, hsize);
3066 bp += hsize;
3067 }
3068
3069 out->pw_shell = NULL;
3070 if (in->pw_shell != NULL)
3071 {
3072 out->pw_shell = bp;
3073 hsize = strlen(in->pw_shell) + 1;
3074 memmove(bp, in->pw_shell, hsize);
3075 bp += hsize;
3076 }
3077
3078 out->pw_expire = in->pw_expire;
3079
3080 return 0;
3081 }
3082
3083 static int
3084 copy_group_r(struct group *in, struct group *out, char *buffer, int buflen)
3085 {
3086 int i, len, hsize;
3087 unsigned long addr;
3088 char *bp, *ap;
3089
3090 if (in == NULL) return -1;
3091 if (out == NULL) return -1;
3092
3093 if (buffer == NULL) buflen = 0;
3094
3095 /* Calculate size of input */
3096 hsize = 0;
3097 if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1);
3098 if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1);
3099
3100 /* NULL pointer at end of list */
3101 hsize += sizeof(char *);
3102
3103 len = 0;
3104 if (in->gr_mem != NULL)
3105 {
3106 for (len = 0; in->gr_mem[len] != NULL; len++)
3107 {
3108 hsize += sizeof(char *);
3109 hsize += (strlen(in->gr_mem[len]) + 1);
3110 }
3111 }
3112
3113 /* Check buffer space */
3114 if (hsize > buflen) return -1;
3115
3116 /* Copy result into caller's struct group, using buffer for memory */
3117 bp = buffer;
3118
3119 out->gr_name = NULL;
3120 if (in->gr_name != NULL)
3121 {
3122 out->gr_name = bp;
3123 hsize = strlen(in->gr_name) + 1;
3124 memmove(bp, in->gr_name, hsize);
3125 bp += hsize;
3126 }
3127
3128 out->gr_passwd = NULL;
3129 if (in->gr_passwd != NULL)
3130 {
3131 out->gr_passwd = bp;
3132 hsize = strlen(in->gr_passwd) + 1;
3133 memmove(bp, in->gr_passwd, hsize);
3134 bp += hsize;
3135 }
3136
3137 out->gr_gid = in->gr_gid;
3138
3139 out->gr_mem = NULL;
3140 ap = bp + ((len + 1) * sizeof(char *));
3141
3142 if (in->gr_mem != NULL)
3143 {
3144 out->gr_mem = (char **)bp;
3145 for (i = 0; i < len; i++)
3146 {
3147 addr = (unsigned long)ap;
3148 memmove(bp, &addr, sizeof(unsigned long));
3149 bp += sizeof(unsigned long);
3150
3151 hsize = strlen(in->gr_mem[i]) + 1;
3152 memmove(ap, in->gr_mem[i], hsize);
3153 ap += hsize;
3154 }
3155 }
3156
3157 memset(bp, 0, sizeof(unsigned long));
3158 bp = ap;
3159
3160 return 0;
3161 }
3162
3163 LIBINFO_EXPORT
3164 int
3165 getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3166 {
3167 si_item_t *item;
3168 struct group *g;
3169 int status;
3170
3171 #ifdef CALL_TRACE
3172 fprintf(stderr, "-> %s %s\n", __func__, name);
3173 #endif
3174
3175 if (result != NULL) *result = NULL;
3176
3177 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3178
3179 item = si_group_byname(si_search(), name);
3180 if (item == NULL) return 0;
3181
3182 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3183
3184 status = copy_group_r(g, grp, buffer, bufsize);
3185 si_item_release(item);
3186
3187 if (status != 0) return ERANGE;
3188
3189 *result = grp;
3190 return 0;
3191 }
3192
3193 LIBINFO_EXPORT
3194 int
3195 getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3196 {
3197 si_item_t *item;
3198 struct group *g;
3199 int status;
3200
3201 #ifdef CALL_TRACE
3202 fprintf(stderr, "-> %s %d\n", __func__, gid);
3203 #endif
3204
3205 if (result != NULL) *result = NULL;
3206
3207 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3208
3209 item = si_group_bygid(si_search(), gid);
3210 if (item == NULL) return 0;
3211
3212 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3213
3214 status = copy_group_r(g, grp, buffer, bufsize);
3215 si_item_release(item);
3216
3217 if (status != 0) return ERANGE;
3218
3219 *result = grp;
3220 return 0;
3221 }
3222
3223 LIBINFO_EXPORT
3224 int
3225 getgruuid_r(uuid_t uuid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3226 {
3227 si_item_t *item;
3228 struct group *g;
3229 int status;
3230
3231 #ifdef CALL_TRACE
3232 uuid_string_t uuidstr;
3233 uuid_unparse_upper(uuid, uuidstr);
3234 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
3235 #endif
3236
3237 if (result != NULL) *result = NULL;
3238
3239 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3240
3241 item = si_group_byuuid(si_search(), uuid);
3242 if (item == NULL) return 0;
3243
3244 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3245
3246 status = copy_group_r(g, grp, buffer, bufsize);
3247 si_item_release(item);
3248
3249 if (status != 0) return ERANGE;
3250
3251 *result = grp;
3252 return 0;
3253 }
3254
3255 LIBINFO_EXPORT
3256 int
3257 getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3258 {
3259 si_item_t *item;
3260 struct passwd *p;
3261 int status;
3262
3263 #ifdef CALL_TRACE
3264 fprintf(stderr, "-> %s %s\n", __func__, name);
3265 #endif
3266
3267 if (result != NULL) *result = NULL;
3268
3269 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3270
3271 item = si_user_byname(si_search(), name);
3272 if (item == NULL) return 0;
3273
3274 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3275
3276 status = copy_user_r(p, pw, buffer, bufsize);
3277 si_item_release(item);
3278
3279 if (status != 0) return ERANGE;
3280
3281 *result = pw;
3282 return 0;
3283 }
3284
3285 LIBINFO_EXPORT
3286 int
3287 getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3288 {
3289 si_item_t *item = NULL;
3290 struct passwd *p;
3291 int status;
3292
3293 #ifdef CALL_TRACE
3294 fprintf(stderr, "-> %s %d\n", __func__, uid);
3295 #endif
3296
3297 if (result != NULL) *result = NULL;
3298
3299 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3300
3301 // Search the file module first for all system uids
3302 // (ie, uid value < 500) since they should all be
3303 // in the /etc/*passwd file.
3304 if (uid < SYSTEM_UID_LIMIT)
3305 item = si_user_byuid(si_search_file(), uid);
3306
3307 if (item == NULL)
3308 item = si_user_byuid(si_search(), uid);
3309 if (item == NULL) return 0;
3310
3311 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3312
3313 status = copy_user_r(p, pw, buffer, bufsize);
3314 si_item_release(item);
3315
3316 if (status != 0) return ERANGE;
3317
3318 *result = pw;
3319 return 0;
3320 }
3321
3322 LIBINFO_EXPORT
3323 int
3324 getpwuuid_r(uuid_t uuid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3325 {
3326 si_item_t *item;
3327 struct passwd *p;
3328 int status;
3329
3330 #ifdef CALL_TRACE
3331 uuid_string_t uuidstr;
3332 uuid_unparse_upper(uuid, uuidstr);
3333 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
3334 #endif
3335
3336 if (result != NULL) *result = NULL;
3337
3338 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3339
3340 item = si_user_byuuid(si_search(), uuid);
3341 if (item == NULL) return 0;
3342
3343 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3344
3345 status = copy_user_r(p, pw, buffer, bufsize);
3346 si_item_release(item);
3347
3348 if (status != 0) return ERANGE;
3349
3350 *result = pw;
3351 return 0;
3352 }
3353
3354 /* misc */
3355
3356 LIBINFO_EXPORT
3357 char *
3358 user_from_uid(uid_t uid, int nouser)
3359 {
3360 struct passwd *pw;
3361 static char buf[16];
3362
3363 pw = getpwuid(uid);
3364 if (pw != NULL) return pw->pw_name;
3365
3366 if (nouser) return NULL;
3367
3368 snprintf(buf, sizeof(buf), "%u", uid);
3369 return buf;
3370 }
3371
3372 LIBINFO_EXPORT
3373 char *
3374 group_from_gid(gid_t gid, int nogroup)
3375 {
3376 struct group *gr;
3377 static char buf[16];
3378
3379 gr = getgrgid(gid);
3380 if (gr != NULL) return gr->gr_name;
3381
3382 if (nogroup) return NULL;
3383
3384 snprintf(buf, sizeof(buf), "%u", gid);
3385 return buf;
3386 }
3387
3388 /* no longer supported */
3389
3390 LIBINFO_EXPORT
3391 const prdb_ent *
3392 prdb_getbyname(const char *name)
3393 {
3394 #ifdef CALL_TRACE
3395 fprintf(stderr, "~~ %s\n", __func__);
3396 #endif
3397 return NULL;
3398 }
3399
3400 LIBINFO_EXPORT
3401 const prdb_ent *
3402 prdb_get(void)
3403 {
3404 #ifdef CALL_TRACE
3405 fprintf(stderr, "~~ %s\n", __func__);
3406 #endif
3407 return NULL;
3408 }
3409
3410 LIBINFO_EXPORT
3411 void
3412 prdb_set(const char *name)
3413 {
3414 #ifdef CALL_TRACE
3415 fprintf(stderr, "~~ %s\n", __func__);
3416 #endif
3417 }
3418
3419 LIBINFO_EXPORT
3420 void
3421 prdb_end(void)
3422 {
3423 #ifdef CALL_TRACE
3424 fprintf(stderr, "~~ %s\n", __func__);
3425 #endif
3426 }
3427
3428 LIBINFO_EXPORT
3429 struct bootparamsent *
3430 bootparams_getbyname(const char *name)
3431 {
3432 #ifdef CALL_TRACE
3433 fprintf(stderr, "~~ %s\n", __func__);
3434 #endif
3435 return NULL;
3436 }
3437
3438 LIBINFO_EXPORT
3439 struct bootparamsent *
3440 bootparams_getent(void)
3441 {
3442 #ifdef CALL_TRACE
3443 fprintf(stderr, "~~ %s\n", __func__);
3444 #endif
3445 return NULL;
3446 }
3447
3448 LIBINFO_EXPORT
3449 void
3450 bootparams_setent(void)
3451 {
3452 #ifdef CALL_TRACE
3453 fprintf(stderr, "~~ %s\n", __func__);
3454 #endif
3455 }
3456
3457 LIBINFO_EXPORT
3458 void
3459 bootparams_endent(void)
3460 {
3461 #ifdef CALL_TRACE
3462 fprintf(stderr, "~~ %s\n", __func__);
3463 #endif
3464 }
3465
3466 int
3467 bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
3468 {
3469 #ifdef CALL_TRACE
3470 fprintf(stderr, "~~ %s\n", __func__);
3471 #endif
3472 return 0;
3473 }
3474
3475 int
3476 bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
3477 {
3478 #ifdef CALL_TRACE
3479 fprintf(stderr, "~~ %s\n", __func__);
3480 #endif
3481 return 0;
3482 }