Exemple #1
0
/*
 * 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;
}
Exemple #3
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);
    }
}
Exemple #4
0
/*
 * 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;
}