diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/asr/asr.c | 8 | ||||
-rw-r--r-- | lib/libc/asr/asr_debug.c | 4 | ||||
-rw-r--r-- | lib/libc/asr/asr_private.h | 11 | ||||
-rw-r--r-- | lib/libc/asr/gethostnamadr_async.c | 70 | ||||
-rw-r--r-- | lib/libc/asr/getnetnamadr_async.c | 428 |
5 files changed, 79 insertions, 442 deletions
diff --git a/lib/libc/asr/asr.c b/lib/libc/asr/asr.c index d7546512a46..4c39785fecf 100644 --- a/lib/libc/asr/asr.c +++ b/lib/libc/asr/asr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asr.c,v 1.59 2018/03/13 12:25:34 jca Exp $ */ +/* $OpenBSD: asr.c,v 1.60 2018/04/28 15:16:49 schwarze Exp $ */ /* * Copyright (c) 2010-2012 Eric Faurot <eric@openbsd.org> * @@ -282,12 +282,6 @@ _asr_async_free(struct asr_query *as) free(as->as.hostnamadr.name); break; - case ASR_GETNETBYNAME: - case ASR_GETNETBYADDR: - if (as->as.netnamadr.name) - free(as->as.netnamadr.name); - break; - case ASR_GETADDRINFO: if (as->as.ai.aifirst) freeaddrinfo(as->as.ai.aifirst); diff --git a/lib/libc/asr/asr_debug.c b/lib/libc/asr/asr_debug.c index 1591bd204c1..141517b8360 100644 --- a/lib/libc/asr/asr_debug.c +++ b/lib/libc/asr/asr_debug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asr_debug.c,v 1.24 2017/02/27 11:31:01 jca Exp $ */ +/* $OpenBSD: asr_debug.c,v 1.25 2018/04/28 15:16:49 schwarze Exp $ */ /* * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> * @@ -338,8 +338,6 @@ _asr_querystr(int type) CASE(ASR_GETRRSETBYNAME); CASE(ASR_GETHOSTBYNAME); CASE(ASR_GETHOSTBYADDR); - CASE(ASR_GETNETBYNAME); - CASE(ASR_GETNETBYADDR); CASE(ASR_GETADDRINFO); CASE(ASR_GETNAMEINFO); default: diff --git a/lib/libc/asr/asr_private.h b/lib/libc/asr/asr_private.h index e922017df24..49123a3c246 100644 --- a/lib/libc/asr/asr_private.h +++ b/lib/libc/asr/asr_private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asr_private.h,v 1.46 2017/02/27 11:38:08 jca Exp $ */ +/* $OpenBSD: asr_private.h,v 1.47 2018/04/28 15:16:49 schwarze Exp $ */ /* * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> * @@ -113,8 +113,6 @@ enum async_type { ASR_GETRRSETBYNAME, ASR_GETHOSTBYNAME, ASR_GETHOSTBYADDR, - ASR_GETNETBYNAME, - ASR_GETNETBYADDR, ASR_GETADDRINFO, ASR_GETNAMEINFO, }; @@ -158,6 +156,7 @@ struct asr { #define ASYNC_NODATA 0x00000100 #define ASYNC_AGAIN 0x00000200 +#define ASYNC_GETNET 0x00001000 #define ASYNC_EXTOBUF 0x00002000 #define ASYNC_NO_INET 0x00010000 @@ -230,12 +229,6 @@ struct asr_query { } hostnamadr; struct { - char *name; - int family; - in_addr_t addr; - } netnamadr; - - struct { char *hostname; char *servname; int port_tcp; diff --git a/lib/libc/asr/gethostnamadr_async.c b/lib/libc/asr/gethostnamadr_async.c index ae882c5d78a..1c30c08a0df 100644 --- a/lib/libc/asr/gethostnamadr_async.c +++ b/lib/libc/asr/gethostnamadr_async.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gethostnamadr_async.c,v 1.43 2017/02/23 17:04:02 eric Exp $ */ +/* $OpenBSD: gethostnamadr_async.c,v 1.44 2018/04/28 15:16:49 schwarze Exp $ */ /* * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> * @@ -44,6 +44,13 @@ struct hostent_ext { char *pos; }; +struct netent_ext { + struct netent n; + char *aliases[MAXALIASES + 1]; + char *end; + char *pos; +}; + static int gethostnamadr_async_run(struct asr_query *, struct asr_result *); static struct hostent_ext *hostent_alloc(int); static int hostent_set_cname(struct hostent_ext *, const char *, int); @@ -53,6 +60,7 @@ static struct hostent_ext *hostent_from_addr(int, const char *, const char *); static struct hostent_ext *hostent_file_match(FILE *, int, int, const char *, int); static struct hostent_ext *hostent_from_packet(int, int, char *, size_t); +static void netent_from_hostent(struct asr_result *ar); struct asr_query * gethostbyname_async(const char *name, void *asr) @@ -344,9 +352,13 @@ gethostnamadr_async_run(struct asr_query *as, struct asr_result *ar) break; case ASR_STATE_HALT: - if (ar->ar_h_errno) + if (ar->ar_h_errno == NETDB_SUCCESS && + as->as_flags & ASYNC_GETNET) + netent_from_hostent(ar); + if (ar->ar_h_errno) { ar->ar_hostent = NULL; - else + ar->ar_netent = NULL; + } else ar->ar_errno = 0; return (ASYNC_DONE); @@ -607,3 +619,55 @@ hostent_add_addr(struct hostent_ext *h, const void *addr, size_t size) h->pos += size; return (0); } + +static void +netent_from_hostent(struct asr_result *ar) +{ + struct in_addr *addr; + struct netent_ext *n; + struct hostent_ext *h; + char **na, **ha; + size_t sz; + + /* Allocate and initialize the output. */ + if ((n = calloc(1, sizeof(*n) + 1024)) == NULL) { + ar->ar_h_errno = NETDB_INTERNAL; + ar->ar_errno = errno; + goto out; + } + n->pos = (char *)(n) + sizeof(*n); + n->end = n->pos + 1024; + n->n.n_name = n->pos; + n->n.n_aliases = n->aliases; + + /* Copy the fixed-size data. */ + h = (struct hostent_ext *)ar->ar_hostent; + addr = (struct in_addr *)h->h.h_addr; + n->n.n_net = ntohl(addr->s_addr); + n->n.n_addrtype = h->h.h_addrtype; + + /* Copy the network name. */ + sz = strlen(h->h.h_name) + 1; + memcpy(n->pos, h->h.h_name, sz); + n->pos += sz; + + /* + * Copy the aliases. + * No overflow check is needed because we are merely copying + * a part of the data from a structure of the same size. + */ + na = n->aliases; + for (ha = h->aliases; *ha != NULL; ha++) { + sz = strlen(*ha) + 1; + memcpy(n->pos, *ha, sz); + *na++ = n->pos; + n->pos += sz; + } + *na = NULL; + + /* Handle the return values. */ + ar->ar_netent = &n->n; +out: + free(ar->ar_hostent); + ar->ar_hostent = NULL; +} diff --git a/lib/libc/asr/getnetnamadr_async.c b/lib/libc/asr/getnetnamadr_async.c index 0b8adc944b9..0b1604d2b21 100644 --- a/lib/libc/asr/getnetnamadr_async.c +++ b/lib/libc/asr/getnetnamadr_async.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getnetnamadr_async.c,v 1.25 2017/02/23 17:04:02 eric Exp $ */ +/* $OpenBSD: getnetnamadr_async.c,v 1.26 2018/04/28 15:16:49 schwarze Exp $ */ /* * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> * @@ -17,446 +17,34 @@ #include <sys/types.h> #include <sys/socket.h> -#include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> #include <netdb.h> - #include <asr.h> -#include <errno.h> -#include <resolv.h> /* for res_hnok */ -#include <stdlib.h> -#include <string.h> -#include <unistd.h> #include "asr_private.h" -#define MAXALIASES 16 - -struct netent_ext { - struct netent n; - char *aliases[MAXALIASES + 1]; - char *end; - char *pos; -}; - -static int getnetnamadr_async_run(struct asr_query *, struct asr_result *); -static struct netent_ext *netent_alloc(int); -static int netent_set_cname(struct netent_ext *, const char *, int); -static int netent_add_alias(struct netent_ext *, const char *, int); -static struct netent_ext *netent_file_match(FILE *, int, const char *); -static struct netent_ext *netent_from_packet(int, char *, size_t); - struct asr_query * getnetbyname_async(const char *name, void *asr) { - struct asr_ctx *ac; struct asr_query *as; - /* The current resolver segfaults. */ - if (name == NULL) { - errno = EINVAL; - return (NULL); - } - - ac = _asr_use_resolver(asr); - if ((as = _asr_async_new(ac, ASR_GETNETBYNAME)) == NULL) - goto abort; /* errno set */ - as->as_run = getnetnamadr_async_run; - - as->as.netnamadr.family = AF_INET; - as->as.netnamadr.name = strdup(name); - if (as->as.netnamadr.name == NULL) - goto abort; /* errno set */ - - _asr_ctx_unref(ac); + if ((as = gethostbyname_async(name, asr)) != NULL) + as->as_flags |= ASYNC_GETNET; return (as); - - abort: - if (as) - _asr_async_free(as); - _asr_ctx_unref(ac); - return (NULL); } DEF_WEAK(getnetbyname_async); struct asr_query * getnetbyaddr_async(in_addr_t net, int family, void *asr) { - struct asr_ctx *ac; + struct in_addr in; struct asr_query *as; - ac = _asr_use_resolver(asr); - if ((as = _asr_async_new(ac, ASR_GETNETBYADDR)) == NULL) - goto abort; /* errno set */ - as->as_run = getnetnamadr_async_run; - - as->as.netnamadr.family = family; - as->as.netnamadr.addr = net; - - _asr_ctx_unref(ac); + in.s_addr = htonl(net); + as = gethostbyaddr_async(&in, sizeof(in), family, asr); + if (as != NULL) + as->as_flags |= ASYNC_GETNET; return (as); - - abort: - if (as) - _asr_async_free(as); - _asr_ctx_unref(ac); - return (NULL); } DEF_WEAK(getnetbyaddr_async); - -static int -getnetnamadr_async_run(struct asr_query *as, struct asr_result *ar) -{ - struct netent_ext *n; - int r, type, saved_errno; - FILE *f; - char dname[MAXDNAME], *name, *data; - in_addr_t in; - - next: - switch (as->as_state) { - - case ASR_STATE_INIT: - - if (as->as.netnamadr.family != AF_INET) { - ar->ar_h_errno = NETDB_INTERNAL; - ar->ar_errno = EAFNOSUPPORT; - async_set_state(as, ASR_STATE_HALT); - break; - } - - if (as->as_type == ASR_GETNETBYNAME && - as->as.netnamadr.name[0] == '\0') { - ar->ar_h_errno = NO_DATA; - async_set_state(as, ASR_STATE_HALT); - break; - } - - async_set_state(as, ASR_STATE_NEXT_DB); - break; - - case ASR_STATE_NEXT_DB: - - if (_asr_iter_db(as) == -1) { - async_set_state(as, ASR_STATE_NOT_FOUND); - break; - } - - switch (AS_DB(as)) { - case ASR_DB_DNS: - - if (as->as_type == ASR_GETNETBYNAME) { - type = T_A; - /* - * I think we want to do the former, but our - * resolver is doing the following, so let's - * preserve bugward-compatibility there. - */ - type = T_PTR; - name = as->as.netnamadr.name; - as->as_subq = _res_search_async_ctx( - name, C_IN, type, as->as_ctx); - } else { - type = T_PTR; - name = dname; - - in = htonl(as->as.netnamadr.addr); - _asr_addr_as_fqdn((char *)&in, - as->as.netnamadr.family, - dname, sizeof(dname)); - as->as_subq = _res_query_async_ctx( - name, C_IN, type, as->as_ctx); - } - - if (as->as_subq == NULL) { - ar->ar_errno = errno; - ar->ar_h_errno = NETDB_INTERNAL; - async_set_state(as, ASR_STATE_HALT); - break; - } - async_set_state(as, ASR_STATE_SUBQUERY); - break; - - case ASR_DB_FILE: - - if ((f = fopen(_PATH_NETWORKS, "re")) == NULL) - break; - - if (as->as_type == ASR_GETNETBYNAME) - data = as->as.netnamadr.name; - else - data = (void *)&as->as.netnamadr.addr; - - n = netent_file_match(f, as->as_type, data); - saved_errno = errno; - fclose(f); - errno = saved_errno; - if (n == NULL) { - if (errno) { - ar->ar_errno = errno; - ar->ar_h_errno = NETDB_INTERNAL; - async_set_state(as, ASR_STATE_HALT); - } - /* otherwise not found */ - break; - } - - ar->ar_netent = &n->n; - ar->ar_h_errno = NETDB_SUCCESS; - async_set_state(as, ASR_STATE_HALT); - break; - } - break; - - case ASR_STATE_SUBQUERY: - - if ((r = asr_run(as->as_subq, ar)) == ASYNC_COND) - return (ASYNC_COND); - as->as_subq = NULL; - - if (ar->ar_datalen == -1) { - async_set_state(as, ASR_STATE_NEXT_DB); - break; - } - - /* Got packet, but no answer */ - if (ar->ar_count == 0) { - free(ar->ar_data); - async_set_state(as, ASR_STATE_NEXT_DB); - break; - } - - n = netent_from_packet(as->as_type, ar->ar_data, - ar->ar_datalen); - free(ar->ar_data); - if (n == NULL) { - ar->ar_errno = errno; - ar->ar_h_errno = NETDB_INTERNAL; - async_set_state(as, ASR_STATE_HALT); - break; - } - - if (as->as_type == ASR_GETNETBYADDR) - n->n.n_net = as->as.netnamadr.addr; - - /* - * No valid hostname or address found in the dns packet. - * Ignore it. - */ - if ((as->as_type == ASR_GETNETBYNAME && n->n.n_net == 0) || - n->n.n_name == NULL) { - free(n); - async_set_state(as, ASR_STATE_NEXT_DB); - break; - } - - ar->ar_netent = &n->n; - ar->ar_h_errno = NETDB_SUCCESS; - async_set_state(as, ASR_STATE_HALT); - break; - - case ASR_STATE_NOT_FOUND: - - ar->ar_errno = 0; - ar->ar_h_errno = HOST_NOT_FOUND; - async_set_state(as, ASR_STATE_HALT); - break; - - case ASR_STATE_HALT: - - if (ar->ar_h_errno) - ar->ar_netent = NULL; - else - ar->ar_errno = 0; - return (ASYNC_DONE); - - default: - ar->ar_errno = EOPNOTSUPP; - ar->ar_h_errno = NETDB_INTERNAL; - ar->ar_gai_errno = EAI_SYSTEM; - async_set_state(as, ASR_STATE_HALT); - break; - } - goto next; -} - -static struct netent_ext * -netent_file_match(FILE *f, int reqtype, const char *data) -{ - struct netent_ext *e; - char *tokens[MAXTOKEN], buf[BUFSIZ + 1]; - int n, i; - in_addr_t net; - - for (;;) { - n = _asr_parse_namedb_line(f, tokens, MAXTOKEN, buf, sizeof(buf)); - if (n == -1) { - errno = 0; /* ignore errors reading the file */ - return (NULL); - } - - /* there must be an address and at least one name */ - if (n < 2) - continue; - - if (reqtype == ASR_GETNETBYADDR) { - net = inet_network(tokens[1]); - if (memcmp(&net, data, sizeof net) == 0) - goto found; - } else { - for (i = 0; i < n; i++) { - if (i == 1) - continue; - if (strcasecmp(data, tokens[i])) - continue; - goto found; - } - } - } - -found: - if ((e = netent_alloc(AF_INET)) == NULL) - return (NULL); - if (netent_set_cname(e, tokens[0], 0) == -1) - goto fail; - for (i = 2; i < n; i ++) - if (netent_add_alias(e, tokens[i], 0) == -1) - goto fail; - e->n.n_net = inet_network(tokens[1]); - return (e); -fail: - free(e); - return (NULL); -} - -static struct netent_ext * -netent_from_packet(int reqtype, char *pkt, size_t pktlen) -{ - struct netent_ext *n; - struct asr_unpack p; - struct asr_dns_header hdr; - struct asr_dns_query q; - struct asr_dns_rr rr; - - if ((n = netent_alloc(AF_INET)) == NULL) - return (NULL); - - _asr_unpack_init(&p, pkt, pktlen); - _asr_unpack_header(&p, &hdr); - for (; hdr.qdcount; hdr.qdcount--) - _asr_unpack_query(&p, &q); - for (; hdr.ancount; hdr.ancount--) { - _asr_unpack_rr(&p, &rr); - if (rr.rr_class != C_IN) - continue; - switch (rr.rr_type) { - case T_CNAME: - if (reqtype == ASR_GETNETBYNAME) { - if (netent_add_alias(n, rr.rr_dname, 1) == -1) - goto fail; - } else { - if (netent_set_cname(n, rr.rr_dname, 1) == -1) - goto fail; - } - break; - - case T_PTR: - if (reqtype != ASR_GETNETBYADDR) - continue; - if (netent_set_cname(n, rr.rr.ptr.ptrname, 1) == -1) - goto fail; - /* XXX See if we need to have MULTI_PTRS_ARE_ALIASES */ - break; - - case T_A: - if (n->n.n_addrtype != AF_INET) - break; - if (netent_set_cname(n, rr.rr_dname, 1) == -1) - goto fail; - n->n.n_net = ntohl(rr.rr.in_a.addr.s_addr); - break; - } - } - - return (n); -fail: - free(n); - return (NULL); -} - -static struct netent_ext * -netent_alloc(int family) -{ - struct netent_ext *n; - size_t alloc; - - alloc = sizeof(*n) + 1024; - if ((n = calloc(1, alloc)) == NULL) - return (NULL); - - n->n.n_addrtype = family; - n->n.n_aliases = n->aliases; - n->pos = (char *)(n) + sizeof(*n); - n->end = n->pos + 1024; - - return (n); -} - -static int -netent_set_cname(struct netent_ext *n, const char *name, int isdname) -{ - char buf[MAXDNAME]; - size_t l; - - if (n->n.n_name) - return (-1); - - if (isdname) { - _asr_strdname(name, buf, sizeof buf); - buf[strlen(buf) - 1] = '\0'; - if (!res_hnok(buf)) - return (-1); - name = buf; - } - - l = strlen(name) + 1; - if (n->pos + l >= n->end) - return (-1); - - n->n.n_name = n->pos; - memmove(n->pos, name, l); - n->pos += l; - - return (0); -} - -static int -netent_add_alias(struct netent_ext *n, const char *name, int isdname) -{ - char buf[MAXDNAME]; - size_t i, l; - - for (i = 0; i < MAXALIASES; i++) - if (n->aliases[i] == NULL) - break; - if (i == MAXALIASES) - return (-1); - - if (isdname) { - _asr_strdname(name, buf, sizeof buf); - buf[strlen(buf)-1] = '\0'; - if (!res_hnok(buf)) - return (-1); - name = buf; - } - - l = strlen(name) + 1; - if (n->pos + l >= n->end) - return (-1); - - n->aliases[i] = n->pos; - memmove(n->pos, name, l); - n->pos += l; - return (0); -} |