struct async *
gethostbyaddr_async(const void *addr, socklen_t len, int af, struct asr *asr)
{
	struct asr_ctx	*ac;
	struct async	*as;

	ac = asr_use_resolver(asr);
	as = gethostbyaddr_async_ctx(addr, len, af, ac);
	asr_ctx_unref(ac);

	return (as);
}
Exemple #2
0
static int
getnameinfo_async_run(struct asr_query *as, struct asr_result *ar)
{
	void		*addr;
	socklen_t	 addrlen;
	int		 r;

    next:
	switch (as->as_state) {

	case ASR_STATE_INIT:

		/* Make sure the parameters are all valid. */

		if (as->as.ni.sa.sa.sa_family != AF_INET &&
		    as->as.ni.sa.sa.sa_family != AF_INET6) {
			ar->ar_gai_errno = EAI_FAMILY;
			async_set_state(as, ASR_STATE_HALT);
			break;
		}

		if ((as->as.ni.sa.sa.sa_family == AF_INET &&
		    (SA_LEN(&as->as.ni.sa.sa) != sizeof (as->as.ni.sa.sain))) ||
		    (as->as.ni.sa.sa.sa_family == AF_INET6 &&
		    (SA_LEN(&as->as.ni.sa.sa) != sizeof (as->as.ni.sa.sain6)))) {
			ar->ar_gai_errno = EAI_FAIL;
			async_set_state(as, ASR_STATE_HALT);
			break;
		}

		/* Set the service name first, if needed. */
		if (_servname(as) == -1) {
			ar->ar_gai_errno = EAI_OVERFLOW;
			async_set_state(as, ASR_STATE_HALT);
			break;
		}

		if (as->as.ni.hostname == NULL || as->as.ni.hostnamelen == 0) {
			ar->ar_gai_errno = 0;
			async_set_state(as, ASR_STATE_HALT);
			break;
		}

		if (as->as.ni.flags & NI_NUMERICHOST) {
			if (_numerichost(as) == -1) {
				if (errno == ENOMEM)
					ar->ar_gai_errno = EAI_MEMORY;
				else if (errno == ENOSPC)
					ar->ar_gai_errno = EAI_OVERFLOW;
				else {
					ar->ar_errno = errno;
					ar->ar_gai_errno = EAI_SYSTEM;
				}
			} else
				ar->ar_gai_errno = 0;
			async_set_state(as, ASR_STATE_HALT);
			break;
		}

		if (as->as.ni.sa.sa.sa_family == AF_INET) {
			addrlen = sizeof(as->as.ni.sa.sain.sin_addr);
			addr = &as->as.ni.sa.sain.sin_addr;
		} else {
			addrlen = sizeof(as->as.ni.sa.sain6.sin6_addr);
			addr = &as->as.ni.sa.sain6.sin6_addr;
		}

		/*
		 * Create a subquery to lookup the address.
		 */
		as->as.ni.subq = gethostbyaddr_async_ctx(addr, addrlen,
		    as->as.ni.sa.sa.sa_family,
		    as->as_ctx);
		if (as->as.ni.subq == NULL) {
			ar->ar_gai_errno = EAI_MEMORY;
			async_set_state(as, ASR_STATE_HALT);
			break;
		}

		async_set_state(as, ASR_STATE_SUBQUERY);
		break;

	case ASR_STATE_SUBQUERY:

		if ((r = asr_run(as->as.ni.subq, ar)) == ASYNC_COND)
			return (ASYNC_COND);

		/*
		 * Request done.
		 */
		as->as.ni.subq = NULL;

		if (ar->ar_hostent == NULL) {
			if (as->as.ni.flags & NI_NAMEREQD) {
				ar->ar_gai_errno = EAI_NONAME;
			} else if (_numerichost(as) == -1) {
				if (errno == ENOMEM)
					ar->ar_gai_errno = EAI_MEMORY;
				else if (errno == ENOSPC)
					ar->ar_gai_errno = EAI_OVERFLOW;
				else {
					ar->ar_errno = errno;
					ar->ar_gai_errno = EAI_SYSTEM;
				}
			} else
				ar->ar_gai_errno = 0;
		} else {
			if (strlcpy(as->as.ni.hostname,
			    ar->ar_hostent->h_name,
			    as->as.ni.hostnamelen) >= as->as.ni.hostnamelen)
				ar->ar_gai_errno = EAI_OVERFLOW;
			else
				ar->ar_gai_errno = 0;
			free(ar->ar_hostent);
		}

		async_set_state(as, ASR_STATE_HALT);
		break;

	case ASR_STATE_HALT:
		return (ASYNC_DONE);

	default:
		ar->ar_errno = EOPNOTSUPP;
		ar->ar_gai_errno = EAI_SYSTEM;
		async_set_state(as, ASR_STATE_HALT);
		break;
	}
	goto next;
}