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