1*d216d6b1Seric /* $OpenBSD: asr_debug.c,v 1.17 2014/03/26 18:13:15 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> 23*d216d6b1Seric #include <netdb.h> 24b44da627Seric 25*d216d6b1Seric #include <asr.h> 26b44da627Seric #include <resolv.h> 27b44da627Seric 28b44da627Seric #include "asr_private.h" 29b44da627Seric 30b44da627Seric static const char *rcodetostr(uint16_t); 31d4cf23afSeric static const char *print_dname(const char *, char *, size_t); 32f90bf415Seric static const char *print_header(const struct asr_dns_header *, char *, size_t); 33f90bf415Seric static const char *print_query(const struct asr_dns_query *, char *, size_t); 34f90bf415Seric static const char *print_rr(const struct asr_dns_rr *, char *, size_t); 35b44da627Seric 36d4cf23afSeric FILE *asr_debug = NULL; 37b44da627Seric 38b44da627Seric #define OPCODE_SHIFT 11 39b44da627Seric #define Z_SHIFT 4 40b44da627Seric 41b44da627Seric static const char * 42b44da627Seric rcodetostr(uint16_t v) 43b44da627Seric { 44d4cf23afSeric switch (v) { 45d4cf23afSeric case NOERROR: return "NOERROR"; 46d4cf23afSeric case FORMERR: return "FORMERR"; 47d4cf23afSeric case SERVFAIL: return "SERVFAIL"; 48d4cf23afSeric case NXDOMAIN: return "NXDOMAIN"; 49d4cf23afSeric case NOTIMP: return "NOTIMP"; 50d4cf23afSeric case REFUSED: return "REFUSED"; 51d4cf23afSeric default: return "?"; 52d4cf23afSeric } 53b44da627Seric } 54b44da627Seric 55b44da627Seric static const char * 56d4cf23afSeric print_dname(const char *_dname, char *buf, size_t max) 57b44da627Seric { 58d4cf23afSeric return (asr_strdname(_dname, buf, max)); 59b44da627Seric } 60b44da627Seric 61d4cf23afSeric static const char * 62f90bf415Seric print_rr(const struct asr_dns_rr *rr, char *buf, size_t max) 63b44da627Seric { 64b44da627Seric char *res; 65b44da627Seric char tmp[256]; 66b44da627Seric char tmp2[256]; 67b44da627Seric int r; 68b44da627Seric 69b44da627Seric res = buf; 70b44da627Seric 71b44da627Seric r = snprintf(buf, max, "%s %u %s %s ", 72b44da627Seric print_dname(rr->rr_dname, tmp, sizeof tmp), 73b44da627Seric rr->rr_ttl, 74d4cf23afSeric __p_class(rr->rr_class), 75d4cf23afSeric __p_type(rr->rr_type)); 76b44da627Seric if (r == -1) { 77b44da627Seric buf[0] = '\0'; 78d4cf23afSeric return (buf); 79b44da627Seric } 80b44da627Seric 81b44da627Seric if ((size_t)r >= max) 82d4cf23afSeric return (buf); 83b44da627Seric 84b44da627Seric max -= r; 85b44da627Seric buf += r; 86b44da627Seric 87b44da627Seric switch (rr->rr_type) { 88b44da627Seric case T_CNAME: 89b44da627Seric print_dname(rr->rr.cname.cname, buf, max); 90b44da627Seric break; 91b44da627Seric case T_MX: 92d4cf23afSeric snprintf(buf, max, "%lu %s", 93d4cf23afSeric (unsigned long)rr->rr.mx.preference, 94b44da627Seric print_dname(rr->rr.mx.exchange, tmp, sizeof tmp)); 95b44da627Seric break; 96b44da627Seric case T_NS: 97b44da627Seric print_dname(rr->rr.ns.nsname, buf, max); 98b44da627Seric break; 99b44da627Seric case T_PTR: 100b44da627Seric print_dname(rr->rr.ptr.ptrname, buf, max); 101b44da627Seric break; 102b44da627Seric case T_SOA: 103d4cf23afSeric snprintf(buf, max, "%s %s %lu %lu %lu %lu %lu", 104b44da627Seric print_dname(rr->rr.soa.rname, tmp, sizeof tmp), 105b44da627Seric print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2), 106d4cf23afSeric (unsigned long)rr->rr.soa.serial, 107d4cf23afSeric (unsigned long)rr->rr.soa.refresh, 108d4cf23afSeric (unsigned long)rr->rr.soa.retry, 109d4cf23afSeric (unsigned long)rr->rr.soa.expire, 110d4cf23afSeric (unsigned long)rr->rr.soa.minimum); 111b44da627Seric break; 112b44da627Seric case T_A: 113b44da627Seric if (rr->rr_class != C_IN) 114b44da627Seric goto other; 115d4cf23afSeric snprintf(buf, max, "%s", inet_ntop(AF_INET, 116d4cf23afSeric &rr->rr.in_a.addr, tmp, sizeof tmp)); 117b44da627Seric break; 118b44da627Seric case T_AAAA: 119b44da627Seric if (rr->rr_class != C_IN) 120b44da627Seric goto other; 121d4cf23afSeric snprintf(buf, max, "%s", inet_ntop(AF_INET6, 122d4cf23afSeric &rr->rr.in_aaaa.addr6, tmp, sizeof tmp)); 123b44da627Seric break; 124b44da627Seric default: 125b44da627Seric other: 126d4cf23afSeric snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen); 127b44da627Seric break; 128b44da627Seric } 129b44da627Seric 130b44da627Seric return (res); 131b44da627Seric } 132b44da627Seric 133d4cf23afSeric static const char * 134f90bf415Seric print_query(const struct asr_dns_query *q, char *buf, size_t max) 135b44da627Seric { 136b44da627Seric char b[256]; 137b44da627Seric 138b44da627Seric snprintf(buf, max, "%s %s %s", 139b44da627Seric print_dname(q->q_dname, b, sizeof b), 140d4cf23afSeric __p_class(q->q_class), __p_type(q->q_type)); 141b44da627Seric 142b44da627Seric return (buf); 143b44da627Seric } 144b44da627Seric 145d4cf23afSeric static const char * 146f90bf415Seric print_header(const struct asr_dns_header *h, char *buf, size_t max) 147b44da627Seric { 148b44da627Seric snprintf(buf, max, 149b44da627Seric "id:0x%04x %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i", 150d4cf23afSeric ((int)h->id), 151b44da627Seric (h->flags & QR_MASK) ? "QR":" ", 152b44da627Seric (int)(OPCODE(h->flags) >> OPCODE_SHIFT), 153b44da627Seric (h->flags & AA_MASK) ? "AA":" ", 154b44da627Seric (h->flags & TC_MASK) ? "TC":" ", 155b44da627Seric (h->flags & RD_MASK) ? "RD":" ", 156b44da627Seric (h->flags & RA_MASK) ? "RA":" ", 157b44da627Seric ((h->flags & Z_MASK) >> Z_SHIFT), 158b44da627Seric rcodetostr(RCODE(h->flags)), 159b44da627Seric h->qdcount, h->ancount, h->nscount, h->arcount); 160b44da627Seric 161b44da627Seric return (buf); 162b44da627Seric } 163b44da627Seric 164b44da627Seric void 165d4cf23afSeric asr_dump_packet(FILE *f, const void *data, size_t len) 166b44da627Seric { 167b44da627Seric char buf[1024]; 168f90bf415Seric struct asr_unpack p; 169f90bf415Seric struct asr_dns_header h; 170f90bf415Seric struct asr_dns_query q; 171f90bf415Seric struct asr_dns_rr rr; 172b44da627Seric int i, an, ns, ar, n; 173b44da627Seric 174b44da627Seric if (f == NULL) 175b44da627Seric return; 176b44da627Seric 1775bd9e5c2Seric asr_unpack_init(&p, data, len); 178b44da627Seric 1795bd9e5c2Seric if (asr_unpack_header(&p, &h) == -1) { 180b44da627Seric fprintf(f, ";; BAD PACKET: %s\n", p.err); 181b44da627Seric return; 182b44da627Seric } 183b44da627Seric 184d4cf23afSeric fprintf(f, ";; HEADER %s\n", print_header(&h, buf, sizeof buf)); 185b44da627Seric 186b44da627Seric if (h.qdcount) 187b44da627Seric fprintf(f, ";; QUERY SECTION:\n"); 188b44da627Seric for (i = 0; i < h.qdcount; i++) { 1895bd9e5c2Seric if (asr_unpack_query(&p, &q) == -1) 190b44da627Seric goto error; 191b44da627Seric fprintf(f, "%s\n", print_query(&q, buf, sizeof buf)); 192b44da627Seric } 193b44da627Seric 194b44da627Seric an = 0; 195b44da627Seric ns = an + h.ancount; 196b44da627Seric ar = ns + h.nscount; 197b44da627Seric n = ar + h.arcount; 198b44da627Seric 199b44da627Seric for (i = 0; i < n; i++) { 200b44da627Seric if (i == an) 201b44da627Seric fprintf(f, "\n;; ANSWER SECTION:\n"); 202b44da627Seric if (i == ns) 203b44da627Seric fprintf(f, "\n;; AUTHORITY SECTION:\n"); 204b44da627Seric if (i == ar) 205b44da627Seric fprintf(f, "\n;; ADDITIONAL SECTION:\n"); 206b44da627Seric 2075bd9e5c2Seric if (asr_unpack_rr(&p, &rr) == -1) 208b44da627Seric goto error; 209b44da627Seric fprintf(f, "%s\n", print_rr(&rr, buf, sizeof buf)); 210b44da627Seric } 211b44da627Seric 212b44da627Seric if (p.offset != len) 213b44da627Seric fprintf(f, ";; REMAINING GARBAGE %zu\n", len - p.offset); 214b44da627Seric 215b44da627Seric error: 216b44da627Seric if (p.err) 217b44da627Seric fprintf(f, ";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len, 218b44da627Seric p.err); 219b44da627Seric } 220b44da627Seric 221d4cf23afSeric const char * 222d4cf23afSeric print_sockaddr(const struct sockaddr *sa, char *buf, size_t len) 223b44da627Seric { 224d4cf23afSeric char h[256]; 225d4cf23afSeric int portno; 226d4cf23afSeric union { 227d4cf23afSeric const struct sockaddr *sa; 228d4cf23afSeric const struct sockaddr_in *sin; 229d4cf23afSeric const struct sockaddr_in6 *sin6; 230d4cf23afSeric } s; 231b44da627Seric 232d4cf23afSeric s.sa = sa; 23346ab4803Seric 234d4cf23afSeric switch (sa->sa_family) { 235d4cf23afSeric case AF_INET: 236d4cf23afSeric inet_ntop(AF_INET, &s.sin->sin_addr, h, sizeof h); 237d4cf23afSeric portno = ntohs(s.sin->sin_port); 238d4cf23afSeric break; 239d4cf23afSeric case AF_INET6: 240d4cf23afSeric inet_ntop(AF_INET6, &s.sin6->sin6_addr, h, sizeof h); 241d4cf23afSeric portno = ntohs(s.sin6->sin6_port); 242d4cf23afSeric break; 243d4cf23afSeric default: 244d4cf23afSeric snprintf(buf, len, "?"); 245d4cf23afSeric return (buf); 246d4cf23afSeric } 247d4cf23afSeric 248d4cf23afSeric snprintf(buf, len, "%s:%i", h, portno); 249d4cf23afSeric return (buf); 250b44da627Seric } 251b44da627Seric 252b44da627Seric void 253d4cf23afSeric asr_dump_config(FILE *f, struct asr *a) 254b44da627Seric { 255d4cf23afSeric char buf[256]; 256d4cf23afSeric int i; 257d4cf23afSeric struct asr_ctx *ac; 258d4cf23afSeric unsigned int o; 259d4cf23afSeric 260d4cf23afSeric if (f == NULL) 261d4cf23afSeric return; 262d4cf23afSeric 263d4cf23afSeric ac = a->a_ctx; 264d4cf23afSeric 265d4cf23afSeric fprintf(f, "--------- ASR CONFIG ---------------\n"); 266d4cf23afSeric if (a->a_path) 267d4cf23afSeric fprintf(f, "CONF FILE \"%s\"\n", a->a_path); 268d4cf23afSeric else 269d4cf23afSeric fprintf(f, "STATIC CONF\n"); 270d4cf23afSeric fprintf(f, "DOMAIN \"%s\"\n", ac->ac_domain); 271d4cf23afSeric fprintf(f, "SEARCH\n"); 272d4cf23afSeric for (i = 0; i < ac->ac_domcount; i++) 273d4cf23afSeric fprintf(f, " \"%s\"\n", ac->ac_dom[i]); 274d4cf23afSeric fprintf(f, "OPTIONS\n"); 275d4cf23afSeric fprintf(f, " options:"); 276d4cf23afSeric o = ac->ac_options; 277d4cf23afSeric 278d4cf23afSeric #define PRINTOPT(flag, n) if (o & (flag)) { fprintf(f, " " n); o &= ~(flag); } 279d4cf23afSeric PRINTOPT(RES_INIT, "INIT"); 280d4cf23afSeric PRINTOPT(RES_DEBUG, "DEBUG"); 281d4cf23afSeric PRINTOPT(RES_USEVC, "USEVC"); 282d4cf23afSeric PRINTOPT(RES_IGNTC, "IGNTC"); 283d4cf23afSeric PRINTOPT(RES_RECURSE, "RECURSE"); 284d4cf23afSeric PRINTOPT(RES_DEFNAMES, "DEFNAMES"); 285d4cf23afSeric PRINTOPT(RES_STAYOPEN, "STAYOPEN"); 286d4cf23afSeric PRINTOPT(RES_DNSRCH, "DNSRCH"); 287d4cf23afSeric PRINTOPT(RES_NOALIASES, "NOALIASES"); 288d4cf23afSeric PRINTOPT(RES_USE_EDNS0, "USE_EDNS0"); 289d4cf23afSeric PRINTOPT(RES_USE_DNSSEC, "USE_DNSSEC"); 290d4cf23afSeric if (o) 291d4cf23afSeric fprintf(f, " 0x%08x", o); 292d4cf23afSeric fprintf(f, "\n"); 293d4cf23afSeric 294d4cf23afSeric fprintf(f, " ndots: %i\n", ac->ac_ndots); 295d4cf23afSeric fprintf(f, " family:"); 296d4cf23afSeric for (i = 0; ac->ac_family[i] != -1; i++) 2976a166a79Sotto fprintf(f, " %s", (ac->ac_family[i] == AF_INET)?"inet4":"inet6"); 298d4cf23afSeric fprintf(f, "\n"); 299d4cf23afSeric fprintf(f, "NAMESERVERS timeout=%i retry=%i\n", 300d4cf23afSeric ac->ac_nstimeout, 301d4cf23afSeric ac->ac_nsretries); 302d4cf23afSeric for (i = 0; i < ac->ac_nscount; i++) 303d4cf23afSeric fprintf(f, " %s\n", print_sockaddr(ac->ac_ns[i], buf, 304d4cf23afSeric sizeof buf)); 305d4cf23afSeric fprintf(f, "HOSTFILE %s\n", ac->ac_hostfile); 3061ed934d0Seric fprintf(f, "LOOKUP %s", ac->ac_db); 307d4cf23afSeric fprintf(f, "\n------------------------------------\n"); 308d4cf23afSeric } 309d4cf23afSeric 310d4cf23afSeric #define CASE(n) case n: return #n 311d4cf23afSeric 312d4cf23afSeric const char * 313d4cf23afSeric asr_statestr(int state) 314d4cf23afSeric { 315d4cf23afSeric switch (state) { 316d4cf23afSeric CASE(ASR_STATE_INIT); 317d4cf23afSeric CASE(ASR_STATE_NEXT_DOMAIN); 318d4cf23afSeric CASE(ASR_STATE_NEXT_DB); 319d4cf23afSeric CASE(ASR_STATE_SAME_DB); 320d4cf23afSeric CASE(ASR_STATE_NEXT_FAMILY); 321d4cf23afSeric CASE(ASR_STATE_NEXT_NS); 322d4cf23afSeric CASE(ASR_STATE_UDP_SEND); 323d4cf23afSeric CASE(ASR_STATE_UDP_RECV); 324d4cf23afSeric CASE(ASR_STATE_TCP_WRITE); 325d4cf23afSeric CASE(ASR_STATE_TCP_READ); 326d4cf23afSeric CASE(ASR_STATE_PACKET); 327d4cf23afSeric CASE(ASR_STATE_SUBQUERY); 328d4cf23afSeric CASE(ASR_STATE_NOT_FOUND); 329d4cf23afSeric CASE(ASR_STATE_HALT); 330d4cf23afSeric default: 331d4cf23afSeric return "?"; 332d4cf23afSeric } 333d4cf23afSeric }; 334d4cf23afSeric 335d4cf23afSeric const char * 336d4cf23afSeric asr_querystr(int type) 337d4cf23afSeric { 338d4cf23afSeric switch (type) { 339d4cf23afSeric CASE(ASR_SEND); 340d4cf23afSeric CASE(ASR_SEARCH); 341d4cf23afSeric CASE(ASR_GETRRSETBYNAME); 342d4cf23afSeric CASE(ASR_GETHOSTBYNAME); 343d4cf23afSeric CASE(ASR_GETHOSTBYADDR); 344d4cf23afSeric CASE(ASR_GETNETBYNAME); 345d4cf23afSeric CASE(ASR_GETNETBYADDR); 346d4cf23afSeric CASE(ASR_GETADDRINFO); 347d4cf23afSeric CASE(ASR_GETNAMEINFO); 348d4cf23afSeric default: 349d4cf23afSeric return "?"; 350d4cf23afSeric } 351d4cf23afSeric } 352d4cf23afSeric 353d4cf23afSeric const char * 354d4cf23afSeric asr_transitionstr(int type) 355d4cf23afSeric { 356d4cf23afSeric switch (type) { 357d4cf23afSeric CASE(ASYNC_COND); 358d4cf23afSeric CASE(ASYNC_DONE); 359d4cf23afSeric default: 360d4cf23afSeric return "?"; 361d4cf23afSeric } 362b44da627Seric } 363