/* * Convert an ipv4 address to a hostname. * * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV * It will never resolv a hostname. * - No IPv6 support. */ int getnameinfo(const struct sockaddr * sa, int salen, char *node, int nodelen, char *service, int servicelen, int flags) { #if defined(WIN32) && !defined(WIN32_CLIENT_ONLY) /* * If Windows has native IPv6 support, use the native Windows routine. * Otherwise, fall through and use our own code. */ if (haveNativeWindowsIPv6routines()) return (*getnameinfo_ptr) (sa, salen, node, nodelen, service, servicelen, flags); #endif /* Invalid arguments. */ if (sa == NULL || (node == NULL && service == NULL)) return EAI_FAIL; /* We don't support those. */ if ((node && !(flags & NI_NUMERICHOST)) || (service && !(flags & NI_NUMERICSERV))) return EAI_FAIL; #ifdef HAVE_IPV6 if (sa->sa_family == AF_INET6) return EAI_FAMILY; #endif if (node) { int ret = -1; if (sa->sa_family == AF_INET) { char *p; p = inet_ntoa(((struct sockaddr_in *) sa)->sin_addr); ret = snprintf(node, nodelen, "%s", p); } if (ret == -1 || ret > nodelen) return EAI_MEMORY; } if (service) { int ret = -1; if (sa->sa_family == AF_INET) { ret = snprintf(service, servicelen, "%d", ntohs(((struct sockaddr_in *) sa)->sin_port)); } if (ret == -1 || ret > servicelen) return EAI_MEMORY; } return 0; }
/* * Convert an ipv4 address to a hostname. * * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV behavior. * It will never resolve a hostname. * - No IPv6 support. */ int getnameinfo(const struct sockaddr * sa, int salen, char *node, int nodelen, char *service, int servicelen, int flags) { #ifdef WIN32 /* * If Windows has native IPv6 support, use the native Windows routine. * Otherwise, fall through and use our own code. */ if (haveNativeWindowsIPv6routines()) return (*getnameinfo_ptr) (sa, salen, node, nodelen, service, servicelen, flags); #endif /* Invalid arguments. */ if (sa == NULL || (node == NULL && service == NULL)) return EAI_FAIL; #ifdef HAVE_IPV6 if (sa->sa_family == AF_INET6) return EAI_FAMILY; #endif /* Unsupported flags. */ if (flags & NI_NAMEREQD) return EAI_AGAIN; if (node) { if (sa->sa_family == AF_INET) { if (inet_net_ntop(AF_INET, &((struct sockaddr_in *) sa)->sin_addr, sa->sa_family == AF_INET ? 32 : 128, node, nodelen) == NULL) return EAI_MEMORY; } else return EAI_MEMORY; } if (service) { int ret = -1; if (sa->sa_family == AF_INET) { ret = snprintf(service, servicelen, "%d", ntohs(((struct sockaddr_in *) sa)->sin_port)); } if (ret == -1 || ret >= servicelen) return EAI_MEMORY; } return 0; }
void freeaddrinfo(struct addrinfo * res) { if (res) { #ifdef WIN32 /* * If Windows has native IPv6 support, use the native Windows routine. * Otherwise, fall through and use our own code. */ if (haveNativeWindowsIPv6routines()) { (*freeaddrinfo_ptr) (res); return; } #endif if (res->ai_addr) free(res->ai_addr); free(res); } }
/* * get address info for ipv4 sockets. * * Bugs: - only one addrinfo is set even though hintp is NULL or * ai_socktype is 0 * - AI_CANONNAME is not supported. * - servname can only be a number, not text. */ int getaddrinfo(const char *node, const char *service, const struct addrinfo * hintp, struct addrinfo ** res) { struct addrinfo *ai; struct sockaddr_in sin, *psin; struct addrinfo hints; #ifdef WIN32 /* * If Windows has native IPv6 support, use the native Windows routine. * Otherwise, fall through and use our own code. */ if (haveNativeWindowsIPv6routines()) return (*getaddrinfo_ptr) (node, service, hintp, res); #endif if (hintp == NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; } else memcpy(&hints, hintp, sizeof(hints)); if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) return EAI_FAMILY; if (hints.ai_socktype == 0) hints.ai_socktype = SOCK_STREAM; if (!node && !service) return EAI_NONAME; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; if (node) { if (node[0] == '\0') sin.sin_addr.s_addr = htonl(INADDR_ANY); else if (hints.ai_flags & AI_NUMERICHOST) { if (!inet_aton(node, &sin.sin_addr)) return EAI_FAIL; } else { struct hostent *hp; #ifdef FRONTEND struct hostent hpstr; char buf[BUFSIZ]; int herrno = 0; pqGethostbyname(node, &hpstr, buf, sizeof(buf), &hp, &herrno); #else hp = gethostbyname(node); #endif if (hp == NULL) { switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: return EAI_NONAME; case TRY_AGAIN: return EAI_AGAIN; case NO_RECOVERY: default: return EAI_FAIL; } } if (hp->h_addrtype != AF_INET) return EAI_FAIL; memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length); } } else { if (hints.ai_flags & AI_PASSIVE) sin.sin_addr.s_addr = htonl(INADDR_ANY); else sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); } if (service) sin.sin_port = htons((unsigned short) atoi(service)); #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN sin.sin_len = sizeof(sin); #endif ai = malloc(sizeof(*ai)); if (!ai) return EAI_MEMORY; psin = malloc(sizeof(*psin)); if (!psin) { free(ai); return EAI_MEMORY; } memcpy(psin, &sin, sizeof(*psin)); ai->ai_flags = 0; ai->ai_family = AF_INET; ai->ai_socktype = hints.ai_socktype; ai->ai_protocol = hints.ai_protocol; ai->ai_addrlen = sizeof(*psin); ai->ai_addr = (struct sockaddr *) psin; ai->ai_canonname = NULL; ai->ai_next = NULL; *res = ai; return 0; }