summaryrefslogtreecommitdiffstats
path: root/lib/libc/asr/hostaddr_async.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/asr/hostaddr_async.c')
-rw-r--r--lib/libc/asr/hostaddr_async.c442
1 files changed, 0 insertions, 442 deletions
diff --git a/lib/libc/asr/hostaddr_async.c b/lib/libc/asr/hostaddr_async.c
deleted file mode 100644
index 8688d3a47fd..00000000000
--- a/lib/libc/asr/hostaddr_async.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/* $OpenBSD: hostaddr_async.c,v 1.4 2012/09/05 16:52:05 eric Exp $ */
-/*
- * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-
-#include <arpa/nameser.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "asr.h"
-#include "asr_private.h"
-
-static int hostaddr_async_run(struct async *, struct async_res *);
-static int addrinfo_add(struct async *, int, const void *, size_t, const char *);
-static int addrinfo_from_file(struct async *, int, FILE *);
-static int addrinfo_from_pkt(struct async *, char *, size_t);
-#ifdef YP
-static int addrinfo_from_yp(struct async *, int, char *);
-#endif
-
-/*
- * This API function allows to iterate over host addresses, for the given
- * family which, must be AF_INET, AF_INET6, or AF_UNSPEC (in which case
- * the family lookup list from the resolver is used). The strategy is to
- * return all addresses found for the first DB that returned at least one
- * address.
- *
- * Flags can be 0, or one of AI_CANONNAME or AI_FQDN. If set, the
- * canonical name will be returned along with the address.
- */
-struct async *
-hostaddr_async_ctx(const char *name, int family, int flags, struct asr_ctx *ac)
-{
- struct async *as;
- char buf[MAXDNAME];
-
-#ifdef DEBUG
- asr_printf("asr: hostaddr_async_ctx(\"%s\", %i)\n", name, family);
-#endif
- if (asr_domcat(name, NULL, buf, sizeof buf) == 0) {
- errno = EINVAL;
- return (NULL);
- }
-
- if ((as = async_new(ac, ASR_HOSTADDR)) == NULL)
- goto err; /* errno set */
- as->as_run = hostaddr_async_run;
-
- as->as.ai.hints.ai_flags = flags;
- as->as.ai.hints.ai_family = family;
- as->as.ai.hostname = strdup(buf);
- if (as->as.ai.hostname == NULL)
- goto err; /* errno set */
-
- return (as);
- err:
- if (as)
- async_free(as);
- return (NULL);
-}
-
-static int
-hostaddr_async_run(struct async *as, struct async_res *ar)
-{
-#ifdef YP
- static char *domain = NULL;
- char *res;
- int len;
-#endif
- char *name;
- int family, type, r;
- FILE *file;
-
- next:
- switch(as->as_state) {
-
- case ASR_STATE_INIT:
-
- if (as->as.ai.hints.ai_family != AF_INET &&
- as->as.ai.hints.ai_family != AF_INET6 &&
- as->as.ai.hints.ai_family != AF_UNSPEC) {
- ar->ar_gai_errno = EAI_FAMILY;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
-
- as->as_count = 0;
- as->as_db_idx = 0;
- async_set_state(as, ASR_STATE_NEXT_DB);
- break;
-
- case ASR_STATE_NEXT_FAMILY:
-
- as->as_family_idx += 1;
- if (as->as.ai.hints.ai_family != AF_UNSPEC ||
- AS_FAMILY(as) == -1) {
- /* The family was specified, or we have tried all
- * families with this DB.
- */
- if (as->as_count) {
- ar->ar_gai_errno = 0;
- async_set_state(as, ASR_STATE_HALT);
- } else
- async_set_state(as, ASR_STATE_NEXT_DB);
- break;
- }
-
- async_set_state(as, ASR_STATE_LOOKUP_FAMILY);
- break;
-
- case ASR_STATE_LOOKUP_FAMILY:
- async_set_state(as, ASR_STATE_SAME_DB);
- break;
-
- case ASR_STATE_NEXT_DB:
- if (asr_iter_db(as) == -1) {
- async_set_state(as, ASR_STATE_NOT_FOUND);
- break;
- }
- as->as_family_idx = 0;
- /* FALLTHROUGH */
-
- case ASR_STATE_SAME_DB:
- /* query the current DB again. */
- switch(AS_DB(as)) {
- case ASR_DB_DNS:
- family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
- AS_FAMILY(as) : as->as.ai.hints.ai_family;
- type = (family == AF_INET6) ? T_AAAA : T_A;
- name = as->as.ai.hostname;
- as->as.ai.subq = res_query_async_ctx(name, C_IN,
- type, NULL, 0, as->as_ctx);
- if (as->as.ai.subq == NULL) {
- if (errno == ENOMEM)
- ar->ar_gai_errno = EAI_MEMORY;
- else
- ar->ar_gai_errno = EAI_FAIL;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
- async_set_state(as, ASR_STATE_SUBQUERY);
- break;
-
- case ASR_DB_FILE:
- file = fopen(as->as_ctx->ac_hostfile, "r");
- if (file == NULL) {
- async_set_state(as, ASR_STATE_NEXT_DB);
- break;
- }
- family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
- AS_FAMILY(as) : as->as.ai.hints.ai_family;
-
- r = addrinfo_from_file(as, family, file);
- if (r == -1) {
- if (errno == ENOMEM)
- ar->ar_gai_errno = EAI_MEMORY;
- else
- ar->ar_gai_errno = EAI_FAIL;
- async_set_state(as, ASR_STATE_HALT);
- } else
- async_set_state(as, ASR_STATE_NEXT_FAMILY);
- fclose(file);
- break;
-
-#ifdef YP
- case ASR_DB_YP:
- if (!domain && _yp_check(&domain) == 0) {
- async_set_state(as, ASR_STATE_NEXT_DB);
- break;
- }
- family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
- AS_FAMILY(as) : as->as.ai.hints.ai_family;
- /* XXX
- * ipnodes.byname could also contain IPv4 address
- */
- name = (family == AF_INET6) ?
- "ipnodes.byname" : "hosts.byname";
- r = yp_match(domain, name, as->as.ai.hostname,
- strlen(as->as.ai.hostname), &res, &len);
- if (r == 0) {
- r = addrinfo_from_yp(as, family, res);
- free(res);
- if (r == -1) {
- if (errno == ENOMEM)
- ar->ar_gai_errno = EAI_MEMORY;
- else
- ar->ar_gai_errno = EAI_FAIL;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
- }
- async_set_state(as, ASR_STATE_NEXT_FAMILY);
- break;
-#endif
-
- default:
- async_set_state(as, ASR_STATE_NEXT_DB);
- }
- break;
-
- case ASR_STATE_SUBQUERY:
- if ((r = async_run(as->as.ai.subq, ar)) == ASYNC_COND)
- return (ASYNC_COND);
- as->as.ai.subq = NULL;
-
- if (ar->ar_datalen == -1) {
- async_set_state(as, ASR_STATE_NEXT_DB);
- break;
- }
-
- r = addrinfo_from_pkt(as, ar->ar_data, ar->ar_datalen);
- if (r == -1) {
- if (errno == ENOMEM)
- ar->ar_gai_errno = EAI_MEMORY;
- else
- ar->ar_gai_errno = EAI_FAIL;
- async_set_state(as, ASR_STATE_HALT);
- } else
- async_set_state(as, ASR_STATE_NEXT_FAMILY);
- free(ar->ar_data);
- break;
-
- case ASR_STATE_NOT_FOUND:
- /* XXX the exact error depends on what query/send returned */
- ar->ar_gai_errno = EAI_NODATA;
- async_set_state(as, ASR_STATE_HALT);
- break;
-
- case ASR_STATE_HALT:
- if (ar->ar_gai_errno == 0) {
- ar->ar_count = as->as_count;
- ar->ar_addrinfo = as->as.ai.aifirst;
- as->as.ai.aifirst = NULL;
- } else {
- ar->ar_count = 0;
- ar->ar_addrinfo = NULL;
- }
- return (ASYNC_DONE);
-
- default:
- ar->ar_errno = EOPNOTSUPP;
- ar->ar_gai_errno = EAI_SYSTEM;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
- goto next;
-}
-
-static int
-addrinfo_add(struct async *as, int family, const void *addr, size_t addrlen,
- const char *name)
-{
- struct addrinfo *ai;
-
- if ((ai = calloc(1, sizeof (*ai) + addrlen)) == NULL)
- return (-1);
-
- ai->ai_family = family;
- ai->ai_addrlen = addrlen;
- ai->ai_addr = (void*)(ai + 1);
- if (name && (ai->ai_canonname = strdup(name)) == NULL) {
- free(ai);
- return (-1);
- }
- memmove(ai->ai_addr, addr, addrlen);
-
- if (!as->as.ai.aifirst)
- as->as.ai.aifirst = ai;
- if (as->as.ai.ailast)
- as->as.ai.ailast->ai_next = ai;
- as->as.ai.ailast = ai;
- as->as_count += 1;
-
- return (0);
-}
-
-static int
-addrinfo_from_file(struct async *as, int family, FILE *f)
-{
- char *tokens[MAXTOKEN], *c;
- int n, i;
- union {
- struct sockaddr sa;
- struct sockaddr_in sain;
- struct sockaddr_in6 sain6;
- } u;
-
- for(;;) {
- n = asr_parse_namedb_line(f, tokens, MAXTOKEN);
- if (n == -1)
- break; /* ignore errors reading the file */
-
- for (i = 1; i < n; i++) {
- if (strcasecmp(as->as.ai.hostname, tokens[i]))
- continue;
- if (sockaddr_from_str(&u.sa, family, tokens[0]) == -1)
- continue;
- break;
- }
- if (i == n)
- continue;
-
- if (as->as.ai.hints.ai_flags & AI_CANONNAME)
- c = tokens[1];
- else if (as->as.ai.hints.ai_flags & AI_FQDN)
- c = as->as.ai.hostname;
- else
- c = NULL;
-
- if (addrinfo_add(as, u.sa.sa_family, &u.sa, u.sa.sa_len, c))
- return (-1); /* errno set */
- }
- return (0);
-}
-
-static int
-addrinfo_from_pkt(struct async *as, char *pkt, size_t pktlen)
-{
- struct packed p;
- struct header h;
- struct query q;
- struct rr rr;
- int i;
- union {
- struct sockaddr sa;
- struct sockaddr_in sain;
- struct sockaddr_in6 sain6;
- } u;
- char buf[MAXDNAME], *c;
-
- packed_init(&p, pkt, pktlen);
- unpack_header(&p, &h);
- for(; h.qdcount; h.qdcount--)
- unpack_query(&p, &q);
-
- for (i = 0; i < h.ancount; i++) {
- unpack_rr(&p, &rr);
- if (rr.rr_type != q.q_type ||
- rr.rr_class != q.q_class)
- continue;
-
- memset(&u, 0, sizeof u);
- if (rr.rr_type == T_A) {
- u.sain.sin_len = sizeof u.sain;
- u.sain.sin_family = AF_INET;
- u.sain.sin_addr = rr.rr.in_a.addr;
- u.sain.sin_port = 0;
- } else if (rr.rr_type == T_AAAA) {
- u.sain6.sin6_len = sizeof u.sain6;
- u.sain6.sin6_family = AF_INET6;
- u.sain6.sin6_addr = rr.rr.in_aaaa.addr6;
- u.sain6.sin6_port = 0;
- } else
- continue;
-
- if (as->as.ai.hints.ai_flags & AI_CANONNAME) {
- asr_strdname(rr.rr_dname, buf, sizeof buf);
- buf[strlen(buf) - 1] = '\0';
- c = buf;
- } else if (as->as.ai.hints.ai_flags & AI_FQDN)
- c = as->as.ai.hostname;
- else
- c = NULL;
-
- if (addrinfo_add(as, u.sa.sa_family, &u.sa, u.sa.sa_len, c))
- return (-1); /* errno set */
- }
- return (0);
-}
-
-#ifdef YP
-static int
-strsplit(char *line, char **tokens, int ntokens)
-{
- int ntok;
- char *cp, **tp;
-
- for(cp = line, tp = tokens, ntok = 0;
- ntok < ntokens && (*tp = strsep(&cp, " \t")) != NULL; )
- if (**tp != '\0') {
- tp++;
- ntok++;
- }
-
- return (ntok);
-}
-
-static int
-addrinfo_from_yp(struct async *as, int family, char *line)
-{
- char *next, *tokens[MAXTOKEN], *c;
- int i, ntok;
- union {
- struct sockaddr sa;
- struct sockaddr_in sain;
- struct sockaddr_in6 sain6;
- } u;
-
- for(next = line; line; line = next) {
- if ((next = strchr(line, '\n'))) {
- *next = '\0';
- next += 1;
- }
- ntok = strsplit(line, tokens, MAXTOKEN);
- if (ntok < 2)
- continue;
-
- if (sockaddr_from_str(&u.sa, family, tokens[0]) == -1)
- continue;
-
- if (as->as.ai.hints.ai_flags & AI_CANONNAME)
- c = tokens[1];
- else if (as->as.ai.hints.ai_flags & AI_FQDN)
- c = as->as.ai.hostname;
- else
- c = NULL;
-
- if (addrinfo_add(as, u.sa.sa_family, &u.sa, u.sa.sa_len, c))
- return (-1); /* errno set */
- }
- return (0);
-}
-#endif