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