Libinfo-517.30.1.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 if (flags == 0) flags = AI_DEFAULT;
2358
2359 #ifdef CALL_TRACE
2360 fprintf(stderr, "-> %s %s %s %u %u %u 0x%08x %s\n", __func__, nodename, servname, family, socktype, protocol, flags, (interface == NULL) ? "" : interface);
2361 #endif
2362
2363 list = si_addrinfo(si_search(), nodename, servname, family, socktype, protocol, flags, interface, &status);
2364 if ((status != SI_STATUS_NO_ERROR) || (list == NULL) || (list->count == 0))
2365 {
2366 si_list_release(list);
2367
2368 if (status == SI_STATUS_NO_ERROR) return EAI_NONAME;
2369 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2370 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2371 else status = status - SI_STATUS_EAI_PLUS_100;
2372 return status;
2373 }
2374
2375 *res = si_list_to_addrinfo(list);
2376 si_list_release(list);
2377 if (*res == NULL) status = EAI_MEMORY;
2378
2379 /* don't return the canonical name unless asked */
2380 if ((flags & AI_CANONNAME) == 0)
2381 {
2382 for (ai = *res; ai != NULL; ai = ai->ai_next)
2383 {
2384 free(ai->ai_canonname);
2385 ai->ai_canonname = NULL;
2386 }
2387 }
2388
2389 return status;
2390 }
2391
2392 int
2393 getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
2394 {
2395 return _getaddrinfo_internal(nodename, servname, hints, NULL, res);
2396 }
2397
2398 #ifdef CALL_TRACE
2399
2400 static char *
2401 socket_name(int sock)
2402 {
2403 static char str[16];
2404
2405 switch(sock)
2406 {
2407 case SOCK_UNSPEC: return "SOCK_UNSPEC";
2408 case SOCK_STREAM: return "SOCK_STREAM";
2409 case SOCK_DGRAM: return "SOCK_DGRAM";
2410 }
2411
2412 sprintf(str, "%d", sock);
2413 return str;
2414 }
2415
2416 static char *
2417 family_name(int pf)
2418 {
2419 static char str[16];
2420
2421 switch(pf)
2422 {
2423 case PF_UNSPEC: return "PF_UNSPEC";
2424 case PF_INET: return "PF_INET";
2425 case PF_INET6: return "PF_INET6";
2426 };
2427
2428 sprintf(str, "%d", pf);
2429 return str;
2430 }
2431
2432 static char *
2433 protocol_name(int p)
2434 {
2435 static char str[16];
2436
2437 switch(p)
2438 {
2439 case IPPROTO_UNSPEC: return "IPPROTO_UNSPEC";
2440 case IPPROTO_TCP: return "IPPROTO_TCP";
2441 case IPPROTO_UDP: return "IPPROTO_UDP";
2442 }
2443
2444 sprintf(str, "%d", p);
2445 return str;
2446 }
2447
2448 static char *
2449 _gai_inet_ntop(struct in6_addr a)
2450 {
2451 static char buf[128];
2452 char t[32];
2453 unsigned short x;
2454 char *p;
2455 int i;
2456
2457 memset(buf, 0, 128);
2458
2459 p = (char *)&a.__u6_addr.__u6_addr32;
2460 for (i = 0; i < 8; i++, x += 1)
2461 {
2462 memmove(&x, p, 2);
2463 p += 2;
2464 sprintf(t, "%hx", x);
2465 strcat(buf, t);
2466 if (i < 7) strcat(buf, ":");
2467 }
2468
2469 return buf;
2470 }
2471
2472 static void
2473 fprint_addrinfo(FILE *f, struct addrinfo *a)
2474 {
2475 int i;
2476 unsigned char v;
2477 struct sockaddr_in *s4;
2478 struct sockaddr_in6 *s6;
2479
2480 if (a == NULL) return;
2481
2482 if (a->ai_flags != 0)
2483 {
2484 fprintf(f, "flags =");
2485 if (a->ai_flags & AI_PASSIVE) fprintf(f, " AI_PASSIVE");
2486 if (a->ai_flags & AI_CANONNAME) fprintf(f, " AI_CANONNAME");
2487 if (a->ai_flags & AI_NUMERICHOST) fprintf(f, " AI_NUMERICHOST");
2488 if (a->ai_flags & AI_NUMERICSERV) fprintf(f, " AI_NUMERICSERV");
2489 fprintf(f, "\n");
2490 }
2491
2492 fprintf(f, "family = %s\n", family_name(a->ai_family));
2493 fprintf(f, "socktype = %s\n", socket_name(a->ai_socktype));
2494 fprintf(f, "protocol = %s\n", protocol_name(a->ai_protocol));
2495
2496 fprintf(f, "canonical name = ");
2497 if (a->ai_canonname == NULL) fprintf(f, "NULL\n");
2498 else fprintf(f, "\"%s\"\n", a->ai_canonname);
2499
2500 fprintf(f, "addrlen = %ld\n", (long int)a->ai_addrlen);
2501
2502 if (a->ai_addr == NULL) fprintf(f, "sockaddr = NULL\n");
2503 else
2504 {
2505 if (a->ai_family == PF_INET)
2506 {
2507 s4 = (struct sockaddr_in *)a->ai_addr;
2508
2509 fprintf(f, "sockaddr_in len = %d\n", s4->sin_len);
2510 fprintf(f, "sockaddr_in family = %s\n", family_name(s4->sin_family));
2511 fprintf(f, "sockaddr_in port = %hu\n", ntohs(s4->sin_port));
2512 fprintf(f, "sockaddr_in address = %s\n", inet_ntoa(s4->sin_addr));
2513 }
2514 else if (a->ai_family == PF_INET6)
2515 {
2516 s6 = (struct sockaddr_in6 *)a->ai_addr;
2517
2518 fprintf(f, "sockaddr_in6 len = %d\n", s6->sin6_len);
2519 fprintf(f, "sockaddr_in6 family = %s\n", family_name(s6->sin6_family));
2520 fprintf(f, "sockaddr_in6 port = %hu\n", ntohs(s6->sin6_port));
2521 fprintf(f, "sockaddr_in6 flowinfo = %d\n", s6->sin6_flowinfo);
2522 fprintf(f, "sockaddr_in6 address = %s\n", _gai_inet_ntop(s6->sin6_addr));
2523 fprintf(f, "sockaddr_in6 scope_id = %d\n", s6->sin6_scope_id);
2524 }
2525 else
2526 {
2527 fprintf(f, "sockaddr len = %d\n", a->ai_addr->sa_len);
2528 fprintf(f, "sockaddr family = %s\n", family_name(a->ai_addr->sa_family));
2529 fprintf(f, "sockaddr data = ");
2530 for (i = 0; i < a->ai_addr->sa_len - 2; i++)
2531 {
2532 v = a->ai_addr->sa_data[i];
2533 fprintf(f, "%02x", v);
2534 }
2535 fprintf(f, "\n");
2536 }
2537 }
2538
2539 if (a->ai_next != NULL)
2540 {
2541 fprintf(f, "NEXT --->\n");
2542 fprint_addrinfo(f, a->ai_next);
2543 }
2544 }
2545
2546 #endif
2547
2548 static void
2549 si_libinfo_addrinfo_callback(si_list_t *list, uint32_t status, void *ctx)
2550 {
2551 si_context_t *sictx;
2552 struct addrinfo *out;
2553
2554 if (ctx == NULL)
2555 {
2556 #ifdef CALL_TRACE
2557 fprintf(stderr, " %s error no context\n", __func__);
2558 #endif
2559 si_list_release(list);
2560 return;
2561 }
2562
2563 sictx = (si_context_t *)ctx;
2564
2565 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2566 {
2567 #ifdef CALL_TRACE
2568 fprintf(stderr, " %s error no callback\n", __func__);
2569 #endif
2570 si_list_release(list);
2571 free(sictx);
2572 return;
2573 }
2574
2575 if (status != SI_STATUS_NO_ERROR)
2576 {
2577 #ifdef CALL_TRACE
2578 fprintf(stderr, " %s original status %d\n", __func__, status);
2579 #endif
2580 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2581 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2582 else status = status - SI_STATUS_EAI_PLUS_100;
2583 }
2584
2585 if (list == NULL)
2586 {
2587 #ifdef CALL_TRACE
2588 fprintf(stderr, " %s result NULL status %d (returning EAI_NONAME)\n", __func__, status);
2589 #endif
2590 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_NONAME, NULL, sictx->orig_context);
2591 free(sictx);
2592 return;
2593 }
2594
2595 out = si_list_to_addrinfo(list);
2596 si_list_release(list);
2597 if (out == NULL)
2598 {
2599 #ifdef CALL_TRACE
2600 fprintf(stderr, " %s result conversion failed returning NULL status %d (returning EAI_MEMORY)\n", __func__, status);
2601 #endif
2602 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_MEMORY, NULL, sictx->orig_context);
2603 free(sictx);
2604 return;
2605 }
2606
2607 #ifdef CALL_TRACE
2608 fprintf(stderr, " %s %d\n", __func__, status);
2609 fprint_addrinfo(stderr, out);
2610 #endif
2611 ((si_addrinfo_async_callback)(sictx->orig_callback))(status, out, sictx->orig_context);
2612
2613 free(sictx);
2614 }
2615
2616 /* SPI */
2617 mach_port_t
2618 _getaddrinfo_interface_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, si_addrinfo_async_callback callback, void *context)
2619 {
2620 si_context_t *sictx;
2621 uint32_t family, socktype, protocol, flags;
2622
2623 family = AF_UNSPEC;
2624 socktype = SOCK_UNSPEC;
2625 protocol = IPPROTO_UNSPEC;
2626 flags = 0;
2627
2628 if (hints != NULL)
2629 {
2630 family = hints->ai_family;
2631 socktype = hints->ai_socktype;
2632 protocol = hints->ai_protocol;
2633 flags = hints->ai_flags;
2634 }
2635
2636 if (flags == 0) flags = AI_DEFAULT;
2637
2638 #ifdef CALL_TRACE
2639 fprintf(stderr, ">> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags);
2640 #endif
2641
2642 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2643 if (sictx == NULL) return MACH_PORT_NULL;
2644
2645 sictx->orig_callback = callback;
2646 sictx->orig_context = context;
2647 sictx->cat = CATEGORY_ADDRINFO;
2648 sictx->key_offset = 0;
2649
2650 return si_async_call(si_search(), SI_CALL_ADDRINFO, nodename, servname, interface, family, socktype, protocol, flags, (void *)si_libinfo_addrinfo_callback, sictx);
2651 }
2652
2653 mach_port_t
2654 getaddrinfo_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2655 {
2656 return _getaddrinfo_interface_async_call(nodename, servname, hints, NULL, callback, context);
2657 }
2658
2659 int32_t
2660 getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2661 {
2662 if (p == NULL) return EAI_SYSTEM;
2663
2664 *p = getaddrinfo_async_call(nodename, servname, hints, callback, context);
2665
2666 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2667 return 0;
2668 }
2669
2670 int32_t
2671 getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints)
2672 {
2673 return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL);
2674 }
2675
2676 int32_t
2677 getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res)
2678 {
2679 /* unsupported Leopard SPI */
2680 return EAI_SYSTEM;
2681 }
2682
2683 void
2684 getaddrinfo_async_cancel(mach_port_t p)
2685 {
2686 #ifdef CALL_TRACE
2687 fprintf(stderr, "-- %s\n", __func__);
2688 #endif
2689
2690 si_async_cancel(p);
2691 }
2692
2693 int32_t
2694 getaddrinfo_async_handle_reply(void *param)
2695 {
2696 mach_msg_header_t *msg;
2697
2698 #ifdef CALL_TRACE
2699 fprintf(stderr, "<< %s\n", __func__);
2700 #endif
2701
2702 msg = (mach_msg_header_t *)param;
2703 si_async_handle_reply(msg);
2704
2705 return 0;
2706 }
2707
2708 /* GETNAMEINFO */
2709
2710 static int
2711 _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)
2712 {
2713 si_item_t *item;
2714 si_nameinfo_t *ni;
2715 uint32_t status, len, wantn, wants;
2716
2717 #ifdef CALL_TRACE
2718 fprintf(stderr, "-> %s\n", __func__);
2719 #endif
2720
2721 status = SI_STATUS_NO_ERROR;
2722
2723 wantn = 0;
2724 if ((node != NULL) && (nodelen > 0)) wantn = 1;
2725
2726 wants = 0;
2727 if ((service != NULL) && (servicelen > 0)) wants = 1;
2728
2729 if ((wantn == 0) && (wants == 0)) return status;
2730
2731 if (wantn == 0) flags |= NI_NUMERICHOST;
2732 if (wants == 0) flags |= NI_NUMERICSERV;
2733
2734 item = si_nameinfo(si_search(), sa, flags, interface, &status);
2735 if ((status != SI_STATUS_NO_ERROR) || (item == NULL))
2736 {
2737 si_item_release(item);
2738
2739 if (status == SI_STATUS_NO_ERROR) status = EAI_NONAME;
2740 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2741 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2742 else status = status - SI_STATUS_EAI_PLUS_100;
2743 return status;
2744 }
2745
2746 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2747
2748 len = 0;
2749 if (ni->ni_node != NULL) len = strlen(ni->ni_node) + 1;
2750 if ((wantn == 1) && (len > 0))
2751 {
2752 if (len > nodelen)
2753 {
2754 si_item_release(item);
2755 return EAI_OVERFLOW;
2756 }
2757
2758 memset(node, 0, nodelen);
2759 memcpy(node, ni->ni_node, len);
2760 }
2761
2762 len = 0;
2763 if (ni->ni_serv != NULL) len = strlen(ni->ni_serv) + 1;
2764 if ((wants == 1) && (len > 0))
2765 {
2766 if (len > servicelen)
2767 {
2768 si_item_release(item);
2769 return EAI_OVERFLOW;
2770 }
2771
2772 memset(service, 0, servicelen);
2773 memcpy(service, ni->ni_serv, len);
2774 }
2775
2776 si_item_release(item);
2777 return 0;
2778 }
2779
2780 int
2781 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags)
2782 {
2783 if (sa == NULL) return EAI_FAIL;
2784
2785 if (sa->sa_family == AF_LINK) return getnameinfo_link(sa, salen, node, nodelen, service, servicelen, flags);
2786 return _getnameinfo_interface_internal(sa, salen, node, nodelen, service, servicelen, flags, NULL);
2787 }
2788
2789 static void
2790 si_libinfo_nameinfo_callback(si_item_t *item, uint32_t status, void *ctx)
2791 {
2792 si_context_t *sictx;
2793 si_nameinfo_t *ni;
2794 char *node, *serv;
2795
2796 if (ctx == NULL) return;
2797
2798 sictx = (si_context_t *)ctx;
2799
2800 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2801 {
2802 si_item_release(item);
2803 free(sictx);
2804 return;
2805 }
2806
2807 if (status != SI_STATUS_NO_ERROR)
2808 {
2809 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2810 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2811 else status = status - SI_STATUS_EAI_PLUS_100;
2812 }
2813
2814 if (item == NULL)
2815 {
2816 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, NULL, NULL, sictx->orig_context);
2817 free(sictx);
2818 return;
2819 }
2820
2821 LI_set_thread_item(CATEGORY_NAMEINFO, item);
2822
2823 node = NULL;
2824 serv = NULL;
2825
2826 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2827 if (ni->ni_node != NULL) node = strdup(ni->ni_node);
2828 if (ni->ni_serv != NULL) serv = strdup(ni->ni_serv);
2829
2830 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, node, serv, sictx->orig_context);
2831 free(sictx);
2832 }
2833
2834 /* SPI */
2835 mach_port_t
2836 _getnameinfo_interface_async_call(const struct sockaddr *sa, size_t len, int flags, const char *interface, si_nameinfo_async_callback callback, void *context)
2837 {
2838 si_context_t *sictx;
2839 uint32_t salen;
2840
2841 #ifdef CALL_TRACE
2842 fprintf(stderr, ">> %s\n", __func__);
2843 #endif
2844
2845 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2846 if (sictx == NULL) return MACH_PORT_NULL;
2847
2848 sictx->orig_callback = callback;
2849 sictx->orig_context = context;
2850 sictx->cat = CATEGORY_ADDRINFO;
2851 sictx->key_offset = 0;
2852
2853 /* sa is not a C string - pass length in num3 */
2854 salen = len;
2855 return si_async_call(si_search(), SI_CALL_NAMEINFO, (const char *)sa, NULL, interface, flags, 0, salen, 0, (void *)si_libinfo_nameinfo_callback, sictx);
2856 }
2857
2858 mach_port_t
2859 getnameinfo_async_call(const struct sockaddr *sa, size_t len, int flags, si_nameinfo_async_callback callback, void *context)
2860 {
2861 return _getnameinfo_interface_async_call(sa, len, flags, NULL, callback, context);
2862 }
2863
2864 int32_t
2865 getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, si_nameinfo_async_callback callback, void *context)
2866 {
2867 if (p == NULL) return EAI_SYSTEM;
2868 *p = getnameinfo_async_call(sa, salen, flags, callback, context);
2869
2870 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2871 return 0;
2872 }
2873
2874 int32_t
2875 getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags)
2876 {
2877 return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL);
2878 }
2879
2880 void
2881 getnameinfo_async_cancel(mach_port_t p)
2882 {
2883 #ifdef CALL_TRACE
2884 fprintf(stderr, "-- %s\n", __func__);
2885 #endif
2886
2887 si_async_cancel(p);
2888 }
2889
2890 int32_t
2891 getnameinfo_async_handle_reply(void *param)
2892 {
2893 mach_msg_header_t *msg;
2894
2895 #ifdef CALL_TRACE
2896 fprintf(stderr, "<< %s\n", __func__);
2897 #endif
2898
2899 msg = (mach_msg_header_t *)param;
2900 si_async_handle_reply(msg);
2901
2902 return 0;
2903 }
2904
2905 /* getpwXXX_r and getgrXXX_r */
2906
2907 static int
2908 copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen)
2909 {
2910 int hsize;
2911 char *bp;
2912
2913 if (in == NULL) return -1;
2914 if (out == NULL) return -1;
2915
2916 if (buffer == NULL) buflen = 0;
2917
2918 /* Calculate size of input */
2919 hsize = 0;
2920 if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1);
2921 if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1);
2922 if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1);
2923 if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1);
2924 if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1);
2925 if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1);
2926
2927 /* Check buffer space */
2928 if (hsize > buflen) return -1;
2929
2930 /* Copy result into caller's struct passwd, using buffer for memory */
2931 bp = buffer;
2932
2933 out->pw_name = NULL;
2934 if (in->pw_name != NULL)
2935 {
2936 out->pw_name = bp;
2937 hsize = strlen(in->pw_name) + 1;
2938 memmove(bp, in->pw_name, hsize);
2939 bp += hsize;
2940 }
2941
2942 out->pw_passwd = NULL;
2943 if (in->pw_passwd != NULL)
2944 {
2945 out->pw_passwd = bp;
2946 hsize = strlen(in->pw_passwd) + 1;
2947 memmove(bp, in->pw_passwd, hsize);
2948 bp += hsize;
2949 }
2950
2951 out->pw_uid = in->pw_uid;
2952
2953 out->pw_gid = in->pw_gid;
2954
2955 out->pw_change = in->pw_change;
2956
2957 out->pw_class = NULL;
2958 if (in->pw_class != NULL)
2959 {
2960 out->pw_class = bp;
2961 hsize = strlen(in->pw_class) + 1;
2962 memmove(bp, in->pw_class, hsize);
2963 bp += hsize;
2964 }
2965
2966 out->pw_gecos = NULL;
2967 if (in->pw_gecos != NULL)
2968 {
2969 out->pw_gecos = bp;
2970 hsize = strlen(in->pw_gecos) + 1;
2971 memmove(bp, in->pw_gecos, hsize);
2972 bp += hsize;
2973 }
2974
2975 out->pw_dir = NULL;
2976 if (in->pw_dir != NULL)
2977 {
2978 out->pw_dir = bp;
2979 hsize = strlen(in->pw_dir) + 1;
2980 memmove(bp, in->pw_dir, hsize);
2981 bp += hsize;
2982 }
2983
2984 out->pw_shell = NULL;
2985 if (in->pw_shell != NULL)
2986 {
2987 out->pw_shell = bp;
2988 hsize = strlen(in->pw_shell) + 1;
2989 memmove(bp, in->pw_shell, hsize);
2990 bp += hsize;
2991 }
2992
2993 out->pw_expire = in->pw_expire;
2994
2995 return 0;
2996 }
2997
2998 static int
2999 copy_group_r(struct group *in, struct group *out, char *buffer, int buflen)
3000 {
3001 int i, len, hsize;
3002 unsigned long addr;
3003 char *bp, *ap;
3004
3005 if (in == NULL) return -1;
3006 if (out == NULL) return -1;
3007
3008 if (buffer == NULL) buflen = 0;
3009
3010 /* Calculate size of input */
3011 hsize = 0;
3012 if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1);
3013 if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1);
3014
3015 /* NULL pointer at end of list */
3016 hsize += sizeof(char *);
3017
3018 len = 0;
3019 if (in->gr_mem != NULL)
3020 {
3021 for (len = 0; in->gr_mem[len] != NULL; len++)
3022 {
3023 hsize += sizeof(char *);
3024 hsize += (strlen(in->gr_mem[len]) + 1);
3025 }
3026 }
3027
3028 /* Check buffer space */
3029 if (hsize > buflen) return -1;
3030
3031 /* Copy result into caller's struct group, using buffer for memory */
3032 bp = buffer;
3033
3034 out->gr_name = NULL;
3035 if (in->gr_name != NULL)
3036 {
3037 out->gr_name = bp;
3038 hsize = strlen(in->gr_name) + 1;
3039 memmove(bp, in->gr_name, hsize);
3040 bp += hsize;
3041 }
3042
3043 out->gr_passwd = NULL;
3044 if (in->gr_passwd != NULL)
3045 {
3046 out->gr_passwd = bp;
3047 hsize = strlen(in->gr_passwd) + 1;
3048 memmove(bp, in->gr_passwd, hsize);
3049 bp += hsize;
3050 }
3051
3052 out->gr_gid = in->gr_gid;
3053
3054 out->gr_mem = NULL;
3055 ap = bp + ((len + 1) * sizeof(char *));
3056
3057 if (in->gr_mem != NULL)
3058 {
3059 out->gr_mem = (char **)bp;
3060 for (i = 0; i < len; i++)
3061 {
3062 addr = (unsigned long)ap;
3063 memmove(bp, &addr, sizeof(unsigned long));
3064 bp += sizeof(unsigned long);
3065
3066 hsize = strlen(in->gr_mem[i]) + 1;
3067 memmove(ap, in->gr_mem[i], hsize);
3068 ap += hsize;
3069 }
3070 }
3071
3072 memset(bp, 0, sizeof(unsigned long));
3073 bp = ap;
3074
3075 return 0;
3076 }
3077
3078 int
3079 getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3080 {
3081 si_item_t *item;
3082 struct group *g;
3083 int status;
3084
3085 #ifdef CALL_TRACE
3086 fprintf(stderr, "-> %s %s\n", __func__, name);
3087 #endif
3088
3089 if (result != NULL) *result = NULL;
3090
3091 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3092
3093 item = si_group_byname(si_search(), name);
3094 if (item == NULL) return 0;
3095
3096 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3097
3098 status = copy_group_r(g, grp, buffer, bufsize);
3099 si_item_release(item);
3100
3101 if (status != 0) return ERANGE;
3102
3103 *result = grp;
3104 return 0;
3105 }
3106
3107 int
3108 getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3109 {
3110 si_item_t *item;
3111 struct group *g;
3112 int status;
3113
3114 #ifdef CALL_TRACE
3115 fprintf(stderr, "-> %s %d\n", __func__, gid);
3116 #endif
3117
3118 if (result != NULL) *result = NULL;
3119
3120 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3121
3122 item = si_group_bygid(si_search(), gid);
3123 if (item == NULL) return 0;
3124
3125 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3126
3127 status = copy_group_r(g, grp, buffer, bufsize);
3128 si_item_release(item);
3129
3130 if (status != 0) return ERANGE;
3131
3132 *result = grp;
3133 return 0;
3134 }
3135
3136 int
3137 getgruuid_r(uuid_t uuid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3138 {
3139 si_item_t *item;
3140 struct group *g;
3141 int status;
3142
3143 #ifdef CALL_TRACE
3144 uuid_string_t uuidstr;
3145 uuid_unparse_upper(uuid, uuidstr);
3146 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
3147 #endif
3148
3149 if (result != NULL) *result = NULL;
3150
3151 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3152
3153 item = si_group_byuuid(si_search(), uuid);
3154 if (item == NULL) return 0;
3155
3156 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3157
3158 status = copy_group_r(g, grp, buffer, bufsize);
3159 si_item_release(item);
3160
3161 if (status != 0) return ERANGE;
3162
3163 *result = grp;
3164 return 0;
3165 }
3166
3167 int
3168 getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3169 {
3170 si_item_t *item;
3171 struct passwd *p;
3172 int status;
3173
3174 #ifdef CALL_TRACE
3175 fprintf(stderr, "-> %s %s\n", __func__, name);
3176 #endif
3177
3178 if (result != NULL) *result = NULL;
3179
3180 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3181
3182 item = si_user_byname(si_search(), name);
3183 if (item == NULL) return 0;
3184
3185 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3186
3187 status = copy_user_r(p, pw, buffer, bufsize);
3188 si_item_release(item);
3189
3190 if (status != 0) return ERANGE;
3191
3192 *result = pw;
3193 return 0;
3194 }
3195
3196 int
3197 getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3198 {
3199 si_item_t *item = NULL;
3200 struct passwd *p;
3201 int status;
3202
3203 #ifdef CALL_TRACE
3204 fprintf(stderr, "-> %s %d\n", __func__, uid);
3205 #endif
3206
3207 if (result != NULL) *result = NULL;
3208
3209 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3210
3211 // Search the file module first for all system uids
3212 // (ie, uid value < 500) since they should all be
3213 // in the /etc/*passwd file.
3214 if (uid < SYSTEM_UID_LIMIT)
3215 item = si_user_byuid(si_search_file(), uid);
3216
3217 if (item == NULL)
3218 item = si_user_byuid(si_search(), uid);
3219 if (item == NULL) return 0;
3220
3221 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3222
3223 status = copy_user_r(p, pw, buffer, bufsize);
3224 si_item_release(item);
3225
3226 if (status != 0) return ERANGE;
3227
3228 *result = pw;
3229 return 0;
3230 }
3231
3232 int
3233 getpwuuid_r(uuid_t uuid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3234 {
3235 si_item_t *item;
3236 struct passwd *p;
3237 int status;
3238
3239 #ifdef CALL_TRACE
3240 uuid_string_t uuidstr;
3241 uuid_unparse_upper(uuid, uuidstr);
3242 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
3243 #endif
3244
3245 if (result != NULL) *result = NULL;
3246
3247 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3248
3249 item = si_user_byuuid(si_search(), uuid);
3250 if (item == NULL) return 0;
3251
3252 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3253
3254 status = copy_user_r(p, pw, buffer, bufsize);
3255 si_item_release(item);
3256
3257 if (status != 0) return ERANGE;
3258
3259 *result = pw;
3260 return 0;
3261 }
3262
3263 /* misc */
3264
3265 char *
3266 user_from_uid(uid_t uid, int nouser)
3267 {
3268 struct passwd *pw;
3269 static char buf[16];
3270
3271 pw = getpwuid(uid);
3272 if (pw != NULL) return pw->pw_name;
3273
3274 if (nouser) return NULL;
3275
3276 snprintf(buf, sizeof(buf), "%u", uid);
3277 return buf;
3278 }
3279
3280 char *
3281 group_from_gid(gid_t gid, int nogroup)
3282 {
3283 struct group *gr;
3284 static char buf[16];
3285
3286 gr = getgrgid(gid);
3287 if (gr != NULL) return gr->gr_name;
3288
3289 if (nogroup) return NULL;
3290
3291 snprintf(buf, sizeof(buf), "%u", gid);
3292 return buf;
3293 }
3294
3295 /* no longer supported */
3296
3297 const prdb_ent *
3298 prdb_getbyname(const char *name)
3299 {
3300 #ifdef CALL_TRACE
3301 fprintf(stderr, "~~ %s\n", __func__);
3302 #endif
3303 return NULL;
3304 }
3305
3306 const prdb_ent *
3307 prdb_get(void)
3308 {
3309 #ifdef CALL_TRACE
3310 fprintf(stderr, "~~ %s\n", __func__);
3311 #endif
3312 return NULL;
3313 }
3314
3315 void
3316 prdb_set(const char *name)
3317 {
3318 #ifdef CALL_TRACE
3319 fprintf(stderr, "~~ %s\n", __func__);
3320 #endif
3321 }
3322
3323 void
3324 prdb_end(void)
3325 {
3326 #ifdef CALL_TRACE
3327 fprintf(stderr, "~~ %s\n", __func__);
3328 #endif
3329 }
3330
3331 struct bootparamsent *
3332 bootparams_getbyname(const char *name)
3333 {
3334 #ifdef CALL_TRACE
3335 fprintf(stderr, "~~ %s\n", __func__);
3336 #endif
3337 return NULL;
3338 }
3339
3340 struct bootparamsent *
3341 bootparams_getent(void)
3342 {
3343 #ifdef CALL_TRACE
3344 fprintf(stderr, "~~ %s\n", __func__);
3345 #endif
3346 return NULL;
3347 }
3348
3349 void
3350 bootparams_setent(void)
3351 {
3352 #ifdef CALL_TRACE
3353 fprintf(stderr, "~~ %s\n", __func__);
3354 #endif
3355 }
3356
3357 void
3358 bootparams_endent(void)
3359 {
3360 #ifdef CALL_TRACE
3361 fprintf(stderr, "~~ %s\n", __func__);
3362 #endif
3363 }
3364
3365 int
3366 bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
3367 {
3368 #ifdef CALL_TRACE
3369 fprintf(stderr, "~~ %s\n", __func__);
3370 #endif
3371 return 0;
3372 }
3373
3374 int
3375 bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
3376 {
3377 #ifdef CALL_TRACE
3378 fprintf(stderr, "~~ %s\n", __func__);
3379 #endif
3380 return 0;
3381 }