예제 #1
0
struct asr_query *
gethostbyname2_async(const char *name, int af, void *asr)
{
	struct asr_ctx	 *ac;
	struct asr_query *as;

	/* the original segfaults */
	if (name == NULL) {
		errno = EINVAL;
		return (NULL);
	}

	ac = _asr_use_resolver(asr);
	if ((as = _asr_async_new(ac, ASR_GETHOSTBYNAME)) == NULL)
		goto abort; /* errno set */
	as->as_run = gethostnamadr_async_run;

	as->as.hostnamadr.family = af;
	if (af == AF_INET)
		as->as.hostnamadr.addrlen = INADDRSZ;
	else if (af == AF_INET6)
		as->as.hostnamadr.addrlen = IN6ADDRSZ;
	as->as.hostnamadr.name = strdup(name);
	if (as->as.hostnamadr.name == NULL)
		goto abort; /* errno set */

	_asr_ctx_unref(ac);
	return (as);

    abort:
	if (as)
		_asr_async_free(as);
	_asr_ctx_unref(ac);
	return (NULL);
}
예제 #2
0
struct asr_query *
gethostbyaddr_async(const void *addr, socklen_t len, int af, void *asr)
{
	struct asr_ctx	 *ac;
	struct asr_query *as;

	ac = _asr_use_resolver(asr);
	as = _gethostbyaddr_async_ctx(addr, len, af, ac);
	_asr_ctx_unref(ac);

	return (as);
}
예제 #3
0
struct asr_query *
getaddrinfo_async(const char *hostname, const char *servname,
	const struct addrinfo *hints, void *asr)
{
	struct asr_ctx		*ac;
	struct asr_query	*as;

	if (hints == NULL || (hints->ai_flags & AI_NUMERICHOST) == 0)
		ac = _asr_use_resolver(asr);
	else
		ac = _asr_no_resolver();
	if ((as = _asr_async_new(ac, ASR_GETADDRINFO)) == NULL)
		goto abort; /* errno set */
	as->as_run = getaddrinfo_async_run;

	if (hostname) {
		if ((as->as.ai.hostname = strdup(hostname)) == NULL)
			goto abort; /* errno set */
	}
	if (servname && (as->as.ai.servname = strdup(servname)) == NULL)
		goto abort; /* errno set */
	if (hints)
		memmove(&as->as.ai.hints, hints, sizeof *hints);
	else {
		memset(&as->as.ai.hints, 0, sizeof as->as.ai.hints);
		as->as.ai.hints.ai_family = PF_UNSPEC;
		as->as.ai.hints.ai_flags = AI_ADDRCONFIG;
	}

	_asr_ctx_unref(ac);
	return (as);
    abort:
	if (as)
		_asr_async_free(as);
	_asr_ctx_unref(ac);
	return (NULL);
}
예제 #4
0
/*
 * Free the "asr" async resolver (or the thread-local resolver if NULL).
 * Drop the reference to the current context.
 */
void
_asr_resolver_done(void *arg)
{
	struct asr *asr = arg;
	struct asr **priv;

	if (asr == NULL) {
		priv = _THREAD_PRIVATE(_asr, _asr, &_asr);
		if (*priv == NULL)
			return;
		asr = *priv;
		*priv = NULL;
	}

	_asr_ctx_unref(asr->a_ctx);
	free(asr);
}
예제 #5
0
/*
 * Reload the configuration file if it has changed on disk.
 */
static void
asr_check_reload(struct asr *asr)
{
	struct asr_ctx	*ac;
	struct stat	 st;
	struct timespec	 ts;
	pid_t		 pid;

	pid = getpid();
	if (pid != asr->a_pid) {
		asr->a_pid = pid;
		asr->a_rtime = 0;
	}

	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
		return;

	if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
		return;
	asr->a_rtime = ts.tv_sec;

	DPRINT("asr: checking for update of \"%s\"\n", _PATH_RESCONF);
	if (stat(_PATH_RESCONF, &st) == -1 ||
	    asr->a_mtime == st.st_mtime ||
	    (ac = asr_ctx_create()) == NULL)
		return;
	asr->a_mtime = st.st_mtime;

	DPRINT("asr: reloading config file\n");
	if (asr_ctx_from_file(ac, _PATH_RESCONF) == -1) {
		asr_ctx_free(ac);
		return;
	}

	asr_ctx_envopts(ac);
	if (asr->a_ctx)
		_asr_ctx_unref(asr->a_ctx);
	asr->a_ctx = ac;
}
예제 #6
0
/*
 * Free an async query and unref the associated context.
 */
