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