/* si_addrinfo_list_from_hostent * Returns an addrinfo list from IPv4 and IPv6 hostent entries */ si_list_t * si_addrinfo_list_from_hostent(si_mod_t *si, uint32_t flags, uint32_t socktype, uint32_t proto, uint16_t port, uint16_t scope, const struct hostent *h4, const struct hostent *h6) { int i; si_list_t *out = NULL; si_list_t *list; if ((h6 != NULL) && (h6->h_addr_list != NULL)) { for (i = 0; h6->h_addr_list[i] != NULL; i++) { struct in6_addr a6; memcpy(&a6, h6->h_addr_list[i], h6->h_length); list = si_addrinfo_list(si, flags, socktype, proto, NULL, &a6, port, scope, NULL, h6->h_name); out = si_list_concat(out, list); si_list_release(list); } } if ((h4 != NULL) && (h4->h_addr_list != NULL)) { for (i = 0; h4->h_addr_list[i] != NULL; i++) { struct in_addr a4; memcpy(&a4, h4->h_addr_list[i], h4->h_length); list = si_addrinfo_list(si, flags, socktype, proto, &a4, NULL, port, 0, h4->h_name, NULL); out = si_list_concat(out, list); si_list_release(list); } } return out; }
static void si_async_workunit_release(si_async_workunit_t *r) { if (r == NULL) return; if (OSAtomicDecrement32Barrier(&(r->refcount)) != 0) return; #ifdef CALL_TRACE fprintf(stderr, "** %s freeing worklist item %p\n", __func__, r); #endif si_async_worklist_remove_unit(r); if (r->resitem != NULL) si_item_release(r->resitem); if (r->reslist != NULL) si_list_release(r->reslist); if (r->str1 != NULL) free(r->str1); if (r->str2 != NULL) free(r->str2); if (r->str3 != NULL) free(r->str3); /* release send-once right if it has not been used */ if (r->send != MACH_PORT_NULL) mach_port_deallocate(mach_task_self(), r->send); /* release receive right */ mach_port_mod_refs(mach_task_self(), r->port, MACH_PORT_RIGHT_RECEIVE, -1); free(r); }
static void _LI_thread_info_free(void *x) { li_thread_data_t *tdata; if (x == NULL) return; tdata = (li_thread_data_t *)x; si_item_release(tdata->thread_item); si_list_release(tdata->thread_list); free(tdata); }
void LI_set_thread_list(uint32_t key, si_list_t *list) { li_thread_data_t *tdata; tdata = LI_get_thread_info(key); if (tdata == NULL) return; si_list_release(tdata->thread_list); si_list_reset(list); tdata->thread_list = list; }
static si_list_t * _gai_srv(si_mod_t *si, const char *node, const char *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err) { int i; char *qname; si_srv_t *srv; si_item_t *item; si_list_t *list = NULL; si_list_t *result = NULL; /* Minimum SRV priority is zero. Start below that. */ int lastprio = -1; int currprio; if (node == NULL || serv == NULL) return NULL; asprintf(&qname, "%s.%s", serv, node); list = si_srv_byname(si, qname, interface, err); free(qname); /* Iterate the SRV records starting at lowest priority and attempt to * lookup the target host name. Returns the first successful lookup. * It's an O(n^2) algorithm but data sets are small (less than 100) and * sorting overhead is dwarfed by network I/O for each element. */ while (list != NULL && result == NULL) { /* Find the next lowest priority level. */ /* Maximum SRV priority is UINT16_MAX. Start above that. */ currprio = INT_MAX; for (i = 0; i < list->count; ++i) { item = list->entry[i]; srv = (si_srv_t *)((uintptr_t)item + sizeof(si_item_t)); if (srv->priority > lastprio && srv->priority < currprio) { currprio = srv->priority; } } if (currprio == INT_MAX) { /* All priorities have been evaluated. Done. */ break; } else { lastprio = currprio; } /* Lookup hosts at the current priority level. Return first match. */ for (i = 0; i < list->count; ++i) { item = list->entry[i]; srv = (si_srv_t *)((uintptr_t)item + sizeof(si_item_t)); if (srv->priority == currprio) { /* So that _gai_simple expects an integer service. */ flags |= AI_NUMERICSERV; result = _gai_simple(si, srv->target, &srv->port, family, socktype, proto, flags, interface, err); if (result) { break; } } } } if (list != NULL) { si_list_release(list); } return result; }
si_list_t * si_addrinfo_list(si_mod_t *si, uint32_t flags, int socktype, int proto, struct in_addr *a4, struct in6_addr *a6, int port, int scopeid, const char *cname4, const char *cname6) { int do_map = 0; si_item_t *item = NULL; si_list_t *out4 = NULL, *out6 = NULL; if ((flags & AI_V4MAPPED) && ((flags & AI_ALL) || (a6 == NULL))) do_map = 1; if (a6 != NULL) { if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) { item = si_addrinfo_v6(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a6, scopeid, cname6); out6 = si_list_add(out6, item); si_item_release(item); } if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) { item = si_addrinfo_v6(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a6, scopeid, cname6); out6 = si_list_add(out6, item); si_item_release(item); } if (proto == IPPROTO_ICMPV6) { item = si_addrinfo_v6(si, 0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, scopeid, cname6); out6 = si_list_add(out6, item); si_item_release(item); } } if (a4 != NULL) { if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) { if (do_map == 0) { item = si_addrinfo_v4(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, cname4); out4 = si_list_add(out4, item); } else { item = si_addrinfo_v4_mapped(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, cname4); out6 = si_list_add(out6, item); } si_item_release(item); } if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) { if (do_map == 0) { item = si_addrinfo_v4(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, cname4); out4 = si_list_add(out4, item); } else { item = si_addrinfo_v4_mapped(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, cname4); out6 = si_list_add(out6, item); } si_item_release(item); } if (proto == IPPROTO_ICMP) { if (do_map == 0) { item = si_addrinfo_v4(si, 0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, cname4); out4 = si_list_add(out4, item); } else { item = si_addrinfo_v4_mapped(si, 0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, cname4); out6 = si_list_add(out6, item); } si_item_release(item); } } out6 = si_list_concat(out6, out4); si_list_release(out4); return out6; }