void
_asr_async_free(struct asr_query *as)
{
	DPRINT("asr: asr_async_free(%p)\n", as);
	switch (as->as_type) {
	case ASR_SEND:
		if (as->as_fd != -1)
			close(as->as_fd);
		if (as->as.dns.obuf && !(as->as.dns.flags & ASYNC_EXTOBUF))
			free(as->as.dns.obuf);
		if (as->as.dns.ibuf)
			free(as->as.dns.ibuf);
		if (as->as.dns.dname)
			free(as->as.dns.dname);
		break;

	case ASR_SEARCH:
		if (as->as.search.subq)
			_asr_async_free(as->as.search.subq);
		if (as->as.search.name)
			free(as->as.search.name);
		break;

	case ASR_GETRRSETBYNAME:
		if (as->as.rrset.subq)
			_asr_async_free(as->as.rrset.subq);
		if (as->as.rrset.name)
			free(as->as.rrset.name);
		break;

	case ASR_GETHOSTBYNAME:
	case ASR_GETHOSTBYADDR:
		if (as->as.hostnamadr.subq)
			_asr_async_free(as->as.hostnamadr.subq);
		if (as->as.hostnamadr.name)
			free(as->as.hostnamadr.name);
		break;

	case ASR_GETNETBYNAME:
	case ASR_GETNETBYADDR:
		if (as->as.netnamadr.subq)
			_asr_async_free(as->as.netnamadr.subq);
		if (as->as.netnamadr.name)
			free(as->as.netnamadr.name);
		break;

	case ASR_GETADDRINFO:
		if (as->as.ai.subq)
			_asr_async_free(as->as.ai.subq);
		if (as->as.ai.aifirst)
			freeaddrinfo(as->as.ai.aifirst);
		if (as->as.ai.hostname)
			free(as->as.ai.hostname);
		if (as->as.ai.servname)
			free(as->as.ai.servname);
		if (as->as.ai.fqdn)
			free(as->as.ai.fqdn);
		break;

	case ASR_GETNAMEINFO:
		if (as->as.ni.subq)
			_asr_async_free(as->as.ni.subq);
		break;
	}

	_asr_ctx_unref(as->as_ctx);
	free(as);
}
예제 #7
0
int
res_init(void)
{
	static void *resinit_mutex;
	struct asr_ctx	*ac;
	int i;

	ac = _asr_use_resolver(NULL);

	/*
	 * The first thread to call res_init() will setup the global _res
	 * structure from the async context, not overriding fields set early
	 * by the user.
	 */
	_MUTEX_LOCK(&resinit_mutex);
	if (!(_res.options & RES_INIT)) {
		if (_res.retry == 0)
			_res.retry = ac->ac_nsretries;
		if (_res.options == 0)
			_res.options = ac->ac_options;
		if (_res.lookups[0] == '\0')
			strlcpy(_res.lookups, ac->ac_db, sizeof(_res.lookups));

		for (i = 0; i < ac->ac_nscount && i < MAXNS; i++) {
			/*
			 * No need to check for length since we copy to a
			 * struct sockaddr_storage with a size of 256 bytes
			 * and sa_len has only 8 bits.
			 */
			memcpy(&_res_ext.nsaddr_list[i], ac->ac_ns[i],
			    ac->ac_ns[i]->sa_len);
			if (ac->ac_ns[i]->sa_len <= sizeof(_res.nsaddr_list[i]))
				memcpy(&_res.nsaddr_list[i], ac->ac_ns[i],
				    ac->ac_ns[i]->sa_len);
			else
				memset(&_res.nsaddr_list[i], 0,
				    sizeof(_res.nsaddr_list[i]));
		}
		_res.nscount = i;
		_res.options |= RES_INIT;
	}
	_MUTEX_UNLOCK(&resinit_mutex);

	/*
	 * If the program is not threaded, we want to reflect (some) changes
	 * made by the user to the global _res structure.
	 * This is a bit of a hack: if there is already an async query on
	 * this context, it might change things in its back.  It is ok
	 * as long as the user only uses the blocking resolver API.
	 * If needed we could consider cloning the context if there is
	 * a running query.
	 */
	if (!__isthreaded) {
		ac->ac_nsretries = _res.retry;
		ac->ac_options = _res.options;
		strlcpy(ac->ac_db, _res.lookups, sizeof(ac->ac_db));
		ac->ac_dbcount = strlen(ac->ac_db);
	}

	_asr_ctx_unref(ac);

	return (0);
}