si_item_t * si_item_call(struct si_mod_s *si, int call, const char *str1, const char *str2, const char *str3, uint32_t num1, uint32_t num2, uint32_t *err) { if (si == NULL) return NULL; switch (call) { case SI_CALL_USER_BYNAME: return si_user_byname(si, str1); case SI_CALL_USER_BYUID: return si_user_byuid(si, (uid_t)num1); case SI_CALL_GROUP_BYNAME: return si_group_byname(si, str1); case SI_CALL_GROUP_BYGID: return si_group_bygid(si, (gid_t)num1); case SI_CALL_GROUPLIST: return si_grouplist(si, str1, (int) num1); case SI_CALL_ALIAS_BYNAME: return si_alias_byname(si, str1); case SI_CALL_HOST_BYNAME: return si_host_byname(si, str1, num1, str3, err); case SI_CALL_HOST_BYADDR: return si_host_byaddr(si, (void *)str1, num1, str3, err); case SI_CALL_NETWORK_BYNAME: return si_network_byname(si, str1); case SI_CALL_NETWORK_BYADDR: return si_network_byaddr(si, num1); case SI_CALL_SERVICE_BYNAME: return si_service_byname(si, str1, str2); case SI_CALL_SERVICE_BYPORT: return si_service_byport(si, num1, str2); case SI_CALL_PROTOCOL_BYNAME: return si_protocol_byname(si, str1); case SI_CALL_PROTOCOL_BYNUMBER: return si_protocol_bynumber(si, num1); case SI_CALL_RPC_BYNAME: return si_network_byname(si, str1); case SI_CALL_RPC_BYNUMBER: return si_rpc_bynumber(si, num1); case SI_CALL_FS_BYSPEC: return si_fs_byspec(si, str1); case SI_CALL_FS_BYFILE: return si_fs_byfile(si, str1); case SI_CALL_NAMEINFO: return si_nameinfo(si, (const struct sockaddr *)str1, num1, str3, err); case SI_CALL_IPNODE_BYNAME: return si_ipnode_byname(si, (const char *)str1, num1, num2, str3, err); case SI_CALL_MAC_BYNAME: return si_mac_byname(si, (const char *)str1); case SI_CALL_MAC_BYMAC: return si_mac_bymac(si, (const char *)str1); /* Support for DNS async calls */ case SI_CALL_DNS_QUERY: case SI_CALL_DNS_SEARCH: { if (si->vtable->sim_item_call == NULL) return NULL; return si->vtable->sim_item_call(si, call, str1, str2, str3, num1, num2, err); } default: return NULL; } return NULL; }
/* _gai_simple * Simple lookup via gethostbyname2(3) mechanism. */ si_list_t * _gai_simple(si_mod_t *si, const void *nodeptr, const void *servptr, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err) { si_item_t *h4_item = NULL, *h6_item = NULL; struct hostent *h4 = NULL, *h6 = NULL; si_list_t *out = NULL; uint16_t port = 0; if ((flags & AI_NUMERICSERV) != 0 && servptr != NULL) { port = *(uint16_t*)servptr; } else if (servptr != NULL) { if (_gai_serv_to_port(servptr, proto, &port) != 0) { if (err) *err = SI_STATUS_EAI_NONAME; return NULL; } } if ((flags & AI_NUMERICHOST) != 0) { if (family == AF_INET) { h4_item = si_host_byaddr(si, nodeptr, AF_INET, interface, NULL); } else if (family == AF_INET6) { h6_item = si_host_byaddr(si, nodeptr, AF_INET6, interface, NULL); } } else { if ((family == AF_INET) || (family == AF_UNSPEC)) { h4_item = si_host_byname(si, nodeptr, AF_INET, interface, NULL); } if ((family == AF_INET6) || (family == AF_UNSPEC)) { h6_item = si_host_byname(si, nodeptr, AF_INET6, interface, NULL); } } if (h4_item != NULL) { h4 = (struct hostent *)((uintptr_t)h4_item + sizeof(si_item_t)); } if (h6_item != NULL) { h6 = (struct hostent *)((uintptr_t)h6_item + sizeof(si_item_t)); } out = si_addrinfo_list_from_hostent(si, flags, socktype, proto, port, 0, h4, h6); si_item_release(h4_item); si_item_release(h6_item); return _gai_sort_list(out, flags); }
si_item_t * si_ipnode_byname(si_mod_t *si, const char *name, int family, int flags, const char *interface, uint32_t *err) { int i, status, want; uint32_t if4, if6; struct in_addr addr4; struct in6_addr addr6; si_item_t *item4, *item6; build_hostent_t *out; struct hostent *h; uint32_t unused; memset(&addr4, 0, sizeof(struct in_addr)); memset(&addr6, 0, sizeof(struct in6_addr)); if (err != NULL) *err = 0; if (family == AF_INET) { status = inet_aton(name, &addr4); if (status == 1) { /* create a host entry */ item4 = make_hostent(si, name, addr4); if (item4 == NULL) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } return item4; } } else if (family == AF_INET6) { status = inet_pton(family, name, &addr6); if (status == 1) { /* create a host entry */ item6 = make_hostent6(si, name, addr6); if (item6 == NULL) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } return item6; } status = inet_aton(name, &addr4); if (status == 1) { if (!(flags & (AI_V4MAPPED | AI_V4MAPPED_CFG))) { if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; return NULL; } addr6.__u6_addr.__u6_addr32[0] = 0x00000000; addr6.__u6_addr.__u6_addr32[1] = 0x00000000; addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr4.s_addr), IPV4_ADDR_LEN); /* create a host entry */ item6 = make_hostent6(si, name, addr6); if (item6 == NULL) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } return item6; } } else { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } /* * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have. */ if4 = 0; if6 = 0; if (flags & AI_ADDRCONFIG) { if (si_inet_config(&if4, &if6) < 0) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } /* Bail out if there are no interfaces */ if ((if4 == 0) && (if6 == 0)) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } } /* * Figure out what we want. * If user asked for AF_INET, we only want V4 addresses. */ want = WANT_A4_ONLY; if (family == AF_INET) { if ((flags & AI_ADDRCONFIG) && (if4 == 0)) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } } else if (family == AF_INET6) { /* family == AF_INET6 */ want = WANT_A6_ONLY; if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)) { if (flags & AI_ALL) { want = WANT_A6_PLUS_MAPPED_A4; } else { want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; } } else { if ((flags & AI_ADDRCONFIG) && (if6 == 0)) { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } } } else { if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } item6 = NULL; item4 = NULL; /* fetch IPv6 data if required */ if ((want == WANT_A6_ONLY) || (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) || (want == WANT_A6_PLUS_MAPPED_A4)) { item6 = si_host_byname(si, name, AF_INET6, interface, (uint32_t *)err); } /* fetch IPv4 data if required */ if ((want == WANT_A4_ONLY) || (want == WANT_A6_PLUS_MAPPED_A4) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (item6 == NULL))) { item4 = si_host_byname(si, name, AF_INET, interface, (uint32_t *)err); } if (want == WANT_A4_ONLY) { si_item_release(item6); if ((item4 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; return item4; } if (want == WANT_A6_ONLY) { si_item_release(item4); if ((item6 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; return item6; } if ((item6 == NULL) && (item4 == NULL)) { if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; return NULL; } /* output item will have IPv6 + mapped IPv4 addresses */ out = (build_hostent_t *)calloc(1, sizeof(build_hostent_t)); if (out == NULL) { si_item_release(item4); si_item_release(item6); if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; return NULL; } if (item4 != NULL) { h = (struct hostent *)((uintptr_t)item4 + sizeof(si_item_t)); out->host.h_name = lower_case(h->h_name); if (h->h_aliases != NULL) { for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out); } for (i = 0; h->h_addr_list[i] != 0; i++) { addr6.__u6_addr.__u6_addr32[0] = 0x00000000; addr6.__u6_addr.__u6_addr32[1] = 0x00000000; addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); memmove(&(addr6.__u6_addr.__u6_addr32[3]), h->h_addr_list[i], IPV4_ADDR_LEN); append_addr((const char *)&addr6, IPV6_ADDR_LEN, out); } } if (item6 != NULL) { h = (struct hostent *)((uintptr_t)item6 + sizeof(si_item_t)); if (out->host.h_name == NULL) out->host.h_name = lower_case(h->h_name); if (h->h_aliases != NULL) { for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out); } for (i = 0; h->h_addr_list[i] != 0; i++) append_addr(h->h_addr_list[i], IPV6_ADDR_LEN, out); } si_item_release(item4); si_item_release(item6); unused = 0; item6 = (si_item_t *)LI_ils_create("L4444s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, out->host.h_name, out->host.h_aliases, AF_INET6, IPV6_ADDR_LEN, out->host.h_addr_list); free_build_hostent(out); return item6; }