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