Libinfo-449.1.3.tar.gz
[apple/libinfo.git] / lookup.subproj / libinfo.c
1 /*
2 * Copyright (c) 2008-2013 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
735 count = 0;
736 merge_gid(gids, basegid, &count);
737 if (gl->gl_gid != NULL) {
738 for (i = 0; i < gl->gl_count; i++) {
739 merge_gid(gids, gl->gl_gid[i], &count);
740 }
741 }
742
743 (*groups) = gids;
744
745 return count;
746 }
747
748 int32_t
749 getgrouplist_2(const char *name, gid_t basegid, gid_t **groups)
750 {
751 /*
752 * Passes back a gid_t list containing all the users groups (and basegid).
753 * Caller must free the list.
754 * Returns the number of gids in the list or -1 on failure.
755 */
756
757 #ifdef CALL_TRACE
758 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
759 #endif
760
761 if (name == NULL) return 0;
762 if (groups == NULL) return 0;
763
764 #if DS_AVAILABLE
765 _check_groups("getgrouplist_2", INT_MAX);
766 #endif
767
768 return _getgrouplist_2_internal(name, basegid, groups);
769 }
770
771 int32_t
772 getgroupcount(const char *name, gid_t basegid)
773 {
774 int32_t count;
775 gid_t *groups;
776
777 #ifdef CALL_TRACE
778 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
779 #endif
780
781 #if DS_AVAILABLE
782 _check_groups("getgroupcount", INT_MAX);
783 #endif
784
785 groups = NULL;
786 count = _getgrouplist_2_internal(name, basegid, &groups);
787 if (groups != NULL) free(groups);
788
789 return count;
790 }
791
792 /* XXX to do: async getgrouplist_2 */
793
794 int
795 initgroups(const char *name, int basegid)
796 {
797 int status;
798 uint32_t ngroups;
799 gid_t groups[NGROUPS];
800 uid_t uid;
801 #ifdef DS_AVAILABLE
802 si_item_t *item;
803 struct passwd *p;
804 #endif
805
806 #ifdef CALL_TRACE
807 fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
808 #endif
809
810 /* KAUTH_UID_NONE tells the kernel not to fetch supplementary groups from DirectoryService */
811 uid = KAUTH_UID_NONE;
812
813 #ifdef DS_AVAILABLE
814 /* get the UID for this user */
815 item = si_user_byname(si_search(), name);
816 if (item != NULL)
817 {
818 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
819 uid = p->pw_uid;
820 si_item_release(item);
821 }
822 #endif
823
824 ngroups = NGROUPS;
825
826 /*
827 * Ignore status.
828 * A failure either means that user belongs to more than NGROUPS groups
829 * or no groups at all.
830 */
831
832 (void) getgrouplist_internal(name, basegid, groups, &ngroups);
833
834 status = __initgroups(ngroups, groups, uid);
835 if (status < 0) return -1;
836
837 return 0;
838 }
839
840 /* ALIAS */
841
842 struct aliasent *
843 alias_getbyname(const char *name)
844 {
845 si_item_t *item;
846
847 #ifdef CALL_TRACE
848 fprintf(stderr, "-> %s %s\n", __func__, name);
849 #endif
850
851 item = si_alias_byname(si_search(), name);
852 LI_set_thread_item(CATEGORY_ALIAS + 100, item);
853 if (item == NULL) return NULL;
854
855 return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t));
856 }
857
858 mach_port_t
859 alias_getbyname_async_call(const char *name, si_alias_async_callback callback, void *context)
860 {
861 si_context_t *sictx;
862
863 #ifdef CALL_TRACE
864 fprintf(stderr, ">> %s %s\n", __func__, name);
865 #endif
866
867 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
868 if (sictx == NULL) return MACH_PORT_NULL;
869
870 sictx->orig_callback = callback;
871 sictx->orig_context = context;
872 sictx->cat = CATEGORY_ALIAS;
873 sictx->key_offset = 100;
874
875 return si_async_call(si_search(), SI_CALL_ALIAS_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
876 }
877
878 void
879 alias_getbyname_async_handle_reply(mach_msg_header_t *msg)
880 {
881 #ifdef CALL_TRACE
882 fprintf(stderr, "<< %s\n", __func__);
883 #endif
884
885 si_async_handle_reply(msg);
886 }
887
888 void
889 alias_setent(void)
890 {
891 #ifdef CALL_TRACE
892 fprintf(stderr, "-> %s\n", __func__);
893 #endif
894
895 LI_set_thread_list(CATEGORY_ALIAS, NULL);
896 }
897
898 struct aliasent *
899 alias_getent(void)
900 {
901 si_list_t *list;
902 si_item_t *item;
903
904 #ifdef CALL_TRACE
905 fprintf(stderr, "-> %s\n", __func__);
906 #endif
907
908 list = LI_get_thread_list(CATEGORY_ALIAS);
909 if (list == NULL)
910 {
911 list = si_alias_all(si_search());
912 LI_set_thread_list(CATEGORY_ALIAS, list);
913 }
914
915 item = si_list_next(list);
916 if (item == NULL) return NULL;
917
918 return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t));
919 }
920
921 void
922 alias_endent(void)
923 {
924 #ifdef CALL_TRACE
925 fprintf(stderr, "-- %s\n", __func__);
926 #endif
927
928 LI_set_thread_list(CATEGORY_ALIAS, NULL);
929 }
930
931 /* HOST */
932
933 void
934 freehostent(struct hostent *h)
935 {
936 if (h == NULL) return;
937
938 si_item_t *item = (si_item_t *)((uintptr_t)h - sizeof(si_item_t));
939 si_item_release(item);
940 }
941
942 struct hostent *
943 gethostbynameerrno(const char *name, int *err)
944 {
945 si_item_t *item;
946 uint32_t status;
947 struct in_addr addr4;
948
949 #ifdef CALL_TRACE
950 fprintf(stderr, "-> %s %s\n", __func__, name);
951 #endif
952
953 memset(&addr4, 0, sizeof(struct in_addr));
954 status = SI_STATUS_NO_ERROR;
955 item = NULL;
956
957 if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, NULL, &status);
958 else item = si_host_byname(si_search(), name, AF_INET, NULL, &status);
959
960 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
961 if (err != NULL) *err = status;
962
963 LI_set_thread_item(CATEGORY_HOST + 100, item);
964 if (item == NULL) return NULL;
965
966 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
967 }
968
969 struct hostent *
970 gethostbyname(const char *name)
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 h_errno = 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 mach_port_t
997 gethostbyname_async_call(const char *name, si_host_async_callback callback, void *context)
998 {
999 si_context_t *sictx;
1000
1001 #ifdef CALL_TRACE
1002 fprintf(stderr, ">> %s %s\n", __func__, name);
1003 #endif
1004
1005 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1006 if (sictx == NULL) return MACH_PORT_NULL;
1007
1008 sictx->orig_callback = callback;
1009 sictx->orig_context = context;
1010 sictx->cat = CATEGORY_HOST;
1011 sictx->key_offset = 100;
1012
1013 return si_async_call(si_search(), SI_CALL_HOST_BYNAME, name, NULL, NULL, AF_INET, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1014 }
1015
1016 mach_port_t
1017 gethostbyname_async_start(const char *name, si_host_async_callback callback, void *context)
1018 {
1019 return gethostbyname_async_call(name, callback, context);
1020 }
1021
1022 void
1023 gethostbyname_async_cancel(mach_port_t p)
1024 {
1025 #ifdef CALL_TRACE
1026 fprintf(stderr, "-- %s\n", __func__);
1027 #endif
1028
1029 si_async_cancel(p);
1030 }
1031
1032 #if 0
1033 void
1034 gethostbyname_async_handle_reply(void *param)
1035 {
1036 mach_msg_header_t *msg;
1037
1038 #ifdef CALL_TRACE
1039 fprintf(stderr, "<< %s\n", __func__);
1040 #endif
1041
1042 msg = (mach_msg_header_t *)param;
1043 si_async_handle_reply(msg);
1044 }
1045 #endif
1046
1047 void
1048 gethostbyname_async_handleReply(void *param)
1049 {
1050 mach_msg_header_t *msg;
1051
1052 #ifdef CALL_TRACE
1053 fprintf(stderr, "<< %s\n", __func__);
1054 #endif
1055
1056 msg = (mach_msg_header_t *)param;
1057 si_async_handle_reply(msg);
1058 }
1059
1060 struct hostent *
1061 gethostbyname2(const char *name, int af)
1062 {
1063 si_item_t *item;
1064 uint32_t status;
1065 struct in_addr addr4;
1066 struct in6_addr addr6;
1067 si_mod_t *search = si_search();
1068
1069 #ifdef CALL_TRACE
1070 fprintf(stderr, "-> %s %s %d\n", __func__, name, af);
1071 #endif
1072
1073 memset(&addr4, 0, sizeof(struct in_addr));
1074 memset(&addr6, 0, sizeof(struct in6_addr));
1075 status = SI_STATUS_NO_ERROR;
1076 item = NULL;
1077
1078 if (((af == AF_INET) && (inet_aton(name, &addr4) == 1)) || ((af == AF_INET6) && (inet_pton(af, name, &addr6) == 1)))
1079 {
1080 item = si_ipnode_byname(search, name, (uint32_t)af, 0, NULL, &status);
1081 }
1082 else
1083 {
1084 item = si_host_byname(search, name, (uint32_t)af, NULL, &status);
1085 }
1086
1087 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1088 h_errno = status;
1089
1090 LI_set_thread_item(CATEGORY_HOST + 100, item);
1091 if (item == NULL) return NULL;
1092
1093 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1094 }
1095
1096 mach_port_t
1097 gethostbyname2_async_call(const char *name, int af, si_group_async_callback callback, void *context)
1098 {
1099 si_context_t *sictx;
1100
1101 #ifdef CALL_TRACE
1102 fprintf(stderr, ">> %s %s %d\n", __func__, name, af);
1103 #endif
1104
1105 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1106 if (sictx == NULL) return MACH_PORT_NULL;
1107
1108 sictx->orig_callback = callback;
1109 sictx->orig_context = context;
1110 sictx->cat = CATEGORY_HOST;
1111 sictx->key_offset = 100;
1112
1113 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);
1114 }
1115
1116 void
1117 gethostbyname2_async_cancel(mach_port_t p)
1118 {
1119 #ifdef CALL_TRACE
1120 fprintf(stderr, "-- %s\n", __func__);
1121 #endif
1122
1123 si_async_cancel(p);
1124 }
1125
1126 void
1127 gethostbyname2_async_handle_reply(mach_msg_header_t *msg)
1128 {
1129 #ifdef CALL_TRACE
1130 fprintf(stderr, "<< %s\n", __func__);
1131 #endif
1132
1133 si_async_handle_reply(msg);
1134 }
1135
1136 struct hostent *
1137 gethostbyaddr(const void *addr, socklen_t len, int type)
1138 {
1139 si_item_t *item;
1140 uint32_t status;
1141
1142 #ifdef CALL_TRACE
1143 fprintf(stderr, "-> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-");
1144 #endif
1145
1146 status = SI_STATUS_NO_ERROR;
1147
1148 item = si_host_byaddr(si_search(), addr, (uint32_t)type, NULL, &status);
1149 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1150 h_errno = status;
1151
1152 LI_set_thread_item(CATEGORY_HOST + 200, item);
1153 if (item == NULL) return NULL;
1154
1155 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1156 }
1157
1158 mach_port_t
1159 gethostbyaddr_async_call(const void *addr, socklen_t len, int type, si_host_async_callback callback, void *context)
1160 {
1161 si_context_t *sictx;
1162 uint32_t addrlen;
1163
1164 #ifdef CALL_TRACE
1165 fprintf(stderr, ">> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-");
1166 #endif
1167
1168 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1169 if (sictx == NULL) return MACH_PORT_NULL;
1170
1171 sictx->orig_callback = callback;
1172 sictx->orig_context = context;
1173 sictx->cat = CATEGORY_HOST;
1174 sictx->key_offset = 200;
1175
1176 /* addr is not a C string - pass length in num3 */
1177 addrlen = len;
1178 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);
1179 }
1180
1181 mach_port_t
1182 gethostbyaddr_async_start(const char *addr, int len, int family, si_host_async_callback callback, void *context)
1183 {
1184 socklen_t slen = len;
1185
1186 return gethostbyaddr_async_call(addr, slen, family, callback, context);
1187 }
1188
1189 void
1190 gethostbyaddr_async_cancel(mach_port_t p)
1191 {
1192 #ifdef CALL_TRACE
1193 fprintf(stderr, "-- %s\n", __func__);
1194 #endif
1195
1196 si_async_cancel(p);
1197 }
1198
1199 #if 0
1200 void
1201 gethostbyaddr_async_handle_reply(void *param)
1202 {
1203
1204 mach_msg_header_t *msg;
1205
1206 #ifdef CALL_TRACE
1207 fprintf(stderr, "<< %s\n", __func__);
1208 #endif
1209
1210 msg = (mach_msg_header_t *)param;
1211 si_async_handle_reply(msg);
1212 }
1213 #endif
1214
1215 void
1216 gethostbyaddr_async_handleReply(void *param)
1217 {
1218 mach_msg_header_t *msg;
1219
1220 #ifdef CALL_TRACE
1221 fprintf(stderr, "<< %s\n", __func__);
1222 #endif
1223
1224 msg = (mach_msg_header_t *)param;
1225 si_async_handle_reply(msg);
1226 }
1227
1228 struct hostent *
1229 getipnodebyname(const char *name, int family, int flags, int *err)
1230 {
1231 si_item_t *item;
1232 uint32_t status;
1233
1234 #ifdef CALL_TRACE
1235 fprintf(stderr, "-> %s %s %d 0x%08x\n", __func__, name, family, flags);
1236 #endif
1237
1238 status = SI_STATUS_NO_ERROR;
1239
1240 item = si_ipnode_byname(si_search(), name, family, flags, NULL, &status);
1241 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1242 if (err != NULL) *err = status;
1243
1244 if (item == NULL) return NULL;
1245
1246 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1247 }
1248
1249 #if 0
1250 mach_port_t
1251 getipnodebyname_async_call(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context)
1252 {
1253 si_context_t *sictx;
1254
1255 #ifdef CALL_TRACE
1256 fprintf(stderr, ">> %s %s %d 0x%08x\n", __func__, name, family, flags);
1257 #endif
1258
1259 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1260 if (sictx == NULL) return MACH_PORT_NULL;
1261
1262 sictx->orig_callback = callback;
1263 sictx->orig_context = context;
1264 sictx->cat = CATEGORY_HOST;
1265 sictx->key_offset = -1;
1266
1267 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);
1268 }
1269
1270 mach_port_t
1271 getipnodebyname_async_start(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context)
1272 {
1273 return getipnodebyname_async_call(name, family, flags, err, callback, context);
1274 }
1275
1276 void
1277 getipnodebyname_async_cancel(mach_port_t p)
1278 {
1279 #ifdef CALL_TRACE
1280 fprintf(stderr, "-- %s\n", __func__);
1281 #endif
1282
1283 si_async_cancel(p);
1284 }
1285
1286 void
1287 getipnodebyname_async_handle_reply(mach_msg_header_t *msg)
1288 {
1289 #ifdef CALL_TRACE
1290 fprintf(stderr, "<< %s\n", __func__);
1291 #endif
1292
1293 si_async_handle_reply(msg);
1294 }
1295
1296 void
1297 getipnodebyname_async_handleReply(mach_msg_header_t *msg)
1298 {
1299 #ifdef CALL_TRACE
1300 fprintf(stderr, "<< %s\n", __func__);
1301 #endif
1302
1303 si_async_handle_reply(msg);
1304 }
1305 #endif
1306
1307 static int
1308 is_a4_mapped(const char *s)
1309 {
1310 int i;
1311 u_int8_t c;
1312
1313 if (s == NULL) return 0;
1314
1315 for (i = 0; i < 10; i++)
1316 {
1317 c = s[i];
1318 if (c != 0x0) return 0;
1319 }
1320
1321 for (i = 10; i < 12; i++)
1322 {
1323 c = s[i];
1324 if (c != 0xff) return 0;
1325 }
1326
1327 return 1;
1328 }
1329
1330 static int
1331 is_a4_compat(const char *s)
1332 {
1333 int i;
1334 u_int8_t c;
1335
1336 if (s == NULL) return 0;
1337
1338 for (i = 0; i < 12; i++)
1339 {
1340 c = s[i];
1341 if (c != 0x0) return 0;
1342 }
1343
1344 /* Check for :: and ::1 */
1345 for (i = 13; i < 15; i++)
1346 {
1347 /* anything non-zero in these 3 bytes means it's a V4 address */
1348 c = s[i];
1349 if (c != 0x0) return 1;
1350 }
1351
1352 /* Leading 15 bytes are all zero */
1353 c = s[15];
1354 if (c == 0x0) return 0;
1355 if (c == 0x1) return 0;
1356
1357 return 1;
1358 }
1359
1360 struct hostent *
1361 getipnodebyaddr(const void *src, size_t len, int family, int *err)
1362 {
1363 si_item_t *item;
1364
1365 #ifdef CALL_TRACE
1366 fprintf(stderr, "-> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-");
1367 #endif
1368
1369 if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src)))
1370 {
1371 src += 12;
1372 len = 4;
1373 family = AF_INET;
1374 }
1375
1376 item = si_host_byaddr(si_search(), src, family, NULL, (uint32_t *)err);
1377 if (item == NULL) return NULL;
1378
1379 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1380 }
1381
1382 #if 0
1383 static void
1384 si_libinfo_ipnode_callback(si_item_t *item, uint32_t status, void *ctx)
1385 {
1386 si_context_t *sictx;
1387 struct hostent *h;
1388
1389 if (ctx == NULL) return;
1390
1391 sictx = (si_context_t *)ctx;
1392
1393 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
1394 {
1395 free(sictx);
1396 si_item_release(item);
1397 return;
1398 }
1399
1400 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY;
1401
1402 if (item == NULL)
1403 {
1404 ((si_ipnode_async_callback)(sictx->orig_callback))(NULL, status, sictx->orig_context);
1405 return;
1406 }
1407
1408 h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1409 ((si_ipnode_async_callback)(sictx->orig_callback))(h, status, sictx->orig_context);
1410
1411 free(sictx);
1412 }
1413
1414 mach_port_t
1415 getipnodebyaddr_async_call(const void *src, socklen_t len, int family, int *err, si_ipnode_async_callback callback, void *context)
1416 {
1417 si_context_t *sictx;
1418 uint32_t srclen;
1419
1420 #ifdef CALL_TRACE
1421 fprintf(stderr, ">> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-");
1422 #endif
1423
1424 if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src)))
1425 {
1426 src += 12;
1427 len = 4;
1428 family = AF_INET;
1429 }
1430
1431 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1432 if (sictx == NULL) return MACH_PORT_NULL;
1433
1434 sictx->orig_callback = callback;
1435 sictx->orig_context = context;
1436 sictx->cat = CATEGORY_HOST;
1437 sictx->key_offset = -1;
1438
1439 /* src is not a C string - pass length in num3 */
1440 srclen = len;
1441 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);
1442 }
1443
1444 mach_port_t
1445 getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, si_ipnode_async_callback callback, void *context)
1446 {
1447 socklen_t slen = len;
1448
1449 return getipnodebyaddr_async_call(addr, slen, family, error, callback, context);
1450 }
1451
1452 void
1453 getipnodebyaddr_async_cancel(mach_port_t p)
1454 {
1455 #ifdef CALL_TRACE
1456 fprintf(stderr, "-- %s\n", __func__);
1457 #endif
1458
1459 si_async_cancel(p);
1460 }
1461
1462 void
1463 getipnodebyaddr_async_handle_reply(mach_msg_header_t *msg)
1464 {
1465 #ifdef CALL_TRACE
1466 fprintf(stderr, "<< %s\n", __func__);
1467 #endif
1468
1469 si_async_handle_reply(msg);
1470 }
1471
1472 void
1473 getipnodebyaddr_async_handleReply(mach_msg_header_t *msg)
1474 {
1475 #ifdef CALL_TRACE
1476 fprintf(stderr, "<< %s\n", __func__);
1477 #endif
1478
1479 si_async_handle_reply(msg);
1480 }
1481 #endif
1482
1483 void
1484 sethostent(int ignored)
1485 {
1486 #ifdef CALL_TRACE
1487 fprintf(stderr, "-- %s\n", __func__);
1488 #endif
1489
1490 LI_set_thread_list(CATEGORY_HOST, NULL);
1491 }
1492
1493 struct hostent *
1494 gethostent(void)
1495 {
1496 si_list_t *list;
1497 si_item_t *item;
1498
1499 #ifdef CALL_TRACE
1500 fprintf(stderr, "-> %s\n", __func__);
1501 #endif
1502
1503 list = LI_get_thread_list(CATEGORY_HOST);
1504 if (list == NULL)
1505 {
1506 list = si_host_all(si_search());
1507 LI_set_thread_list(CATEGORY_HOST, list);
1508 }
1509
1510 item = si_list_next(list);
1511 if (item == NULL) return NULL;
1512
1513 return (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
1514 }
1515
1516 void
1517 endhostent(void)
1518 {
1519 #ifdef CALL_TRACE
1520 fprintf(stderr, "-- %s\n", __func__);
1521 #endif
1522
1523 LI_set_thread_list(CATEGORY_HOST, NULL);
1524 }
1525
1526 /* MAC ADDRESS */
1527
1528 int
1529 ether_hostton(const char *name, struct ether_addr *e)
1530 {
1531 si_item_t *item;
1532 si_mac_t *mac;
1533 uint32_t t[6];
1534 int i;
1535
1536 #ifdef CALL_TRACE
1537 fprintf(stderr, "-> %s %s\n", __func__, name);
1538 #endif
1539
1540 if (name == NULL) return -1;
1541 if (e == NULL) return -1;
1542
1543 item = si_mac_byname(si_search(), name);
1544 LI_set_thread_item(CATEGORY_MAC + 100, item);
1545 if (item == NULL) return -1;
1546
1547 mac = (si_mac_t *)((uintptr_t)item + sizeof(si_item_t));
1548
1549 i = sscanf(mac->mac, " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]);
1550 if (i != 6) return -1;
1551
1552 for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i];
1553 return 0;
1554 }
1555
1556 /* XXX to do? async ether_hostton */
1557
1558 int
1559 ether_ntohost(char *name, const struct ether_addr *e)
1560 {
1561 si_item_t *item;
1562 si_mac_t *mac;
1563 uint32_t i, x[6];
1564 char str[256];
1565
1566 if (name == NULL) return -1;
1567 if (e == NULL) return -1;
1568
1569 for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i];
1570 snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]);
1571
1572 #ifdef CALL_TRACE
1573 fprintf(stderr, "-> %s %s\n", __func__, str);
1574 #endif
1575
1576 item = si_mac_bymac(si_search(), str);
1577 LI_set_thread_item(CATEGORY_MAC + 200, item);
1578 if (item == NULL) return -1;
1579
1580 mac = (si_mac_t *)((uintptr_t)item + sizeof(si_item_t));
1581
1582 memcpy(name, mac->host, strlen(mac->host) + 1);
1583 return 0;
1584 }
1585
1586 /* XXX to do? async ether_ntohost */
1587
1588 /* NETWORK */
1589
1590 struct netent *
1591 getnetbyname(const char *name)
1592 {
1593 si_item_t *item;
1594
1595 #ifdef CALL_TRACE
1596 fprintf(stderr, "-> %s %s\n", __func__, name);
1597 #endif
1598
1599 item = si_network_byname(si_search(), name);
1600 LI_set_thread_item(CATEGORY_NETWORK + 100, item);
1601 if (item == NULL) return NULL;
1602
1603 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1604 }
1605
1606 mach_port_t
1607 getnetbyname_async_call(const char *name, si_network_async_callback callback, void *context)
1608 {
1609 si_context_t *sictx;
1610
1611 #ifdef CALL_TRACE
1612 fprintf(stderr, ">> %s %s\n", __func__, name);
1613 #endif
1614
1615 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1616 if (sictx == NULL) return MACH_PORT_NULL;
1617
1618 sictx->orig_callback = callback;
1619 sictx->orig_context = context;
1620 sictx->cat = CATEGORY_NETWORK;
1621 sictx->key_offset = 100;
1622
1623 return si_async_call(si_search(), SI_CALL_NETWORK_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1624 }
1625
1626 void
1627 getnetbyname_async_handle_reply(mach_msg_header_t *msg)
1628 {
1629 #ifdef CALL_TRACE
1630 fprintf(stderr, "<< %s\n", __func__);
1631 #endif
1632
1633 si_async_handle_reply(msg);
1634 }
1635
1636 struct netent *
1637 getnetbyaddr(uint32_t net, int type)
1638 {
1639 si_item_t *item;
1640
1641 #ifdef CALL_TRACE
1642 fprintf(stderr, "-> %s 0x%08x\n", __func__, net);
1643 #endif
1644
1645 if (type != AF_INET) return NULL;
1646
1647 item = si_network_byaddr(si_search(), net);
1648 LI_set_thread_item(CATEGORY_NETWORK + 200, item);
1649 if (item == NULL) return NULL;
1650
1651 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1652 }
1653
1654 mach_port_t
1655 getnetbyaddr_async_call(uint32_t net, int type, si_group_async_callback callback, void *context)
1656 {
1657 si_context_t *sictx;
1658
1659 #ifdef CALL_TRACE
1660 fprintf(stderr, ">> %s 0x%08x\n", __func__, net);
1661 #endif
1662
1663 if (type != AF_INET) return MACH_PORT_NULL;
1664
1665 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1666 if (sictx == NULL) return MACH_PORT_NULL;
1667
1668 sictx->orig_callback = callback;
1669 sictx->orig_context = context;
1670 sictx->cat = CATEGORY_NETWORK;
1671 sictx->key_offset = 200;
1672
1673 return si_async_call(si_search(), SI_CALL_NETWORK_BYADDR, NULL, NULL, NULL, net, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1674 }
1675
1676 void
1677 getnetbyaddr_async_handle_reply(mach_msg_header_t *msg)
1678 {
1679 #ifdef CALL_TRACE
1680 fprintf(stderr, "<< %s\n", __func__);
1681 #endif
1682
1683 si_async_handle_reply(msg);
1684 }
1685
1686 void
1687 setnetent(int ignored)
1688 {
1689 #ifdef CALL_TRACE
1690 fprintf(stderr, "-- %s\n", __func__);
1691 #endif
1692
1693 LI_set_thread_list(CATEGORY_NETWORK, NULL);
1694 }
1695
1696 struct netent *
1697 getnetent(void)
1698 {
1699 si_list_t *list;
1700 si_item_t *item;
1701
1702 #ifdef CALL_TRACE
1703 fprintf(stderr, "-> %s\n", __func__);
1704 #endif
1705
1706 list = LI_get_thread_list(CATEGORY_NETWORK);
1707 if (list == NULL)
1708 {
1709 list = si_network_all(si_search());
1710 LI_set_thread_list(CATEGORY_NETWORK, list);
1711 }
1712
1713 item = si_list_next(list);
1714 if (item == NULL) return NULL;
1715
1716 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1717 }
1718
1719 void
1720 endnetent(void)
1721 {
1722 #ifdef CALL_TRACE
1723 fprintf(stderr, "-- %s\n", __func__);
1724 #endif
1725
1726 LI_set_thread_list(CATEGORY_NETWORK, NULL);
1727 }
1728
1729 /* SERVICE */
1730
1731 struct servent *
1732 getservbyname(const char *name, const char *proto)
1733 {
1734 si_item_t *item;
1735
1736 #ifdef CALL_TRACE
1737 fprintf(stderr, "-> %s %s %s\n", __func__, name, proto);
1738 #endif
1739
1740 item = si_service_byname(si_search(), name, proto);
1741 LI_set_thread_item(CATEGORY_SERVICE + 100, item);
1742 if (item == NULL) return NULL;
1743
1744 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1745 }
1746
1747 mach_port_t
1748 getservbyname_async_call(const char *name, const char *proto, si_service_async_callback callback, void *context)
1749 {
1750 si_context_t *sictx;
1751
1752 #ifdef CALL_TRACE
1753 fprintf(stderr, ">> %s %s %s\n", __func__, name, proto);
1754 #endif
1755
1756 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1757 if (sictx == NULL) return MACH_PORT_NULL;
1758
1759 sictx->orig_callback = callback;
1760 sictx->orig_context = context;
1761 sictx->cat = CATEGORY_SERVICE;
1762 sictx->key_offset = 100;
1763
1764 return si_async_call(si_search(), SI_CALL_SERVICE_BYNAME, name, proto, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1765 }
1766
1767 void
1768 getservbyname_async_handle_reply(mach_msg_header_t *msg)
1769 {
1770 #ifdef CALL_TRACE
1771 fprintf(stderr, "<< %s\n", __func__);
1772 #endif
1773
1774 si_async_handle_reply(msg);
1775 }
1776
1777 struct servent *
1778 getservbyport(int port, const char *proto)
1779 {
1780 si_item_t *item;
1781
1782 #ifdef CALL_TRACE
1783 fprintf(stderr, "-> %s %d %s\n", __func__, ntohs((uint16_t)port), proto);
1784 #endif
1785
1786 item = si_service_byport(si_search(), port, proto);
1787 LI_set_thread_item(CATEGORY_SERVICE + 200, item);
1788 if (item == NULL) return NULL;
1789
1790 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1791 }
1792
1793 mach_port_t
1794 getservbyport_async_call(int port, const char *proto, si_group_async_callback callback, void *context)
1795 {
1796 si_context_t *sictx;
1797
1798 #ifdef CALL_TRACE
1799 fprintf(stderr, ">> %s %d %s\n", __func__, port, proto);
1800 #endif
1801
1802 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1803 if (sictx == NULL) return MACH_PORT_NULL;
1804
1805 sictx->orig_callback = callback;
1806 sictx->orig_context = context;
1807 sictx->cat = CATEGORY_SERVICE;
1808 sictx->key_offset = 200;
1809
1810 return si_async_call(si_search(), SI_CALL_SERVICE_BYPORT, NULL, proto, NULL, port, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1811 }
1812
1813 void
1814 getservbyport_async_handle_reply(mach_msg_header_t *msg)
1815 {
1816 #ifdef CALL_TRACE
1817 fprintf(stderr, "<< %s\n", __func__);
1818 #endif
1819
1820 si_async_handle_reply(msg);
1821 }
1822
1823 void
1824 setservent(int ignored)
1825 {
1826 #ifdef CALL_TRACE
1827 fprintf(stderr, "-- %s\n", __func__);
1828 #endif
1829
1830 LI_set_thread_list(CATEGORY_SERVICE, NULL);
1831 }
1832
1833 struct servent *
1834 getservent(void)
1835 {
1836 si_list_t *list;
1837 si_item_t *item;
1838
1839 #ifdef CALL_TRACE
1840 fprintf(stderr, "-> %s\n", __func__);
1841 #endif
1842
1843 list = LI_get_thread_list(CATEGORY_SERVICE);
1844 if (list == NULL)
1845 {
1846 list = si_service_all(si_search());
1847 LI_set_thread_list(CATEGORY_SERVICE, list);
1848 }
1849
1850 item = si_list_next(list);
1851 if (item == NULL) return NULL;
1852
1853 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1854 }
1855
1856 void
1857 endservent(void)
1858 {
1859 #ifdef CALL_TRACE
1860 fprintf(stderr, "-- %s\n", __func__);
1861 #endif
1862
1863 LI_set_thread_list(CATEGORY_SERVICE, NULL);
1864 }
1865
1866 /* PROTOCOL */
1867
1868 struct protoent *
1869 getprotobyname(const char *name)
1870 {
1871 si_item_t *item;
1872
1873 #ifdef CALL_TRACE
1874 fprintf(stderr, "-> %s %s\n", __func__, name);
1875 #endif
1876
1877 item = si_protocol_byname(si_search(), name);
1878 LI_set_thread_item(CATEGORY_PROTOCOL + 100, item);
1879 if (item == NULL) return NULL;
1880
1881 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1882 }
1883
1884 mach_port_t
1885 getprotobyname_async_call(const char *name, si_protocol_async_callback callback, void *context)
1886 {
1887 si_context_t *sictx;
1888
1889 #ifdef CALL_TRACE
1890 fprintf(stderr, ">> %s %s\n", __func__, name);
1891 #endif
1892
1893 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1894 if (sictx == NULL) return MACH_PORT_NULL;
1895
1896 sictx->orig_callback = callback;
1897 sictx->orig_context = context;
1898 sictx->cat = CATEGORY_PROTOCOL;
1899 sictx->key_offset = 100;
1900
1901 return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1902 }
1903
1904 void
1905 getprotobyname_async_handle_reply(mach_msg_header_t *msg)
1906 {
1907 #ifdef CALL_TRACE
1908 fprintf(stderr, "<< %s\n", __func__);
1909 #endif
1910
1911 si_async_handle_reply(msg);
1912 }
1913
1914 struct protoent *
1915 getprotobynumber(int number)
1916 {
1917 si_item_t *item;
1918
1919 #ifdef CALL_TRACE
1920 fprintf(stderr, "-> %s %d\n", __func__, number);
1921 #endif
1922
1923 item = si_protocol_bynumber(si_search(), number);
1924 LI_set_thread_item(CATEGORY_PROTOCOL + 200, item);
1925 if (item == NULL) return NULL;
1926
1927 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1928 }
1929
1930 mach_port_t
1931 getprotobynumber_async_call(int number, si_group_async_callback callback, void *context)
1932 {
1933 si_context_t *sictx;
1934
1935 #ifdef CALL_TRACE
1936 fprintf(stderr, ">> %s %d\n", __func__, number);
1937 #endif
1938
1939 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1940 if (sictx == NULL) return MACH_PORT_NULL;
1941
1942 sictx->orig_callback = callback;
1943 sictx->orig_context = context;
1944 sictx->cat = CATEGORY_PROTOCOL;
1945 sictx->key_offset = 200;
1946
1947 return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1948 }
1949
1950 void
1951 getprotobynumber_async_handle_reply(mach_msg_header_t *msg)
1952 {
1953 #ifdef CALL_TRACE
1954 fprintf(stderr, "<< %s\n", __func__);
1955 #endif
1956
1957 si_async_handle_reply(msg);
1958 }
1959
1960 void
1961 setprotoent(int ignored)
1962 {
1963 #ifdef CALL_TRACE
1964 fprintf(stderr, "-- %s\n", __func__);
1965 #endif
1966
1967 LI_set_thread_list(CATEGORY_PROTOCOL, NULL);
1968 }
1969
1970 struct protoent *
1971 getprotoent(void)
1972 {
1973 si_list_t *list;
1974 si_item_t *item;
1975
1976 #ifdef CALL_TRACE
1977 fprintf(stderr, "-> %s\n", __func__);
1978 #endif
1979
1980 list = LI_get_thread_list(CATEGORY_PROTOCOL);
1981 if (list == NULL)
1982 {
1983 list = si_protocol_all(si_search());
1984 LI_set_thread_list(CATEGORY_PROTOCOL, list);
1985 }
1986
1987 item = si_list_next(list);
1988 if (item == NULL) return NULL;
1989
1990 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1991 }
1992
1993 void
1994 endprotoent(void)
1995 {
1996 #ifdef CALL_TRACE
1997 fprintf(stderr, "-- %s\n", __func__);
1998 #endif
1999
2000 LI_set_thread_list(CATEGORY_PROTOCOL, NULL);
2001 }
2002
2003 /* RPC */
2004
2005 struct rpcent *
2006 getrpcbyname(const char *name)
2007 {
2008 si_item_t *item;
2009
2010 #ifdef CALL_TRACE
2011 fprintf(stderr, "-> %s %s\n", __func__, name);
2012 #endif
2013
2014 item = si_rpc_byname(si_search(), name);
2015 LI_set_thread_item(CATEGORY_RPC + 100, item);
2016 if (item == NULL) return NULL;
2017
2018 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2019 }
2020
2021 mach_port_t
2022 getrpcbyname_async_call(const char *name, si_rpc_async_callback callback, void *context)
2023 {
2024 si_context_t *sictx;
2025
2026 #ifdef CALL_TRACE
2027 fprintf(stderr, ">> %s %s\n", __func__, name);
2028 #endif
2029
2030 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2031 if (sictx == NULL) return MACH_PORT_NULL;
2032
2033 sictx->orig_callback = callback;
2034 sictx->orig_context = context;
2035 sictx->cat = CATEGORY_RPC;
2036 sictx->key_offset = 100;
2037
2038 return si_async_call(si_search(), SI_CALL_RPC_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2039 }
2040
2041 void
2042 getrpcbyname_async_handle_reply(mach_msg_header_t *msg)
2043 {
2044 #ifdef CALL_TRACE
2045 fprintf(stderr, "<< %s\n", __func__);
2046 #endif
2047
2048 si_async_handle_reply(msg);
2049 }
2050
2051 struct rpcent *
2052 getrpcbynumber
2053 (
2054 #ifdef __LP64__
2055 int number
2056 #else
2057 long number
2058 #endif
2059 )
2060 {
2061 si_item_t *item;
2062
2063 #ifdef CALL_TRACE
2064 fprintf(stderr, "-> %s %ld\n", __func__, (long int)number);
2065 #endif
2066
2067 item = si_rpc_bynumber(si_search(), number);
2068 LI_set_thread_item(CATEGORY_RPC + 200, item);
2069 if (item == NULL) return NULL;
2070
2071 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2072 }
2073
2074 mach_port_t
2075 getrpcbynumber_async_call(int number, si_group_async_callback callback, void *context)
2076 {
2077 si_context_t *sictx;
2078
2079 #ifdef CALL_TRACE
2080 fprintf(stderr, ">> %s %d\n", __func__, number);
2081 #endif
2082
2083 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2084 if (sictx == NULL) return MACH_PORT_NULL;
2085
2086 sictx->orig_callback = callback;
2087 sictx->orig_context = context;
2088 sictx->cat = CATEGORY_RPC;
2089 sictx->key_offset = 200;
2090
2091 return si_async_call(si_search(), SI_CALL_RPC_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2092 }
2093
2094 void
2095 getrpcbynumber_async_handle_reply(mach_msg_header_t *msg)
2096 {
2097 #ifdef CALL_TRACE
2098 fprintf(stderr, "<< %s\n", __func__);
2099 #endif
2100
2101 si_async_handle_reply(msg);
2102 }
2103
2104 void
2105 setrpcent(int ignored)
2106 {
2107 #ifdef CALL_TRACE
2108 fprintf(stderr, "-- %s\n", __func__);
2109 #endif
2110
2111 LI_set_thread_list(CATEGORY_RPC, NULL);
2112 }
2113
2114 struct rpcent *
2115 getrpcent(void)
2116 {
2117 si_list_t *list;
2118 si_item_t *item;
2119
2120 #ifdef CALL_TRACE
2121 fprintf(stderr, "-> %s\n", __func__);
2122 #endif
2123
2124 list = LI_get_thread_list(CATEGORY_RPC);
2125 if (list == NULL)
2126 {
2127 list = si_rpc_all(si_search());
2128 LI_set_thread_list(CATEGORY_RPC, list);
2129 }
2130
2131 item = si_list_next(list);
2132 if (item == NULL) return NULL;
2133
2134 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2135 }
2136
2137 void
2138 endrpcent(void)
2139 {
2140 #ifdef CALL_TRACE
2141 fprintf(stderr, "-- %s\n", __func__);
2142 #endif
2143
2144 LI_set_thread_list(CATEGORY_RPC, NULL);
2145 }
2146
2147 /* FS */
2148
2149 struct fstab *
2150 getfsspec(const char *spec)
2151 {
2152 si_item_t *item;
2153
2154 #ifdef CALL_TRACE
2155 fprintf(stderr, "-> %s %s\n", __func__, spec);
2156 #endif
2157
2158 item = si_fs_byspec(si_search(), spec);
2159 LI_set_thread_item(CATEGORY_FS + 100, item);
2160 if (item == NULL) return NULL;
2161
2162 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2163 }
2164
2165 struct fstab *
2166 getfsbyname(const char *name)
2167 {
2168 #ifdef CALL_TRACE
2169 fprintf(stderr, "-> %s %s\n", __func__, name);
2170 #endif
2171
2172 return getfsspec(name);
2173 }
2174
2175 mach_port_t
2176 getfsspec_async_call(const char *spec, si_fs_async_callback callback, void *context)
2177 {
2178 si_context_t *sictx;
2179
2180 #ifdef CALL_TRACE
2181 fprintf(stderr, ">> %s %s\n", __func__, spec);
2182 #endif
2183
2184 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2185 if (sictx == NULL) return MACH_PORT_NULL;
2186
2187 sictx->orig_callback = callback;
2188 sictx->orig_context = context;
2189 sictx->cat = CATEGORY_FS;
2190 sictx->key_offset = 100;
2191
2192 return si_async_call(si_search(), SI_CALL_FS_BYSPEC, spec, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2193 }
2194
2195 void
2196 getfsspec_async_handle_reply(mach_msg_header_t *msg)
2197 {
2198 #ifdef CALL_TRACE
2199 fprintf(stderr, "<< %s\n", __func__);
2200 #endif
2201
2202 si_async_handle_reply(msg);
2203 }
2204
2205 struct fstab *
2206 getfsfile(const char *file)
2207 {
2208 si_item_t *item;
2209
2210 #ifdef CALL_TRACE
2211 fprintf(stderr, "-> %s %s\n", __func__, file);
2212 #endif
2213
2214 item = si_fs_byfile(si_search(), file);
2215 LI_set_thread_item(CATEGORY_FS + 200, item);
2216 if (item == NULL) return NULL;
2217
2218 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2219 }
2220
2221 mach_port_t
2222 getfsfile_async_call(const char *file, si_fs_async_callback callback, void *context)
2223 {
2224 si_context_t *sictx;
2225
2226 #ifdef CALL_TRACE
2227 fprintf(stderr, ">> %s %s\n", __func__, file);
2228 #endif
2229
2230 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2231 if (sictx == NULL) return MACH_PORT_NULL;
2232
2233 sictx->orig_callback = callback;
2234 sictx->orig_context = context;
2235 sictx->cat = CATEGORY_FS;
2236 sictx->key_offset = 200;
2237
2238 return si_async_call(si_search(), SI_CALL_FS_BYFILE, file, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2239 }
2240
2241 void
2242 getfsfile_async_handle_reply(mach_msg_header_t *msg)
2243 {
2244 #ifdef CALL_TRACE
2245 fprintf(stderr, "<< %s\n", __func__);
2246 #endif
2247
2248 si_async_handle_reply(msg);
2249 }
2250
2251 int
2252 setfsent(void)
2253 {
2254 #ifdef CALL_TRACE
2255 fprintf(stderr, "-> %s\n", __func__);
2256 #endif
2257
2258 LI_set_thread_list(CATEGORY_FS, NULL);
2259 return 1;
2260 }
2261
2262 struct fstab *
2263 getfsent(void)
2264 {
2265 si_list_t *list;
2266 si_item_t *item;
2267
2268 #ifdef CALL_TRACE
2269 fprintf(stderr, "-> %s\n", __func__);
2270 #endif
2271
2272 list = LI_get_thread_list(CATEGORY_FS);
2273 if (list == NULL)
2274 {
2275 list = si_fs_all(si_search());
2276 LI_set_thread_list(CATEGORY_FS, list);
2277 }
2278
2279 item = si_list_next(list);
2280 if (item == NULL) return NULL;
2281
2282 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2283 }
2284
2285 void
2286 endfsent(void)
2287 {
2288 #ifdef CALL_TRACE
2289 fprintf(stderr, "-- %s\n", __func__);
2290 #endif
2291
2292 LI_set_thread_list(CATEGORY_FS, NULL);
2293 }
2294
2295 /* GETADDRINFO */
2296
2297 static int
2298 _getaddrinfo_internal(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, struct addrinfo **res)
2299 {
2300 si_list_t *list;
2301 uint32_t family, socktype, protocol, flags, status;
2302 struct addrinfo *ai;
2303
2304 family = AF_UNSPEC;
2305 socktype = SOCK_UNSPEC;
2306 protocol = IPPROTO_UNSPEC;
2307 flags = 0;
2308 status = SI_STATUS_NO_ERROR;
2309
2310 if (res == NULL) return 0;
2311 *res = NULL;
2312
2313 if (hints != NULL)
2314 {
2315 family = hints->ai_family;
2316 socktype = hints->ai_socktype;
2317 protocol = hints->ai_protocol;
2318 flags = hints->ai_flags;
2319 }
2320
2321 #ifdef CALL_TRACE
2322 fprintf(stderr, "-> %s %s %s %u %u %u 0x%08x %s\n", __func__, nodename, servname, family, socktype, protocol, flags, (interface == NULL) ? "" : interface);
2323 #endif
2324
2325 list = si_addrinfo(si_search(), nodename, servname, family, socktype, protocol, flags, interface, &status);
2326 if ((status != SI_STATUS_NO_ERROR) || (list == NULL) || (list->count == 0))
2327 {
2328 si_list_release(list);
2329
2330 if (status == SI_STATUS_NO_ERROR) return EAI_NONAME;
2331 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2332 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2333 else status = status - SI_STATUS_EAI_PLUS_100;
2334 return status;
2335 }
2336
2337 *res = si_list_to_addrinfo(list);
2338 si_list_release(list);
2339 if (*res == NULL) status = EAI_MEMORY;
2340
2341 /* don't return the canonical name unless asked */
2342 if ((flags & AI_CANONNAME) == 0)
2343 {
2344 for (ai = *res; ai != NULL; ai = ai->ai_next)
2345 {
2346 free(ai->ai_canonname);
2347 ai->ai_canonname = NULL;
2348 }
2349 }
2350
2351 return status;
2352 }
2353
2354 int
2355 getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
2356 {
2357 return _getaddrinfo_internal(nodename, servname, hints, NULL, res);
2358 }
2359
2360 #ifdef CALL_TRACE
2361
2362 static char *
2363 socket_name(int sock)
2364 {
2365 static char str[16];
2366
2367 switch(sock)
2368 {
2369 case SOCK_UNSPEC: return "SOCK_UNSPEC";
2370 case SOCK_STREAM: return "SOCK_STREAM";
2371 case SOCK_DGRAM: return "SOCK_DGRAM";
2372 }
2373
2374 sprintf(str, "%d", sock);
2375 return str;
2376 }
2377
2378 static char *
2379 family_name(int pf)
2380 {
2381 static char str[16];
2382
2383 switch(pf)
2384 {
2385 case PF_UNSPEC: return "PF_UNSPEC";
2386 case PF_INET: return "PF_INET";
2387 case PF_INET6: return "PF_INET6";
2388 };
2389
2390 sprintf(str, "%d", pf);
2391 return str;
2392 }
2393
2394 static char *
2395 protocol_name(int p)
2396 {
2397 static char str[16];
2398
2399 switch(p)
2400 {
2401 case IPPROTO_UNSPEC: return "IPPROTO_UNSPEC";
2402 case IPPROTO_TCP: return "IPPROTO_TCP";
2403 case IPPROTO_UDP: return "IPPROTO_UDP";
2404 }
2405
2406 sprintf(str, "%d", p);
2407 return str;
2408 }
2409
2410 static char *
2411 _gai_inet_ntop(struct in6_addr a)
2412 {
2413 static char buf[128];
2414 char t[32];
2415 unsigned short x;
2416 char *p;
2417 int i;
2418
2419 memset(buf, 0, 128);
2420
2421 p = (char *)&a.__u6_addr.__u6_addr32;
2422 for (i = 0; i < 8; i++, x += 1)
2423 {
2424 memmove(&x, p, 2);
2425 p += 2;
2426 sprintf(t, "%hx", x);
2427 strcat(buf, t);
2428 if (i < 7) strcat(buf, ":");
2429 }
2430
2431 return buf;
2432 }
2433
2434 static void
2435 fprint_addrinfo(FILE *f, struct addrinfo *a)
2436 {
2437 int i;
2438 unsigned char v;
2439 struct sockaddr_in *s4;
2440 struct sockaddr_in6 *s6;
2441
2442 if (a == NULL) return;
2443
2444 if (a->ai_flags != 0)
2445 {
2446 fprintf(f, "flags =");
2447 if (a->ai_flags & AI_PASSIVE) fprintf(f, " AI_PASSIVE");
2448 if (a->ai_flags & AI_CANONNAME) fprintf(f, " AI_CANONNAME");
2449 if (a->ai_flags & AI_NUMERICHOST) fprintf(f, " AI_NUMERICHOST");
2450 if (a->ai_flags & AI_NUMERICSERV) fprintf(f, " AI_NUMERICSERV");
2451 fprintf(f, "\n");
2452 }
2453
2454 fprintf(f, "family = %s\n", family_name(a->ai_family));
2455 fprintf(f, "socktype = %s\n", socket_name(a->ai_socktype));
2456 fprintf(f, "protocol = %s\n", protocol_name(a->ai_protocol));
2457
2458 fprintf(f, "canonical name = ");
2459 if (a->ai_canonname == NULL) fprintf(f, "NULL\n");
2460 else fprintf(f, "\"%s\"\n", a->ai_canonname);
2461
2462 fprintf(f, "addrlen = %ld\n", (long int)a->ai_addrlen);
2463
2464 if (a->ai_addr == NULL) fprintf(f, "sockaddr = NULL\n");
2465 else
2466 {
2467 if (a->ai_family == PF_INET)
2468 {
2469 s4 = (struct sockaddr_in *)a->ai_addr;
2470
2471 fprintf(f, "sockaddr_in len = %d\n", s4->sin_len);
2472 fprintf(f, "sockaddr_in family = %s\n", family_name(s4->sin_family));
2473 fprintf(f, "sockaddr_in port = %hu\n", ntohs(s4->sin_port));
2474 fprintf(f, "sockaddr_in address = %s\n", inet_ntoa(s4->sin_addr));
2475 }
2476 else if (a->ai_family == PF_INET6)
2477 {
2478 s6 = (struct sockaddr_in6 *)a->ai_addr;
2479
2480 fprintf(f, "sockaddr_in6 len = %d\n", s6->sin6_len);
2481 fprintf(f, "sockaddr_in6 family = %s\n", family_name(s6->sin6_family));
2482 fprintf(f, "sockaddr_in6 port = %hu\n", ntohs(s6->sin6_port));
2483 fprintf(f, "sockaddr_in6 flowinfo = %d\n", s6->sin6_flowinfo);
2484 fprintf(f, "sockaddr_in6 address = %s\n", _gai_inet_ntop(s6->sin6_addr));
2485 fprintf(f, "sockaddr_in6 scope_id = %d\n", s6->sin6_scope_id);
2486 }
2487 else
2488 {
2489 fprintf(f, "sockaddr len = %d\n", a->ai_addr->sa_len);
2490 fprintf(f, "sockaddr family = %s\n", family_name(a->ai_addr->sa_family));
2491 fprintf(f, "sockaddr data = ");
2492 for (i = 0; i < a->ai_addr->sa_len - 2; i++)
2493 {
2494 v = a->ai_addr->sa_data[i];
2495 fprintf(f, "%02x", v);
2496 }
2497 fprintf(f, "\n");
2498 }
2499 }
2500
2501 if (a->ai_next != NULL)
2502 {
2503 fprintf(f, "NEXT --->\n");
2504 fprint_addrinfo(f, a->ai_next);
2505 }
2506 }
2507
2508 #endif
2509
2510 static void
2511 si_libinfo_addrinfo_callback(si_list_t *list, uint32_t status, void *ctx)
2512 {
2513 si_context_t *sictx;
2514 struct addrinfo *out;
2515
2516 if (ctx == NULL)
2517 {
2518 #ifdef CALL_TRACE
2519 fprintf(stderr, " %s error no context\n", __func__);
2520 #endif
2521 si_list_release(list);
2522 return;
2523 }
2524
2525 sictx = (si_context_t *)ctx;
2526
2527 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2528 {
2529 #ifdef CALL_TRACE
2530 fprintf(stderr, " %s error no callback\n", __func__);
2531 #endif
2532 si_list_release(list);
2533 free(sictx);
2534 return;
2535 }
2536
2537 if (status != SI_STATUS_NO_ERROR)
2538 {
2539 #ifdef CALL_TRACE
2540 fprintf(stderr, " %s original status %d\n", __func__, status);
2541 #endif
2542 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2543 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2544 else status = status - SI_STATUS_EAI_PLUS_100;
2545 }
2546
2547 if (list == NULL)
2548 {
2549 #ifdef CALL_TRACE
2550 fprintf(stderr, " %s result NULL status %d (returning EAI_NONAME)\n", __func__, status);
2551 #endif
2552 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_NONAME, NULL, sictx->orig_context);
2553 free(sictx);
2554 return;
2555 }
2556
2557 out = si_list_to_addrinfo(list);
2558 si_list_release(list);
2559 if (out == NULL)
2560 {
2561 #ifdef CALL_TRACE
2562 fprintf(stderr, " %s result conversion failed returning NULL status %d (returning EAI_MEMORY)\n", __func__, status);
2563 #endif
2564 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_MEMORY, NULL, sictx->orig_context);
2565 free(sictx);
2566 return;
2567 }
2568
2569 #ifdef CALL_TRACE
2570 fprintf(stderr, " %s %d\n", __func__, status);
2571 fprint_addrinfo(stderr, out);
2572 #endif
2573 ((si_addrinfo_async_callback)(sictx->orig_callback))(status, out, sictx->orig_context);
2574
2575 free(sictx);
2576 }
2577
2578 /* SPI */
2579 mach_port_t
2580 _getaddrinfo_interface_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, si_addrinfo_async_callback callback, void *context)
2581 {
2582 si_context_t *sictx;
2583 uint32_t family, socktype, protocol, flags;
2584
2585 family = AF_UNSPEC;
2586 socktype = SOCK_UNSPEC;
2587 protocol = IPPROTO_UNSPEC;
2588 flags = 0;
2589
2590 if (hints != NULL)
2591 {
2592 family = hints->ai_family;
2593 socktype = hints->ai_socktype;
2594 protocol = hints->ai_protocol;
2595 flags = hints->ai_flags;
2596 }
2597
2598 #ifdef CALL_TRACE
2599 fprintf(stderr, ">> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags);
2600 #endif
2601
2602 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2603 if (sictx == NULL) return MACH_PORT_NULL;
2604
2605 sictx->orig_callback = callback;
2606 sictx->orig_context = context;
2607 sictx->cat = CATEGORY_ADDRINFO;
2608 sictx->key_offset = 0;
2609
2610 return si_async_call(si_search(), SI_CALL_ADDRINFO, nodename, servname, interface, family, socktype, protocol, flags, (void *)si_libinfo_addrinfo_callback, sictx);
2611 }
2612
2613 mach_port_t
2614 getaddrinfo_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2615 {
2616 return _getaddrinfo_interface_async_call(nodename, servname, hints, NULL, callback, context);
2617 }
2618
2619 int32_t
2620 getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2621 {
2622 if (p == NULL) return EAI_SYSTEM;
2623
2624 *p = getaddrinfo_async_call(nodename, servname, hints, callback, context);
2625
2626 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2627 return 0;
2628 }
2629
2630 int32_t
2631 getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints)
2632 {
2633 return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL);
2634 }
2635
2636 int32_t
2637 getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res)
2638 {
2639 /* unsupported Leopard SPI */
2640 return EAI_SYSTEM;
2641 }
2642
2643 void
2644 getaddrinfo_async_cancel(mach_port_t p)
2645 {
2646 #ifdef CALL_TRACE
2647 fprintf(stderr, "-- %s\n", __func__);
2648 #endif
2649
2650 si_async_cancel(p);
2651 }
2652
2653 int32_t
2654 getaddrinfo_async_handle_reply(void *param)
2655 {
2656 mach_msg_header_t *msg;
2657
2658 #ifdef CALL_TRACE
2659 fprintf(stderr, "<< %s\n", __func__);
2660 #endif
2661
2662 msg = (mach_msg_header_t *)param;
2663 si_async_handle_reply(msg);
2664
2665 return 0;
2666 }
2667
2668 /* GETNAMEINFO */
2669
2670 static int
2671 _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)
2672 {
2673 si_item_t *item;
2674 si_nameinfo_t *ni;
2675 uint32_t status, len, wantn, wants;
2676
2677 #ifdef CALL_TRACE
2678 fprintf(stderr, "-> %s\n", __func__);
2679 #endif
2680
2681 status = SI_STATUS_NO_ERROR;
2682
2683 wantn = 0;
2684 if ((node != NULL) && (nodelen > 0)) wantn = 1;
2685
2686 wants = 0;
2687 if ((service != NULL) && (servicelen > 0)) wants = 1;
2688
2689 if ((wantn == 0) && (wants == 0)) return status;
2690
2691 if (wantn == 0) flags |= NI_NUMERICHOST;
2692 if (wants == 0) flags |= NI_NUMERICSERV;
2693
2694 item = si_nameinfo(si_search(), sa, flags, interface, &status);
2695 if ((status != SI_STATUS_NO_ERROR) || (item == NULL))
2696 {
2697 si_item_release(item);
2698
2699 if (status == SI_STATUS_NO_ERROR) status = EAI_NONAME;
2700 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2701 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2702 else status = status - SI_STATUS_EAI_PLUS_100;
2703 return status;
2704 }
2705
2706 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2707
2708 len = 0;
2709 if (ni->ni_node != NULL) len = strlen(ni->ni_node) + 1;
2710 if ((wantn == 1) && (len > 0))
2711 {
2712 if (len > nodelen)
2713 {
2714 si_item_release(item);
2715 return EAI_OVERFLOW;
2716 }
2717
2718 memset(node, 0, nodelen);
2719 memcpy(node, ni->ni_node, len);
2720 }
2721
2722 len = 0;
2723 if (ni->ni_serv != NULL) len = strlen(ni->ni_serv) + 1;
2724 if ((wants == 1) && (len > 0))
2725 {
2726 if (len > servicelen)
2727 {
2728 si_item_release(item);
2729 return EAI_OVERFLOW;
2730 }
2731
2732 memset(service, 0, servicelen);
2733 memcpy(service, ni->ni_serv, len);
2734 }
2735
2736 si_item_release(item);
2737 return 0;
2738 }
2739
2740 int
2741 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags)
2742 {
2743 if (sa == NULL) return EAI_FAIL;
2744
2745 if (sa->sa_family == AF_LINK) return getnameinfo_link(sa, salen, node, nodelen, service, servicelen, flags);
2746 return _getnameinfo_interface_internal(sa, salen, node, nodelen, service, servicelen, flags, NULL);
2747 }
2748
2749 static void
2750 si_libinfo_nameinfo_callback(si_item_t *item, uint32_t status, void *ctx)
2751 {
2752 si_context_t *sictx;
2753 si_nameinfo_t *ni;
2754 char *node, *serv;
2755
2756 if (ctx == NULL) return;
2757
2758 sictx = (si_context_t *)ctx;
2759
2760 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2761 {
2762 si_item_release(item);
2763 free(sictx);
2764 return;
2765 }
2766
2767 if (status != SI_STATUS_NO_ERROR)
2768 {
2769 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2770 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2771 else status = status - SI_STATUS_EAI_PLUS_100;
2772 }
2773
2774 if (item == NULL)
2775 {
2776 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, NULL, NULL, sictx->orig_context);
2777 free(sictx);
2778 return;
2779 }
2780
2781 LI_set_thread_item(CATEGORY_NAMEINFO, item);
2782
2783 node = NULL;
2784 serv = NULL;
2785
2786 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2787 if (ni->ni_node != NULL) node = strdup(ni->ni_node);
2788 if (ni->ni_serv != NULL) serv = strdup(ni->ni_serv);
2789
2790 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, node, serv, sictx->orig_context);
2791 free(sictx);
2792 }
2793
2794 /* SPI */
2795 mach_port_t
2796 _getnameinfo_interface_async_call(const struct sockaddr *sa, size_t len, int flags, const char *interface, si_nameinfo_async_callback callback, void *context)
2797 {
2798 si_context_t *sictx;
2799 uint32_t salen;
2800
2801 #ifdef CALL_TRACE
2802 fprintf(stderr, ">> %s\n", __func__);
2803 #endif
2804
2805 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2806 if (sictx == NULL) return MACH_PORT_NULL;
2807
2808 sictx->orig_callback = callback;
2809 sictx->orig_context = context;
2810 sictx->cat = CATEGORY_ADDRINFO;
2811 sictx->key_offset = 0;
2812
2813 /* sa is not a C string - pass length in num3 */
2814 salen = len;
2815 return si_async_call(si_search(), SI_CALL_NAMEINFO, (const char *)sa, NULL, interface, flags, 0, salen, 0, (void *)si_libinfo_nameinfo_callback, sictx);
2816 }
2817
2818 mach_port_t
2819 getnameinfo_async_call(const struct sockaddr *sa, size_t len, int flags, si_nameinfo_async_callback callback, void *context)
2820 {
2821 return _getnameinfo_interface_async_call(sa, len, flags, NULL, callback, context);
2822 }
2823
2824 int32_t
2825 getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, si_nameinfo_async_callback callback, void *context)
2826 {
2827 if (p == NULL) return EAI_SYSTEM;
2828 *p = getnameinfo_async_call(sa, salen, flags, callback, context);
2829
2830 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2831 return 0;
2832 }
2833
2834 int32_t
2835 getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags)
2836 {
2837 return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL);
2838 }
2839
2840 void
2841 getnameinfo_async_cancel(mach_port_t p)
2842 {
2843 #ifdef CALL_TRACE
2844 fprintf(stderr, "-- %s\n", __func__);
2845 #endif
2846
2847 si_async_cancel(p);
2848 }
2849
2850 int32_t
2851 getnameinfo_async_handle_reply(void *param)
2852 {
2853 mach_msg_header_t *msg;
2854
2855 #ifdef CALL_TRACE
2856 fprintf(stderr, "<< %s\n", __func__);
2857 #endif
2858
2859 msg = (mach_msg_header_t *)param;
2860 si_async_handle_reply(msg);
2861
2862 return 0;
2863 }
2864
2865 /* getpwXXX_r and getgrXXX_r */
2866
2867 static int
2868 copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen)
2869 {
2870 int hsize;
2871 char *bp;
2872
2873 if (in == NULL) return -1;
2874 if (out == NULL) return -1;
2875
2876 if (buffer == NULL) buflen = 0;
2877
2878 /* Calculate size of input */
2879 hsize = 0;
2880 if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1);
2881 if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1);
2882 if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1);
2883 if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1);
2884 if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1);
2885 if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1);
2886
2887 /* Check buffer space */
2888 if (hsize > buflen) return -1;
2889
2890 /* Copy result into caller's struct passwd, using buffer for memory */
2891 bp = buffer;
2892
2893 out->pw_name = NULL;
2894 if (in->pw_name != NULL)
2895 {
2896 out->pw_name = bp;
2897 hsize = strlen(in->pw_name) + 1;
2898 memmove(bp, in->pw_name, hsize);
2899 bp += hsize;
2900 }
2901
2902 out->pw_passwd = NULL;
2903 if (in->pw_passwd != NULL)
2904 {
2905 out->pw_passwd = bp;
2906 hsize = strlen(in->pw_passwd) + 1;
2907 memmove(bp, in->pw_passwd, hsize);
2908 bp += hsize;
2909 }
2910
2911 out->pw_uid = in->pw_uid;
2912
2913 out->pw_gid = in->pw_gid;
2914
2915 out->pw_change = in->pw_change;
2916
2917 out->pw_class = NULL;
2918 if (in->pw_class != NULL)
2919 {
2920 out->pw_class = bp;
2921 hsize = strlen(in->pw_class) + 1;
2922 memmove(bp, in->pw_class, hsize);
2923 bp += hsize;
2924 }
2925
2926 out->pw_gecos = NULL;
2927 if (in->pw_gecos != NULL)
2928 {
2929 out->pw_gecos = bp;
2930 hsize = strlen(in->pw_gecos) + 1;
2931 memmove(bp, in->pw_gecos, hsize);
2932 bp += hsize;
2933 }
2934
2935 out->pw_dir = NULL;
2936 if (in->pw_dir != NULL)
2937 {
2938 out->pw_dir = bp;
2939 hsize = strlen(in->pw_dir) + 1;
2940 memmove(bp, in->pw_dir, hsize);
2941 bp += hsize;
2942 }
2943
2944 out->pw_shell = NULL;
2945 if (in->pw_shell != NULL)
2946 {
2947 out->pw_shell = bp;
2948 hsize = strlen(in->pw_shell) + 1;
2949 memmove(bp, in->pw_shell, hsize);
2950 bp += hsize;
2951 }
2952
2953 out->pw_expire = in->pw_expire;
2954
2955 return 0;
2956 }
2957
2958 static int
2959 copy_group_r(struct group *in, struct group *out, char *buffer, int buflen)
2960 {
2961 int i, len, hsize;
2962 unsigned long addr;
2963 char *bp, *ap;
2964
2965 if (in == NULL) return -1;
2966 if (out == NULL) return -1;
2967
2968 if (buffer == NULL) buflen = 0;
2969
2970 /* Calculate size of input */
2971 hsize = 0;
2972 if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1);
2973 if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1);
2974
2975 /* NULL pointer at end of list */
2976 hsize += sizeof(char *);
2977
2978 len = 0;
2979 if (in->gr_mem != NULL)
2980 {
2981 for (len = 0; in->gr_mem[len] != NULL; len++)
2982 {
2983 hsize += sizeof(char *);
2984 hsize += (strlen(in->gr_mem[len]) + 1);
2985 }
2986 }
2987
2988 /* Check buffer space */
2989 if (hsize > buflen) return -1;
2990
2991 /* Copy result into caller's struct group, using buffer for memory */
2992 bp = buffer;
2993
2994 out->gr_name = NULL;
2995 if (in->gr_name != NULL)
2996 {
2997 out->gr_name = bp;
2998 hsize = strlen(in->gr_name) + 1;
2999 memmove(bp, in->gr_name, hsize);
3000 bp += hsize;
3001 }
3002
3003 out->gr_passwd = NULL;
3004 if (in->gr_passwd != NULL)
3005 {
3006 out->gr_passwd = bp;
3007 hsize = strlen(in->gr_passwd) + 1;
3008 memmove(bp, in->gr_passwd, hsize);
3009 bp += hsize;
3010 }
3011
3012 out->gr_gid = in->gr_gid;
3013
3014 out->gr_mem = NULL;
3015 ap = bp + ((len + 1) * sizeof(char *));
3016
3017 if (in->gr_mem != NULL)
3018 {
3019 out->gr_mem = (char **)bp;
3020 for (i = 0; i < len; i++)
3021 {
3022 addr = (unsigned long)ap;
3023 memmove(bp, &addr, sizeof(unsigned long));
3024 bp += sizeof(unsigned long);
3025
3026 hsize = strlen(in->gr_mem[i]) + 1;
3027 memmove(ap, in->gr_mem[i], hsize);
3028 ap += hsize;
3029 }
3030 }
3031
3032 memset(bp, 0, sizeof(unsigned long));
3033 bp = ap;
3034
3035 return 0;
3036 }
3037
3038 int
3039 getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3040 {
3041 si_item_t *item;
3042 struct group *g;
3043 int status;
3044
3045 #ifdef CALL_TRACE
3046 fprintf(stderr, "-> %s %s\n", __func__, name);
3047 #endif
3048
3049 if (result != NULL) *result = NULL;
3050
3051 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3052
3053 item = si_group_byname(si_search(), name);
3054 if (item == NULL) return 0;
3055
3056 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3057
3058 status = copy_group_r(g, grp, buffer, bufsize);
3059 si_item_release(item);
3060
3061 if (status != 0) return ERANGE;
3062
3063 *result = grp;
3064 return 0;
3065 }
3066
3067 int
3068 getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3069 {
3070 si_item_t *item;
3071 struct group *g;
3072 int status;
3073
3074 #ifdef CALL_TRACE
3075 fprintf(stderr, "-> %s %d\n", __func__, gid);
3076 #endif
3077
3078 if (result != NULL) *result = NULL;
3079
3080 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3081
3082 item = si_group_bygid(si_search(), gid);
3083 if (item == NULL) return 0;
3084
3085 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3086
3087 status = copy_group_r(g, grp, buffer, bufsize);
3088 si_item_release(item);
3089
3090 if (status != 0) return ERANGE;
3091
3092 *result = grp;
3093 return 0;
3094 }
3095
3096 int
3097 getgruuid_r(uuid_t uuid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3098 {
3099 si_item_t *item;
3100 struct group *g;
3101 int status;
3102
3103 #ifdef CALL_TRACE
3104 uuid_string_t uuidstr;
3105 uuid_unparse_upper(uuid, uuidstr);
3106 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
3107 #endif
3108
3109 if (result != NULL) *result = NULL;
3110
3111 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3112
3113 item = si_group_byuuid(si_search(), uuid);
3114 if (item == NULL) return 0;
3115
3116 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3117
3118 status = copy_group_r(g, grp, buffer, bufsize);
3119 si_item_release(item);
3120
3121 if (status != 0) return ERANGE;
3122
3123 *result = grp;
3124 return 0;
3125 }
3126
3127 int
3128 getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3129 {
3130 si_item_t *item;
3131 struct passwd *p;
3132 int status;
3133
3134 #ifdef CALL_TRACE
3135 fprintf(stderr, "-> %s %s\n", __func__, name);
3136 #endif
3137
3138 if (result != NULL) *result = NULL;
3139
3140 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3141
3142 item = si_user_byname(si_search(), name);
3143 if (item == NULL) return 0;
3144
3145 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3146
3147 status = copy_user_r(p, pw, buffer, bufsize);
3148 si_item_release(item);
3149
3150 if (status != 0) return ERANGE;
3151
3152 *result = pw;
3153 return 0;
3154 }
3155
3156 int
3157 getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3158 {
3159 si_item_t *item;
3160 struct passwd *p;
3161 int status;
3162
3163 #ifdef CALL_TRACE
3164 fprintf(stderr, "-> %s %d\n", __func__, uid);
3165 #endif
3166
3167 if (result != NULL) *result = NULL;
3168
3169 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3170
3171 item = si_user_byuid(si_search(), uid);
3172 if (item == NULL) return 0;
3173
3174 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3175
3176 status = copy_user_r(p, pw, buffer, bufsize);
3177 si_item_release(item);
3178
3179 if (status != 0) return ERANGE;
3180
3181 *result = pw;
3182 return 0;
3183 }
3184
3185 int
3186 getpwuuid_r(uuid_t uuid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3187 {
3188 si_item_t *item;
3189 struct passwd *p;
3190 int status;
3191
3192 #ifdef CALL_TRACE
3193 uuid_string_t uuidstr;
3194 uuid_unparse_upper(uuid, uuidstr);
3195 fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
3196 #endif
3197
3198 if (result != NULL) *result = NULL;
3199
3200 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3201
3202 item = si_user_byuuid(si_search(), uuid);
3203 if (item == NULL) return 0;
3204
3205 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3206
3207 status = copy_user_r(p, pw, buffer, bufsize);
3208 si_item_release(item);
3209
3210 if (status != 0) return ERANGE;
3211
3212 *result = pw;
3213 return 0;
3214 }
3215
3216 /* misc */
3217
3218 char *
3219 user_from_uid(uid_t uid, int nouser)
3220 {
3221 struct passwd *pw;
3222 static char buf[16];
3223
3224 pw = getpwuid(uid);
3225 if (pw != NULL) return pw->pw_name;
3226
3227 if (nouser) return NULL;
3228
3229 snprintf(buf, sizeof(buf), "%u", uid);
3230 return buf;
3231 }
3232
3233 char *
3234 group_from_gid(gid_t gid, int nogroup)
3235 {
3236 struct group *gr;
3237 static char buf[16];
3238
3239 gr = getgrgid(gid);
3240 if (gr != NULL) return gr->gr_name;
3241
3242 if (nogroup) return NULL;
3243
3244 snprintf(buf, sizeof(buf), "%u", gid);
3245 return buf;
3246 }
3247
3248 /* no longer supported */
3249
3250 const prdb_ent *
3251 prdb_getbyname(const char *name)
3252 {
3253 #ifdef CALL_TRACE
3254 fprintf(stderr, "~~ %s\n", __func__);
3255 #endif
3256 return NULL;
3257 }
3258
3259 const prdb_ent *
3260 prdb_get(void)
3261 {
3262 #ifdef CALL_TRACE
3263 fprintf(stderr, "~~ %s\n", __func__);
3264 #endif
3265 return NULL;
3266 }
3267
3268 void
3269 prdb_set(const char *name)
3270 {
3271 #ifdef CALL_TRACE
3272 fprintf(stderr, "~~ %s\n", __func__);
3273 #endif
3274 }
3275
3276 void
3277 prdb_end(void)
3278 {
3279 #ifdef CALL_TRACE
3280 fprintf(stderr, "~~ %s\n", __func__);
3281 #endif
3282 }
3283
3284 struct bootparamsent *
3285 bootparams_getbyname(const char *name)
3286 {
3287 #ifdef CALL_TRACE
3288 fprintf(stderr, "~~ %s\n", __func__);
3289 #endif
3290 return NULL;
3291 }
3292
3293 struct bootparamsent *
3294 bootparams_getent(void)
3295 {
3296 #ifdef CALL_TRACE
3297 fprintf(stderr, "~~ %s\n", __func__);
3298 #endif
3299 return NULL;
3300 }
3301
3302 void
3303 bootparams_setent(void)
3304 {
3305 #ifdef CALL_TRACE
3306 fprintf(stderr, "~~ %s\n", __func__);
3307 #endif
3308 }
3309
3310 void
3311 bootparams_endent(void)
3312 {
3313 #ifdef CALL_TRACE
3314 fprintf(stderr, "~~ %s\n", __func__);
3315 #endif
3316 }
3317
3318 int
3319 bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
3320 {
3321 #ifdef CALL_TRACE
3322 fprintf(stderr, "~~ %s\n", __func__);
3323 #endif
3324 return 0;
3325 }
3326
3327 int
3328 bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
3329 {
3330 #ifdef CALL_TRACE
3331 fprintf(stderr, "~~ %s\n", __func__);
3332 #endif
3333 return 0;
3334 }