1*d4cf23afSeric /* $OpenBSD: asr_debug.c,v 1.8 2012/09/09 12:15:32 eric Exp $ */ 2b44da627Seric /* 3*d4cf23afSeric * 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 */ 17b44da627Seric #include <sys/types.h> 18b44da627Seric #include <sys/socket.h> 19b44da627Seric 20b44da627Seric #include <netinet/in.h> 21b44da627Seric #include <arpa/nameser.h> 22*d4cf23afSeric #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); 30*d4cf23afSeric static const char* print_dname(const char *, char *, size_t); 31*d4cf23afSeric static const char* print_header(const struct header *, char *, size_t); 32*d4cf23afSeric static const char* print_query(const struct query *, char *, size_t); 33*d4cf23afSeric static const char* print_rr(const struct rr*, char *, size_t); 34b44da627Seric 35*d4cf23afSeric 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 { 43*d4cf23afSeric switch(v) { 44*d4cf23afSeric case NOERROR: return "NOERROR"; 45*d4cf23afSeric case FORMERR: return "FORMERR"; 46*d4cf23afSeric case SERVFAIL: return "SERVFAIL"; 47*d4cf23afSeric case NXDOMAIN: return "NXDOMAIN"; 48*d4cf23afSeric case NOTIMP: return "NOTIMP"; 49*d4cf23afSeric case REFUSED: return "REFUSED"; 50*d4cf23afSeric default: return "?"; 51*d4cf23afSeric } 52b44da627Seric } 53b44da627Seric 54b44da627Seric static const char* 55*d4cf23afSeric print_dname(const char *_dname, char *buf, size_t max) 56b44da627Seric { 57*d4cf23afSeric return (asr_strdname(_dname, buf, max)); 58b44da627Seric } 59b44da627Seric 60*d4cf23afSeric static const char* 61*d4cf23afSeric 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, 73*d4cf23afSeric __p_class(rr->rr_class), 74*d4cf23afSeric __p_type(rr->rr_type)); 75b44da627Seric if (r == -1) { 76b44da627Seric buf[0] = '\0'; 77*d4cf23afSeric return (buf); 78b44da627Seric } 79b44da627Seric 80b44da627Seric if ((size_t)r >= max) 81*d4cf23afSeric 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: 91*d4cf23afSeric snprintf(buf, max, "%lu %s", 92*d4cf23afSeric (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: 102*d4cf23afSeric 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), 105*d4cf23afSeric (unsigned long)rr->rr.soa.serial, 106*d4cf23afSeric (unsigned long)rr->rr.soa.refresh, 107*d4cf23afSeric (unsigned long)rr->rr.soa.retry, 108*d4cf23afSeric (unsigned long)rr->rr.soa.expire, 109*d4cf23afSeric (unsigned long)rr->rr.soa.minimum); 110b44da627Seric break; 111b44da627Seric case T_A: 112b44da627Seric if (rr->rr_class != C_IN) 113b44da627Seric goto other; 114*d4cf23afSeric snprintf(buf, max, "%s", inet_ntop(AF_INET, 115*d4cf23afSeric &rr->rr.in_a.addr, tmp, sizeof tmp)); 116b44da627Seric break; 117b44da627Seric case T_AAAA: 118b44da627Seric if (rr->rr_class != C_IN) 119b44da627Seric goto other; 120*d4cf23afSeric snprintf(buf, max, "%s", inet_ntop(AF_INET6, 121*d4cf23afSeric &rr->rr.in_aaaa.addr6, tmp, sizeof tmp)); 122b44da627Seric break; 123b44da627Seric default: 124b44da627Seric other: 125*d4cf23afSeric snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen); 126b44da627Seric break; 127b44da627Seric } 128b44da627Seric 129b44da627Seric return (res); 130b44da627Seric } 131b44da627Seric 132*d4cf23afSeric static const char* 133*d4cf23afSeric 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), 139*d4cf23afSeric __p_class(q->q_class), __p_type(q->q_type)); 140b44da627Seric 141b44da627Seric return (buf); 142b44da627Seric } 143b44da627Seric 144*d4cf23afSeric static const char* 145*d4cf23afSeric 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", 149*d4cf23afSeric ((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 164*d4cf23afSeric asr_dump_packet(FILE *f, const void *data, size_t len) 165b44da627Seric { 166b44da627Seric char buf[1024]; 167b44da627Seric struct packed 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 176b44da627Seric packed_init(&p, (char *)data, len); 177b44da627Seric 178b44da627Seric if (unpack_header(&p, &h) == -1) { 179b44da627Seric fprintf(f, ";; BAD PACKET: %s\n", p.err); 180b44da627Seric return; 181b44da627Seric } 182b44da627Seric 183*d4cf23afSeric 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 220*d4cf23afSeric const char * 221*d4cf23afSeric print_sockaddr(const struct sockaddr *sa, char *buf, size_t len) 222b44da627Seric { 223*d4cf23afSeric char h[256]; 224*d4cf23afSeric int portno; 225*d4cf23afSeric union { 226*d4cf23afSeric const struct sockaddr *sa; 227*d4cf23afSeric const struct sockaddr_in *sin; 228*d4cf23afSeric const struct sockaddr_in6 *sin6; 229*d4cf23afSeric } s; 230b44da627Seric 231*d4cf23afSeric s.sa = sa; 23246ab4803Seric 233*d4cf23afSeric switch (sa->sa_family) { 234*d4cf23afSeric case AF_INET: 235*d4cf23afSeric inet_ntop(AF_INET, &s.sin->sin_addr, h, sizeof h); 236*d4cf23afSeric portno = ntohs(s.sin->sin_port); 237*d4cf23afSeric break; 238*d4cf23afSeric case AF_INET6: 239*d4cf23afSeric inet_ntop(AF_INET6, &s.sin6->sin6_addr, h, sizeof h); 240*d4cf23afSeric portno = ntohs(s.sin6->sin6_port); 241*d4cf23afSeric break; 242*d4cf23afSeric default: 243*d4cf23afSeric snprintf(buf, len, "?"); 244*d4cf23afSeric return (buf); 245*d4cf23afSeric } 246*d4cf23afSeric 247*d4cf23afSeric snprintf(buf, len, "%s:%i", h, portno); 248*d4cf23afSeric return (buf); 249b44da627Seric } 250b44da627Seric 251b44da627Seric void 252*d4cf23afSeric asr_dump_config(FILE *f, struct asr *a) 253b44da627Seric { 254*d4cf23afSeric char buf[256]; 255*d4cf23afSeric int i; 256*d4cf23afSeric struct asr_ctx *ac; 257*d4cf23afSeric unsigned int o; 258*d4cf23afSeric 259*d4cf23afSeric if (f == NULL) 260*d4cf23afSeric return; 261*d4cf23afSeric 262*d4cf23afSeric ac = a->a_ctx; 263*d4cf23afSeric 264*d4cf23afSeric fprintf(f, "--------- ASR CONFIG ---------------\n"); 265*d4cf23afSeric if (a->a_path) 266*d4cf23afSeric fprintf(f, "CONF FILE \"%s\"\n", a->a_path); 267*d4cf23afSeric else 268*d4cf23afSeric fprintf(f, "STATIC CONF\n"); 269*d4cf23afSeric fprintf(f, "DOMAIN \"%s\"\n", ac->ac_domain); 270*d4cf23afSeric fprintf(f, "SEARCH\n"); 271*d4cf23afSeric for(i = 0; i < ac->ac_domcount; i++) 272*d4cf23afSeric fprintf(f, " \"%s\"\n", ac->ac_dom[i]); 273*d4cf23afSeric fprintf(f, "OPTIONS\n"); 274*d4cf23afSeric fprintf(f, " options:"); 275*d4cf23afSeric o = ac->ac_options; 276*d4cf23afSeric 277*d4cf23afSeric #define PRINTOPT(flag, n) if (o & (flag)) { fprintf(f, " " n); o &= ~(flag); } 278*d4cf23afSeric PRINTOPT(RES_INIT, "INIT"); 279*d4cf23afSeric PRINTOPT(RES_DEBUG, "DEBUG"); 280*d4cf23afSeric PRINTOPT(RES_USEVC, "USEVC"); 281*d4cf23afSeric PRINTOPT(RES_IGNTC, "IGNTC"); 282*d4cf23afSeric PRINTOPT(RES_RECURSE, "RECURSE"); 283*d4cf23afSeric PRINTOPT(RES_DEFNAMES, "DEFNAMES"); 284*d4cf23afSeric PRINTOPT(RES_STAYOPEN, "STAYOPEN"); 285*d4cf23afSeric PRINTOPT(RES_DNSRCH, "DNSRCH"); 286*d4cf23afSeric PRINTOPT(RES_NOALIASES, "NOALIASES"); 287*d4cf23afSeric PRINTOPT(RES_USE_EDNS0, "USE_EDNS0"); 288*d4cf23afSeric PRINTOPT(RES_USE_DNSSEC, "USE_DNSSEC"); 289*d4cf23afSeric if (o) 290*d4cf23afSeric fprintf(f, " 0x%08x", o); 291*d4cf23afSeric fprintf(f, "\n"); 292*d4cf23afSeric 293*d4cf23afSeric fprintf(f, " ndots: %i\n", ac->ac_ndots); 294*d4cf23afSeric fprintf(f, " family:"); 295*d4cf23afSeric for(i = 0; ac->ac_family[i] != -1; i++) 296*d4cf23afSeric fprintf(f, " %s", (ac->ac_family[i] == AF_INET)?"inet":"inet6"); 297*d4cf23afSeric fprintf(f, "\n"); 298*d4cf23afSeric fprintf(f, "NAMESERVERS timeout=%i retry=%i\n", 299*d4cf23afSeric ac->ac_nstimeout, 300*d4cf23afSeric ac->ac_nsretries); 301*d4cf23afSeric for(i = 0; i < ac->ac_nscount; i++) 302*d4cf23afSeric fprintf(f, " %s\n", print_sockaddr(ac->ac_ns[i], buf, 303*d4cf23afSeric sizeof buf)); 304*d4cf23afSeric fprintf(f, "HOSTFILE %s\n", ac->ac_hostfile); 305*d4cf23afSeric fprintf(f, "LOOKUP"); 306*d4cf23afSeric for(i = 0; i < ac->ac_dbcount; i++) { 307*d4cf23afSeric switch (ac->ac_db[i]) { 308*d4cf23afSeric case ASR_DB_FILE: 309*d4cf23afSeric fprintf(f, " file"); 310*d4cf23afSeric break; 311*d4cf23afSeric case ASR_DB_DNS: 312*d4cf23afSeric fprintf(f, " dns"); 313*d4cf23afSeric break; 314*d4cf23afSeric case ASR_DB_YP: 315*d4cf23afSeric fprintf(f, " yp"); 316*d4cf23afSeric break; 317*d4cf23afSeric default: 318*d4cf23afSeric fprintf(f, " ?%i", ac->ac_db[i]); 319*d4cf23afSeric } 320*d4cf23afSeric } 321*d4cf23afSeric fprintf(f, "\n------------------------------------\n"); 322*d4cf23afSeric } 323*d4cf23afSeric 324*d4cf23afSeric #define CASE(n) case n: return #n 325*d4cf23afSeric 326*d4cf23afSeric const char * 327*d4cf23afSeric asr_statestr(int state) 328*d4cf23afSeric { 329*d4cf23afSeric switch (state) { 330*d4cf23afSeric CASE(ASR_STATE_INIT); 331*d4cf23afSeric CASE(ASR_STATE_NEXT_DOMAIN); 332*d4cf23afSeric CASE(ASR_STATE_NEXT_DB); 333*d4cf23afSeric CASE(ASR_STATE_SAME_DB); 334*d4cf23afSeric CASE(ASR_STATE_NEXT_FAMILY); 335*d4cf23afSeric CASE(ASR_STATE_NEXT_NS); 336*d4cf23afSeric CASE(ASR_STATE_UDP_SEND); 337*d4cf23afSeric CASE(ASR_STATE_UDP_RECV); 338*d4cf23afSeric CASE(ASR_STATE_TCP_WRITE); 339*d4cf23afSeric CASE(ASR_STATE_TCP_READ); 340*d4cf23afSeric CASE(ASR_STATE_PACKET); 341*d4cf23afSeric CASE(ASR_STATE_SUBQUERY); 342*d4cf23afSeric CASE(ASR_STATE_NOT_FOUND); 343*d4cf23afSeric CASE(ASR_STATE_HALT); 344*d4cf23afSeric default: 345*d4cf23afSeric return "?"; 346*d4cf23afSeric } 347*d4cf23afSeric }; 348*d4cf23afSeric 349*d4cf23afSeric const char * 350*d4cf23afSeric asr_querystr(int type) 351*d4cf23afSeric { 352*d4cf23afSeric switch (type) { 353*d4cf23afSeric CASE(ASR_SEND); 354*d4cf23afSeric CASE(ASR_SEARCH); 355*d4cf23afSeric CASE(ASR_GETRRSETBYNAME); 356*d4cf23afSeric CASE(ASR_GETHOSTBYNAME); 357*d4cf23afSeric CASE(ASR_GETHOSTBYADDR); 358*d4cf23afSeric CASE(ASR_GETNETBYNAME); 359*d4cf23afSeric CASE(ASR_GETNETBYADDR); 360*d4cf23afSeric CASE(ASR_GETADDRINFO); 361*d4cf23afSeric CASE(ASR_GETNAMEINFO); 362*d4cf23afSeric default: 363*d4cf23afSeric return "?"; 364*d4cf23afSeric } 365*d4cf23afSeric } 366*d4cf23afSeric 367*d4cf23afSeric const char * 368*d4cf23afSeric asr_transitionstr(int type) 369*d4cf23afSeric { 370*d4cf23afSeric switch(type) { 371*d4cf23afSeric CASE(ASYNC_COND); 372*d4cf23afSeric CASE(ASYNC_YIELD); 373*d4cf23afSeric CASE(ASYNC_DONE); 374*d4cf23afSeric default: 375*d4cf23afSeric return "?"; 376*d4cf23afSeric } 377b44da627Seric } 378