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