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