1*92f75510Seric /* $OpenBSD: asr_debug.c,v 1.23 2017/02/17 22:24:45 eric Exp $ */ 2b44da627Seric /* 3d4cf23afSeric * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 4b44da627Seric * 5b44da627Seric * Permission to use, copy, modify, and distribute this software for any 6b44da627Seric * purpose with or without fee is hereby granted, provided that the above 7b44da627Seric * copyright notice and this permission notice appear in all copies. 8b44da627Seric * 9b44da627Seric * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10b44da627Seric * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11b44da627Seric * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12b44da627Seric * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13b44da627Seric * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14b44da627Seric * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15b44da627Seric * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16b44da627Seric */ 1780f48568Seric 18b44da627Seric #include <sys/types.h> 19b44da627Seric #include <sys/socket.h> 20b44da627Seric #include <netinet/in.h> 21b44da627Seric #include <arpa/nameser.h> 22d4cf23afSeric #include <arpa/inet.h> 23d216d6b1Seric #include <netdb.h> 24b44da627Seric 25d216d6b1Seric #include <asr.h> 26b44da627Seric #include <resolv.h> 27*92f75510Seric #include <string.h> 28b44da627Seric 29b44da627Seric #include "asr_private.h" 30b44da627Seric 31b44da627Seric static const char *rcodetostr(uint16_t); 32d4cf23afSeric static const char *print_dname(const char *, char *, size_t); 33f90bf415Seric static const char *print_header(const struct asr_dns_header *, char *, size_t); 34f90bf415Seric static const char *print_query(const struct asr_dns_query *, char *, size_t); 35f90bf415Seric static const char *print_rr(const struct asr_dns_rr *, char *, size_t); 36b44da627Seric 3755f55055Seric FILE *_asr_debug = NULL; 38b44da627Seric 39b44da627Seric #define OPCODE_SHIFT 11 40b44da627Seric #define Z_SHIFT 4 41b44da627Seric 42b44da627Seric static const char * 43b44da627Seric rcodetostr(uint16_t v) 44b44da627Seric { 45d4cf23afSeric switch (v) { 46d4cf23afSeric case NOERROR: return "NOERROR"; 47d4cf23afSeric case FORMERR: return "FORMERR"; 48d4cf23afSeric case SERVFAIL: return "SERVFAIL"; 49d4cf23afSeric case NXDOMAIN: return "NXDOMAIN"; 50d4cf23afSeric case NOTIMP: return "NOTIMP"; 51d4cf23afSeric case REFUSED: return "REFUSED"; 52d4cf23afSeric default: return "?"; 53d4cf23afSeric } 54b44da627Seric } 55b44da627Seric 56b44da627Seric static const char * 57d4cf23afSeric print_dname(const char *_dname, char *buf, size_t max) 58b44da627Seric { 59253ef892Sderaadt return (_asr_strdname(_dname, buf, max)); 60b44da627Seric } 61b44da627Seric 62d4cf23afSeric static const char * 63f90bf415Seric print_rr(const struct asr_dns_rr *rr, char *buf, size_t max) 64b44da627Seric { 65b44da627Seric char *res; 66b44da627Seric char tmp[256]; 67b44da627Seric char tmp2[256]; 68b44da627Seric int r; 69b44da627Seric 70b44da627Seric res = buf; 71b44da627Seric 72b44da627Seric r = snprintf(buf, max, "%s %u %s %s ", 73b44da627Seric print_dname(rr->rr_dname, tmp, sizeof tmp), 74b44da627Seric rr->rr_ttl, 75d4cf23afSeric __p_class(rr->rr_class), 76d4cf23afSeric __p_type(rr->rr_type)); 77b44da627Seric if (r == -1) { 78b44da627Seric buf[0] = '\0'; 79d4cf23afSeric return (buf); 80b44da627Seric } 81b44da627Seric 82b44da627Seric if ((size_t)r >= max) 83d4cf23afSeric return (buf); 84b44da627Seric 85b44da627Seric max -= r; 86b44da627Seric buf += r; 87b44da627Seric 88b44da627Seric switch (rr->rr_type) { 89b44da627Seric case T_CNAME: 90b44da627Seric print_dname(rr->rr.cname.cname, buf, max); 91b44da627Seric break; 92b44da627Seric case T_MX: 93d4cf23afSeric snprintf(buf, max, "%lu %s", 94d4cf23afSeric (unsigned long)rr->rr.mx.preference, 95b44da627Seric print_dname(rr->rr.mx.exchange, tmp, sizeof tmp)); 96b44da627Seric break; 97b44da627Seric case T_NS: 98b44da627Seric print_dname(rr->rr.ns.nsname, buf, max); 99b44da627Seric break; 100b44da627Seric case T_PTR: 101b44da627Seric print_dname(rr->rr.ptr.ptrname, buf, max); 102b44da627Seric break; 103b44da627Seric case T_SOA: 104d4cf23afSeric snprintf(buf, max, "%s %s %lu %lu %lu %lu %lu", 105b44da627Seric print_dname(rr->rr.soa.rname, tmp, sizeof tmp), 106b44da627Seric print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2), 107d4cf23afSeric (unsigned long)rr->rr.soa.serial, 108d4cf23afSeric (unsigned long)rr->rr.soa.refresh, 109d4cf23afSeric (unsigned long)rr->rr.soa.retry, 110d4cf23afSeric (unsigned long)rr->rr.soa.expire, 111d4cf23afSeric (unsigned long)rr->rr.soa.minimum); 112b44da627Seric break; 113b44da627Seric case T_A: 114b44da627Seric if (rr->rr_class != C_IN) 115b44da627Seric goto other; 116d4cf23afSeric snprintf(buf, max, "%s", inet_ntop(AF_INET, 117d4cf23afSeric &rr->rr.in_a.addr, tmp, sizeof tmp)); 118b44da627Seric break; 119b44da627Seric case T_AAAA: 120b44da627Seric if (rr->rr_class != C_IN) 121b44da627Seric goto other; 122d4cf23afSeric snprintf(buf, max, "%s", inet_ntop(AF_INET6, 123d4cf23afSeric &rr->rr.in_aaaa.addr6, tmp, sizeof tmp)); 124b44da627Seric break; 125b44da627Seric default: 126b44da627Seric other: 127d4cf23afSeric snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen); 128b44da627Seric break; 129b44da627Seric } 130b44da627Seric 131b44da627Seric return (res); 132b44da627Seric } 133b44da627Seric 134d4cf23afSeric static const char * 135f90bf415Seric print_query(const struct asr_dns_query *q, char *buf, size_t max) 136b44da627Seric { 137b44da627Seric char b[256]; 138b44da627Seric 139b44da627Seric snprintf(buf, max, "%s %s %s", 140b44da627Seric print_dname(q->q_dname, b, sizeof b), 141d4cf23afSeric __p_class(q->q_class), __p_type(q->q_type)); 142b44da627Seric 143b44da627Seric return (buf); 144b44da627Seric } 145b44da627Seric 146d4cf23afSeric static const char * 147f90bf415Seric print_header(const struct asr_dns_header *h, char *buf, size_t max) 148b44da627Seric { 149b44da627Seric snprintf(buf, max, 150b44da627Seric "id:0x%04x %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i", 151d4cf23afSeric ((int)h->id), 152b44da627Seric (h->flags & QR_MASK) ? "QR":" ", 153b44da627Seric (int)(OPCODE(h->flags) >> OPCODE_SHIFT), 154b44da627Seric (h->flags & AA_MASK) ? "AA":" ", 155b44da627Seric (h->flags & TC_MASK) ? "TC":" ", 156b44da627Seric (h->flags & RD_MASK) ? "RD":" ", 157b44da627Seric (h->flags & RA_MASK) ? "RA":" ", 158b44da627Seric ((h->flags & Z_MASK) >> Z_SHIFT), 159b44da627Seric rcodetostr(RCODE(h->flags)), 160b44da627Seric h->qdcount, h->ancount, h->nscount, h->arcount); 161b44da627Seric 162b44da627Seric return (buf); 163b44da627Seric } 164b44da627Seric 165b44da627Seric void 166253ef892Sderaadt _asr_dump_packet(FILE *f, const void *data, size_t len) 167b44da627Seric { 168b44da627Seric char buf[1024]; 169f90bf415Seric struct asr_unpack p; 170f90bf415Seric struct asr_dns_header h; 171f90bf415Seric struct asr_dns_query q; 172f90bf415Seric struct asr_dns_rr rr; 173b44da627Seric int i, an, ns, ar, n; 174b44da627Seric 175b44da627Seric if (f == NULL) 176b44da627Seric return; 177b44da627Seric 178253ef892Sderaadt _asr_unpack_init(&p, data, len); 179b44da627Seric 180253ef892Sderaadt if (_asr_unpack_header(&p, &h) == -1) { 181*92f75510Seric fprintf(f, ";; BAD PACKET: %s\n", strerror(p.err)); 182b44da627Seric return; 183b44da627Seric } 184b44da627Seric 185d4cf23afSeric fprintf(f, ";; HEADER %s\n", print_header(&h, buf, sizeof buf)); 186b44da627Seric 187b44da627Seric if (h.qdcount) 188b44da627Seric fprintf(f, ";; QUERY SECTION:\n"); 189b44da627Seric for (i = 0; i < h.qdcount; i++) { 190253ef892Sderaadt if (_asr_unpack_query(&p, &q) == -1) 191b44da627Seric goto error; 192b44da627Seric fprintf(f, "%s\n", print_query(&q, buf, sizeof buf)); 193b44da627Seric } 194b44da627Seric 195b44da627Seric an = 0; 196b44da627Seric ns = an + h.ancount; 197b44da627Seric ar = ns + h.nscount; 198b44da627Seric n = ar + h.arcount; 199b44da627Seric 200b44da627Seric for (i = 0; i < n; i++) { 201b44da627Seric if (i == an) 202b44da627Seric fprintf(f, "\n;; ANSWER SECTION:\n"); 203b44da627Seric if (i == ns) 204b44da627Seric fprintf(f, "\n;; AUTHORITY SECTION:\n"); 205b44da627Seric if (i == ar) 206b44da627Seric fprintf(f, "\n;; ADDITIONAL SECTION:\n"); 207b44da627Seric 208253ef892Sderaadt if (_asr_unpack_rr(&p, &rr) == -1) 209b44da627Seric goto error; 210b44da627Seric fprintf(f, "%s\n", print_rr(&rr, buf, sizeof buf)); 211b44da627Seric } 212b44da627Seric 213b44da627Seric if (p.offset != len) 214b44da627Seric fprintf(f, ";; REMAINING GARBAGE %zu\n", len - p.offset); 215b44da627Seric 216b44da627Seric error: 217b44da627Seric if (p.err) 218b44da627Seric fprintf(f, ";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len, 219*92f75510Seric strerror(p.err)); 220b44da627Seric } 221b44da627Seric 222d4cf23afSeric const char * 223253ef892Sderaadt _asr_print_sockaddr(const struct sockaddr *sa, char *buf, size_t len) 224b44da627Seric { 225d4cf23afSeric char h[256]; 226d4cf23afSeric int portno; 227d4cf23afSeric union { 228d4cf23afSeric const struct sockaddr *sa; 229d4cf23afSeric const struct sockaddr_in *sin; 230d4cf23afSeric const struct sockaddr_in6 *sin6; 231d4cf23afSeric } s; 232b44da627Seric 233d4cf23afSeric s.sa = sa; 23446ab4803Seric 235d4cf23afSeric switch (sa->sa_family) { 236d4cf23afSeric case AF_INET: 237d4cf23afSeric inet_ntop(AF_INET, &s.sin->sin_addr, h, sizeof h); 238d4cf23afSeric portno = ntohs(s.sin->sin_port); 239d4cf23afSeric break; 240d4cf23afSeric case AF_INET6: 241d4cf23afSeric inet_ntop(AF_INET6, &s.sin6->sin6_addr, h, sizeof h); 242d4cf23afSeric portno = ntohs(s.sin6->sin6_port); 243d4cf23afSeric break; 244d4cf23afSeric default: 245d4cf23afSeric snprintf(buf, len, "?"); 246d4cf23afSeric return (buf); 247d4cf23afSeric } 248d4cf23afSeric 249d4cf23afSeric snprintf(buf, len, "%s:%i", h, portno); 250d4cf23afSeric return (buf); 251b44da627Seric } 252b44da627Seric 253b44da627Seric void 254253ef892Sderaadt _asr_dump_config(FILE *f, struct asr *a) 255b44da627Seric { 256d4cf23afSeric char buf[256]; 257d4cf23afSeric int i; 258d4cf23afSeric struct asr_ctx *ac; 259d4cf23afSeric unsigned int o; 260d4cf23afSeric 261d4cf23afSeric if (f == NULL) 262d4cf23afSeric return; 263d4cf23afSeric 264d4cf23afSeric ac = a->a_ctx; 265d4cf23afSeric 266d4cf23afSeric fprintf(f, "--------- ASR CONFIG ---------------\n"); 267d4cf23afSeric fprintf(f, "DOMAIN \"%s\"\n", ac->ac_domain); 268d4cf23afSeric fprintf(f, "SEARCH\n"); 269d4cf23afSeric for (i = 0; i < ac->ac_domcount; i++) 270d4cf23afSeric fprintf(f, " \"%s\"\n", ac->ac_dom[i]); 271d4cf23afSeric fprintf(f, "OPTIONS\n"); 272d4cf23afSeric fprintf(f, " options:"); 273d4cf23afSeric o = ac->ac_options; 274d4cf23afSeric 275d4cf23afSeric #define PRINTOPT(flag, n) if (o & (flag)) { fprintf(f, " " n); o &= ~(flag); } 276d4cf23afSeric PRINTOPT(RES_INIT, "INIT"); 277d4cf23afSeric PRINTOPT(RES_DEBUG, "DEBUG"); 278d4cf23afSeric PRINTOPT(RES_USEVC, "USEVC"); 279d4cf23afSeric PRINTOPT(RES_IGNTC, "IGNTC"); 280d4cf23afSeric PRINTOPT(RES_RECURSE, "RECURSE"); 281d4cf23afSeric PRINTOPT(RES_DEFNAMES, "DEFNAMES"); 282d4cf23afSeric PRINTOPT(RES_STAYOPEN, "STAYOPEN"); 283d4cf23afSeric PRINTOPT(RES_DNSRCH, "DNSRCH"); 284d4cf23afSeric PRINTOPT(RES_NOALIASES, "NOALIASES"); 285d4cf23afSeric PRINTOPT(RES_USE_EDNS0, "USE_EDNS0"); 286d4cf23afSeric PRINTOPT(RES_USE_DNSSEC, "USE_DNSSEC"); 287d4cf23afSeric if (o) 288d4cf23afSeric fprintf(f, " 0x%08x", o); 289d4cf23afSeric fprintf(f, "\n"); 290d4cf23afSeric 291d4cf23afSeric fprintf(f, " ndots: %i\n", ac->ac_ndots); 292d4cf23afSeric fprintf(f, " family:"); 293d4cf23afSeric for (i = 0; ac->ac_family[i] != -1; i++) 2946a166a79Sotto fprintf(f, " %s", (ac->ac_family[i] == AF_INET)?"inet4":"inet6"); 295d4cf23afSeric fprintf(f, "\n"); 296d4cf23afSeric fprintf(f, "NAMESERVERS timeout=%i retry=%i\n", 297d4cf23afSeric ac->ac_nstimeout, 298d4cf23afSeric ac->ac_nsretries); 299d4cf23afSeric for (i = 0; i < ac->ac_nscount; i++) 300253ef892Sderaadt fprintf(f, " %s\n", _asr_print_sockaddr(ac->ac_ns[i], buf, 301d4cf23afSeric sizeof buf)); 3021ed934d0Seric fprintf(f, "LOOKUP %s", ac->ac_db); 303d4cf23afSeric fprintf(f, "\n------------------------------------\n"); 304d4cf23afSeric } 305d4cf23afSeric 306d4cf23afSeric #define CASE(n) case n: return #n 307d4cf23afSeric 308d4cf23afSeric const char * 309253ef892Sderaadt _asr_statestr(int state) 310d4cf23afSeric { 311d4cf23afSeric switch (state) { 312d4cf23afSeric CASE(ASR_STATE_INIT); 313d4cf23afSeric CASE(ASR_STATE_NEXT_DOMAIN); 314d4cf23afSeric CASE(ASR_STATE_NEXT_DB); 315d4cf23afSeric CASE(ASR_STATE_SAME_DB); 316d4cf23afSeric CASE(ASR_STATE_NEXT_FAMILY); 317d4cf23afSeric CASE(ASR_STATE_NEXT_NS); 318d4cf23afSeric CASE(ASR_STATE_UDP_SEND); 319d4cf23afSeric CASE(ASR_STATE_UDP_RECV); 320d4cf23afSeric CASE(ASR_STATE_TCP_WRITE); 321d4cf23afSeric CASE(ASR_STATE_TCP_READ); 322d4cf23afSeric CASE(ASR_STATE_PACKET); 323d4cf23afSeric CASE(ASR_STATE_SUBQUERY); 324d4cf23afSeric CASE(ASR_STATE_NOT_FOUND); 325d4cf23afSeric CASE(ASR_STATE_HALT); 326d4cf23afSeric default: 327d4cf23afSeric return "?"; 328d4cf23afSeric } 329d4cf23afSeric }; 330d4cf23afSeric 331d4cf23afSeric const char * 332253ef892Sderaadt _asr_querystr(int type) 333d4cf23afSeric { 334d4cf23afSeric switch (type) { 335d4cf23afSeric CASE(ASR_SEND); 336d4cf23afSeric CASE(ASR_SEARCH); 337d4cf23afSeric CASE(ASR_GETRRSETBYNAME); 338d4cf23afSeric CASE(ASR_GETHOSTBYNAME); 339d4cf23afSeric CASE(ASR_GETHOSTBYADDR); 340d4cf23afSeric CASE(ASR_GETNETBYNAME); 341d4cf23afSeric CASE(ASR_GETNETBYADDR); 342d4cf23afSeric CASE(ASR_GETADDRINFO); 343d4cf23afSeric CASE(ASR_GETNAMEINFO); 344d4cf23afSeric default: 345d4cf23afSeric return "?"; 346d4cf23afSeric } 347d4cf23afSeric } 348d4cf23afSeric 349d4cf23afSeric const char * 350253ef892Sderaadt _asr_transitionstr(int type) 351d4cf23afSeric { 352d4cf23afSeric switch (type) { 353d4cf23afSeric CASE(ASYNC_COND); 354d4cf23afSeric CASE(ASYNC_DONE); 355d4cf23afSeric default: 356d4cf23afSeric return "?"; 357d4cf23afSeric } 358b44da627Seric } 359