diff options
Diffstat (limited to 'sbin/unwind')
-rw-r--r-- | sbin/unwind/Makefile | 3 | ||||
-rw-r--r-- | sbin/unwind/asr_private.h | 299 | ||||
-rw-r--r-- | sbin/unwind/asr_utils.c | 663 | ||||
-rw-r--r-- | sbin/unwind/frontend.c | 129 | ||||
-rw-r--r-- | sbin/unwind/resolver.c | 53 |
5 files changed, 103 insertions, 1044 deletions
diff --git a/sbin/unwind/Makefile b/sbin/unwind/Makefile index b20ac0ed9fc..245c528ffbb 100644 --- a/sbin/unwind/Makefile +++ b/sbin/unwind/Makefile @@ -1,8 +1,7 @@ -# $OpenBSD: Makefile,v 1.1 2019/01/23 13:11:00 florian Exp $ +# $OpenBSD: Makefile,v 1.2 2019/01/24 15:33:44 florian Exp $ PROG= unwind SRCS= control.c resolver.c frontend.c uw_log.c unwind.c uw_parse.y printconf.c -SRCS+= asr_utils.c MAN= unwind.8 unwind.conf.5 .include "${.CURDIR}/libunbound/Makefile.inc" diff --git a/sbin/unwind/asr_private.h b/sbin/unwind/asr_private.h deleted file mode 100644 index d18acb01d1d..00000000000 --- a/sbin/unwind/asr_private.h +++ /dev/null @@ -1,299 +0,0 @@ -/* $OpenBSD: asr_private.h,v 1.1 2019/01/23 13:11:00 florian 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. - */ - -#define QR_MASK (0x1 << 15) -#define OPCODE_MASK (0xf << 11) -#define AA_MASK (0x1 << 10) -#define TC_MASK (0x1 << 9) -#define RD_MASK (0x1 << 8) -#define RA_MASK (0x1 << 7) -#define Z_MASK (0x1 << 6) -#define AD_MASK (0x1 << 5) -#define CD_MASK (0x1 << 4) -#define RCODE_MASK (0xf) - -#define OPCODE(v) ((v) & OPCODE_MASK) -#define RCODE(v) ((v) & RCODE_MASK) - -struct asr_pack { - char *buf; - size_t len; - size_t offset; - int err; -}; - -struct asr_unpack { - const char *buf; - size_t len; - size_t offset; - int err; -}; - -struct asr_dns_header { - uint16_t id; - uint16_t flags; - uint16_t qdcount; - uint16_t ancount; - uint16_t nscount; - uint16_t arcount; -}; - -struct asr_dns_query { - char q_dname[MAXDNAME]; - uint16_t q_type; - uint16_t q_class; -}; - -struct asr_dns_rr { - char rr_dname[MAXDNAME]; - uint16_t rr_type; - uint16_t rr_class; - uint32_t rr_ttl; - union { - struct { - char cname[MAXDNAME]; - } cname; - struct { - uint16_t preference; - char exchange[MAXDNAME]; - } mx; - struct { - char nsname[MAXDNAME]; - } ns; - struct { - char ptrname[MAXDNAME]; - } ptr; - struct { - char mname[MAXDNAME]; - char rname[MAXDNAME]; - uint32_t serial; - uint32_t refresh; - uint32_t retry; - uint32_t expire; - uint32_t minimum; - } soa; - struct { - struct in_addr addr; - } in_a; - struct { - struct in6_addr addr6; - } in_aaaa; - struct { - uint16_t rdlen; - const void *rdata; - } other; - } rr; -}; - - -#define ASR_MAXNS 5 -#define ASR_MAXDB 3 -#define ASR_MAXDOM 10 - -enum async_type { - ASR_SEND, - ASR_SEARCH, - ASR_GETRRSETBYNAME, - ASR_GETHOSTBYNAME, - ASR_GETHOSTBYADDR, - ASR_GETADDRINFO, - ASR_GETNAMEINFO, -}; - -#define ASR_DB_FILE 'f' -#define ASR_DB_DNS 'b' - -struct asr_ctx { - int ac_refcount; - int ac_options; - int ac_ndots; - char *ac_domain; - int ac_domcount; - char *ac_dom[ASR_MAXDOM]; - int ac_dbcount; - char ac_db[ASR_MAXDB + 1]; - int ac_family[3]; - - int ac_nscount; - int ac_nstimeout; - int ac_nsretries; - struct sockaddr *ac_ns[ASR_MAXNS]; - -}; - -struct asr { - pid_t a_pid; - time_t a_mtime; - time_t a_rtime; - struct asr_ctx *a_ctx; -}; - -#define ASYNC_COND 0 -#define ASYNC_DONE 1 - -#define ASYNC_DOM_FQDN 0x00000001 -#define ASYNC_DOM_NDOTS 0x00000002 -#define ASYNC_DOM_DOMAIN 0x00000004 -#define ASYNC_DOM_ASIS 0x00000008 - -#define ASYNC_NODATA 0x00000100 -#define ASYNC_AGAIN 0x00000200 - -#define ASYNC_GETNET 0x00001000 -#define ASYNC_EXTOBUF 0x00002000 - -#define ASYNC_NO_INET 0x00010000 -#define ASYNC_NO_INET6 0x00020000 - -struct asr_query { - int (*as_run)(struct asr_query *, struct asr_result *); - struct asr_ctx *as_ctx; - int as_type; - int as_flags; - int as_state; - - /* cond */ - int as_timeout; - int as_fd; - struct asr_query *as_subq; - - /* loop indices in ctx */ - int as_dom_step; - int as_dom_idx; - int as_dom_flags; - int as_family_idx; - int as_db_idx; - - int as_count; - - union { - struct { - uint16_t reqid; - int class; - int type; - char *dname; /* not fqdn! */ - int rcode; /* response code */ - int ancount; /* answer count */ - - int nsidx; - int nsloop; - - /* io buffers for query/response */ - unsigned char *obuf; - size_t obuflen; - size_t obufsize; - unsigned char *ibuf; - size_t ibuflen; - size_t ibufsize; - size_t datalen; /* for tcp io */ - uint16_t pktlen; - } dns; - - struct { - int class; - int type; - char *name; - int saved_h_errno; - } search; - - struct { - int flags; - int class; - int type; - char *name; - } rrset; - - struct { - char *name; - int family; - char addr[16]; - int addrlen; - int subq_h_errno; - } hostnamadr; - - struct { - char *hostname; - char *servname; - int port_tcp; - int port_udp; - union { - struct sockaddr sa; - struct sockaddr_in sain; - struct sockaddr_in6 sain6; - } sa; - - struct addrinfo hints; - char *fqdn; - struct addrinfo *aifirst; - struct addrinfo *ailast; - } ai; - - struct { - char *hostname; - char *servname; - size_t hostnamelen; - size_t servnamelen; - union { - struct sockaddr sa; - struct sockaddr_in sain; - struct sockaddr_in6 sain6; - } sa; - int flags; - } ni; -#define MAXTOKEN 10 - } as; - -}; - -#define AS_DB(p) ((p)->as_ctx->ac_db[(p)->as_db_idx - 1]) -#define AS_FAMILY(p) ((p)->as_ctx->ac_family[(p)->as_family_idx]) - -enum asr_state { - ASR_STATE_INIT, - ASR_STATE_NEXT_DOMAIN, - ASR_STATE_NEXT_DB, - ASR_STATE_SAME_DB, - ASR_STATE_NEXT_FAMILY, - ASR_STATE_NEXT_NS, - ASR_STATE_UDP_SEND, - ASR_STATE_UDP_RECV, - ASR_STATE_TCP_WRITE, - ASR_STATE_TCP_READ, - ASR_STATE_PACKET, - ASR_STATE_SUBQUERY, - ASR_STATE_NOT_FOUND, - ASR_STATE_HALT, -}; - -#define MAXPACKETSZ 4096 - -/* asr_utils.c */ -void _asr_pack_init(struct asr_pack *, char *, size_t); -int _asr_pack_header(struct asr_pack *, const struct asr_dns_header *); -int _asr_pack_query(struct asr_pack *, uint16_t, uint16_t, const char *); -int _asr_pack_edns0(struct asr_pack *, uint16_t, int); -void _asr_unpack_init(struct asr_unpack *, const char *, size_t); -int _asr_unpack_header(struct asr_unpack *, struct asr_dns_header *); -int _asr_unpack_query(struct asr_unpack *, struct asr_dns_query *); -int _asr_unpack_rr(struct asr_unpack *, struct asr_dns_rr *); -int _asr_sockaddr_from_str(struct sockaddr *, int, const char *); -ssize_t _asr_dname_from_fqdn(const char *, char *, size_t); -ssize_t _asr_addr_as_fqdn(const char *, int, char *, size_t); - -const char *print_dname(const char *, char *, size_t); -const char *print_header(const struct asr_dns_header *, char *, size_t); -const char *print_query(const struct asr_dns_query *, char *, size_t); diff --git a/sbin/unwind/asr_utils.c b/sbin/unwind/asr_utils.c deleted file mode 100644 index 94855ec61b6..00000000000 --- a/sbin/unwind/asr_utils.c +++ /dev/null @@ -1,663 +0,0 @@ -/* $OpenBSD: asr_utils.c,v 1.1 2019/01/23 13:11:00 florian Exp $ */ -/* - * Copyright (c) 2009-2012 Eric Faurot <eric@faurot.net> - * - * 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/socket.h> -#include <net/if.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> -#include <netdb.h> - -#include <asr.h> -#include <ctype.h> -#include <errno.h> -#include <resolv.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "asr_private.h" - -static int dname_check_label(const char *, size_t); -static ssize_t dname_expand(const unsigned char *, size_t, size_t, size_t *, - char *, size_t); - -static int unpack_data(struct asr_unpack *, void *, size_t); -static int unpack_u16(struct asr_unpack *, uint16_t *); -static int unpack_u32(struct asr_unpack *, uint32_t *); -static int unpack_inaddr(struct asr_unpack *, struct in_addr *); -static int unpack_in6addr(struct asr_unpack *, struct in6_addr *); -static int unpack_dname(struct asr_unpack *, char *, size_t); - -static int pack_data(struct asr_pack *, const void *, size_t); -static int pack_u16(struct asr_pack *, uint16_t); -static int pack_dname(struct asr_pack *, const char *); - -/* from asr_debug.c */ -static const char *rcodetostr(uint16_t); - -/* from asr.c */ -char * _asr_strdname(const char *, char *, size_t); - -static int -dname_check_label(const char *s, size_t l) -{ - if (l == 0 || l > 63) - return (-1); - - return (0); -} - -ssize_t -_asr_dname_from_fqdn(const char *str, char *dst, size_t max) -{ - ssize_t res; - size_t l, n; - char *d; - - res = 0; - - /* special case: the root domain */ - if (str[0] == '.') { - if (str[1] != '\0') - return (-1); - if (dst && max >= 1) - *dst = '\0'; - return (1); - } - - for (; *str; str = d + 1) { - - d = strchr(str, '.'); - if (d == NULL || d == str) - return (-1); - - l = (d - str); - - if (dname_check_label(str, l) == -1) - return (-1); - - res += l + 1; - - if (dst) { - *dst++ = l; - max -= 1; - n = (l > max) ? max : l; - memmove(dst, str, n); - max -= n; - if (max == 0) - dst = NULL; - else - dst += n; - } - } - - if (dst) - *dst++ = '\0'; - - return (res + 1); -} - -static ssize_t -dname_expand(const unsigned char *data, size_t len, size_t offset, - size_t *newoffset, char *dst, size_t max) -{ - size_t n, count, end, ptr, start; - ssize_t res; - - if (offset >= len) - return (-1); - - res = 0; - end = start = offset; - - for (; (n = data[offset]); ) { - if ((n & 0xc0) == 0xc0) { - if (offset + 2 > len) - return (-1); - ptr = 256 * (n & ~0xc0) + data[offset + 1]; - if (ptr >= start) - return (-1); - if (end < offset + 2) - end = offset + 2; - offset = start = ptr; - continue; - } - if (offset + n + 1 > len) - return (-1); - - if (dname_check_label(data + offset + 1, n) == -1) - return (-1); - - /* copy n + at offset+1 */ - if (dst != NULL && max != 0) { - count = (max < n + 1) ? (max) : (n + 1); - memmove(dst, data + offset, count); - dst += count; - max -= count; - } - res += n + 1; - offset += n + 1; - if (end < offset) - end = offset; - } - if (end < offset + 1) - end = offset + 1; - - if (dst != NULL && max != 0) - dst[0] = 0; - if (newoffset) - *newoffset = end; - return (res + 1); -} - -void -_asr_pack_init(struct asr_pack *pack, char *buf, size_t len) -{ - pack->buf = buf; - pack->len = len; - pack->offset = 0; - pack->err = 0; -} - -void -_asr_unpack_init(struct asr_unpack *unpack, const char *buf, size_t len) -{ - unpack->buf = buf; - unpack->len = len; - unpack->offset = 0; - unpack->err = 0; -} - -static int -unpack_data(struct asr_unpack *p, void *data, size_t len) -{ - if (p->err) - return (-1); - - if (p->len - p->offset < len) { - p->err = EOVERFLOW; - return (-1); - } - - memmove(data, p->buf + p->offset, len); - p->offset += len; - - return (0); -} - -static int -unpack_u16(struct asr_unpack *p, uint16_t *u16) -{ - if (unpack_data(p, u16, 2) == -1) - return (-1); - - *u16 = ntohs(*u16); - - return (0); -} - -static int -unpack_u32(struct asr_unpack *p, uint32_t *u32) -{ - if (unpack_data(p, u32, 4) == -1) - return (-1); - - *u32 = ntohl(*u32); - - return (0); -} - -static int -unpack_inaddr(struct asr_unpack *p, struct in_addr *a) -{ - return (unpack_data(p, a, 4)); -} - -static int -unpack_in6addr(struct asr_unpack *p, struct in6_addr *a6) -{ - return (unpack_data(p, a6, 16)); -} - -static int -unpack_dname(struct asr_unpack *p, char *dst, size_t max) -{ - ssize_t e; - - if (p->err) - return (-1); - - e = dname_expand(p->buf, p->len, p->offset, &p->offset, dst, max); - if (e == -1) { - p->err = EINVAL; - return (-1); - } - if (e < 0 || e > MAXDNAME) { - p->err = ERANGE; - return (-1); - } - - return (0); -} - -int -_asr_unpack_header(struct asr_unpack *p, struct asr_dns_header *h) -{ - if (unpack_data(p, h, HFIXEDSZ) == -1) - return (-1); - - h->flags = ntohs(h->flags); - h->qdcount = ntohs(h->qdcount); - h->ancount = ntohs(h->ancount); - h->nscount = ntohs(h->nscount); - h->arcount = ntohs(h->arcount); - - return (0); -} - -int -_asr_unpack_query(struct asr_unpack *p, struct asr_dns_query *q) -{ - unpack_dname(p, q->q_dname, sizeof(q->q_dname)); - unpack_u16(p, &q->q_type); - unpack_u16(p, &q->q_class); - - return (p->err) ? (-1) : (0); -} - -int -_asr_unpack_rr(struct asr_unpack *p, struct asr_dns_rr *rr) -{ - uint16_t rdlen; - size_t save_offset; - - unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname)); - unpack_u16(p, &rr->rr_type); - unpack_u16(p, &rr->rr_class); - unpack_u32(p, &rr->rr_ttl); - unpack_u16(p, &rdlen); - - if (p->err) - return (-1); - - if (p->len - p->offset < rdlen) { - p->err = EOVERFLOW; - return (-1); - } - - save_offset = p->offset; - - switch (rr->rr_type) { - - case T_CNAME: - unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname)); - break; - - case T_MX: - unpack_u16(p, &rr->rr.mx.preference); - unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange)); - break; - - case T_NS: - unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname)); - break; - - case T_PTR: - unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname)); - break; - - case T_SOA: - unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname)); - unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname)); - unpack_u32(p, &rr->rr.soa.serial); - unpack_u32(p, &rr->rr.soa.refresh); - unpack_u32(p, &rr->rr.soa.retry); - unpack_u32(p, &rr->rr.soa.expire); - unpack_u32(p, &rr->rr.soa.minimum); - break; - - case T_A: - if (rr->rr_class != C_IN) - goto other; - unpack_inaddr(p, &rr->rr.in_a.addr); - break; - - case T_AAAA: - if (rr->rr_class != C_IN) - goto other; - unpack_in6addr(p, &rr->rr.in_aaaa.addr6); - break; - default: - other: - rr->rr.other.rdata = p->buf + p->offset; - rr->rr.other.rdlen = rdlen; - p->offset += rdlen; - } - - if (p->err) - return (-1); - - /* make sure that the advertised rdlen is really ok */ - if (p->offset - save_offset != rdlen) - p->err = EINVAL; - - return (p->err) ? (-1) : (0); -} - -static int -pack_data(struct asr_pack *p, const void *data, size_t len) -{ - if (p->err) - return (-1); - - if (p->len < p->offset + len) { - p->err = EOVERFLOW; - return (-1); - } - - memmove(p->buf + p->offset, data, len); - p->offset += len; - - return (0); -} - -static int -pack_u16(struct asr_pack *p, uint16_t v) -{ - v = htons(v); - - return (pack_data(p, &v, 2)); -} - -static int -pack_dname(struct asr_pack *p, const char *dname) -{ - /* dname compression would be nice to have here. - * need additionnal context. - */ - return (pack_data(p, dname, strlen(dname) + 1)); -} - -int -_asr_pack_header(struct asr_pack *p, const struct asr_dns_header *h) -{ - struct asr_dns_header c; - - c.id = h->id; - c.flags = htons(h->flags); - c.qdcount = htons(h->qdcount); - c.ancount = htons(h->ancount); - c.nscount = htons(h->nscount); - c.arcount = htons(h->arcount); - - return (pack_data(p, &c, HFIXEDSZ)); -} - -int -_asr_pack_query(struct asr_pack *p, uint16_t type, uint16_t class, const char *dname) -{ - pack_dname(p, dname); - pack_u16(p, type); - pack_u16(p, class); - - return (p->err) ? (-1) : (0); -} - -int -_asr_pack_edns0(struct asr_pack *p, uint16_t pktsz, int dnssec_do) -{ - pack_dname(p, ""); /* root */ - pack_u16(p, T_OPT); /* OPT */ - pack_u16(p, pktsz); /* UDP payload size */ - - /* extended RCODE and flags */ - pack_u16(p, 0); - pack_u16(p, dnssec_do ? DNS_MESSAGEEXTFLAG_DO : 0); - - pack_u16(p, 0); /* RDATA len */ - - return (p->err) ? (-1) : (0); -} - -int -_asr_sockaddr_from_str(struct sockaddr *sa, int family, const char *str) -{ - struct in_addr ina; - struct in6_addr in6a; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - char *cp, *str2; - const char *errstr; - - switch (family) { - case PF_UNSPEC: - if (_asr_sockaddr_from_str(sa, PF_INET, str) == 0) - return (0); - return _asr_sockaddr_from_str(sa, PF_INET6, str); - - case PF_INET: - if (inet_pton(PF_INET, str, &ina) != 1) - return (-1); - - sin = (struct sockaddr_in *)sa; - memset(sin, 0, sizeof *sin); - sin->sin_len = sizeof(struct sockaddr_in); - sin->sin_family = PF_INET; - sin->sin_addr.s_addr = ina.s_addr; - return (0); - - case PF_INET6: - cp = strchr(str, SCOPE_DELIMITER); - if (cp) { - str2 = strdup(str); - if (str2 == NULL) - return (-1); - str2[cp - str] = '\0'; - if (inet_pton(PF_INET6, str2, &in6a) != 1) { - free(str2); - return (-1); - } - cp++; - free(str2); - } else if (inet_pton(PF_INET6, str, &in6a) != 1) - return (-1); - - sin6 = (struct sockaddr_in6 *)sa; - memset(sin6, 0, sizeof *sin6); - sin6->sin6_len = sizeof(struct sockaddr_in6); - sin6->sin6_family = PF_INET6; - sin6->sin6_addr = in6a; - - if (cp == NULL) - return (0); - - if (IN6_IS_ADDR_LINKLOCAL(&in6a) || - IN6_IS_ADDR_MC_LINKLOCAL(&in6a) || - IN6_IS_ADDR_MC_INTFACELOCAL(&in6a)) - if ((sin6->sin6_scope_id = if_nametoindex(cp))) - return (0); - - sin6->sin6_scope_id = strtonum(cp, 0, UINT32_MAX, &errstr); - if (errstr) - return (-1); - return (0); - - default: - break; - } - - return (-1); -} - -ssize_t -_asr_addr_as_fqdn(const char *addr, int family, char *dst, size_t max) -{ - const struct in6_addr *in6_addr; - in_addr_t in_addr; - - switch (family) { - case AF_INET: - in_addr = ntohl(*((const in_addr_t *)addr)); - snprintf(dst, max, - "%d.%d.%d.%d.in-addr.arpa.", - in_addr & 0xff, - (in_addr >> 8) & 0xff, - (in_addr >> 16) & 0xff, - (in_addr >> 24) & 0xff); - break; - case AF_INET6: - in6_addr = (const struct in6_addr *)addr; - snprintf(dst, max, - "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." - "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." - "ip6.arpa.", - in6_addr->s6_addr[15] & 0xf, - (in6_addr->s6_addr[15] >> 4) & 0xf, - in6_addr->s6_addr[14] & 0xf, - (in6_addr->s6_addr[14] >> 4) & 0xf, - in6_addr->s6_addr[13] & 0xf, - (in6_addr->s6_addr[13] >> 4) & 0xf, - in6_addr->s6_addr[12] & 0xf, - (in6_addr->s6_addr[12] >> 4) & 0xf, - in6_addr->s6_addr[11] & 0xf, - (in6_addr->s6_addr[11] >> 4) & 0xf, - in6_addr->s6_addr[10] & 0xf, - (in6_addr->s6_addr[10] >> 4) & 0xf, - in6_addr->s6_addr[9] & 0xf, - (in6_addr->s6_addr[9] >> 4) & 0xf, - in6_addr->s6_addr[8] & 0xf, - (in6_addr->s6_addr[8] >> 4) & 0xf, - in6_addr->s6_addr[7] & 0xf, - (in6_addr->s6_addr[7] >> 4) & 0xf, - in6_addr->s6_addr[6] & 0xf, - (in6_addr->s6_addr[6] >> 4) & 0xf, - in6_addr->s6_addr[5] & 0xf, - (in6_addr->s6_addr[5] >> 4) & 0xf, - in6_addr->s6_addr[4] & 0xf, - (in6_addr->s6_addr[4] >> 4) & 0xf, - in6_addr->s6_addr[3] & 0xf, - (in6_addr->s6_addr[3] >> 4) & 0xf, - in6_addr->s6_addr[2] & 0xf, - (in6_addr->s6_addr[2] >> 4) & 0xf, - in6_addr->s6_addr[1] & 0xf, - (in6_addr->s6_addr[1] >> 4) & 0xf, - in6_addr->s6_addr[0] & 0xf, - (in6_addr->s6_addr[0] >> 4) & 0xf); - break; - default: - return (-1); - } - return (0); -} - -/* from asr_debug.c */ -static const char * -rcodetostr(uint16_t v) -{ - switch (v) { - case NOERROR: return "NOERROR"; - case FORMERR: return "FORMERR"; - case SERVFAIL: return "SERVFAIL"; - case NXDOMAIN: return "NXDOMAIN"; - case NOTIMP: return "NOTIMP"; - case REFUSED: return "REFUSED"; - default: return "?"; - } -} - -#define OPCODE_SHIFT 11 - -const char * -print_header(const struct asr_dns_header *h, char *buf, size_t max) -{ - snprintf(buf, max, - "id:0x%04x %s op:%i %s %s %s %s z:%i %s %s r:%s qd:%i an:%i ns:%i ar:%i", - ((int)h->id), - (h->flags & QR_MASK) ? "QR":" ", - (int)(OPCODE(h->flags) >> OPCODE_SHIFT), - (h->flags & AA_MASK) ? "AA":" ", - (h->flags & TC_MASK) ? "TC":" ", - (h->flags & RD_MASK) ? "RD":" ", - (h->flags & RA_MASK) ? "RA":" ", - (h->flags & Z_MASK), - (h->flags & AD_MASK) ? "AD":" ", - (h->flags & CD_MASK) ? "CD":" ", - rcodetostr(RCODE(h->flags)), - h->qdcount, h->ancount, h->nscount, h->arcount); - - return (buf); -} - -const char * -print_query(const struct asr_dns_query *q, char *buf, size_t max) -{ - char b[256]; - - snprintf(buf, max, "%s %s %s", - print_dname(q->q_dname, b, sizeof b), - __p_class(q->q_class), __p_type(q->q_type)); - - return (buf); -} - -const char * -print_dname(const char *_dname, char *buf, size_t max) -{ - return (_asr_strdname(_dname, buf, max)); -} - -#if 0 -/* from asr.c XXX when linking statically we get access to this via libc */ -/* - * Turn a (uncompressed) DNS domain name into a regular nul-terminated string - * where labels are separated by dots. The result is put into the "buf" buffer, - * truncated if it exceeds "max" chars. The function returns "buf". - */ -char * -_asr_strdname(const char *_dname, char *buf, size_t max) -{ - const unsigned char *dname = _dname; - char *res; - size_t left, n, count; - - if (_dname[0] == 0) { - strlcpy(buf, ".", max); - return buf; - } - - res = buf; - left = max - 1; - for (n = 0; dname[0] && left; n += dname[0]) { - count = (dname[0] < (left - 1)) ? dname[0] : (left - 1); - memmove(buf, dname + 1, count); - dname += dname[0] + 1; - left -= count; - buf += count; - if (left) { - left -= 1; - *buf++ = '.'; - } - } - buf[0] = 0; - - return (res); -} -#endif diff --git a/sbin/unwind/frontend.c b/sbin/unwind/frontend.c index d4b0fd7ab03..a1542257b62 100644 --- a/sbin/unwind/frontend.c +++ b/sbin/unwind/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.1 2019/01/23 13:11:00 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.2 2019/01/24 15:33:44 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -47,7 +47,15 @@ #include <string.h> #include <unistd.h> -#include "asr_private.h" +#include <assert.h> +#include "libunbound/config.h" +#include "libunbound/libunbound/unbound.h" +#include "libunbound/unbound-event.h" +#include "libunbound/sldns/rrdef.h" +#include "libunbound/sldns/pkthdr.h" +#include "libunbound/sldns/sbuffer.h" +#include "libunbound/sldns/wire2str.h" + #include "uw_log.h" #include "unwind.h" #include "frontend.h" @@ -483,41 +491,62 @@ udp_receive(int fd, short events, void *arg) struct udp_ev *udpev = (struct udp_ev *)arg; struct pending_query *pq; struct query_imsg *query_imsg; - struct asr_unpack p; - struct asr_dns_header h; - struct asr_dns_query q; - ssize_t len; - char *str_from, buf[1024]; - + ssize_t len, rem_len, buf_len; + uint16_t qdcount, ancount, nscount, arcount, t, c; + uint8_t *queryp; + char *str_from, *str, buf[1024], *bufp; if ((len = recvmsg(fd, &udpev->rcvmhdr, 0)) < 0) { log_warn("recvmsg"); return; } - str_from = ip_port((struct sockaddr *)&udpev->from); + bufp = buf; + buf_len = sizeof(buf); - _asr_unpack_init(&p, udpev->query, len); + str_from = ip_port((struct sockaddr *)&udpev->from); - if (_asr_unpack_header(&p, &h) == -1) { - log_warnx("bad query: %s, from: %s", strerror(p.err), str_from); + if (len < LDNS_HEADER_SIZE) { + log_warnx("bad query: too short, from: %s", str_from); return; } - if (h.qdcount != 1 && h.ancount != 0 && h.nscount != 0 && - h.arcount != 0) { + qdcount = LDNS_QDCOUNT(udpev->query); + ancount = LDNS_ANCOUNT(udpev->query); + nscount = LDNS_NSCOUNT(udpev->query); + arcount = LDNS_ARCOUNT(udpev->query); + + if (qdcount != 1 && ancount != 0 && nscount != 0 && arcount != 0) { log_warnx("invalid query from %s, qdcount: %d, ancount: %d " - "nscount: %d, arcount: %d", str_from, h.qdcount, h.ancount, - h.nscount, h.arcount); + "nscount: %d, arcount: %d", str_from, qdcount, ancount, + nscount, arcount); return; } log_debug("query from %s", str_from); - log_debug(";; HEADER %s", print_header(&h, buf, sizeof(buf))); - log_debug(";; QUERY SECTION:"); - if (_asr_unpack_query(&p, &q) == -1) - goto error; - log_debug("%s", print_query(&q, buf, sizeof(buf))); + if ((str = sldns_wire2str_pkt(udpev->query, len)) != NULL) { + log_debug("%s", str); + free(str); + } + + queryp = udpev->query; + rem_len = len; + + queryp += LDNS_HEADER_SIZE; + rem_len -= LDNS_HEADER_SIZE; + + sldns_wire2str_dname_scan(&queryp, &rem_len, &bufp, &buf_len, + udpev->query, len); + + if (rem_len < 4) { + log_warnx("malformed query"); + return; + } + + t = sldns_read_uint16(queryp); + c = sldns_read_uint16(queryp+2); + queryp += 4; + rem_len -= 4; if ((pq = malloc(sizeof(*pq))) == NULL) { log_warn(NULL); @@ -544,11 +573,18 @@ udp_receive(int fd, short events, void *arg) return; } - /* XXX */ - print_dname(q.q_dname, query_imsg->qname, sizeof(query_imsg->qname)); + if (strlcpy(query_imsg->qname, buf, sizeof(query_imsg->qname)) >= + sizeof(buf)) { + log_warnx("qname too long"); + free(query_imsg); + /* XXX SERVFAIL */ + free(pq->query); + free(pq); + return; + } query_imsg->id = pq->imsg_id; - query_imsg->t = q.q_type; - query_imsg->c = q.q_class; + query_imsg->t = t; + query_imsg->c = c; if (frontend_imsg_compose_resolver(IMSG_QUERY, 0, query_imsg, sizeof(*query_imsg)) != -1) { @@ -560,62 +596,39 @@ udp_receive(int fd, short events, void *arg) free(pq); } -error: - if (p.err) - log_debug(";; ERROR AT OFFSET %zu/%zu: %s", p.offset, p.len, - strerror(p.err)); } void send_answer(struct pending_query *pq, uint8_t *answer, ssize_t len) { - struct asr_pack p; - struct asr_unpack query_u, answer_u; - struct asr_dns_header query_h, answer_h; - log_debug("result for %s", ip_port((struct sockaddr*)&pq->from)); - _asr_unpack_init(&query_u, pq->query, pq->len); - _asr_unpack_header(&query_u, &query_h); /* XXX */ - if (answer == NULL) { answer = pq->query; len = pq->len; - _asr_unpack_init(&answer_u, answer, len); - _asr_unpack_header(&answer_u, &answer_h); /* XXX */ - answer_h.flags = 0; - answer_h.flags |= RA_MASK; - answer_h.flags = (answer_h.flags & ~RCODE_MASK) | SERVFAIL; + LDNS_QR_SET(answer); + LDNS_RA_SET(answer); + LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL); } else { - _asr_unpack_init(&answer_u, answer, len); - _asr_unpack_header(&answer_u, &answer_h); /* XXX */ - if (pq->bogus) { - if(query_h.flags & CD_MASK) { - answer_h.id = query_h.id; - answer_h.flags |= CD_MASK; + if(LDNS_CD_WIRE(pq->query)) { + LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query)); + LDNS_CD_SET(answer); } else { answer = pq->query; len = pq->len; - _asr_unpack_init(&answer_u, answer, len); - _asr_unpack_header(&answer_u, &answer_h); /* XXX */ - - answer_h.flags = 0; - answer_h.flags |= RA_MASK; - answer_h.flags = (answer_h.flags & ~RCODE_MASK) - | SERVFAIL; + LDNS_QR_SET(answer); + LDNS_RA_SET(answer); + LDNS_RCODE_SET(answer, LDNS_RCODE_SERVFAIL); } } else { - answer_h.id = query_h.id; + LDNS_ID_SET(answer, LDNS_ID_WIRE(pq->query)); } } - _asr_pack_init(&p, answer, len); - _asr_pack_header(&p, &answer_h); - if(sendto(pq->fd, answer, len, 0, (struct sockaddr *) &pq->from, pq->from.ss_len) == -1) log_warn("sendto"); diff --git a/sbin/unwind/resolver.c b/sbin/unwind/resolver.c index d8b742c205a..708d5485f4a 100644 --- a/sbin/unwind/resolver.c +++ b/sbin/unwind/resolver.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolver.c,v 1.2 2019/01/24 15:32:08 florian Exp $ */ +/* $OpenBSD: resolver.c,v 1.3 2019/01/24 15:33:44 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -28,7 +28,6 @@ #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> -#include <arpa/nameser.h> #include <errno.h> #include <event.h> @@ -43,17 +42,22 @@ #include <time.h> #include <unistd.h> -#include <unbound.h> -#include <unbound-event.h> +#include <assert.h> +#include "libunbound/config.h" +#include "libunbound/libunbound/unbound.h" +#include "libunbound/unbound-event.h" +#include "libunbound/sldns/rrdef.h" +#include "libunbound/sldns/pkthdr.h" +#include "libunbound/sldns/sbuffer.h" +#include "libunbound/sldns/wire2str.h" #include <openssl/crypto.h> -#include "asr_private.h" #include "uw_log.h" #include "unwind.h" #include "resolver.h" -#define CHROOT_DIR "/etc/unwind" +#define CHROOT "/etc/unwind" #define DB_DIR "/trustanchor/" #define ROOT_KEY DB_DIR"root.key" @@ -163,7 +167,7 @@ resolver(int debug, int verbose) if ((pw = getpwnam(UNWIND_USER)) == NULL) fatal("getpwnam"); - if (chroot(CHROOT_DIR) == -1) + if (chroot(CHROOT) == -1) fatal("chroot"); if (chdir("/") == -1) fatal("chdir(\"/\")"); @@ -474,11 +478,10 @@ resolve_done(void *arg, int rcode, void *answer_packet, int answer_len, { struct query_imsg *query_imsg; struct unwind_resolver *res; - struct asr_unpack p; - struct asr_dns_header h; struct timespec tp, elapsed; int64_t ms; size_t i; + char *str; clock_gettime(CLOCK_MONOTONIC, &tp); @@ -504,19 +507,22 @@ resolve_done(void *arg, int rcode, void *answer_packet, int answer_len, log_debug("%s: rcode: %d", __func__, rcode); - _asr_unpack_init(&p, answer_packet, answer_len); - - if (_asr_unpack_header(&p, &h) == -1) { - log_warnx("bad packet: %s", strerror(p.err)); + if (answer_len < LDNS_HEADER_SIZE) { + log_warnx("bad packet: too short"); goto servfail; } - if (rcode == SERVFAIL) { + if (rcode == LDNS_RCODE_SERVFAIL) { if (res->stop != 1) check_resolver(res); goto servfail; } + if ((str = sldns_wire2str_pkt(answer_packet, answer_len)) != NULL) { + log_debug("%s", str); + free(str); + } + query_imsg->err = 0; if (res->state == VALIDATING) @@ -748,7 +754,8 @@ check_resolver(struct unwind_resolver *res) data->check_res = check_res; data->res = res; - if ((err = ub_resolve_event(check_res->ctx, ".", T_NS, C_IN, data, + if ((err = ub_resolve_event(check_res->ctx, ".", LDNS_RR_TYPE_NS, + LDNS_RR_CLASS_IN, data, check_resolver_done, NULL)) != 0) { log_warn("%s: ub_resolve_event: err: %d, %s", __func__, err, ub_strerror(err)); @@ -763,26 +770,28 @@ check_resolver_done(void *arg, int rcode, void *answer_packet, int answer_len, int sec, char *why_bogus, int was_ratelimited) { struct check_resolver_data *data; - struct asr_unpack p; - struct asr_dns_header h; + char *str; data = (struct check_resolver_data *)arg; log_debug("%s: rcode: %d", __func__, rcode); - _asr_unpack_init(&p, answer_packet, answer_len); - - if (_asr_unpack_header(&p, &h) == -1) { + if (answer_len < LDNS_HEADER_SIZE) { data->res->state = DEAD; - log_warnx("bad packet: %s", strerror(p.err)); + log_warnx("bad packet: too short"); goto out; } - if (rcode == SERVFAIL) { + if (rcode == LDNS_RCODE_SERVFAIL) { data->res->state = DEAD; goto out; } + if ((str = sldns_wire2str_pkt(answer_packet, answer_len)) != NULL) { + log_debug("%s", str); + free(str); + } + if (sec == 2) data->res->state = VALIDATING; else if (rcode == 0) { |