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