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