Libinfo-330.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, 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, 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, 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, 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, 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, NULL, &status);
899 else item = si_host_byname(si_search(), name, AF_INET, NULL, &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, NULL, &status);
926 else item = si_host_byname(si_search(), name, AF_INET, NULL, &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, 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, NULL, &status);
1022 }
1023 else
1024 {
1025 item = si_host_byname(search, name, (uint32_t)af, NULL, &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, 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, NULL, &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, 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, NULL, &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, 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, NULL, (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, 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
1500 ether_ntohost(char *name, const struct ether_addr *e)
1501 {
1502 si_item_t *item;
1503 char *cname;
1504 uint32_t i, x[6];
1505 char str[256];
1506
1507 if (name == NULL) return -1;
1508 if (e == NULL) return -1;
1509
1510 for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i];
1511 snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]);
1512
1513 #ifdef CALL_TRACE
1514 fprintf(stderr, "-> %s %s\n", __func__, str);
1515 #endif
1516
1517 item = si_mac_bymac(si_search(), str);
1518 LI_set_thread_item(CATEGORY_MAC + 200, item);
1519 if (item == NULL) return -1;
1520
1521 cname = (char *)((uintptr_t)item + sizeof(si_item_t));
1522
1523 memcpy(name, cname, strlen(cname) + 1);
1524 return 0;
1525 }
1526
1527 /* XXX to do? async ether_ntohost */
1528
1529 /* NETWORK */
1530
1531 struct netent *
1532 getnetbyname(const char *name)
1533 {
1534 si_item_t *item;
1535
1536 #ifdef CALL_TRACE
1537 fprintf(stderr, "-> %s %s\n", __func__, name);
1538 #endif
1539
1540 item = si_network_byname(si_search(), name);
1541 LI_set_thread_item(CATEGORY_NETWORK + 100, item);
1542 if (item == NULL) return NULL;
1543
1544 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1545 }
1546
1547 mach_port_t
1548 getnetbyname_async_call(const char *name, si_network_async_callback callback, void *context)
1549 {
1550 si_context_t *sictx;
1551
1552 #ifdef CALL_TRACE
1553 fprintf(stderr, ">> %s %s\n", __func__, name);
1554 #endif
1555
1556 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1557 if (sictx == NULL) return MACH_PORT_NULL;
1558
1559 sictx->orig_callback = callback;
1560 sictx->orig_context = context;
1561 sictx->cat = CATEGORY_NETWORK;
1562 sictx->key_offset = 100;
1563
1564 return si_async_call(si_search(), SI_CALL_NETWORK_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1565 }
1566
1567 void
1568 getnetbyname_async_handle_reply(mach_msg_header_t *msg)
1569 {
1570 #ifdef CALL_TRACE
1571 fprintf(stderr, "<< %s\n", __func__);
1572 #endif
1573
1574 si_async_handle_reply(msg);
1575 }
1576
1577 struct netent *
1578 getnetbyaddr(uint32_t net, int type)
1579 {
1580 si_item_t *item;
1581
1582 #ifdef CALL_TRACE
1583 fprintf(stderr, "-> %s 0x%08x\n", __func__, net);
1584 #endif
1585
1586 if (type != AF_INET) return NULL;
1587
1588 item = si_network_byaddr(si_search(), net);
1589 LI_set_thread_item(CATEGORY_NETWORK + 200, item);
1590 if (item == NULL) return NULL;
1591
1592 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1593 }
1594
1595 mach_port_t
1596 getnetbyaddr_async_call(uint32_t net, int type, si_group_async_callback callback, void *context)
1597 {
1598 si_context_t *sictx;
1599
1600 #ifdef CALL_TRACE
1601 fprintf(stderr, ">> %s 0x%08x\n", __func__, net);
1602 #endif
1603
1604 if (type != AF_INET) return MACH_PORT_NULL;
1605
1606 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1607 if (sictx == NULL) return MACH_PORT_NULL;
1608
1609 sictx->orig_callback = callback;
1610 sictx->orig_context = context;
1611 sictx->cat = CATEGORY_NETWORK;
1612 sictx->key_offset = 200;
1613
1614 return si_async_call(si_search(), SI_CALL_NETWORK_BYADDR, NULL, NULL, NULL, net, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1615 }
1616
1617 void
1618 getnetbyaddr_async_handle_reply(mach_msg_header_t *msg)
1619 {
1620 #ifdef CALL_TRACE
1621 fprintf(stderr, "<< %s\n", __func__);
1622 #endif
1623
1624 si_async_handle_reply(msg);
1625 }
1626
1627 void
1628 setnetent(int ignored)
1629 {
1630 #ifdef CALL_TRACE
1631 fprintf(stderr, "-- %s\n", __func__);
1632 #endif
1633
1634 LI_set_thread_list(CATEGORY_NETWORK, NULL);
1635 }
1636
1637 struct netent *
1638 getnetent(void)
1639 {
1640 si_list_t *list;
1641 si_item_t *item;
1642
1643 #ifdef CALL_TRACE
1644 fprintf(stderr, "-> %s\n", __func__);
1645 #endif
1646
1647 list = LI_get_thread_list(CATEGORY_NETWORK);
1648 if (list == NULL)
1649 {
1650 list = si_network_all(si_search());
1651 LI_set_thread_list(CATEGORY_NETWORK, list);
1652 }
1653
1654 item = si_list_next(list);
1655 if (item == NULL) return NULL;
1656
1657 return (struct netent *)((uintptr_t)item + sizeof(si_item_t));
1658 }
1659
1660 void
1661 endnetent(void)
1662 {
1663 #ifdef CALL_TRACE
1664 fprintf(stderr, "-- %s\n", __func__);
1665 #endif
1666
1667 LI_set_thread_list(CATEGORY_NETWORK, NULL);
1668 }
1669
1670 /* SERVICE */
1671
1672 struct servent *
1673 getservbyname(const char *name, const char *proto)
1674 {
1675 si_item_t *item;
1676
1677 #ifdef CALL_TRACE
1678 fprintf(stderr, "-> %s %s %s\n", __func__, name, proto);
1679 #endif
1680
1681 item = si_service_byname(si_search(), name, proto);
1682 LI_set_thread_item(CATEGORY_SERVICE + 100, item);
1683 if (item == NULL) return NULL;
1684
1685 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1686 }
1687
1688 mach_port_t
1689 getservbyname_async_call(const char *name, const char *proto, si_service_async_callback callback, void *context)
1690 {
1691 si_context_t *sictx;
1692
1693 #ifdef CALL_TRACE
1694 fprintf(stderr, ">> %s %s %s\n", __func__, name, proto);
1695 #endif
1696
1697 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1698 if (sictx == NULL) return MACH_PORT_NULL;
1699
1700 sictx->orig_callback = callback;
1701 sictx->orig_context = context;
1702 sictx->cat = CATEGORY_SERVICE;
1703 sictx->key_offset = 100;
1704
1705 return si_async_call(si_search(), SI_CALL_SERVICE_BYNAME, name, proto, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1706 }
1707
1708 void
1709 getservbyname_async_handle_reply(mach_msg_header_t *msg)
1710 {
1711 #ifdef CALL_TRACE
1712 fprintf(stderr, "<< %s\n", __func__);
1713 #endif
1714
1715 si_async_handle_reply(msg);
1716 }
1717
1718 struct servent *
1719 getservbyport(int port, const char *proto)
1720 {
1721 si_item_t *item;
1722
1723 #ifdef CALL_TRACE
1724 fprintf(stderr, "-> %s %d %s\n", __func__, ntohs((uint16_t)port), proto);
1725 #endif
1726
1727 item = si_service_byport(si_search(), port, proto);
1728 LI_set_thread_item(CATEGORY_SERVICE + 200, item);
1729 if (item == NULL) return NULL;
1730
1731 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1732 }
1733
1734 mach_port_t
1735 getservbyport_async_call(int port, const char *proto, si_group_async_callback callback, void *context)
1736 {
1737 si_context_t *sictx;
1738
1739 #ifdef CALL_TRACE
1740 fprintf(stderr, ">> %s %d %s\n", __func__, port, proto);
1741 #endif
1742
1743 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1744 if (sictx == NULL) return MACH_PORT_NULL;
1745
1746 sictx->orig_callback = callback;
1747 sictx->orig_context = context;
1748 sictx->cat = CATEGORY_SERVICE;
1749 sictx->key_offset = 200;
1750
1751 return si_async_call(si_search(), SI_CALL_SERVICE_BYPORT, NULL, proto, NULL, port, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1752 }
1753
1754 void
1755 getservbyport_async_handle_reply(mach_msg_header_t *msg)
1756 {
1757 #ifdef CALL_TRACE
1758 fprintf(stderr, "<< %s\n", __func__);
1759 #endif
1760
1761 si_async_handle_reply(msg);
1762 }
1763
1764 void
1765 setservent(int ignored)
1766 {
1767 #ifdef CALL_TRACE
1768 fprintf(stderr, "-- %s\n", __func__);
1769 #endif
1770
1771 LI_set_thread_list(CATEGORY_SERVICE, NULL);
1772 }
1773
1774 struct servent *
1775 getservent(void)
1776 {
1777 si_list_t *list;
1778 si_item_t *item;
1779
1780 #ifdef CALL_TRACE
1781 fprintf(stderr, "-> %s\n", __func__);
1782 #endif
1783
1784 list = LI_get_thread_list(CATEGORY_SERVICE);
1785 if (list == NULL)
1786 {
1787 list = si_service_all(si_search());
1788 LI_set_thread_list(CATEGORY_SERVICE, list);
1789 }
1790
1791 item = si_list_next(list);
1792 if (item == NULL) return NULL;
1793
1794 return (struct servent *)((uintptr_t)item + sizeof(si_item_t));
1795 }
1796
1797 void
1798 endservent(void)
1799 {
1800 #ifdef CALL_TRACE
1801 fprintf(stderr, "-- %s\n", __func__);
1802 #endif
1803
1804 LI_set_thread_list(CATEGORY_SERVICE, NULL);
1805 }
1806
1807 /* PROTOCOL */
1808
1809 struct protoent *
1810 getprotobyname(const char *name)
1811 {
1812 si_item_t *item;
1813
1814 #ifdef CALL_TRACE
1815 fprintf(stderr, "-> %s %s\n", __func__, name);
1816 #endif
1817
1818 item = si_protocol_byname(si_search(), name);
1819 LI_set_thread_item(CATEGORY_PROTOCOL + 100, item);
1820 if (item == NULL) return NULL;
1821
1822 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1823 }
1824
1825 mach_port_t
1826 getprotobyname_async_call(const char *name, si_protocol_async_callback callback, void *context)
1827 {
1828 si_context_t *sictx;
1829
1830 #ifdef CALL_TRACE
1831 fprintf(stderr, ">> %s %s\n", __func__, name);
1832 #endif
1833
1834 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1835 if (sictx == NULL) return MACH_PORT_NULL;
1836
1837 sictx->orig_callback = callback;
1838 sictx->orig_context = context;
1839 sictx->cat = CATEGORY_PROTOCOL;
1840 sictx->key_offset = 100;
1841
1842 return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1843 }
1844
1845 void
1846 getprotobyname_async_handle_reply(mach_msg_header_t *msg)
1847 {
1848 #ifdef CALL_TRACE
1849 fprintf(stderr, "<< %s\n", __func__);
1850 #endif
1851
1852 si_async_handle_reply(msg);
1853 }
1854
1855 struct protoent *
1856 getprotobynumber(int number)
1857 {
1858 si_item_t *item;
1859
1860 #ifdef CALL_TRACE
1861 fprintf(stderr, "-> %s %d\n", __func__, number);
1862 #endif
1863
1864 item = si_protocol_bynumber(si_search(), number);
1865 LI_set_thread_item(CATEGORY_PROTOCOL + 200, item);
1866 if (item == NULL) return NULL;
1867
1868 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1869 }
1870
1871 mach_port_t
1872 getprotobynumber_async_call(int number, si_group_async_callback callback, void *context)
1873 {
1874 si_context_t *sictx;
1875
1876 #ifdef CALL_TRACE
1877 fprintf(stderr, ">> %s %d\n", __func__, number);
1878 #endif
1879
1880 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1881 if (sictx == NULL) return MACH_PORT_NULL;
1882
1883 sictx->orig_callback = callback;
1884 sictx->orig_context = context;
1885 sictx->cat = CATEGORY_PROTOCOL;
1886 sictx->key_offset = 200;
1887
1888 return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1889 }
1890
1891 void
1892 getprotobynumber_async_handle_reply(mach_msg_header_t *msg)
1893 {
1894 #ifdef CALL_TRACE
1895 fprintf(stderr, "<< %s\n", __func__);
1896 #endif
1897
1898 si_async_handle_reply(msg);
1899 }
1900
1901 void
1902 setprotoent(int ignored)
1903 {
1904 #ifdef CALL_TRACE
1905 fprintf(stderr, "-- %s\n", __func__);
1906 #endif
1907
1908 LI_set_thread_list(CATEGORY_PROTOCOL, NULL);
1909 }
1910
1911 struct protoent *
1912 getprotoent(void)
1913 {
1914 si_list_t *list;
1915 si_item_t *item;
1916
1917 #ifdef CALL_TRACE
1918 fprintf(stderr, "-> %s\n", __func__);
1919 #endif
1920
1921 list = LI_get_thread_list(CATEGORY_PROTOCOL);
1922 if (list == NULL)
1923 {
1924 list = si_protocol_all(si_search());
1925 LI_set_thread_list(CATEGORY_PROTOCOL, list);
1926 }
1927
1928 item = si_list_next(list);
1929 if (item == NULL) return NULL;
1930
1931 return (struct protoent *)((uintptr_t)item + sizeof(si_item_t));
1932 }
1933
1934 void
1935 endprotoent(void)
1936 {
1937 #ifdef CALL_TRACE
1938 fprintf(stderr, "-- %s\n", __func__);
1939 #endif
1940
1941 LI_set_thread_list(CATEGORY_PROTOCOL, NULL);
1942 }
1943
1944 /* RPC */
1945
1946 struct rpcent *
1947 getrpcbyname(const char *name)
1948 {
1949 si_item_t *item;
1950
1951 #ifdef CALL_TRACE
1952 fprintf(stderr, "-> %s %s\n", __func__, name);
1953 #endif
1954
1955 item = si_rpc_byname(si_search(), name);
1956 LI_set_thread_item(CATEGORY_RPC + 100, item);
1957 if (item == NULL) return NULL;
1958
1959 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
1960 }
1961
1962 mach_port_t
1963 getrpcbyname_async_call(const char *name, si_rpc_async_callback callback, void *context)
1964 {
1965 si_context_t *sictx;
1966
1967 #ifdef CALL_TRACE
1968 fprintf(stderr, ">> %s %s\n", __func__, name);
1969 #endif
1970
1971 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
1972 if (sictx == NULL) return MACH_PORT_NULL;
1973
1974 sictx->orig_callback = callback;
1975 sictx->orig_context = context;
1976 sictx->cat = CATEGORY_RPC;
1977 sictx->key_offset = 100;
1978
1979 return si_async_call(si_search(), SI_CALL_RPC_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
1980 }
1981
1982 void
1983 getrpcbyname_async_handle_reply(mach_msg_header_t *msg)
1984 {
1985 #ifdef CALL_TRACE
1986 fprintf(stderr, "<< %s\n", __func__);
1987 #endif
1988
1989 si_async_handle_reply(msg);
1990 }
1991
1992 struct rpcent *
1993 getrpcbynumber
1994 (
1995 #ifdef __LP64__
1996 int number
1997 #else
1998 long number
1999 #endif
2000 )
2001 {
2002 si_item_t *item;
2003
2004 #ifdef CALL_TRACE
2005 fprintf(stderr, "-> %s %ld\n", __func__, (long int)number);
2006 #endif
2007
2008 item = si_rpc_bynumber(si_search(), number);
2009 LI_set_thread_item(CATEGORY_RPC + 200, item);
2010 if (item == NULL) return NULL;
2011
2012 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2013 }
2014
2015 mach_port_t
2016 getrpcbynumber_async_call(int number, si_group_async_callback callback, void *context)
2017 {
2018 si_context_t *sictx;
2019
2020 #ifdef CALL_TRACE
2021 fprintf(stderr, ">> %s %d\n", __func__, number);
2022 #endif
2023
2024 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2025 if (sictx == NULL) return MACH_PORT_NULL;
2026
2027 sictx->orig_callback = callback;
2028 sictx->orig_context = context;
2029 sictx->cat = CATEGORY_RPC;
2030 sictx->key_offset = 200;
2031
2032 return si_async_call(si_search(), SI_CALL_RPC_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2033 }
2034
2035 void
2036 getrpcbynumber_async_handle_reply(mach_msg_header_t *msg)
2037 {
2038 #ifdef CALL_TRACE
2039 fprintf(stderr, "<< %s\n", __func__);
2040 #endif
2041
2042 si_async_handle_reply(msg);
2043 }
2044
2045 void
2046 setrpcent(int ignored)
2047 {
2048 #ifdef CALL_TRACE
2049 fprintf(stderr, "-- %s\n", __func__);
2050 #endif
2051
2052 LI_set_thread_list(CATEGORY_RPC, NULL);
2053 }
2054
2055 struct rpcent *
2056 getrpcent(void)
2057 {
2058 si_list_t *list;
2059 si_item_t *item;
2060
2061 #ifdef CALL_TRACE
2062 fprintf(stderr, "-> %s\n", __func__);
2063 #endif
2064
2065 list = LI_get_thread_list(CATEGORY_RPC);
2066 if (list == NULL)
2067 {
2068 list = si_rpc_all(si_search());
2069 LI_set_thread_list(CATEGORY_RPC, list);
2070 }
2071
2072 item = si_list_next(list);
2073 if (item == NULL) return NULL;
2074
2075 return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t));
2076 }
2077
2078 void
2079 endrpcent(void)
2080 {
2081 #ifdef CALL_TRACE
2082 fprintf(stderr, "-- %s\n", __func__);
2083 #endif
2084
2085 LI_set_thread_list(CATEGORY_RPC, NULL);
2086 }
2087
2088 /* FS */
2089
2090 struct fstab *
2091 getfsspec(const char *spec)
2092 {
2093 si_item_t *item;
2094
2095 #ifdef CALL_TRACE
2096 fprintf(stderr, "-> %s %s\n", __func__, spec);
2097 #endif
2098
2099 item = si_fs_byspec(si_search(), spec);
2100 LI_set_thread_item(CATEGORY_FS + 100, item);
2101 if (item == NULL) return NULL;
2102
2103 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2104 }
2105
2106 struct fstab *
2107 getfsbyname(const char *name)
2108 {
2109 #ifdef CALL_TRACE
2110 fprintf(stderr, "-> %s %s\n", __func__, name);
2111 #endif
2112
2113 return getfsspec(name);
2114 }
2115
2116 mach_port_t
2117 getfsspec_async_call(const char *spec, si_fs_async_callback callback, void *context)
2118 {
2119 si_context_t *sictx;
2120
2121 #ifdef CALL_TRACE
2122 fprintf(stderr, ">> %s %s\n", __func__, spec);
2123 #endif
2124
2125 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2126 if (sictx == NULL) return MACH_PORT_NULL;
2127
2128 sictx->orig_callback = callback;
2129 sictx->orig_context = context;
2130 sictx->cat = CATEGORY_FS;
2131 sictx->key_offset = 100;
2132
2133 return si_async_call(si_search(), SI_CALL_FS_BYSPEC, spec, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2134 }
2135
2136 void
2137 getfsspec_async_handle_reply(mach_msg_header_t *msg)
2138 {
2139 #ifdef CALL_TRACE
2140 fprintf(stderr, "<< %s\n", __func__);
2141 #endif
2142
2143 si_async_handle_reply(msg);
2144 }
2145
2146 struct fstab *
2147 getfsfile(const char *file)
2148 {
2149 si_item_t *item;
2150
2151 #ifdef CALL_TRACE
2152 fprintf(stderr, "-> %s %s\n", __func__, file);
2153 #endif
2154
2155 item = si_fs_byfile(si_search(), file);
2156 LI_set_thread_item(CATEGORY_FS + 200, item);
2157 if (item == NULL) return NULL;
2158
2159 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2160 }
2161
2162 mach_port_t
2163 getfsfile_async_call(const char *file, si_fs_async_callback callback, void *context)
2164 {
2165 si_context_t *sictx;
2166
2167 #ifdef CALL_TRACE
2168 fprintf(stderr, ">> %s %s\n", __func__, file);
2169 #endif
2170
2171 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2172 if (sictx == NULL) return MACH_PORT_NULL;
2173
2174 sictx->orig_callback = callback;
2175 sictx->orig_context = context;
2176 sictx->cat = CATEGORY_FS;
2177 sictx->key_offset = 200;
2178
2179 return si_async_call(si_search(), SI_CALL_FS_BYFILE, file, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx);
2180 }
2181
2182 void
2183 getfsfile_async_handle_reply(mach_msg_header_t *msg)
2184 {
2185 #ifdef CALL_TRACE
2186 fprintf(stderr, "<< %s\n", __func__);
2187 #endif
2188
2189 si_async_handle_reply(msg);
2190 }
2191
2192 int
2193 setfsent(void)
2194 {
2195 #ifdef CALL_TRACE
2196 fprintf(stderr, "-> %s\n", __func__);
2197 #endif
2198
2199 LI_set_thread_list(CATEGORY_FS, NULL);
2200 return 1;
2201 }
2202
2203 struct fstab *
2204 getfsent(void)
2205 {
2206 si_list_t *list;
2207 si_item_t *item;
2208
2209 #ifdef CALL_TRACE
2210 fprintf(stderr, "-> %s\n", __func__);
2211 #endif
2212
2213 list = LI_get_thread_list(CATEGORY_FS);
2214 if (list == NULL)
2215 {
2216 list = si_fs_all(si_search());
2217 LI_set_thread_list(CATEGORY_FS, list);
2218 }
2219
2220 item = si_list_next(list);
2221 if (item == NULL) return NULL;
2222
2223 return (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
2224 }
2225
2226 void
2227 endfsent(void)
2228 {
2229 #ifdef CALL_TRACE
2230 fprintf(stderr, "-- %s\n", __func__);
2231 #endif
2232
2233 LI_set_thread_list(CATEGORY_FS, NULL);
2234 }
2235
2236 /* GETADDRINFO */
2237
2238 static int
2239 _getaddrinfo_internal(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, struct addrinfo **res)
2240 {
2241 si_list_t *list;
2242 uint32_t family, socktype, protocol, flags, status;
2243 struct addrinfo *ai;
2244
2245 family = AF_UNSPEC;
2246 socktype = SOCK_UNSPEC;
2247 protocol = IPPROTO_UNSPEC;
2248 flags = 0;
2249 status = SI_STATUS_NO_ERROR;
2250
2251 if (res == NULL) return 0;
2252 *res = NULL;
2253
2254 if (hints != NULL)
2255 {
2256 family = hints->ai_family;
2257 socktype = hints->ai_socktype;
2258 protocol = hints->ai_protocol;
2259 flags = hints->ai_flags;
2260 }
2261
2262 #ifdef CALL_TRACE
2263 fprintf(stderr, "-> %s %s %s %u %u %u 0x%08x %s\n", __func__, nodename, servname, family, socktype, protocol, flags, (interface == NULL) ? "" : interface);
2264 #endif
2265
2266 list = si_addrinfo(si_search(), nodename, servname, family, socktype, protocol, flags, interface, &status);
2267 if ((status != SI_STATUS_NO_ERROR) || (list == NULL))
2268 {
2269 si_list_release(list);
2270
2271 if (status == SI_STATUS_NO_ERROR) return EAI_NONAME;
2272 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2273 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2274 else status = status - SI_STATUS_EAI_PLUS_100;
2275 return status;
2276 }
2277
2278 *res = si_list_to_addrinfo(list);
2279 si_list_release(list);
2280 if (*res == NULL) status = EAI_MEMORY;
2281
2282 /* don't return the canonical name unless asked */
2283 if ((flags & AI_CANONNAME) == 0)
2284 {
2285 for (ai = *res; ai != NULL; ai = ai->ai_next)
2286 {
2287 free(ai->ai_canonname);
2288 ai->ai_canonname = NULL;
2289 }
2290 }
2291
2292 return status;
2293 }
2294
2295 int
2296 getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
2297 {
2298 return _getaddrinfo_internal(nodename, servname, hints, NULL, res);
2299 }
2300
2301 #ifdef CALL_TRACE
2302
2303 static char *
2304 socket_name(int sock)
2305 {
2306 static char str[16];
2307
2308 switch(sock)
2309 {
2310 case SOCK_UNSPEC: return "SOCK_UNSPEC";
2311 case SOCK_STREAM: return "SOCK_STREAM";
2312 case SOCK_DGRAM: return "SOCK_DGRAM";
2313 }
2314
2315 sprintf(str, "%d", sock);
2316 return str;
2317 }
2318
2319 static char *
2320 family_name(int pf)
2321 {
2322 static char str[16];
2323
2324 switch(pf)
2325 {
2326 case PF_UNSPEC: return "PF_UNSPEC";
2327 case PF_INET: return "PF_INET";
2328 case PF_INET6: return "PF_INET6";
2329 };
2330
2331 sprintf(str, "%d", pf);
2332 return str;
2333 }
2334
2335 static char *
2336 protocol_name(int p)
2337 {
2338 static char str[16];
2339
2340 switch(p)
2341 {
2342 case IPPROTO_UNSPEC: return "IPPROTO_UNSPEC";
2343 case IPPROTO_TCP: return "IPPROTO_TCP";
2344 case IPPROTO_UDP: return "IPPROTO_UDP";
2345 }
2346
2347 sprintf(str, "%d", p);
2348 return str;
2349 }
2350
2351 static char *
2352 _gai_inet_ntop(struct in6_addr a)
2353 {
2354 static char buf[128];
2355 char t[32];
2356 unsigned short x;
2357 char *p;
2358 int i;
2359
2360 memset(buf, 0, 128);
2361
2362 p = (char *)&a.__u6_addr.__u6_addr32;
2363 for (i = 0; i < 8; i++, x += 1)
2364 {
2365 memmove(&x, p, 2);
2366 p += 2;
2367 sprintf(t, "%hx", x);
2368 strcat(buf, t);
2369 if (i < 7) strcat(buf, ":");
2370 }
2371
2372 return buf;
2373 }
2374
2375 static void
2376 fprint_addrinfo(FILE *f, struct addrinfo *a)
2377 {
2378 int i;
2379 unsigned char v;
2380 struct sockaddr_in *s4;
2381 struct sockaddr_in6 *s6;
2382
2383 if (a == NULL) return;
2384
2385 if (a->ai_flags != 0)
2386 {
2387 fprintf(f, "flags =");
2388 if (a->ai_flags & AI_PASSIVE) fprintf(f, " AI_PASSIVE");
2389 if (a->ai_flags & AI_CANONNAME) fprintf(f, " AI_CANONNAME");
2390 if (a->ai_flags & AI_NUMERICHOST) fprintf(f, " AI_NUMERICHOST");
2391 if (a->ai_flags & AI_NUMERICSERV) fprintf(f, " AI_NUMERICSERV");
2392 fprintf(f, "\n");
2393 }
2394
2395 fprintf(f, "family = %s\n", family_name(a->ai_family));
2396 fprintf(f, "socktype = %s\n", socket_name(a->ai_socktype));
2397 fprintf(f, "protocol = %s\n", protocol_name(a->ai_protocol));
2398
2399 fprintf(f, "canonical name = ");
2400 if (a->ai_canonname == NULL) fprintf(f, "NULL\n");
2401 else fprintf(f, "\"%s\"\n", a->ai_canonname);
2402
2403 fprintf(f, "addrlen = %ld\n", (long int)a->ai_addrlen);
2404
2405 if (a->ai_addr == NULL) fprintf(f, "sockaddr = NULL\n");
2406 else
2407 {
2408 if (a->ai_family == PF_INET)
2409 {
2410 s4 = (struct sockaddr_in *)a->ai_addr;
2411
2412 fprintf(f, "sockaddr_in len = %d\n", s4->sin_len);
2413 fprintf(f, "sockaddr_in family = %s\n", family_name(s4->sin_family));
2414 fprintf(f, "sockaddr_in port = %hu\n", ntohs(s4->sin_port));
2415 fprintf(f, "sockaddr_in address = %s\n", inet_ntoa(s4->sin_addr));
2416 }
2417 else if (a->ai_family == PF_INET6)
2418 {
2419 s6 = (struct sockaddr_in6 *)a->ai_addr;
2420
2421 fprintf(f, "sockaddr_in6 len = %d\n", s6->sin6_len);
2422 fprintf(f, "sockaddr_in6 family = %s\n", family_name(s6->sin6_family));
2423 fprintf(f, "sockaddr_in6 port = %hu\n", ntohs(s6->sin6_port));
2424 fprintf(f, "sockaddr_in6 flowinfo = %d\n", s6->sin6_flowinfo);
2425 fprintf(f, "sockaddr_in6 address = %s\n", _gai_inet_ntop(s6->sin6_addr));
2426 fprintf(f, "sockaddr_in6 scope_id = %d\n", s6->sin6_scope_id);
2427 }
2428 else
2429 {
2430 fprintf(f, "sockaddr len = %d\n", a->ai_addr->sa_len);
2431 fprintf(f, "sockaddr family = %s\n", family_name(a->ai_addr->sa_family));
2432 fprintf(f, "sockaddr data = ");
2433 for (i = 0; i < a->ai_addr->sa_len - 2; i++)
2434 {
2435 v = a->ai_addr->sa_data[i];
2436 fprintf(f, "%02x", v);
2437 }
2438 fprintf(f, "\n");
2439 }
2440 }
2441
2442 if (a->ai_next != NULL)
2443 {
2444 fprintf(f, "NEXT --->\n");
2445 fprint_addrinfo(f, a->ai_next);
2446 }
2447 }
2448
2449 #endif
2450
2451 static void
2452 si_libinfo_addrinfo_callback(si_list_t *list, uint32_t status, void *ctx)
2453 {
2454 si_context_t *sictx;
2455 struct addrinfo *out;
2456
2457 if (ctx == NULL)
2458 {
2459 #ifdef CALL_TRACE
2460 fprintf(stderr, " %s error no context\n", __func__);
2461 #endif
2462 si_list_release(list);
2463 return;
2464 }
2465
2466 sictx = (si_context_t *)ctx;
2467
2468 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2469 {
2470 #ifdef CALL_TRACE
2471 fprintf(stderr, " %s error no callback\n", __func__);
2472 #endif
2473 si_list_release(list);
2474 free(sictx);
2475 return;
2476 }
2477
2478 if (status != SI_STATUS_NO_ERROR)
2479 {
2480 #ifdef CALL_TRACE
2481 fprintf(stderr, " %s original status %d\n", __func__, status);
2482 #endif
2483 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2484 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2485 else status = status - SI_STATUS_EAI_PLUS_100;
2486 }
2487
2488 if (list == NULL)
2489 {
2490 #ifdef CALL_TRACE
2491 fprintf(stderr, " %s result NULL status %d (returning EAI_NONAME)\n", __func__, status);
2492 #endif
2493 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_NONAME, NULL, sictx->orig_context);
2494 free(sictx);
2495 return;
2496 }
2497
2498 out = si_list_to_addrinfo(list);
2499 si_list_release(list);
2500 if (out == NULL)
2501 {
2502 #ifdef CALL_TRACE
2503 fprintf(stderr, " %s result conversion failed returning NULL status %d (returning EAI_MEMORY)\n", __func__, status);
2504 #endif
2505 ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_MEMORY, NULL, sictx->orig_context);
2506 free(sictx);
2507 return;
2508 }
2509
2510 #ifdef CALL_TRACE
2511 fprintf(stderr, " %s %d\n", __func__, status);
2512 fprint_addrinfo(stderr, out);
2513 #endif
2514 ((si_addrinfo_async_callback)(sictx->orig_callback))(status, out, sictx->orig_context);
2515
2516 free(sictx);
2517 }
2518
2519 /* SPI */
2520 mach_port_t
2521 _getaddrinfo_interface_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, si_addrinfo_async_callback callback, void *context)
2522 {
2523 si_context_t *sictx;
2524 uint32_t family, socktype, protocol, flags;
2525
2526 family = AF_UNSPEC;
2527 socktype = SOCK_UNSPEC;
2528 protocol = IPPROTO_UNSPEC;
2529 flags = 0;
2530
2531 if (hints != NULL)
2532 {
2533 family = hints->ai_family;
2534 socktype = hints->ai_socktype;
2535 protocol = hints->ai_protocol;
2536 flags = hints->ai_flags;
2537 }
2538
2539 #ifdef CALL_TRACE
2540 fprintf(stderr, ">> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags);
2541 #endif
2542
2543 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2544 if (sictx == NULL) return MACH_PORT_NULL;
2545
2546 sictx->orig_callback = callback;
2547 sictx->orig_context = context;
2548 sictx->cat = CATEGORY_ADDRINFO;
2549 sictx->key_offset = 0;
2550
2551 return si_async_call(si_search(), SI_CALL_ADDRINFO, nodename, servname, interface, family, socktype, protocol, flags, (void *)si_libinfo_addrinfo_callback, sictx);
2552 }
2553
2554 mach_port_t
2555 getaddrinfo_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2556 {
2557 return _getaddrinfo_interface_async_call(nodename, servname, hints, NULL, callback, context);
2558 }
2559
2560 int32_t
2561 getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context)
2562 {
2563 if (p == NULL) return EAI_SYSTEM;
2564
2565 *p = getaddrinfo_async_call(nodename, servname, hints, callback, context);
2566
2567 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2568 return 0;
2569 }
2570
2571 int32_t
2572 getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints)
2573 {
2574 return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL);
2575 }
2576
2577 int32_t
2578 getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res)
2579 {
2580 /* unsupported Leopard SPI */
2581 return EAI_SYSTEM;
2582 }
2583
2584 void
2585 getaddrinfo_async_cancel(mach_port_t p)
2586 {
2587 #ifdef CALL_TRACE
2588 fprintf(stderr, "-- %s\n", __func__);
2589 #endif
2590
2591 si_async_cancel(p);
2592 }
2593
2594 int32_t
2595 getaddrinfo_async_handle_reply(void *param)
2596 {
2597 mach_msg_header_t *msg;
2598
2599 #ifdef CALL_TRACE
2600 fprintf(stderr, "<< %s\n", __func__);
2601 #endif
2602
2603 msg = (mach_msg_header_t *)param;
2604 si_async_handle_reply(msg);
2605
2606 return 0;
2607 }
2608
2609 /* GETNAMEINFO */
2610
2611 static int
2612 _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)
2613 {
2614 si_item_t *item;
2615 si_nameinfo_t *ni;
2616 uint32_t status, len, wantn, wants;
2617
2618 #ifdef CALL_TRACE
2619 fprintf(stderr, "-> %s\n", __func__);
2620 #endif
2621
2622 status = SI_STATUS_NO_ERROR;
2623
2624 wantn = 0;
2625 if ((node != NULL) && (nodelen > 0)) wantn = 1;
2626
2627 wants = 0;
2628 if ((service != NULL) && (servicelen > 0)) wants = 1;
2629
2630 if ((wantn == 0) && (wants == 0)) return status;
2631
2632 if (wantn == 0) flags |= NI_NUMERICHOST;
2633 if (wants == 0) flags |= NI_NUMERICSERV;
2634
2635 item = si_nameinfo(si_search(), sa, flags, interface, &status);
2636 if ((status != SI_STATUS_NO_ERROR) || (item == NULL))
2637 {
2638 si_item_release(item);
2639
2640 if (status == SI_STATUS_NO_ERROR) status = EAI_NONAME;
2641 else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2642 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2643 else status = status - SI_STATUS_EAI_PLUS_100;
2644 return status;
2645 }
2646
2647 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2648
2649 len = 0;
2650 if (ni->ni_node != NULL) len = strlen(ni->ni_node) + 1;
2651 if ((wantn == 1) && (len > 0))
2652 {
2653 if (len > nodelen)
2654 {
2655 si_item_release(item);
2656 return EAI_OVERFLOW;
2657 }
2658
2659 memset(node, 0, nodelen);
2660 memcpy(node, ni->ni_node, len);
2661 }
2662
2663 len = 0;
2664 if (ni->ni_serv != NULL) len = strlen(ni->ni_serv) + 1;
2665 if ((wants == 1) && (len > 0))
2666 {
2667 if (len > servicelen)
2668 {
2669 si_item_release(item);
2670 return EAI_OVERFLOW;
2671 }
2672
2673 memset(service, 0, servicelen);
2674 memcpy(service, ni->ni_serv, len);
2675 }
2676
2677 si_item_release(item);
2678 return 0;
2679 }
2680
2681 int
2682 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags)
2683 {
2684 return _getnameinfo_interface_internal(sa, salen, node, nodelen, service, servicelen, flags, NULL);
2685 }
2686
2687 static void
2688 si_libinfo_nameinfo_callback(si_item_t *item, uint32_t status, void *ctx)
2689 {
2690 si_context_t *sictx;
2691 si_nameinfo_t *ni;
2692 char *node, *serv;
2693
2694 if (ctx == NULL) return;
2695
2696 sictx = (si_context_t *)ctx;
2697
2698 if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED))
2699 {
2700 si_item_release(item);
2701 free(sictx);
2702 return;
2703 }
2704
2705 if (status != SI_STATUS_NO_ERROR)
2706 {
2707 if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL;
2708 else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL;
2709 else status = status - SI_STATUS_EAI_PLUS_100;
2710 }
2711
2712 if (item == NULL)
2713 {
2714 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, NULL, NULL, sictx->orig_context);
2715 free(sictx);
2716 return;
2717 }
2718
2719 LI_set_thread_item(CATEGORY_NAMEINFO, item);
2720
2721 node = NULL;
2722 serv = NULL;
2723
2724 ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t));
2725 if (ni->ni_node != NULL) node = strdup(ni->ni_node);
2726 if (ni->ni_serv != NULL) serv = strdup(ni->ni_serv);
2727
2728 ((si_nameinfo_async_callback)(sictx->orig_callback))(status, node, serv, sictx->orig_context);
2729 free(sictx);
2730 }
2731
2732 /* SPI */
2733 mach_port_t
2734 _getnameinfo_interface_async_call(const struct sockaddr *sa, size_t len, int flags, const char *interface, si_nameinfo_async_callback callback, void *context)
2735 {
2736 si_context_t *sictx;
2737 uint32_t salen;
2738
2739 #ifdef CALL_TRACE
2740 fprintf(stderr, ">> %s\n", __func__);
2741 #endif
2742
2743 sictx = (si_context_t *)calloc(1, sizeof(si_context_t));
2744 if (sictx == NULL) return MACH_PORT_NULL;
2745
2746 sictx->orig_callback = callback;
2747 sictx->orig_context = context;
2748 sictx->cat = CATEGORY_ADDRINFO;
2749 sictx->key_offset = 0;
2750
2751 /* sa is not a C string - pass length in num3 */
2752 salen = len;
2753 return si_async_call(si_search(), SI_CALL_NAMEINFO, (const char *)sa, NULL, interface, flags, 0, salen, 0, (void *)si_libinfo_nameinfo_callback, sictx);
2754 }
2755
2756 mach_port_t
2757 getnameinfo_async_call(const struct sockaddr *sa, size_t len, int flags, si_nameinfo_async_callback callback, void *context)
2758 {
2759 return _getnameinfo_interface_async_call(sa, len, flags, NULL, callback, context);
2760 }
2761
2762 int32_t
2763 getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, si_nameinfo_async_callback callback, void *context)
2764 {
2765 if (p == NULL) return EAI_SYSTEM;
2766 *p = getnameinfo_async_call(sa, salen, flags, callback, context);
2767
2768 if (*p == MACH_PORT_NULL) return EAI_SYSTEM;
2769 return 0;
2770 }
2771
2772 int32_t
2773 getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags)
2774 {
2775 return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL);
2776 }
2777
2778 void
2779 getnameinfo_async_cancel(mach_port_t p)
2780 {
2781 #ifdef CALL_TRACE
2782 fprintf(stderr, "-- %s\n", __func__);
2783 #endif
2784
2785 si_async_cancel(p);
2786 }
2787
2788 int32_t
2789 getnameinfo_async_handle_reply(void *param)
2790 {
2791 mach_msg_header_t *msg;
2792
2793 #ifdef CALL_TRACE
2794 fprintf(stderr, "<< %s\n", __func__);
2795 #endif
2796
2797 msg = (mach_msg_header_t *)param;
2798 si_async_handle_reply(msg);
2799
2800 return 0;
2801 }
2802
2803 /* getpwXXX_r and getgrXXX_r */
2804
2805 static int
2806 copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen)
2807 {
2808 int hsize;
2809 char *bp;
2810
2811 if (in == NULL) return -1;
2812 if (out == NULL) return -1;
2813
2814 if (buffer == NULL) buflen = 0;
2815
2816 /* Calculate size of input */
2817 hsize = 0;
2818 if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1);
2819 if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1);
2820 if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1);
2821 if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1);
2822 if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1);
2823 if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1);
2824
2825 /* Check buffer space */
2826 if (hsize > buflen) return -1;
2827
2828 /* Copy result into caller's struct passwd, using buffer for memory */
2829 bp = buffer;
2830
2831 out->pw_name = NULL;
2832 if (in->pw_name != NULL)
2833 {
2834 out->pw_name = bp;
2835 hsize = strlen(in->pw_name) + 1;
2836 memmove(bp, in->pw_name, hsize);
2837 bp += hsize;
2838 }
2839
2840 out->pw_passwd = NULL;
2841 if (in->pw_passwd != NULL)
2842 {
2843 out->pw_passwd = bp;
2844 hsize = strlen(in->pw_passwd) + 1;
2845 memmove(bp, in->pw_passwd, hsize);
2846 bp += hsize;
2847 }
2848
2849 out->pw_uid = in->pw_uid;
2850
2851 out->pw_gid = in->pw_gid;
2852
2853 out->pw_change = in->pw_change;
2854
2855 out->pw_class = NULL;
2856 if (in->pw_class != NULL)
2857 {
2858 out->pw_class = bp;
2859 hsize = strlen(in->pw_class) + 1;
2860 memmove(bp, in->pw_class, hsize);
2861 bp += hsize;
2862 }
2863
2864 out->pw_gecos = NULL;
2865 if (in->pw_gecos != NULL)
2866 {
2867 out->pw_gecos = bp;
2868 hsize = strlen(in->pw_gecos) + 1;
2869 memmove(bp, in->pw_gecos, hsize);
2870 bp += hsize;
2871 }
2872
2873 out->pw_dir = NULL;
2874 if (in->pw_dir != NULL)
2875 {
2876 out->pw_dir = bp;
2877 hsize = strlen(in->pw_dir) + 1;
2878 memmove(bp, in->pw_dir, hsize);
2879 bp += hsize;
2880 }
2881
2882 out->pw_shell = NULL;
2883 if (in->pw_shell != NULL)
2884 {
2885 out->pw_shell = bp;
2886 hsize = strlen(in->pw_shell) + 1;
2887 memmove(bp, in->pw_shell, hsize);
2888 bp += hsize;
2889 }
2890
2891 out->pw_expire = in->pw_expire;
2892
2893 return 0;
2894 }
2895
2896 static int
2897 copy_group_r(struct group *in, struct group *out, char *buffer, int buflen)
2898 {
2899 int i, len, hsize;
2900 unsigned long addr;
2901 char *bp, *ap;
2902
2903 if (in == NULL) return -1;
2904 if (out == NULL) return -1;
2905
2906 if (buffer == NULL) buflen = 0;
2907
2908 /* Calculate size of input */
2909 hsize = 0;
2910 if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1);
2911 if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1);
2912
2913 /* NULL pointer at end of list */
2914 hsize += sizeof(char *);
2915
2916 len = 0;
2917 if (in->gr_mem != NULL)
2918 {
2919 for (len = 0; in->gr_mem[len] != NULL; len++)
2920 {
2921 hsize += sizeof(char *);
2922 hsize += (strlen(in->gr_mem[len]) + 1);
2923 }
2924 }
2925
2926 /* Check buffer space */
2927 if (hsize > buflen) return -1;
2928
2929 /* Copy result into caller's struct group, using buffer for memory */
2930 bp = buffer;
2931
2932 out->gr_name = NULL;
2933 if (in->gr_name != NULL)
2934 {
2935 out->gr_name = bp;
2936 hsize = strlen(in->gr_name) + 1;
2937 memmove(bp, in->gr_name, hsize);
2938 bp += hsize;
2939 }
2940
2941 out->gr_passwd = NULL;
2942 if (in->gr_passwd != NULL)
2943 {
2944 out->gr_passwd = bp;
2945 hsize = strlen(in->gr_passwd) + 1;
2946 memmove(bp, in->gr_passwd, hsize);
2947 bp += hsize;
2948 }
2949
2950 out->gr_gid = in->gr_gid;
2951
2952 out->gr_mem = NULL;
2953 ap = bp + ((len + 1) * sizeof(char *));
2954
2955 if (in->gr_mem != NULL)
2956 {
2957 out->gr_mem = (char **)bp;
2958 for (i = 0; i < len; i++)
2959 {
2960 addr = (unsigned long)ap;
2961 memmove(bp, &addr, sizeof(unsigned long));
2962 bp += sizeof(unsigned long);
2963
2964 hsize = strlen(in->gr_mem[i]) + 1;
2965 memmove(ap, in->gr_mem[i], hsize);
2966 ap += hsize;
2967 }
2968 }
2969
2970 memset(bp, 0, sizeof(unsigned long));
2971 bp = ap;
2972
2973 return 0;
2974 }
2975
2976 int
2977 getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result)
2978 {
2979 si_item_t *item;
2980 struct group *g;
2981 int status;
2982
2983 #ifdef CALL_TRACE
2984 fprintf(stderr, "-> %s %s\n", __func__, name);
2985 #endif
2986
2987 if (result != NULL) *result = NULL;
2988
2989 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
2990
2991 item = si_group_byname(si_search(), name);
2992 if (item == NULL) return 0;
2993
2994 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
2995
2996 status = copy_group_r(g, grp, buffer, bufsize);
2997 si_item_release(item);
2998
2999 if (status != 0) return ERANGE;
3000
3001 *result = grp;
3002 return 0;
3003 }
3004
3005 int
3006 getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
3007 {
3008 si_item_t *item;
3009 struct group *g;
3010 int status;
3011
3012 #ifdef CALL_TRACE
3013 fprintf(stderr, "-> %s %d\n", __func__, gid);
3014 #endif
3015
3016 if (result != NULL) *result = NULL;
3017
3018 if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3019
3020 item = si_group_bygid(si_search(), gid);
3021 if (item == NULL) return 0;
3022
3023 g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
3024
3025 status = copy_group_r(g, grp, buffer, bufsize);
3026 si_item_release(item);
3027
3028 if (status != 0) return ERANGE;
3029
3030 *result = grp;
3031 return 0;
3032 }
3033
3034 int
3035 getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3036 {
3037 si_item_t *item;
3038 struct passwd *p;
3039 int status;
3040
3041 #ifdef CALL_TRACE
3042 fprintf(stderr, "-> %s %s\n", __func__, name);
3043 #endif
3044
3045 if (result != NULL) *result = NULL;
3046
3047 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3048
3049 item = si_user_byname(si_search(), name);
3050 if (item == NULL) return 0;
3051
3052 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3053
3054 status = copy_user_r(p, pw, buffer, bufsize);
3055 si_item_release(item);
3056
3057 if (status != 0) return ERANGE;
3058
3059 *result = pw;
3060 return 0;
3061 }
3062
3063 int
3064 getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
3065 {
3066 si_item_t *item;
3067 struct passwd *p;
3068 int status;
3069
3070 #ifdef CALL_TRACE
3071 fprintf(stderr, "-> %s %d\n", __func__, uid);
3072 #endif
3073
3074 if (result != NULL) *result = NULL;
3075
3076 if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
3077
3078 item = si_user_byuid(si_search(), uid);
3079 if (item == NULL) return 0;
3080
3081 p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
3082
3083 status = copy_user_r(p, pw, buffer, bufsize);
3084 si_item_release(item);
3085
3086 if (status != 0) return ERANGE;
3087
3088 *result = pw;
3089 return 0;
3090 }
3091
3092 /* misc */
3093
3094 char *
3095 user_from_uid(uid_t uid, int nouser)
3096 {
3097 struct passwd *pw;
3098 static char buf[16];
3099
3100 pw = getpwuid(uid);
3101 if (pw != NULL) return pw->pw_name;
3102
3103 if (nouser) return NULL;
3104
3105 snprintf(buf, sizeof(buf), "%u", uid);
3106 return buf;
3107 }
3108
3109 char *
3110 group_from_gid(gid_t gid, int nogroup)
3111 {
3112 struct group *gr;
3113 static char buf[16];
3114
3115 gr = getgrgid(gid);
3116 if (gr != NULL) return gr->gr_name;
3117
3118 if (nogroup) return NULL;
3119
3120 snprintf(buf, sizeof(buf), "%u", gid);
3121 return buf;
3122 }
3123
3124 /* no longer supported */
3125
3126 const prdb_ent *
3127 prdb_getbyname(const char *name)
3128 {
3129 #ifdef CALL_TRACE
3130 fprintf(stderr, "~~ %s\n", __func__);
3131 #endif
3132 return NULL;
3133 }
3134
3135 const prdb_ent *
3136 prdb_get(void)
3137 {
3138 #ifdef CALL_TRACE
3139 fprintf(stderr, "~~ %s\n", __func__);
3140 #endif
3141 return NULL;
3142 }
3143
3144 void
3145 prdb_set(const char *name)
3146 {
3147 #ifdef CALL_TRACE
3148 fprintf(stderr, "~~ %s\n", __func__);
3149 #endif
3150 }
3151
3152 void
3153 prdb_end(void)
3154 {
3155 #ifdef CALL_TRACE
3156 fprintf(stderr, "~~ %s\n", __func__);
3157 #endif
3158 }
3159
3160 struct bootparamsent *
3161 bootparams_getbyname(const char *name)
3162 {
3163 #ifdef CALL_TRACE
3164 fprintf(stderr, "~~ %s\n", __func__);
3165 #endif
3166 return NULL;
3167 }
3168
3169 struct bootparamsent *
3170 bootparams_getent(void)
3171 {
3172 #ifdef CALL_TRACE
3173 fprintf(stderr, "~~ %s\n", __func__);
3174 #endif
3175 return NULL;
3176 }
3177
3178 void
3179 bootparams_setent(void)
3180 {
3181 #ifdef CALL_TRACE
3182 fprintf(stderr, "~~ %s\n", __func__);
3183 #endif
3184 }
3185
3186 void
3187 bootparams_endent(void)
3188 {
3189 #ifdef CALL_TRACE
3190 fprintf(stderr, "~~ %s\n", __func__);
3191 #endif
3192 }
3193
3194 int
3195 bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
3196 {
3197 #ifdef CALL_TRACE
3198 fprintf(stderr, "~~ %s\n", __func__);
3199 #endif
3200 return 0;
3201 }
3202
3203 int
3204 bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
3205 {
3206 #ifdef CALL_TRACE
3207 fprintf(stderr, "~~ %s\n", __func__);
3208 #endif
3209 return 0;
3210 }