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