/*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */ struct hostent * lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { struct hostent *he1, *he2; lwres_context_t *lwrctx = NULL; lwres_gnbaresponse_t *by = NULL; lwres_result_t n; union { const void *konst; struct in6_addr *in6; } u; /* * Sanity checks. */ if (src == NULL) { *error_num = NO_RECOVERY; return (NULL); } switch (af) { case AF_INET: if (len != (unsigned int)INADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; case AF_INET6: if (len != (unsigned int)IN6ADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; default: *error_num = NO_RECOVERY; return (NULL); } /* * The de-"const"-ing game is done because at least one * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_* * macros in such a way that they discard the const with * internal casting, and gcc ends up complaining. Rather * than replacing their own (possibly optimized) definitions * with our own, cleanly discarding the const is the easiest * thing to do. */ u.konst = src; /* * Look up IPv4 and IPv4 mapped/compatible addresses. */ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) || (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) || (af == AF_INET)) { const unsigned char *cp = src; if (af == AF_INET6) cp += 12; n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == LWRES_R_SUCCESS) (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == LWRES_R_SUCCESS) n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4, INADDRSZ, cp, &by); if (n != LWRES_R_SUCCESS) { lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); if (n == LWRES_R_NOTFOUND) *error_num = HOST_NOT_FOUND; else *error_num = NO_RECOVERY; return (NULL); } he1 = hostfromaddr(by, AF_INET, cp); lwres_gnbaresponse_free(lwrctx, &by); lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); if (af != AF_INET6) return (he1); /* * Convert from AF_INET to AF_INET6. */ he2 = copyandmerge(he1, NULL, af, error_num); lwres_freehostent(he1); if (he2 == NULL) return (NULL); /* * Restore original address. */ memcpy(he2->h_addr, src, len); return (he2); } /* * Lookup IPv6 address. */ if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) { *error_num = HOST_NOT_FOUND; return (NULL); } n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == LWRES_R_SUCCESS) (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == LWRES_R_SUCCESS) n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ, src, &by); if (n != 0) { lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); if (n == LWRES_R_NOTFOUND) *error_num = HOST_NOT_FOUND; else *error_num = NO_RECOVERY; return (NULL); } he1 = hostfromaddr(by, AF_INET6, src); lwres_gnbaresponse_free(lwrctx, &by); if (he1 == NULL) *error_num = NO_RECOVERY; lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); return (he1); }
struct hostent * lwres_getipnodebyname(const char *name, int af, int flags, int *error_num) { int have_v4 = 1, have_v6 = 1; struct in_addr in4; struct in6_addr in6; struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL; int v4 = 0, v6 = 0; int tmp_err = 0; lwres_context_t *lwrctx = NULL; lwres_gabnresponse_t *by = NULL; int n; /* * If we care about active interfaces then check. */ if ((flags & AI_ADDRCONFIG) != 0) if (scan_interfaces(&have_v4, &have_v6) == -1) { *error_num = NO_RECOVERY; return (NULL); } /* Check for literal address. */ if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1) v6 = lwres_net_pton(AF_INET6, name, &in6); /* * Impossible combination? */ if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || (af == AF_INET && v6 == 1) || (have_v4 == 0 && v4 == 1) || (have_v6 == 0 && v6 == 1) || (have_v4 == 0 && af == AF_INET) || (have_v6 == 0 && af == AF_INET6 && (((flags & AI_V4MAPPED) != 0 && have_v4) || (flags & AI_V4MAPPED) == 0))) { *error_num = HOST_NOT_FOUND; return (NULL); } /* * Literal address? */ if (v4 == 1 || v6 == 1) { char *addr_list[2]; char *aliases[1]; char mappedname[sizeof("::ffff:123.123.123.123")]; union { const char *const_name; char *deconst_name; } u; u.const_name = name; if (v4 == 1 && af == AF_INET6) { strcpy(mappedname, "::ffff:"); lwres_net_ntop(AF_INET, (char *)&in4, mappedname + sizeof("::ffff:") - 1, sizeof(mappedname) - sizeof("::ffff:") + 1); he.h_name = mappedname; } else he.h_name = u.deconst_name; he.h_addr_list = addr_list; he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; he.h_addr_list[1] = NULL; he.h_aliases = aliases; he.h_aliases[0] = NULL; he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; return (copyandmerge(&he, NULL, af, error_num)); } n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n != 0) { *error_num = NO_RECOVERY; goto cleanup; } (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); tmp_err = NO_RECOVERY; if (have_v6 && af == AF_INET6) { n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by); if (n == 0) { he1 = hostfromname(by, AF_INET6); lwres_gabnresponse_free(lwrctx, &by); if (he1 == NULL) { *error_num = NO_RECOVERY; goto cleanup; } } else { if (n == LWRES_R_NOTFOUND) tmp_err = HOST_NOT_FOUND; else { *error_num = NO_RECOVERY; goto cleanup; } } } if (have_v4 && ((af == AF_INET) || (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && (he1 == NULL || (flags & AI_ALL) != 0)))) { n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by); if (n == 0) { he2 = hostfromname(by, AF_INET); lwres_gabnresponse_free(lwrctx, &by); if (he2 == NULL) { *error_num = NO_RECOVERY; goto cleanup; } } else if (he1 == NULL) { if (n == LWRES_R_NOTFOUND) *error_num = HOST_NOT_FOUND; else *error_num = NO_RECOVERY; goto cleanup; } } else *error_num = tmp_err; he3 = copyandmerge(he1, he2, af, error_num); cleanup: if (he1 != NULL) lwres_freehostent(he1); if (he2 != NULL) lwres_freehostent(he2); if (lwrctx != NULL) { lwres_conf_clear(lwrctx); lwres_context_destroy(&lwrctx); } return (he3); }
/* * AI_V4MAPPED + AF_INET6 * If no IPv6 address then a query for IPv4 and map returned values. * * AI_ALL + AI_V4MAPPED + AF_INET6 * Return IPv6 and IPv4 mapped. * * AI_ADDRCONFIG * Only return IPv6 / IPv4 address if there is an interface of that * type active. */ struct hostent * W32_CALL getipnodebyname (const char *name, int af, int flags, int *error) { struct hostent *he1 = NULL; struct hostent *he2 = NULL; struct in_addr in4; struct in6_addr in6; BOOL have_v4 = TRUE, have_v6 = TRUE; BOOL v4 = FALSE, v6 = FALSE; int tmp_err; SOCK_DEBUGF (("\ngetipnodebyname: %s ", name)); /* If we care about active interfaces then check. */ if (flags & AI_ADDRCONFIG) scan_interface (&have_v4, &have_v6); /* Check for literal address. */ v4 = inet_pton (AF_INET, name, &in4); if (!v4) v6 = inet_pton (AF_INET6, name, &in6); /* Impossible combination? */ if ((af == AF_INET6 && !(flags & AI_V4MAPPED) && v4) || (af == AF_INET && v6) || (!have_v4 && v4) || (!have_v6 && v6) || (!have_v4 && af == AF_INET) || ((!have_v6 && af == AF_INET6) && ((flags & AI_V4MAPPED) && have_v4)) || !(flags & AI_V4MAPPED)) { *error = HOST_NOT_FOUND; return (NULL); } /* Literal address? */ if (v4 || v6) { struct hostent he; char *addr_list[2]; char *aliases[1]; he.h_name = (char*) name; he.h_addr_list = addr_list; he.h_addr_list[0] = (v4 ? (char*)&in4 : (char*)&in6); he.h_addr_list[1] = NULL; he.h_aliases = aliases; he.h_aliases[0] = NULL; he.h_length = (v4 ? INADDRSZ : IN6ADDRSZ); he.h_addrtype = (v4 ? AF_INET : AF_INET6); return copyandmerge (&he, NULL, af, error); } tmp_err = NO_RECOVERY; if (have_v6 && af == AF_INET6) { #if defined(USE_IPV6) he1 = gethostbyname6 (name); #else he1 = NULL; #endif if (!he1) tmp_err = HOST_NOT_FOUND; } if (have_v4 && (af == AF_INET || (af == AF_INET6 && (flags & AI_V4MAPPED) && (!he1 || (flags & AI_ALL))))) { SOCK_ENTER_SCOPE(); he2 = gethostbyname (name); SOCK_LEAVE_SCOPE(); if (!he2 || !he1) { *error = HOST_NOT_FOUND; return (NULL); } } else *error = tmp_err; return copyandmerge (he1, he2, af, error); }
struct hostent * W32_CALL getipnodebyaddr (const void *src, size_t len, int af, int *error) { struct hostent *he1, *he2; const BYTE *cp = (const BYTE*) src; SOCK_DEBUGF (("\ngetipnodebyaddr: ")); if (!src) { *error = NO_RECOVERY; return (NULL); } switch (af) { case AF_INET: if (len < INADDRSZ) { *error = NO_RECOVERY; return (NULL); } break; #if defined(USE_IPV6) case AF_INET6: if (len < IN6ADDRSZ) { *error = NO_RECOVERY; return (NULL); } break; #endif default: *error = NO_RECOVERY; return (NULL); } /* Look up IPv4 and IPv4 mapped/compatible addresses. */ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(cp)) || (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(cp)) || (af == AF_INET)) { if (af == AF_INET6) cp += 12; SOCK_ENTER_SCOPE(); he1 = gethostbyaddr ((const char*)cp, 4, AF_INET); SOCK_LEAVE_SCOPE(); if (af == AF_INET) goto ret_copy; /* Convert from AF_INET to AF_INET6. */ he2 = copyandmerge (he1, NULL, af, error); if (he2) { memcpy (he2->h_addr, src, len); /* Restore original address */ SOCK_DEBUGF (("%s", af == AF_INET ? inet_ntoa(*(struct in_addr*)&he2->h_addr) : _inet6_ntoa(he2->h_addr))); } return (he2); } he1 = gethostbyaddr (src, len, AF_INET6); /* Lookup IPv6 address */ ret_copy: if (!he1) { *error = HOST_NOT_FOUND; return (NULL); } return copyandmerge (he1, NULL, af, error); }
struct hostent * getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { struct hostent *he1, *he2; struct net_data *net_data = init(); /* Sanity Checks. */ if (src == NULL) { *error_num = NO_RECOVERY; return (NULL); } switch (af) { case AF_INET: if (len != (size_t)INADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; case AF_INET6: if (len != (size_t)IN6ADDRSZ) { *error_num = NO_RECOVERY; return (NULL); } break; default: *error_num = NO_RECOVERY; return (NULL); } /* * Lookup IPv4 and IPv4 mapped/compatible addresses */ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || (af == AF_INET)) { const char *cp = src; if (af == AF_INET6) cp += 12; he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data); if (he1 == NULL) { *error_num = net_data->res->res_h_errno; return (NULL); } he2 = copyandmerge(he1, NULL, af, error_num); if (he2 == NULL) return (NULL); /* * Restore original address if mapped/compatible. */ if (af == AF_INET6) memcpy(he1->h_addr, src, len); return (he2); } /* * Lookup IPv6 address. */ if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { *error_num = HOST_NOT_FOUND; return (NULL); } he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data); if (he1 == NULL) { *error_num = net_data->res->res_h_errno; return (NULL); } return (copyandmerge(he1, NULL, af, error_num)); }
struct hostent * getipnodebyname(const char *name, int af, int flags, int *error_num) { int have_v4 = 1, have_v6 = 1; struct in_addr in4; struct in6_addr in6; struct hostent he, *he1 = NULL, *he2 = NULL, *he3; int v4 = 0, v6 = 0; struct net_data *net_data = init(); u_long options; int tmp_err; if (net_data == NULL) { *error_num = NO_RECOVERY; return (NULL); } /* If we care about active interfaces then check. */ if ((flags & AI_ADDRCONFIG) != 0) if (scan_interfaces(&have_v4, &have_v6) == -1) { *error_num = NO_RECOVERY; return (NULL); } /* Check for literal address. */ if ((v4 = inet_pton(AF_INET, name, &in4)) != 1) v6 = inet_pton(AF_INET6, name, &in6); /* Impossible combination? */ if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || (af == AF_INET && v6 == 1) || (have_v4 == 0 && v4 == 1) || (have_v6 == 0 && v6 == 1) || (have_v4 == 0 && af == AF_INET) || (have_v6 == 0 && af == AF_INET6)) { *error_num = HOST_NOT_FOUND; return (NULL); } /* Literal address? */ if (v4 == 1 || v6 == 1) { char *addr_list[2]; char *aliases[1]; DE_CONST(name, he.h_name); he.h_addr_list = addr_list; he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; he.h_addr_list[1] = NULL; he.h_aliases = aliases; he.h_aliases[0] = NULL; he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; return (copyandmerge(&he, NULL, af, error_num)); } options = net_data->res->options; net_data->res->options &= ~RES_USE_INET6; tmp_err = NO_RECOVERY; if (have_v6 && af == AF_INET6) { he2 = gethostbyname2_p(name, AF_INET6, net_data); if (he2 != NULL) { he1 = copyandmerge(he2, NULL, af, error_num); if (he1 == NULL) return (NULL); he2 = NULL; } else { tmp_err = net_data->res->res_h_errno; } } if (have_v4 && ((af == AF_INET) || (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && (he1 == NULL || (flags & AI_ALL) != 0)))) { he2 = gethostbyname2_p(name, AF_INET, net_data); if (he1 == NULL && he2 == NULL) { *error_num = net_data->res->res_h_errno; return (NULL); } } else *error_num = tmp_err; net_data->res->options = options; he3 = copyandmerge(he1, he2, af, error_num); if (he1 != NULL) freehostent(he1); return (he3); }