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); }
/* * Resume the "as" async query resolution. Return one of ASYNC_COND, * or ASYNC_DONE and put query-specific return values in the user-allocated * memory at "ar". */ int asr_run(struct asr_query *as, struct asr_result *ar) { int r, saved_errno = errno; DPRINT("asr: asr_run(%p, %p) %s ctx=[%p]\n", as, ar, _asr_querystr(as->as_type), as->as_ctx); r = as->as_run(as, ar); DPRINT("asr: asr_run(%p, %p) -> %s", as, ar, _asr_transitionstr(r)); #ifdef DEBUG if (r == ASYNC_COND) #endif DPRINT(" fd=%i timeout=%i", ar->ar_fd, ar->ar_timeout); DPRINT("\n"); if (r == ASYNC_DONE) _asr_async_free(as); errno = saved_errno; return (r); }
struct asr_query * _gethostbyaddr_async_ctx(const void *addr, socklen_t len, int af, struct asr_ctx *ac) { struct asr_query *as; if ((as = _asr_async_new(ac, ASR_GETHOSTBYADDR)) == NULL) goto abort; /* errno set */ as->as_run = gethostnamadr_async_run; as->as.hostnamadr.family = af; as->as.hostnamadr.addrlen = len; if (len > 0) memmove(as->as.hostnamadr.addr, addr, (len > 16) ? 16 : len); return (as); abort: if (as) _asr_async_free(as); return (NULL); }
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); }
/* * 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); }
/* * Cancel an async query. */ void asr_abort(struct asr_query *as) { _asr_async_free(as); }