/* * Copyright (c) 2008 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "si_module.h" #include "libinfo.h" #include #include #include "netdb_async.h" #define SOCK_UNSPEC 0 #define IPPROTO_UNSPEC 0 #define IPV6_ADDR_LEN 16 #define IPV4_ADDR_LEN 4 /* SPI from long ago */ int _proto_stayopen; __private_extern__ struct addrinfo *si_list_to_addrinfo(si_list_t *list); /* * Impedence matching for async calls. * * This layer holds on to the caller's callback and context in this * structure, which gets passed to the si_module async routines along * with a callbac in this layer. When this layer gets a callback, * it can save the item or list in thread-specific memory and then * invoke the caller's callback with the appropriate data type. */ typedef struct { void *orig_callback; void *orig_context; uint32_t cat; int32_t key_offset; } si_context_t; __private_extern__ si_mod_t * si_search(void) { static si_mod_t *search = NULL; static OSSpinLock spin = OS_SPINLOCK_INIT; if (search == NULL) { OSSpinLockLock(&spin); if (search == NULL) search = si_module_with_name("search"); OSSpinLockUnlock(&spin); } return search; } static void si_libinfo_general_callback(si_item_t *item, uint32_t status, void *ctx) { si_context_t *sictx; union { char *x; struct passwd *u; struct group *g; struct grouplist_s *l; struct hostent *h; struct netent *n; struct servent *s; struct protoent *p; struct rpcent *r; struct fstab *f; } res; if (ctx == NULL) return; sictx = (si_context_t *)ctx; if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) { free(sictx); si_item_release(item); return; } if (sictx->key_offset >= 0) { LI_set_thread_item(sictx->cat + sictx->key_offset, item); } res.x = NULL; if (item != NULL) res.x = (char*)((uintptr_t)item + sizeof(si_item_t)); switch (sictx->cat) { case CATEGORY_USER: { ((si_user_async_callback)(sictx->orig_callback))(res.u, sictx->orig_context); break; } case CATEGORY_GROUP: { ((si_group_async_callback)(sictx->orig_callback))(res.g, sictx->orig_context); break; } case CATEGORY_GROUPLIST: { ((si_grouplist_async_callback)(sictx->orig_callback))(res.l, sictx->orig_context); break; } case CATEGORY_HOST_IPV4: case CATEGORY_HOST_IPV6: { ((si_host_async_callback)(sictx->orig_callback))(res.h, sictx->orig_context); break; } case CATEGORY_NETWORK: { ((si_network_async_callback)(sictx->orig_callback))(res.n, sictx->orig_context); break; } case CATEGORY_SERVICE: { ((si_service_async_callback)(sictx->orig_callback))(res.s, sictx->orig_context); break; } case CATEGORY_PROTOCOL: { ((si_protocol_async_callback)(sictx->orig_callback))(res.p, sictx->orig_context); break; } case CATEGORY_RPC: { ((si_rpc_async_callback)(sictx->orig_callback))(res.r, sictx->orig_context); break; } case CATEGORY_FS: { ((si_fs_async_callback)(sictx->orig_callback))(res.f, sictx->orig_context); break; } } free(sictx); } /* USER */ struct passwd * getpwnam(const char *name) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif item = si_user_byname(si_search(), name); LI_set_thread_item(CATEGORY_USER + 100, item); if (item == NULL) return NULL; return (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getpwnam_async_call(const char *name, si_user_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_USER; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_USER_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getpwnam_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct passwd * getpwuid(uid_t uid) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %d\n", __func__, uid); #endif item = si_user_byuid(si_search(), uid); LI_set_thread_item(CATEGORY_USER + 200, item); if (item == NULL) return NULL; return (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getpwuid_async_call(uid_t uid, si_user_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %d\n", __func__, uid); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_USER; sictx->key_offset = 200; 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); } void getpwuid_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void setpwent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_USER, NULL); } struct passwd * getpwent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_USER); if (list == NULL) { list = si_user_all(si_search()); LI_set_thread_list(CATEGORY_USER, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); } void endpwent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_USER, NULL); } int setpassent(int ignored) { si_list_t *list; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_USER); si_list_reset(list); if (list == NULL) return 0; return 1; } /* GROUP */ struct group * getgrnam(const char *name) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif item = si_group_byname(si_search(), name); LI_set_thread_item(CATEGORY_GROUP + 100, item); if (item == NULL) return NULL; return (struct group *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getgrnam_async_call(const char *name, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_GROUP; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_GROUP_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getgrnam_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct group * getgrgid(gid_t gid) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %d\n", __func__, gid); #endif item = si_group_bygid(si_search(), gid); LI_set_thread_item(CATEGORY_GROUP + 200, item); if (item == NULL) return NULL; return (struct group *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getgrgid_async_call(gid_t gid, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %d\n", __func__, gid); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_GROUP; sictx->key_offset = 200; 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); } void getgruid_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void setgrent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_GROUP, NULL); } struct group * getgrent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_GROUP); if (list == NULL) { list = si_group_all(si_search()); LI_set_thread_list(CATEGORY_GROUP, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct group *)((uintptr_t)item + sizeof(si_item_t)); } void endgrent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_GROUP, NULL); } int setgroupent(int ignored) { si_list_t *list; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_GROUP); si_list_reset(list); if (list == NULL) return 0; return 1; } /* NETGROUP */ int innetgr(const char *group, const char *host, const char *user, const char *domain) { int res; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %s %s %s\n", __func__, group, host, user, domain); #endif res = si_in_netgroup(si_search(), group, host, user, domain); #ifdef CALL_TRACE fprintf(stderr, "<- %s %d\n", __func__, res); #endif return res; } /* N.B. there is no async innetgr */ /* * setnetgrent is really more like a getXXXbyname routine than a * setXXXent routine, since we are looking up a netgroup by name. */ void setnetgrent(const char *name) { si_list_t *list; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif list = si_netgroup_byname(si_search(), name); LI_set_thread_list(CATEGORY_NETGROUP, list); } /* N.B. there is no async getnetgrent */ int getnetgrent(char **host, char **user, char **domain) { si_list_t *list; si_item_t *item; struct netgrent_s *ng; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_NETGROUP); item = si_list_next(list); if (item == NULL) return 0; ng = (struct netgrent_s *)((uintptr_t)item + sizeof(si_item_t)); *host = ng->ng_host; *user = ng->ng_user; *domain = ng->ng_domain; return 1; } void endnetgrent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_NETGROUP, NULL); } /* GROUPLIST */ int getgrouplist(const char *name, int basegid, int *groups, int *ngroups) { int i, j, x, g, add, max; si_item_t *item; si_grouplist_t *gl; /* * On input, ngroups specifies the size of the groups array. * On output, it is set to the number of groups that are being returned. * Returns -1 if the size is too small to fit all the groups that were found. */ #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); #endif if (name == NULL) return 0; if (groups == NULL) return 0; if (ngroups == NULL) return 0; max = *ngroups; *ngroups = 0; if (max <= 0) return 0; groups[0] = basegid; *ngroups = 1; item = si_grouplist(si_search(), name); LI_set_thread_item(CATEGORY_GROUPLIST, item); if (item == NULL) return 0; gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t)); x = 1; if (gl->gl_basegid != basegid) { if (x >= max) return -1; groups[x] = gl->gl_basegid; x++; *ngroups = x; } for (i = 0; i < gl->gl_count; i++) { g = (int)*(gl->gl_gid[i]); add = 1; for (j = 0; (j < x) && (add == 1); j++) if (groups[j] == g) add = 0; if (add == 0) continue; if (x >= max) return -1; groups[x] = g; x++; *ngroups = x; } return 0; } /* XXX to do: async getgrouplist */ static int merge_gid(gid_t **list, gid_t g, int32_t *count) { int i; if (list == NULL) return -1; if (*count == 0) { *list = (gid_t *)calloc(1, sizeof(gid_t)); if (list == NULL) { errno = ENOMEM; return -1; } (*list)[(*count)++] = g; return 0; } for (i = 0; i < *count; i++) if ((*list)[i] == g) return 0; *list = (gid_t *)reallocf(*list, (*count + 1) * sizeof(gid_t)); (*list)[(*count)++] = g; return 0; } int32_t getgrouplist_2(const char *name, gid_t basegid, gid_t **groups) { int32_t i, status, count; gid_t g; si_item_t *item; si_grouplist_t *gl; /* * Passes back a gid_t list containing all the users groups (and basegid). * Caller must free the list. * Returns the number of gids in the list or -1 on failure. */ #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); #endif if (name == NULL) return 0; if (groups == NULL) return 0; item = si_grouplist(si_search(), name); LI_set_thread_item(CATEGORY_GROUPLIST, item); if (item == NULL) return -1; gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t)); count = 0; *groups = NULL; status = merge_gid(groups, basegid, &count); if (status != 0) return status; status = merge_gid(groups, gl->gl_basegid, &count); if (status != 0) return status; for (i = 0; i < gl->gl_count; i++) { g = (gid_t)*(gl->gl_gid[i]); status = merge_gid(groups, g, &count); if (status != 0) return status; } return count; } int32_t getgroupcount(const char *name, gid_t basegid) { int32_t i, status, count; gid_t g; si_item_t *item; si_grouplist_t *gl; gid_t *groups; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); #endif if (name == NULL) return 0; item = si_grouplist(si_search(), name); LI_set_thread_item(CATEGORY_GROUPLIST, item); if (item == NULL) return -1; gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t)); count = 0; groups = NULL; status = merge_gid(&groups, basegid, &count); if (status != 0) return status; status = merge_gid(&groups, gl->gl_basegid, &count); if (status != 0) return status; for (i = 0; i < gl->gl_count; i++) { g = (gid_t)*(gl->gl_gid[i]); status = merge_gid(&groups, g, &count); if (status != 0) return status; } if (groups != NULL) free(groups); return count; } /* XXX to do: async getgrouplist_2 */ int initgroups(const char *name, int basegid) { int status, ngroups, groups[NGROUPS]; uid_t uid; #ifdef DS_AVAILABLE si_item_t *item; struct passwd *p; #endif #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); #endif /* KAUTH_UID_NONE tells the kernel not to fetch supplementary groups from DirectoryService */ uid = KAUTH_UID_NONE; #ifdef DS_AVAILABLE /* get the UID for this user */ item = si_user_byname(si_search(), name); if (item != NULL) { p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); uid = p->pw_uid; si_item_release(item); } #endif ngroups = NGROUPS; status = getgrouplist(name, basegid, groups, &ngroups); /* * Ignore status. * A failure either means that user belongs to more than NGROUPS groups * or no groups at all. */ status = syscall(SYS_initgroups, ngroups, groups, uid); if (status < 0) return -1; return 0; } /* ALIAS */ struct aliasent * alias_getbyname(const char *name) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif item = si_alias_byname(si_search(), name); LI_set_thread_item(CATEGORY_ALIAS + 100, item); if (item == NULL) return NULL; return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t alias_getbyname_async_call(const char *name, si_alias_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_ALIAS; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_ALIAS_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void alias_getbyname_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void alias_setent(void) { #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif LI_set_thread_list(CATEGORY_ALIAS, NULL); } struct aliasent * alias_getent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_ALIAS); if (list == NULL) { list = si_alias_all(si_search()); LI_set_thread_list(CATEGORY_ALIAS, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t)); } void alias_endent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_ALIAS, NULL); } /* HOST */ void freehostent(struct hostent *h) { if (h == NULL) return; si_item_t *item = (si_item_t *)((uintptr_t)h - sizeof(si_item_t)); si_item_release(item); } struct hostent * gethostbynameerrno(const char *name, int *err) { si_item_t *item; uint32_t status; struct in_addr addr4; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif memset(&addr4, 0, sizeof(struct in_addr)); status = SI_STATUS_NO_ERROR; item = NULL; if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, NULL, &status); else item = si_host_byname(si_search(), name, AF_INET, NULL, &status); if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; if (err != NULL) *err = status; LI_set_thread_item(CATEGORY_HOST + 100, item); if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } struct hostent * gethostbyname(const char *name) { si_item_t *item; uint32_t status; struct in_addr addr4; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif memset(&addr4, 0, sizeof(struct in_addr)); status = SI_STATUS_NO_ERROR; item = NULL; if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, NULL, &status); else item = si_host_byname(si_search(), name, AF_INET, NULL, &status); if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; h_errno = status; LI_set_thread_item(CATEGORY_HOST + 100, item); if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t gethostbyname_async_call(const char *name, si_host_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_HOST; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_HOST_BYNAME, name, NULL, NULL, AF_INET, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } mach_port_t gethostbyname_async_start(const char *name, si_host_async_callback callback, void *context) { return gethostbyname_async_call(name, callback, context); } void gethostbyname_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } #if 0 void gethostbyname_async_handle_reply(void *param) { mach_msg_header_t *msg; #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif msg = (mach_msg_header_t *)param; si_async_handle_reply(msg); } #endif void gethostbyname_async_handleReply(void *param) { mach_msg_header_t *msg; #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif msg = (mach_msg_header_t *)param; si_async_handle_reply(msg); } struct hostent * gethostbyname2(const char *name, int af) { si_item_t *item; uint32_t status; struct in_addr addr4; struct in6_addr addr6; si_mod_t *search = si_search(); #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %d\n", __func__, name, af); #endif memset(&addr4, 0, sizeof(struct in_addr)); memset(&addr6, 0, sizeof(struct in6_addr)); status = SI_STATUS_NO_ERROR; item = NULL; if (((af == AF_INET) && (inet_aton(name, &addr4) == 1)) || ((af == AF_INET6) && (inet_pton(af, name, &addr6) == 1))) { item = si_ipnode_byname(search, name, (uint32_t)af, 0, NULL, &status); } else { item = si_host_byname(search, name, (uint32_t)af, NULL, &status); } if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; h_errno = status; LI_set_thread_item(CATEGORY_HOST + 100, item); if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t gethostbyname2_async_call(const char *name, int af, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s %d\n", __func__, name, af); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_HOST; sictx->key_offset = 100; 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); } void gethostbyname2_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } void gethostbyname2_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct hostent * gethostbyaddr(const void *addr, socklen_t len, int type) { si_item_t *item; uint32_t status; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-"); #endif status = SI_STATUS_NO_ERROR; item = si_host_byaddr(si_search(), addr, (uint32_t)type, NULL, &status); if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; h_errno = status; LI_set_thread_item(CATEGORY_HOST + 200, item); if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t gethostbyaddr_async_call(const void *addr, socklen_t len, int type, si_host_async_callback callback, void *context) { si_context_t *sictx; uint32_t addrlen; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-"); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_HOST; sictx->key_offset = 200; /* addr is not a C string - pass length in num3 */ addrlen = len; 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); } mach_port_t gethostbyaddr_async_start(const char *addr, int len, int family, si_host_async_callback callback, void *context) { socklen_t slen = len; return gethostbyaddr_async_call(addr, slen, family, callback, context); } void gethostbyaddr_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } #if 0 void gethostbyaddr_async_handle_reply(void *param) { mach_msg_header_t *msg; #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif msg = (mach_msg_header_t *)param; si_async_handle_reply(msg); } #endif void gethostbyaddr_async_handleReply(void *param) { mach_msg_header_t *msg; #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif msg = (mach_msg_header_t *)param; si_async_handle_reply(msg); } struct hostent * getipnodebyname(const char *name, int family, int flags, int *err) { si_item_t *item; uint32_t status; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %d 0x%08x\n", __func__, name, family, flags); #endif status = SI_STATUS_NO_ERROR; item = si_ipnode_byname(si_search(), name, family, flags, NULL, &status); if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; if (err != NULL) *err = status; if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } #if 0 mach_port_t getipnodebyname_async_call(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s %d 0x%08x\n", __func__, name, family, flags); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_HOST; sictx->key_offset = -1; 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); } mach_port_t getipnodebyname_async_start(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context) { return getipnodebyname_async_call(name, family, flags, err, callback, context); } void getipnodebyname_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } void getipnodebyname_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void getipnodebyname_async_handleReply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } #endif static int is_a4_mapped(const char *s) { int i; u_int8_t c; if (s == NULL) return 0; for (i = 0; i < 10; i++) { c = s[i]; if (c != 0x0) return 0; } for (i = 10; i < 12; i++) { c = s[i]; if (c != 0xff) return 0; } return 1; } static int is_a4_compat(const char *s) { int i; u_int8_t c; if (s == NULL) return 0; for (i = 0; i < 12; i++) { c = s[i]; if (c != 0x0) return 0; } /* Check for :: and ::1 */ for (i = 13; i < 15; i++) { /* anything non-zero in these 3 bytes means it's a V4 address */ c = s[i]; if (c != 0x0) return 1; } /* Leading 15 bytes are all zero */ c = s[15]; if (c == 0x0) return 0; if (c == 0x1) return 0; return 1; } struct hostent * getipnodebyaddr(const void *src, size_t len, int family, int *err) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-"); #endif if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src))) { src += 12; len = 4; family = AF_INET; } item = si_host_byaddr(si_search(), src, family, NULL, (uint32_t *)err); if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } #if 0 static void si_libinfo_ipnode_callback(si_item_t *item, uint32_t status, void *ctx) { si_context_t *sictx; struct hostent *h; if (ctx == NULL) return; sictx = (si_context_t *)ctx; if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) { free(sictx); si_item_release(item); return; } if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; if (item == NULL) { ((si_ipnode_async_callback)(sictx->orig_callback))(NULL, status, sictx->orig_context); return; } h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); ((si_ipnode_async_callback)(sictx->orig_callback))(h, status, sictx->orig_context); free(sictx); } mach_port_t getipnodebyaddr_async_call(const void *src, socklen_t len, int family, int *err, si_ipnode_async_callback callback, void *context) { si_context_t *sictx; uint32_t srclen; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-"); #endif if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src))) { src += 12; len = 4; family = AF_INET; } sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_HOST; sictx->key_offset = -1; /* src is not a C string - pass length in num3 */ srclen = len; 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); } mach_port_t getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, si_ipnode_async_callback callback, void *context) { socklen_t slen = len; return getipnodebyaddr_async_call(addr, slen, family, error, callback, context); } void getipnodebyaddr_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } void getipnodebyaddr_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void getipnodebyaddr_async_handleReply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } #endif void sethostent(int ignored) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_HOST, NULL); } struct hostent * gethostent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_HOST); if (list == NULL) { list = si_host_all(si_search()); LI_set_thread_list(CATEGORY_HOST, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); } void endhostent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_HOST, NULL); } /* MAC ADDRESS */ int ether_hostton(const char *name, struct ether_addr *e) { si_item_t *item; char *cmac; uint32_t t[6]; int i; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif if (name == NULL) return -1; if (e == NULL) return -1; item = si_mac_byname(si_search(), name); LI_set_thread_item(CATEGORY_MAC + 100, item); if (item == NULL) return -1; cmac = (char *)((uintptr_t)item + sizeof(si_item_t)); i = sscanf(cmac, " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]); if (i != 6) return -1; for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i]; return 0; } /* XXX to do? async ether_hostton */ int ether_ntohost(char *name, const struct ether_addr *e) { si_item_t *item; char *cname; uint32_t i, x[6]; char str[256]; if (name == NULL) return -1; if (e == NULL) return -1; for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i]; snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]); #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, str); #endif item = si_mac_bymac(si_search(), str); LI_set_thread_item(CATEGORY_MAC + 200, item); if (item == NULL) return -1; cname = (char *)((uintptr_t)item + sizeof(si_item_t)); memcpy(name, cname, strlen(cname) + 1); return 0; } /* XXX to do? async ether_ntohost */ /* NETWORK */ struct netent * getnetbyname(const char *name) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif item = si_network_byname(si_search(), name); LI_set_thread_item(CATEGORY_NETWORK + 100, item); if (item == NULL) return NULL; return (struct netent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getnetbyname_async_call(const char *name, si_network_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_NETWORK; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_NETWORK_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getnetbyname_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct netent * getnetbyaddr(uint32_t net, int type) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s 0x%08x\n", __func__, net); #endif if (type != AF_INET) return NULL; item = si_network_byaddr(si_search(), net); LI_set_thread_item(CATEGORY_NETWORK + 200, item); if (item == NULL) return NULL; return (struct netent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getnetbyaddr_async_call(uint32_t net, int type, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s 0x%08x\n", __func__, net); #endif if (type != AF_INET) return MACH_PORT_NULL; sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_NETWORK; sictx->key_offset = 200; return si_async_call(si_search(), SI_CALL_NETWORK_BYADDR, NULL, NULL, NULL, net, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getnetbyaddr_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void setnetent(int ignored) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_NETWORK, NULL); } struct netent * getnetent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_NETWORK); if (list == NULL) { list = si_network_all(si_search()); LI_set_thread_list(CATEGORY_NETWORK, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct netent *)((uintptr_t)item + sizeof(si_item_t)); } void endnetent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_NETWORK, NULL); } /* SERVICE */ struct servent * getservbyname(const char *name, const char *proto) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %s\n", __func__, name, proto); #endif item = si_service_byname(si_search(), name, proto); LI_set_thread_item(CATEGORY_SERVICE + 100, item); if (item == NULL) return NULL; return (struct servent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getservbyname_async_call(const char *name, const char *proto, si_service_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s %s\n", __func__, name, proto); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_SERVICE; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_SERVICE_BYNAME, name, proto, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getservbyname_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct servent * getservbyport(int port, const char *proto) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %d %s\n", __func__, ntohs((uint16_t)port), proto); #endif item = si_service_byport(si_search(), port, proto); LI_set_thread_item(CATEGORY_SERVICE + 200, item); if (item == NULL) return NULL; return (struct servent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getservbyport_async_call(int port, const char *proto, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %d %s\n", __func__, port, proto); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_SERVICE; sictx->key_offset = 200; return si_async_call(si_search(), SI_CALL_SERVICE_BYPORT, NULL, proto, NULL, port, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getservbyport_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void setservent(int ignored) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_SERVICE, NULL); } struct servent * getservent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_SERVICE); if (list == NULL) { list = si_service_all(si_search()); LI_set_thread_list(CATEGORY_SERVICE, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct servent *)((uintptr_t)item + sizeof(si_item_t)); } void endservent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_SERVICE, NULL); } /* PROTOCOL */ struct protoent * getprotobyname(const char *name) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif item = si_protocol_byname(si_search(), name); LI_set_thread_item(CATEGORY_PROTOCOL + 100, item); if (item == NULL) return NULL; return (struct protoent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getprotobyname_async_call(const char *name, si_protocol_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_PROTOCOL; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getprotobyname_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct protoent * getprotobynumber(int number) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %d\n", __func__, number); #endif item = si_protocol_bynumber(si_search(), number); LI_set_thread_item(CATEGORY_PROTOCOL + 200, item); if (item == NULL) return NULL; return (struct protoent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getprotobynumber_async_call(int number, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %d\n", __func__, number); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_PROTOCOL; sictx->key_offset = 200; return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getprotobynumber_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void setprotoent(int ignored) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_PROTOCOL, NULL); } struct protoent * getprotoent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_PROTOCOL); if (list == NULL) { list = si_protocol_all(si_search()); LI_set_thread_list(CATEGORY_PROTOCOL, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct protoent *)((uintptr_t)item + sizeof(si_item_t)); } void endprotoent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_PROTOCOL, NULL); } /* RPC */ struct rpcent * getrpcbyname(const char *name) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif item = si_rpc_byname(si_search(), name); LI_set_thread_item(CATEGORY_RPC + 100, item); if (item == NULL) return NULL; return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getrpcbyname_async_call(const char *name, si_rpc_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, name); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_RPC; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_RPC_BYNAME, name, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getrpcbyname_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct rpcent * getrpcbynumber ( #ifdef __LP64__ int number #else long number #endif ) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %ld\n", __func__, (long int)number); #endif item = si_rpc_bynumber(si_search(), number); LI_set_thread_item(CATEGORY_RPC + 200, item); if (item == NULL) return NULL; return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getrpcbynumber_async_call(int number, si_group_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %d\n", __func__, number); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_RPC; sictx->key_offset = 200; return si_async_call(si_search(), SI_CALL_RPC_BYNUMBER, NULL, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getrpcbynumber_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } void setrpcent(int ignored) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_RPC, NULL); } struct rpcent * getrpcent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_RPC); if (list == NULL) { list = si_rpc_all(si_search()); LI_set_thread_list(CATEGORY_RPC, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t)); } void endrpcent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_RPC, NULL); } /* FS */ struct fstab * getfsspec(const char *spec) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, spec); #endif item = si_fs_byspec(si_search(), spec); LI_set_thread_item(CATEGORY_FS + 100, item); if (item == NULL) return NULL; return (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); } struct fstab * getfsbyname(const char *name) { #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif return getfsspec(name); } mach_port_t getfsspec_async_call(const char *spec, si_fs_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, spec); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_FS; sictx->key_offset = 100; return si_async_call(si_search(), SI_CALL_FS_BYSPEC, spec, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getfsspec_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } struct fstab * getfsfile(const char *file) { si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, file); #endif item = si_fs_byfile(si_search(), file); LI_set_thread_item(CATEGORY_FS + 200, item); if (item == NULL) return NULL; return (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); } mach_port_t getfsfile_async_call(const char *file, si_fs_async_callback callback, void *context) { si_context_t *sictx; #ifdef CALL_TRACE fprintf(stderr, ">> %s %s\n", __func__, file); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_FS; sictx->key_offset = 200; return si_async_call(si_search(), SI_CALL_FS_BYFILE, file, NULL, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); } void getfsfile_async_handle_reply(mach_msg_header_t *msg) { #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif si_async_handle_reply(msg); } int setfsent(void) { #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif LI_set_thread_list(CATEGORY_FS, NULL); return 1; } struct fstab * getfsent(void) { si_list_t *list; si_item_t *item; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif list = LI_get_thread_list(CATEGORY_FS); if (list == NULL) { list = si_fs_all(si_search()); LI_set_thread_list(CATEGORY_FS, list); } item = si_list_next(list); if (item == NULL) return NULL; return (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); } void endfsent(void) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif LI_set_thread_list(CATEGORY_FS, NULL); } /* GETADDRINFO */ static int _getaddrinfo_internal(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, struct addrinfo **res) { si_list_t *list; uint32_t family, socktype, protocol, flags, status; struct addrinfo *ai; family = AF_UNSPEC; socktype = SOCK_UNSPEC; protocol = IPPROTO_UNSPEC; flags = 0; status = SI_STATUS_NO_ERROR; if (res == NULL) return 0; *res = NULL; if (hints != NULL) { family = hints->ai_family; socktype = hints->ai_socktype; protocol = hints->ai_protocol; flags = hints->ai_flags; } #ifdef CALL_TRACE fprintf(stderr, "-> %s %s %s %u %u %u 0x%08x %s\n", __func__, nodename, servname, family, socktype, protocol, flags, (interface == NULL) ? "" : interface); #endif list = si_addrinfo(si_search(), nodename, servname, family, socktype, protocol, flags, interface, &status); if ((status != SI_STATUS_NO_ERROR) || (list == NULL)) { si_list_release(list); if (status == SI_STATUS_NO_ERROR) return EAI_NONAME; else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; else status = status - SI_STATUS_EAI_PLUS_100; return status; } *res = si_list_to_addrinfo(list); si_list_release(list); if (*res == NULL) status = EAI_MEMORY; /* don't return the canonical name unless asked */ if ((flags & AI_CANONNAME) == 0) { for (ai = *res; ai != NULL; ai = ai->ai_next) { free(ai->ai_canonname); ai->ai_canonname = NULL; } } return status; } int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { return _getaddrinfo_internal(nodename, servname, hints, NULL, res); } #ifdef CALL_TRACE static char * socket_name(int sock) { static char str[16]; switch(sock) { case SOCK_UNSPEC: return "SOCK_UNSPEC"; case SOCK_STREAM: return "SOCK_STREAM"; case SOCK_DGRAM: return "SOCK_DGRAM"; } sprintf(str, "%d", sock); return str; } static char * family_name(int pf) { static char str[16]; switch(pf) { case PF_UNSPEC: return "PF_UNSPEC"; case PF_INET: return "PF_INET"; case PF_INET6: return "PF_INET6"; }; sprintf(str, "%d", pf); return str; } static char * protocol_name(int p) { static char str[16]; switch(p) { case IPPROTO_UNSPEC: return "IPPROTO_UNSPEC"; case IPPROTO_TCP: return "IPPROTO_TCP"; case IPPROTO_UDP: return "IPPROTO_UDP"; } sprintf(str, "%d", p); return str; } static char * _gai_inet_ntop(struct in6_addr a) { static char buf[128]; char t[32]; unsigned short x; char *p; int i; memset(buf, 0, 128); p = (char *)&a.__u6_addr.__u6_addr32; for (i = 0; i < 8; i++, x += 1) { memmove(&x, p, 2); p += 2; sprintf(t, "%hx", x); strcat(buf, t); if (i < 7) strcat(buf, ":"); } return buf; } static void fprint_addrinfo(FILE *f, struct addrinfo *a) { int i; unsigned char v; struct sockaddr_in *s4; struct sockaddr_in6 *s6; if (a == NULL) return; if (a->ai_flags != 0) { fprintf(f, "flags ="); if (a->ai_flags & AI_PASSIVE) fprintf(f, " AI_PASSIVE"); if (a->ai_flags & AI_CANONNAME) fprintf(f, " AI_CANONNAME"); if (a->ai_flags & AI_NUMERICHOST) fprintf(f, " AI_NUMERICHOST"); if (a->ai_flags & AI_NUMERICSERV) fprintf(f, " AI_NUMERICSERV"); fprintf(f, "\n"); } fprintf(f, "family = %s\n", family_name(a->ai_family)); fprintf(f, "socktype = %s\n", socket_name(a->ai_socktype)); fprintf(f, "protocol = %s\n", protocol_name(a->ai_protocol)); fprintf(f, "canonical name = "); if (a->ai_canonname == NULL) fprintf(f, "NULL\n"); else fprintf(f, "\"%s\"\n", a->ai_canonname); fprintf(f, "addrlen = %ld\n", (long int)a->ai_addrlen); if (a->ai_addr == NULL) fprintf(f, "sockaddr = NULL\n"); else { if (a->ai_family == PF_INET) { s4 = (struct sockaddr_in *)a->ai_addr; fprintf(f, "sockaddr_in len = %d\n", s4->sin_len); fprintf(f, "sockaddr_in family = %s\n", family_name(s4->sin_family)); fprintf(f, "sockaddr_in port = %hu\n", ntohs(s4->sin_port)); fprintf(f, "sockaddr_in address = %s\n", inet_ntoa(s4->sin_addr)); } else if (a->ai_family == PF_INET6) { s6 = (struct sockaddr_in6 *)a->ai_addr; fprintf(f, "sockaddr_in6 len = %d\n", s6->sin6_len); fprintf(f, "sockaddr_in6 family = %s\n", family_name(s6->sin6_family)); fprintf(f, "sockaddr_in6 port = %hu\n", ntohs(s6->sin6_port)); fprintf(f, "sockaddr_in6 flowinfo = %d\n", s6->sin6_flowinfo); fprintf(f, "sockaddr_in6 address = %s\n", _gai_inet_ntop(s6->sin6_addr)); fprintf(f, "sockaddr_in6 scope_id = %d\n", s6->sin6_scope_id); } else { fprintf(f, "sockaddr len = %d\n", a->ai_addr->sa_len); fprintf(f, "sockaddr family = %s\n", family_name(a->ai_addr->sa_family)); fprintf(f, "sockaddr data = "); for (i = 0; i < a->ai_addr->sa_len - 2; i++) { v = a->ai_addr->sa_data[i]; fprintf(f, "%02x", v); } fprintf(f, "\n"); } } if (a->ai_next != NULL) { fprintf(f, "NEXT --->\n"); fprint_addrinfo(f, a->ai_next); } } #endif static void si_libinfo_addrinfo_callback(si_list_t *list, uint32_t status, void *ctx) { si_context_t *sictx; struct addrinfo *out; if (ctx == NULL) { #ifdef CALL_TRACE fprintf(stderr, " %s error no context\n", __func__); #endif si_list_release(list); return; } sictx = (si_context_t *)ctx; if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) { #ifdef CALL_TRACE fprintf(stderr, " %s error no callback\n", __func__); #endif si_list_release(list); free(sictx); return; } if (status != SI_STATUS_NO_ERROR) { #ifdef CALL_TRACE fprintf(stderr, " %s original status %d\n", __func__, status); #endif if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; else status = status - SI_STATUS_EAI_PLUS_100; } if (list == NULL) { #ifdef CALL_TRACE fprintf(stderr, " %s result NULL status %d (returning EAI_NONAME)\n", __func__, status); #endif ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_NONAME, NULL, sictx->orig_context); free(sictx); return; } out = si_list_to_addrinfo(list); si_list_release(list); if (out == NULL) { #ifdef CALL_TRACE fprintf(stderr, " %s result conversion failed returning NULL status %d (returning EAI_MEMORY)\n", __func__, status); #endif ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_MEMORY, NULL, sictx->orig_context); free(sictx); return; } #ifdef CALL_TRACE fprintf(stderr, " %s %d\n", __func__, status); fprint_addrinfo(stderr, out); #endif ((si_addrinfo_async_callback)(sictx->orig_callback))(status, out, sictx->orig_context); free(sictx); } /* SPI */ mach_port_t _getaddrinfo_interface_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, const char *interface, si_addrinfo_async_callback callback, void *context) { si_context_t *sictx; uint32_t family, socktype, protocol, flags; family = AF_UNSPEC; socktype = SOCK_UNSPEC; protocol = IPPROTO_UNSPEC; flags = 0; if (hints != NULL) { family = hints->ai_family; socktype = hints->ai_socktype; protocol = hints->ai_protocol; flags = hints->ai_flags; } #ifdef CALL_TRACE fprintf(stderr, ">> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_ADDRINFO; sictx->key_offset = 0; return si_async_call(si_search(), SI_CALL_ADDRINFO, nodename, servname, interface, family, socktype, protocol, flags, (void *)si_libinfo_addrinfo_callback, sictx); } mach_port_t getaddrinfo_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context) { return _getaddrinfo_interface_async_call(nodename, servname, hints, NULL, callback, context); } int32_t getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context) { if (p == NULL) return EAI_SYSTEM; *p = getaddrinfo_async_call(nodename, servname, hints, callback, context); if (*p == MACH_PORT_NULL) return EAI_SYSTEM; return 0; } int32_t getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints) { return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL); } int32_t getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res) { /* unsupported Leopard SPI */ return EAI_SYSTEM; } void getaddrinfo_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } int32_t getaddrinfo_async_handle_reply(void *param) { mach_msg_header_t *msg; #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif msg = (mach_msg_header_t *)param; si_async_handle_reply(msg); return 0; } /* GETNAMEINFO */ static int _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) { si_item_t *item; si_nameinfo_t *ni; uint32_t status, len, wantn, wants; #ifdef CALL_TRACE fprintf(stderr, "-> %s\n", __func__); #endif status = SI_STATUS_NO_ERROR; wantn = 0; if ((node != NULL) && (nodelen > 0)) wantn = 1; wants = 0; if ((service != NULL) && (servicelen > 0)) wants = 1; if ((wantn == 0) && (wants == 0)) return status; if (wantn == 0) flags |= NI_NUMERICHOST; if (wants == 0) flags |= NI_NUMERICSERV; item = si_nameinfo(si_search(), sa, flags, interface, &status); if ((status != SI_STATUS_NO_ERROR) || (item == NULL)) { si_item_release(item); if (status == SI_STATUS_NO_ERROR) status = EAI_NONAME; else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; else status = status - SI_STATUS_EAI_PLUS_100; return status; } ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t)); len = 0; if (ni->ni_node != NULL) len = strlen(ni->ni_node) + 1; if ((wantn == 1) && (len > 0)) { if (len > nodelen) { si_item_release(item); return EAI_OVERFLOW; } memset(node, 0, nodelen); memcpy(node, ni->ni_node, len); } len = 0; if (ni->ni_serv != NULL) len = strlen(ni->ni_serv) + 1; if ((wants == 1) && (len > 0)) { if (len > servicelen) { si_item_release(item); return EAI_OVERFLOW; } memset(service, 0, servicelen); memcpy(service, ni->ni_serv, len); } si_item_release(item); return 0; } int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags) { return _getnameinfo_interface_internal(sa, salen, node, nodelen, service, servicelen, flags, NULL); } static void si_libinfo_nameinfo_callback(si_item_t *item, uint32_t status, void *ctx) { si_context_t *sictx; si_nameinfo_t *ni; char *node, *serv; if (ctx == NULL) return; sictx = (si_context_t *)ctx; if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) { si_item_release(item); free(sictx); return; } if (status != SI_STATUS_NO_ERROR) { if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; else status = status - SI_STATUS_EAI_PLUS_100; } if (item == NULL) { ((si_nameinfo_async_callback)(sictx->orig_callback))(status, NULL, NULL, sictx->orig_context); free(sictx); return; } LI_set_thread_item(CATEGORY_NAMEINFO, item); node = NULL; serv = NULL; ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t)); if (ni->ni_node != NULL) node = strdup(ni->ni_node); if (ni->ni_serv != NULL) serv = strdup(ni->ni_serv); ((si_nameinfo_async_callback)(sictx->orig_callback))(status, node, serv, sictx->orig_context); free(sictx); } /* SPI */ mach_port_t _getnameinfo_interface_async_call(const struct sockaddr *sa, size_t len, int flags, const char *interface, si_nameinfo_async_callback callback, void *context) { si_context_t *sictx; uint32_t salen; #ifdef CALL_TRACE fprintf(stderr, ">> %s\n", __func__); #endif sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); if (sictx == NULL) return MACH_PORT_NULL; sictx->orig_callback = callback; sictx->orig_context = context; sictx->cat = CATEGORY_ADDRINFO; sictx->key_offset = 0; /* sa is not a C string - pass length in num3 */ salen = len; return si_async_call(si_search(), SI_CALL_NAMEINFO, (const char *)sa, NULL, interface, flags, 0, salen, 0, (void *)si_libinfo_nameinfo_callback, sictx); } mach_port_t getnameinfo_async_call(const struct sockaddr *sa, size_t len, int flags, si_nameinfo_async_callback callback, void *context) { return _getnameinfo_interface_async_call(sa, len, flags, NULL, callback, context); } int32_t getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, si_nameinfo_async_callback callback, void *context) { if (p == NULL) return EAI_SYSTEM; *p = getnameinfo_async_call(sa, salen, flags, callback, context); if (*p == MACH_PORT_NULL) return EAI_SYSTEM; return 0; } int32_t getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags) { return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL); } void getnameinfo_async_cancel(mach_port_t p) { #ifdef CALL_TRACE fprintf(stderr, "-- %s\n", __func__); #endif si_async_cancel(p); } int32_t getnameinfo_async_handle_reply(void *param) { mach_msg_header_t *msg; #ifdef CALL_TRACE fprintf(stderr, "<< %s\n", __func__); #endif msg = (mach_msg_header_t *)param; si_async_handle_reply(msg); return 0; } /* getpwXXX_r and getgrXXX_r */ static int copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen) { int hsize; char *bp; if (in == NULL) return -1; if (out == NULL) return -1; if (buffer == NULL) buflen = 0; /* Calculate size of input */ hsize = 0; if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1); if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1); if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1); if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1); if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1); if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1); /* Check buffer space */ if (hsize > buflen) return -1; /* Copy result into caller's struct passwd, using buffer for memory */ bp = buffer; out->pw_name = NULL; if (in->pw_name != NULL) { out->pw_name = bp; hsize = strlen(in->pw_name) + 1; memmove(bp, in->pw_name, hsize); bp += hsize; } out->pw_passwd = NULL; if (in->pw_passwd != NULL) { out->pw_passwd = bp; hsize = strlen(in->pw_passwd) + 1; memmove(bp, in->pw_passwd, hsize); bp += hsize; } out->pw_uid = in->pw_uid; out->pw_gid = in->pw_gid; out->pw_change = in->pw_change; out->pw_class = NULL; if (in->pw_class != NULL) { out->pw_class = bp; hsize = strlen(in->pw_class) + 1; memmove(bp, in->pw_class, hsize); bp += hsize; } out->pw_gecos = NULL; if (in->pw_gecos != NULL) { out->pw_gecos = bp; hsize = strlen(in->pw_gecos) + 1; memmove(bp, in->pw_gecos, hsize); bp += hsize; } out->pw_dir = NULL; if (in->pw_dir != NULL) { out->pw_dir = bp; hsize = strlen(in->pw_dir) + 1; memmove(bp, in->pw_dir, hsize); bp += hsize; } out->pw_shell = NULL; if (in->pw_shell != NULL) { out->pw_shell = bp; hsize = strlen(in->pw_shell) + 1; memmove(bp, in->pw_shell, hsize); bp += hsize; } out->pw_expire = in->pw_expire; return 0; } static int copy_group_r(struct group *in, struct group *out, char *buffer, int buflen) { int i, len, hsize; unsigned long addr; char *bp, *ap; if (in == NULL) return -1; if (out == NULL) return -1; if (buffer == NULL) buflen = 0; /* Calculate size of input */ hsize = 0; if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1); if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1); /* NULL pointer at end of list */ hsize += sizeof(char *); len = 0; if (in->gr_mem != NULL) { for (len = 0; in->gr_mem[len] != NULL; len++) { hsize += sizeof(char *); hsize += (strlen(in->gr_mem[len]) + 1); } } /* Check buffer space */ if (hsize > buflen) return -1; /* Copy result into caller's struct group, using buffer for memory */ bp = buffer; out->gr_name = NULL; if (in->gr_name != NULL) { out->gr_name = bp; hsize = strlen(in->gr_name) + 1; memmove(bp, in->gr_name, hsize); bp += hsize; } out->gr_passwd = NULL; if (in->gr_passwd != NULL) { out->gr_passwd = bp; hsize = strlen(in->gr_passwd) + 1; memmove(bp, in->gr_passwd, hsize); bp += hsize; } out->gr_gid = in->gr_gid; out->gr_mem = NULL; ap = bp + ((len + 1) * sizeof(char *)); if (in->gr_mem != NULL) { out->gr_mem = (char **)bp; for (i = 0; i < len; i++) { addr = (unsigned long)ap; memmove(bp, &addr, sizeof(unsigned long)); bp += sizeof(unsigned long); hsize = strlen(in->gr_mem[i]) + 1; memmove(ap, in->gr_mem[i], hsize); ap += hsize; } } memset(bp, 0, sizeof(unsigned long)); bp = ap; return 0; } int getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result) { si_item_t *item; struct group *g; int status; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif if (result != NULL) *result = NULL; if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; item = si_group_byname(si_search(), name); if (item == NULL) return 0; g = (struct group *)((uintptr_t)item + sizeof(si_item_t)); status = copy_group_r(g, grp, buffer, bufsize); si_item_release(item); if (status != 0) return ERANGE; *result = grp; return 0; } int getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result) { si_item_t *item; struct group *g; int status; #ifdef CALL_TRACE fprintf(stderr, "-> %s %d\n", __func__, gid); #endif if (result != NULL) *result = NULL; if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; item = si_group_bygid(si_search(), gid); if (item == NULL) return 0; g = (struct group *)((uintptr_t)item + sizeof(si_item_t)); status = copy_group_r(g, grp, buffer, bufsize); si_item_release(item); if (status != 0) return ERANGE; *result = grp; return 0; } int getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result) { si_item_t *item; struct passwd *p; int status; #ifdef CALL_TRACE fprintf(stderr, "-> %s %s\n", __func__, name); #endif if (result != NULL) *result = NULL; if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; item = si_user_byname(si_search(), name); if (item == NULL) return 0; p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); status = copy_user_r(p, pw, buffer, bufsize); si_item_release(item); if (status != 0) return ERANGE; *result = pw; return 0; } int getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result) { si_item_t *item; struct passwd *p; int status; #ifdef CALL_TRACE fprintf(stderr, "-> %s %d\n", __func__, uid); #endif if (result != NULL) *result = NULL; if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; item = si_user_byuid(si_search(), uid); if (item == NULL) return 0; p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); status = copy_user_r(p, pw, buffer, bufsize); si_item_release(item); if (status != 0) return ERANGE; *result = pw; return 0; } /* misc */ char * user_from_uid(uid_t uid, int nouser) { struct passwd *pw; static char buf[16]; pw = getpwuid(uid); if (pw != NULL) return pw->pw_name; if (nouser) return NULL; snprintf(buf, sizeof(buf), "%u", uid); return buf; } char * group_from_gid(gid_t gid, int nogroup) { struct group *gr; static char buf[16]; gr = getgrgid(gid); if (gr != NULL) return gr->gr_name; if (nogroup) return NULL; snprintf(buf, sizeof(buf), "%u", gid); return buf; } /* no longer supported */ const prdb_ent * prdb_getbyname(const char *name) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif return NULL; } const prdb_ent * prdb_get(void) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif return NULL; } void prdb_set(const char *name) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif } void prdb_end(void) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif } struct bootparamsent * bootparams_getbyname(const char *name) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif return NULL; } struct bootparamsent * bootparams_getent(void) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif return NULL; } void bootparams_setent(void) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif } void bootparams_endent(void) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif } int bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif return 0; } int bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile) { #ifdef CALL_TRACE fprintf(stderr, "~~ %s\n", __func__); #endif return 0; }