ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt *query_pkt) { ldns_pkt *answer_pkt = NULL; ldns_status stat = LDNS_STATUS_OK; stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt); if (stat != LDNS_STATUS_OK) { if(answer_pkt) { ldns_pkt_free(answer_pkt); answer_pkt = NULL; } } else { /* if tc=1 fall back to EDNS and/or TCP */ /* check for tcp first (otherwise we don't care about tc=1) */ if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) { if (ldns_pkt_tc(answer_pkt)) { /* was EDNS0 set? */ if (ldns_pkt_edns_udp_size(query_pkt) == 0) { ldns_pkt_set_edns_udp_size(query_pkt, 4096); ldns_pkt_free(answer_pkt); stat = ldns_send(&answer_pkt, r, query_pkt); } /* either way, if it is still truncated, use TCP */ if (stat != LDNS_STATUS_OK || ldns_pkt_tc(answer_pkt)) { ldns_resolver_set_usevc(r, true); ldns_pkt_free(answer_pkt); stat = ldns_send(&answer_pkt, r, query_pkt); ldns_resolver_set_usevc(r, false); } } } } if (answer) { *answer = answer_pkt; } return stat; }
/** match all of the packet */ static int match_all(ldns_pkt* q, ldns_pkt* p) { if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p)) { verbose(3, "allmatch: opcode different"); return 0;} if(ldns_pkt_get_rcode(q) != ldns_pkt_get_rcode(p)) { verbose(3, "allmatch: rcode different"); return 0;} if(ldns_pkt_id(q) != ldns_pkt_id(p)) { verbose(3, "allmatch: id different"); return 0;} if(cmp_bool(ldns_pkt_qr(q), ldns_pkt_qr(p)) != 0) { verbose(3, "allmatch: qr different"); return 0;} if(cmp_bool(ldns_pkt_aa(q), ldns_pkt_aa(p)) != 0) { verbose(3, "allmatch: aa different"); return 0;} if(cmp_bool(ldns_pkt_tc(q), ldns_pkt_tc(p)) != 0) { verbose(3, "allmatch: tc different"); return 0;} if(cmp_bool(ldns_pkt_rd(q), ldns_pkt_rd(p)) != 0) { verbose(3, "allmatch: rd different"); return 0;} if(cmp_bool(ldns_pkt_cd(q), ldns_pkt_cd(p)) != 0) { verbose(3, "allmatch: cd different"); return 0;} if(cmp_bool(ldns_pkt_ra(q), ldns_pkt_ra(p)) != 0) { verbose(3, "allmatch: ra different"); return 0;} if(cmp_bool(ldns_pkt_ad(q), ldns_pkt_ad(p)) != 0) { verbose(3, "allmatch: ad different"); return 0;} if(ldns_pkt_qdcount(q) != ldns_pkt_qdcount(p)) { verbose(3, "allmatch: qdcount different"); return 0;} if(ldns_pkt_ancount(q) != ldns_pkt_ancount(p)) { verbose(3, "allmatch: ancount different"); return 0;} if(ldns_pkt_nscount(q) != ldns_pkt_nscount(p)) { verbose(3, "allmatch: nscount different"); return 0;} if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p)) { verbose(3, "allmatch: arcount different"); return 0;} if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p))) { verbose(3, "allmatch: qd section different"); return 0;} if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p))) { verbose(3, "allmatch: an section different"); return 0;} if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p))) { verbose(3, "allmatch: ns section different"); return 0;} if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p))) { verbose(3, "allmatch: ar section different"); return 0;} if(!match_edns(q, p)) { verbose(3, "edns different."); return 0;} return 1; }
void dnspkt_proc (const char *bytes, uint16_t len, struct timeval ts, host_t *src, host_t *dst) { ldns_pkt *pkt; if (ldns_wire2pkt(&pkt, bytes, len) != LDNS_STATUS_OK) { return; } if (ldns_pkt_get_opcode(pkt) != LDNS_PACKET_QUERY) goto done; uint16_t i; ldns_rr_list *rrlist; if (ldns_pkt_qr(pkt) == 0) { rrlist = ldns_pkt_question(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printqry(ldns_rr_list_rr(rrlist, i), ts, src, dst); } } else { dnspkt_printresp(pkt, ts, src, dst); if (ldns_pkt_aa(pkt) == 0) goto done; if (ldns_pkt_tc(pkt) == 1) goto done; if (ldns_pkt_rd(pkt) == 1) goto done; if (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) goto done; rrlist = ldns_pkt_answer(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printrr(ldns_rr_list_rr(rrlist, i), ts, src, dst, 0); } rrlist = ldns_pkt_authority(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printrr(ldns_rr_list_rr(rrlist, i), ts, src, dst, 1); } rrlist = ldns_pkt_additional(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printrr(ldns_rr_list_rr(rrlist, i), ts, src, dst, 2); } } done: ldns_pkt_free(pkt); }
void dnspkt_printresp (ldns_pkt *pkt, struct timeval ts, host_t *src, host_t *dst) { FILE *output = dnsfile_resp(); __print_ts(output, ts); __print_ip(output, src); __print_ip(output, dst); fprintf(output, "%u\t", (uint16_t)ldns_pkt_size(pkt)); fprintf(output, "%u\t", ldns_pkt_aa(pkt)); fprintf(output, "%u\t", ldns_pkt_tc(pkt)); fprintf(output, "%u\t", ldns_pkt_rd(pkt)); fprintf(output, "%u\t", ldns_pkt_ra(pkt)); fprintf(output, "%u\t", ldns_pkt_get_rcode(pkt)); fprintf(output, "%u\t", ldns_pkt_qdcount(pkt)); fprintf(output, "%u\t", ldns_pkt_ancount(pkt)); fprintf(output, "%u\t", ldns_pkt_nscount(pkt)); fprintf(output, "%u\t", ldns_pkt_arcount(pkt)); ldns_rr_list *rrlist = ldns_pkt_question(pkt); if (ldns_rr_list_rr_count(rrlist) > 0) { ldns_rr_print(output, ldns_rr_list_rr(rrlist, 0)); } else { fprintf(output, "\t\t\n"); } }
/* * Copies the packet header data to the buffer in wire format */ static ldns_status ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) { uint8_t flags; uint16_t arcount; if (ldns_buffer_reserve(buffer, 12)) { ldns_buffer_write_u16(buffer, ldns_pkt_id(packet)); flags = ldns_pkt_qr(packet) << 7 | ldns_pkt_get_opcode(packet) << 3 | ldns_pkt_aa(packet) << 2 | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet); ldns_buffer_write_u8(buffer, flags); flags = ldns_pkt_ra(packet) << 7 /*| ldns_pkt_z(packet) << 6*/ | ldns_pkt_ad(packet) << 5 | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet); ldns_buffer_write_u8(buffer, flags); ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet)); ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet)); ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet)); /* add EDNS0 and TSIG to additional if they are there */ arcount = ldns_pkt_arcount(packet); if (ldns_pkt_tsig(packet)) { arcount++; } if (ldns_pkt_edns(packet)) { arcount++; } ldns_buffer_write_u16(buffer, arcount); } return ldns_buffer_status(buffer); }
void dns_parser (packetinfo *pi) { ldns_status status; ldns_pkt *dns_pkt; status = LDNS_STATUS_ERR; /* In DNS tcp messages, the first 2 bytes signal the * amount of data to expect. So we need to skip them in the read. */ if (pi->plen <= 2) return; /* The minimum bytes in a packet - else return */ if ( pi->af == AF_INET ) { switch (pi->ip4->ip_p) { case IP_PROTO_TCP: status = ldns_wire2pkt(&dns_pkt,pi->payload + 2, pi->plen - 2); break; case IP_PROTO_UDP: status = ldns_wire2pkt(&dns_pkt,pi->payload, pi->plen); break; default: break; } } else if ( pi->af == AF_INET6 ) { switch (pi->ip6->next) { case IP_PROTO_TCP: status = ldns_wire2pkt(&dns_pkt,pi->payload + 2, pi->plen - 2); break; case IP_PROTO_UDP: status = ldns_wire2pkt(&dns_pkt,pi->payload, pi->plen); break; default: break; } } if (status != LDNS_STATUS_OK) { dlog("[D] ldns_wire2pkt status: %d\n", status); update_dns_stats(pi,ERROR); return; } /* We dont want to process Truncated packets */ if (ldns_pkt_tc(dns_pkt)) { dlog("[D] DNS packet with Truncated (TC) bit set! Skipping!\n"); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } /* we only care about answers when we record data */ if (ldns_pkt_qr(dns_pkt)) { /* Answer must come from the server, and the client has to have sent a packet! */ if ( pi->sc != SC_SERVER || pi->cxt->s_total_pkts == 0 ) { dlog("[D] DNS Answer without a Question?: Query TID = %d and Answer TID = %d\n",pi->cxt->plid,ldns_pkt_id(dns_pkt)); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } dlog("[D] DNS Answer\n"); /* Check the DNS TID */ if ( (pi->cxt->plid == ldns_pkt_id(dns_pkt)) ) { dlog("[D] DNS Query TID match Answer TID: %d\n", pi->cxt->plid); } else { dlog("[D] DNS Query TID did not match Answer TID: %d != %d - Skipping!\n", pi->cxt->plid, ldns_pkt_id(dns_pkt)); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } /* From isc.org wording: * We do not collect any of the query-response traffic that * occurs when the client sets the RD or "Recursion Desired" * bit to 1, that is, the traffic that occurs between DNS * "stub" clients and the caching server itself, since only the * traffic generated in response to a cache miss (RD bit set to 0) * is strictly needed in order to build a passive DNS database. */ if (ldns_pkt_rd(dns_pkt)) { dlog("[D] DNS packet with Recursion Desired (RD) bit set!\n"); /* Between DNS-server to DNS-server, we should drop this kind * of traffic if we are thinking hardening and correctness! * But for people trying this out in a corporate network etc, * between a client and a DNS proxy, will need this most likely * to see any traffic at all. In the future, this might be * controlled by a cmdline switch. */ //ldns_pkt_free(decoded_dns); //return; } if (!ldns_pkt_qdcount(dns_pkt)) { /* no questions or answers */ dlog("[D] DNS packet did not contain a question. Skipping!\n"); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } // send it off for processing if (process_dns_answer(pi, dns_pkt) < 0) { dlog("[D] process_dns_answer() returned -1\n"); } } else { /* We need to get the DNS TID from the Query to later match with the * DNS TID in the answer - to harden the implementation. */ /* Question must come from the client (and the server should not have sent a packet). */ if ( pi->sc != SC_CLIENT ) { dlog("[D] DNS Query not from a client? Skipping!\n"); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } /* Check for reuse of a session and a hack for * no timeout of sessions when reading pcaps atm. :/ * 60 Secs are default UDP timeout in cxt, and should * be enough for a TCP session of DNS too. */ if ( (pi->cxt->plid != 0 && pi->cxt->plid != ldns_pkt_id(dns_pkt)) && ((pi->cxt->last_pkt_time - pi->cxt->start_time) <= 60) ) { dlog("[D] DNS Query on an established DNS session - TID: Old:%d New:%d\n", pi->cxt->plid, ldns_pkt_id(dns_pkt)); /* Some clients have bad or strange random src * port generator and will gladly reuse the same * src port several times in a short time period. * To implment this fully, each cxt should be include * the TID in its tuple, but still this will make a mess :/ */ } else { dlog("[D] New DNS Query\n"); } if (!ldns_pkt_qdcount(dns_pkt)) { /* no questions or answers */ dlog("[D] DNS Query packet did not contain a question? Skipping!\n"); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } if ( (pi->cxt->plid = ldns_pkt_id(dns_pkt)) ) { dlog("[D] DNS Query with TID = %d\n", pi->cxt->plid); } else { dlog("[E] Error getting DNS TID from Query!\n"); ldns_pkt_free(dns_pkt); update_dns_stats(pi,ERROR); return; } /* For hardening, we can extract the query and add it to the cxt * and then check it later in the answer, that they match. */ /* if (update_query_cxt(pi, dns_pkt) < 0) { dlog("[D] update_query_cxt() returned -1\n"); } */ } ldns_pkt_free(dns_pkt); }
/** * Main function of drill * parse the arguments and prepare a query */ int main(int argc, char *argv[]) { ldns_resolver *res = NULL; ldns_resolver *cmdline_res = NULL; /* only used to resolv @name names */ ldns_rr_list *cmdline_rr_list = NULL; ldns_rdf *cmdline_dname = NULL; ldns_rdf *qname, *qname_tmp; ldns_pkt *pkt; ldns_pkt *qpkt; char *serv; const char *name; char *name2; char *progname; char *query_file = NULL; char *answer_file = NULL; ldns_buffer *query_buffer = NULL; ldns_rdf *serv_rdf; ldns_rr_type type; ldns_rr_class clas; #if 0 ldns_pkt_opcode opcode = LDNS_PACKET_QUERY; #endif int i, c; int int_type; int int_clas; int PURPOSE; char *tsig_name = NULL; char *tsig_data = NULL; char *tsig_algorithm = NULL; size_t tsig_separator; size_t tsig_separator2; ldns_rr *axfr_rr; ldns_status status; char *type_str; /* list of keys used in dnssec operations */ ldns_rr_list *key_list = ldns_rr_list_new(); /* what key verify the current answer */ ldns_rr_list *key_verified; /* resolver options */ uint16_t qflags; uint16_t qbuf; uint16_t qport; uint8_t qfamily; bool qdnssec; bool qfallback; bool qds; bool qusevc; bool qrandom; char *resolv_conf_file = NULL; ldns_rdf *trace_start_name = NULL; int result = 0; #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif int_type = -1; serv = NULL; type = 0; int_clas = -1; name = NULL; clas = 0; qname = NULL; progname = strdup(argv[0]); #ifdef USE_WINSOCK r = WSAStartup(MAKEWORD(2,2), &wsa_data); if(r != 0) { printf("Failed WSAStartup: %d\n", r); result = EXIT_FAILURE; goto exit; } #endif /* USE_WINSOCK */ PURPOSE = DRILL_QUERY; qflags = LDNS_RD; qport = LDNS_PORT; verbosity = 2; qdnssec = false; qfamily = LDNS_RESOLV_INETANY; qfallback = false; qds = false; qbuf = 0; qusevc = false; qrandom = true; key_verified = NULL; ldns_init_random(NULL, 0); if (argc == 0) { usage(stdout, progname); result = EXIT_FAILURE; goto exit; } /* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */ /* global first, query opt next, option with parm's last * and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */ while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:Ik:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) { switch(c) { /* global options */ case '4': qfamily = LDNS_RESOLV_INET; break; case '6': qfamily = LDNS_RESOLV_INET6; break; case 'D': qdnssec = true; break; case 'I': /* reserved for backward compatibility */ break; case 'T': if (PURPOSE == DRILL_CHASE) { fprintf(stderr, "-T and -S cannot be used at the same time.\n"); exit(EXIT_FAILURE); } PURPOSE = DRILL_TRACE; break; #ifdef HAVE_SSL case 'S': if (PURPOSE == DRILL_TRACE) { fprintf(stderr, "-T and -S cannot be used at the same time.\n"); exit(EXIT_FAILURE); } PURPOSE = DRILL_CHASE; break; #endif /* HAVE_SSL */ case 'V': if (strtok(optarg, "0123456789") != NULL) { fprintf(stderr, "-V expects an number as an argument.\n"); exit(EXIT_FAILURE); } verbosity = atoi(optarg); break; case 'Q': verbosity = -1; break; case 'f': query_file = optarg; break; case 'i': answer_file = optarg; PURPOSE = DRILL_AFROMFILE; break; case 'w': answer_file = optarg; break; case 'q': query_file = optarg; PURPOSE = DRILL_QTOFILE; break; case 'r': if (global_dns_root) { fprintf(stderr, "There was already a series of root servers set\n"); exit(EXIT_FAILURE); } global_dns_root = read_root_hints(optarg); if (!global_dns_root) { fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg); exit(EXIT_FAILURE); } break; /* query options */ case 'a': qfallback = true; break; case 'b': qbuf = (uint16_t)atoi(optarg); if (qbuf == 0) { error("%s", "<bufsize> could not be converted"); } break; case 'c': resolv_conf_file = optarg; break; case 't': qusevc = true; break; case 'k': status = read_key_file(optarg, key_list, false); if (status != LDNS_STATUS_OK) { error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status)); } qdnssec = true; /* enable that too */ break; case 'o': /* only looks at the first hit: capital=ON, lowercase=OFF*/ if (strstr(optarg, "QR")) { DRILL_ON(qflags, LDNS_QR); } if (strstr(optarg, "qr")) { DRILL_OFF(qflags, LDNS_QR); } if (strstr(optarg, "AA")) { DRILL_ON(qflags, LDNS_AA); } if (strstr(optarg, "aa")) { DRILL_OFF(qflags, LDNS_AA); } if (strstr(optarg, "TC")) { DRILL_ON(qflags, LDNS_TC); } if (strstr(optarg, "tc")) { DRILL_OFF(qflags, LDNS_TC); } if (strstr(optarg, "RD")) { DRILL_ON(qflags, LDNS_RD); } if (strstr(optarg, "rd")) { DRILL_OFF(qflags, LDNS_RD); } if (strstr(optarg, "CD")) { DRILL_ON(qflags, LDNS_CD); } if (strstr(optarg, "cd")) { DRILL_OFF(qflags, LDNS_CD); } if (strstr(optarg, "RA")) { DRILL_ON(qflags, LDNS_RA); } if (strstr(optarg, "ra")) { DRILL_OFF(qflags, LDNS_RA); } if (strstr(optarg, "AD")) { DRILL_ON(qflags, LDNS_AD); } if (strstr(optarg, "ad")) { DRILL_OFF(qflags, LDNS_AD); } break; case 'p': qport = (uint16_t)atoi(optarg); if (qport == 0) { error("%s", "<port> could not be converted"); } break; case 's': qds = true; break; case 'u': qusevc = false; break; case 'v': version(stdout, progname); result = EXIT_SUCCESS; goto exit; case 'x': PURPOSE = DRILL_REVERSE; break; case 'y': #ifdef HAVE_SSL if (strchr(optarg, ':')) { tsig_separator = (size_t) (strchr(optarg, ':') - optarg); if (strchr(optarg + tsig_separator + 1, ':')) { tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg); tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2); strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2); tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0'; } else { tsig_separator2 = strlen(optarg); tsig_algorithm = xmalloc(26); strncpy(tsig_algorithm, "hmac-md5.sig-alg.reg.int.", 25); tsig_algorithm[25] = '\0'; } tsig_name = xmalloc(tsig_separator + 1); tsig_data = xmalloc(tsig_separator2 - tsig_separator); strncpy(tsig_name, optarg, tsig_separator); strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1); /* strncpy does not append \0 if source is longer than n */ tsig_name[tsig_separator] = '\0'; tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0'; } #else fprintf(stderr, "TSIG requested, but SSL is not supported\n"); result = EXIT_FAILURE; goto exit; #endif /* HAVE_SSL */ break; case 'z': qrandom = false; break; case 'd': trace_start_name = ldns_dname_new_frm_str(optarg); if (!trace_start_name) { fprintf(stderr, "Unable to parse argument for -%c\n", c); result = EXIT_FAILURE; goto exit; } break; case 'h': version(stdout, progname); usage(stdout, progname); result = EXIT_SUCCESS; goto exit; break; default: fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c); result = EXIT_FAILURE; goto exit; } } argc -= optind; argv += optind; if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) && ldns_rr_list_rr_count(key_list) == 0) { (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true); } if (ldns_rr_list_rr_count(key_list) > 0) { printf(";; Number of trusted keys: %d\n", (int) ldns_rr_list_rr_count(key_list)); } /* do a secure trace when requested */ if (PURPOSE == DRILL_TRACE && qdnssec) { #ifdef HAVE_SSL if (ldns_rr_list_rr_count(key_list) == 0) { warning("%s", "No trusted keys were given. Will not be able to verify authenticity!"); } PURPOSE = DRILL_SECTRACE; #else fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n"); exit(1); #endif /* HAVE_SSL */ } /* parse the arguments, with multiple arguments, the last argument * found is used */ for(i = 0; i < argc; i++) { /* if ^@ then it's a server */ if (argv[i][0] == '@') { if (strlen(argv[i]) == 1) { warning("%s", "No nameserver given"); exit(EXIT_FAILURE); } serv = argv[i] + 1; continue; } /* if has a dot, it's a name */ if (strchr(argv[i], '.')) { name = argv[i]; continue; } /* if it matches a type, it's a type */ if (int_type == -1) { type = ldns_get_rr_type_by_name(argv[i]); if (type != 0) { int_type = 0; continue; } } /* if it matches a class, it's a class */ if (int_clas == -1) { clas = ldns_get_rr_class_by_name(argv[i]); if (clas != 0) { int_clas = 0; continue; } } /* it all fails assume it's a name */ name = argv[i]; } /* act like dig and use for . NS */ if (!name) { name = "."; int_type = 0; type = LDNS_RR_TYPE_NS; } /* defaults if not given */ if (int_clas == -1) { clas = LDNS_RR_CLASS_IN; } if (int_type == -1) { if (PURPOSE != DRILL_REVERSE) { type = LDNS_RR_TYPE_A; } else { type = LDNS_RR_TYPE_PTR; } } /* set the nameserver to use */ if (!serv) { /* no server given make a resolver from /etc/resolv.conf */ status = ldns_resolver_new_frm_file(&res, resolv_conf_file); if (status != LDNS_STATUS_OK) { warning("Could not create a resolver structure: %s (%s)\n" "Try drill @localhost if you have a resolver running on your machine.", ldns_get_errorstr_by_id(status), resolv_conf_file); result = EXIT_FAILURE; goto exit; } } else { res = ldns_resolver_new(); if (!res || strlen(serv) <= 0) { warning("Could not create a resolver structure"); result = EXIT_FAILURE; goto exit; } /* add the nameserver */ serv_rdf = ldns_rdf_new_addr_frm_str(serv); if (!serv_rdf) { /* try to resolv the name if possible */ status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file); if (status != LDNS_STATUS_OK) { error("%s", "@server ip could not be converted"); } ldns_resolver_set_dnssec(cmdline_res, qdnssec); ldns_resolver_set_ip6(cmdline_res, qfamily); ldns_resolver_set_fallback(cmdline_res, qfallback); ldns_resolver_set_usevc(cmdline_res, qusevc); cmdline_dname = ldns_dname_new_frm_str(serv); cmdline_rr_list = ldns_get_rr_list_addr_by_name( cmdline_res, cmdline_dname, LDNS_RR_CLASS_IN, qflags); ldns_rdf_deep_free(cmdline_dname); if (!cmdline_rr_list) { /* This error msg is not always accurate */ error("%s `%s\'", "could not find any address for the name:", serv); } else { if (ldns_resolver_push_nameserver_rr_list( res, cmdline_rr_list ) != LDNS_STATUS_OK) { error("%s", "pushing nameserver"); } } } else { if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) { error("%s", "pushing nameserver"); } else { ldns_rdf_deep_free(serv_rdf); } } } /* set the resolver options */ ldns_resolver_set_port(res, qport); if (verbosity >= 5) { ldns_resolver_set_debug(res, true); } else { ldns_resolver_set_debug(res, false); } ldns_resolver_set_dnssec(res, qdnssec); /* ldns_resolver_set_dnssec_cd(res, qdnssec);*/ ldns_resolver_set_ip6(res, qfamily); ldns_resolver_set_fallback(res, qfallback); ldns_resolver_set_usevc(res, qusevc); ldns_resolver_set_random(res, qrandom); if (qbuf != 0) { ldns_resolver_set_edns_udp_size(res, qbuf); } if (!name && PURPOSE != DRILL_AFROMFILE && !query_file ) { usage(stdout, progname); result = EXIT_FAILURE; goto exit; } if (tsig_name && tsig_data) { ldns_resolver_set_tsig_keyname(res, tsig_name); ldns_resolver_set_tsig_keydata(res, tsig_data); ldns_resolver_set_tsig_algorithm(res, tsig_algorithm); } /* main switching part of drill */ switch(PURPOSE) { case DRILL_TRACE: /* do a trace from the root down */ if (!global_dns_root) { init_root(); } qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "parsing query name"); } /* don't care about return packet */ (void)do_trace(res, qname, type, clas); clear_root(); break; case DRILL_SECTRACE: /* do a secure trace from the root down */ if (!global_dns_root) { init_root(); } qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "making qname"); } /* don't care about return packet */ #ifdef HAVE_SSL result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name); #endif /* HAVE_SSL */ clear_root(); break; case DRILL_CHASE: qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "making qname"); } ldns_resolver_set_dnssec(res, true); ldns_resolver_set_dnssec_cd(res, true); /* set dnssec implies udp_size of 4096 */ ldns_resolver_set_edns_udp_size(res, 4096); pkt = ldns_resolver_query(res, qname, type, clas, qflags); if (!pkt) { error("%s", "error pkt sending"); result = EXIT_FAILURE; } else { if (verbosity >= 3) { ldns_pkt_print(stdout, pkt); } if (!ldns_pkt_answer(pkt)) { mesg("No answer in packet"); } else { #ifdef HAVE_SSL ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list)); result = do_chase(res, qname, type, clas, key_list, pkt, qflags, NULL, verbosity); if (result == LDNS_STATUS_OK) { if (verbosity != -1) { mesg("Chase successful"); } result = 0; } else { if (verbosity != -1) { mesg("Chase failed."); } } #endif /* HAVE_SSL */ } ldns_pkt_free(pkt); } break; case DRILL_AFROMFILE: pkt = read_hex_pkt(answer_file); if (pkt) { if (verbosity != -1) { ldns_pkt_print(stdout, pkt); } ldns_pkt_free(pkt); } break; case DRILL_QTOFILE: qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "making qname"); } status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags); if(status != LDNS_STATUS_OK) { error("%s", "making query: %s", ldns_get_errorstr_by_id(status)); } dump_hex(qpkt, query_file); ldns_pkt_free(qpkt); break; case DRILL_NSEC: break; case DRILL_REVERSE: /* ipv4 or ipv6 addr? */ if (strchr(name, ':')) { if (strchr(name, '.')) { error("Syntax error: both '.' and ':' seen in address\n"); } name2 = malloc(IP6_ARPA_MAX_LEN + 20); c = 0; for (i=0; i<(int)strlen(name); i++) { if (i >= IP6_ARPA_MAX_LEN) { error("%s", "reverse argument to long"); } if (name[i] == ':') { if (i < (int) strlen(name) && name[i + 1] == ':') { error("%s", ":: not supported (yet)"); } else { if (i + 2 == (int) strlen(name) || name[i + 2] == ':') { name2[c++] = '0'; name2[c++] = '.'; name2[c++] = '0'; name2[c++] = '.'; name2[c++] = '0'; name2[c++] = '.'; } else if (i + 3 == (int) strlen(name) || name[i + 3] == ':') { name2[c++] = '0'; name2[c++] = '.'; name2[c++] = '0'; name2[c++] = '.'; } else if (i + 4 == (int) strlen(name) || name[i + 4] == ':') { name2[c++] = '0'; name2[c++] = '.'; } } } else { name2[c++] = name[i]; name2[c++] = '.'; } } name2[c++] = '\0'; qname = ldns_dname_new_frm_str(name2); qname_tmp = ldns_dname_reverse(qname); ldns_rdf_deep_free(qname); qname = qname_tmp; qname_tmp = ldns_dname_new_frm_str("ip6.arpa."); status = ldns_dname_cat(qname, qname_tmp); if (status != LDNS_STATUS_OK) { error("%s", "could not create reverse address for ip6: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rdf_deep_free(qname_tmp); free(name2); } else { qname = ldns_dname_new_frm_str(name); qname_tmp = ldns_dname_reverse(qname); ldns_rdf_deep_free(qname); qname = qname_tmp; qname_tmp = ldns_dname_new_frm_str("in-addr.arpa."); status = ldns_dname_cat(qname, qname_tmp); if (status != LDNS_STATUS_OK) { error("%s", "could not create reverse address for ip4: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rdf_deep_free(qname_tmp); } if (!qname) { error("%s", "-x implies an ip address"); } /* create a packet and set the RD flag on it */ pkt = ldns_resolver_query(res, qname, type, clas, qflags); if (!pkt) { error("%s", "pkt sending"); result = EXIT_FAILURE; } else { if (verbosity != -1) { ldns_pkt_print(stdout, pkt); } ldns_pkt_free(pkt); } break; case DRILL_QUERY: default: if (query_file) { /* this old way, the query packet needed to be parseable, but we want to be able to send mangled packets, so we need to do it directly */ #if 0 qpkt = read_hex_pkt(query_file); if (qpkt) { status = ldns_resolver_send_pkt(&pkt, res, qpkt); if (status != LDNS_STATUS_OK) { printf("Error: %s\n", ldns_get_errorstr_by_id(status)); exit(1); } } else { /* qpkt was bogus, reset pkt */ pkt = NULL; } #endif query_buffer = read_hex_buffer(query_file); if (query_buffer) { status = ldns_send_buffer(&pkt, res, query_buffer, NULL); ldns_buffer_free(query_buffer); if (status != LDNS_STATUS_OK) { printf("Error: %s\n", ldns_get_errorstr_by_id(status)); exit(1); } } else { printf("NO BUFFER\n"); pkt = NULL; } } else { qname = ldns_dname_new_frm_str(name); if (!qname) { error("%s", "error in making qname"); } if (type == LDNS_RR_TYPE_AXFR) { status = ldns_axfr_start(res, qname, clas); if(status != LDNS_STATUS_OK) { error("Error starting axfr: %s", ldns_get_errorstr_by_id(status)); } axfr_rr = ldns_axfr_next(res); if(!axfr_rr) { fprintf(stderr, "AXFR failed.\n"); ldns_pkt_print(stdout, ldns_axfr_last_pkt(res)); goto exit; } while (axfr_rr) { if (verbosity != -1) { ldns_rr_print(stdout, axfr_rr); } ldns_rr_free(axfr_rr); axfr_rr = ldns_axfr_next(res); } goto exit; } else { /* create a packet and set the RD flag on it */ pkt = ldns_resolver_query(res, qname, type, clas, qflags); } } if (!pkt) { mesg("No packet received"); result = EXIT_FAILURE; } else { if (verbosity != -1) { ldns_pkt_print(stdout, pkt); if (ldns_pkt_tc(pkt)) { fprintf(stdout, "\n;; WARNING: The answer packet was truncated; you might want to\n"); fprintf(stdout, ";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n"); } } if (qds) { if (verbosity != -1) { print_ds_of_keys(pkt); printf("\n"); } } if (ldns_rr_list_rr_count(key_list) > 0) { /* -k's were given on the cmd line */ ldns_rr_list *rrset_verified; uint16_t key_count; rrset_verified = ldns_pkt_rr_list_by_name_and_type( pkt, qname, type, LDNS_SECTION_ANY_NOQUESTION); if (type == LDNS_RR_TYPE_ANY) { /* don't verify this */ break; } if (verbosity != -1) { printf("; "); ldns_rr_list_print(stdout, rrset_verified); } /* verify */ #ifdef HAVE_SSL key_verified = ldns_rr_list_new(); result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified); if (result == LDNS_STATUS_ERR) { /* is the existence denied then? */ result = ldns_verify_denial(pkt, qname, type, NULL, NULL); if (result == LDNS_STATUS_OK) { if (verbosity != -1) { printf("Existence denied for "); ldns_rdf_print(stdout, qname); type_str = ldns_rr_type2str(type); printf("\t%s\n", type_str); LDNS_FREE(type_str); } } else { if (verbosity != -1) { printf("Bad data; RR for name and " "type not found or failed to " "verify, and denial of " "existence failed.\n"); } } } else if (result == LDNS_STATUS_OK) { for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified); key_count++) { if (verbosity != -1) { printf("; VALIDATED by id = %u, owner = ", (unsigned int)ldns_calc_keytag( ldns_rr_list_rr(key_verified, key_count))); ldns_rdf_print(stdout, ldns_rr_owner( ldns_rr_list_rr(key_list, key_count))); printf("\n"); } } } else { for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list); key_count++) { if (verbosity != -1) { printf("; %s for id = %u, owner = ", ldns_get_errorstr_by_id(result), (unsigned int)ldns_calc_keytag( ldns_rr_list_rr(key_list, key_count))); ldns_rdf_print(stdout, ldns_rr_owner( ldns_rr_list_rr(key_list, key_count))); printf("\n"); } } } ldns_rr_list_free(key_verified); #else (void) key_count; #endif /* HAVE_SSL */ } if (answer_file) { dump_hex(pkt, answer_file); } ldns_pkt_free(pkt); } break; } exit: ldns_rdf_deep_free(qname); ldns_resolver_deep_free(res); ldns_resolver_deep_free(cmdline_res); ldns_rr_list_deep_free(key_list); ldns_rr_list_deep_free(cmdline_rr_list); ldns_rdf_deep_free(trace_start_name); xfree(progname); xfree(tsig_name); xfree(tsig_data); xfree(tsig_algorithm); #ifdef HAVE_SSL ERR_remove_state(0); CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); EVP_cleanup(); #endif #ifdef USE_WINSOCK WSACleanup(); #endif return result; }
int output_cbor(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *payload, size_t payloadlen) { ldns_pkt *pkt = 0; ldns_status ldns_rc; if (!payload) { return DUMP_CBOR_EINVAL; } if (!payloadlen) { return DUMP_CBOR_EINVAL; } /* if (!cbor_stringrefs) {*/ /* cbor_stringrefs = calloc(1, cbor_stringref_size);*/ /* }*/ if (!cbor_buf) { if (!(cbor_buf = calloc(1, cbor_size + cbor_reserve))) { return DUMP_CBOR_ENOMEM; } } if (cbor_flushed) { CborError cbor_err; cbor_encoder_init(&cbor_root, cbor_buf, cbor_size, 0); /* cbor_err = cbor_encode_tag(&cbor_root, 256);*/ /* if (cbor_err == CborNoError)*/ cbor_err = cbor_encoder_create_array(&cbor_root, &cbor_pkts, CborIndefiniteLength); if (cbor_err != CborNoError) { fprintf(stderr, "cbor init error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } cbor_flushed = 0; } ldns_rc = ldns_wire2pkt(&pkt, payload, payloadlen); if (ldns_rc != LDNS_STATUS_OK) { fprintf(stderr, "ldns error [%d]: %s\n", ldns_rc, ldns_get_errorstr_by_id(ldns_rc)); return DUMP_CBOR_ELDNS; } if (!pkt) { return DUMP_CBOR_ELDNS; } CborEncoder cbor, ip; CborError cbor_err = CborNoError; int should_flush = 0; cbor_err = append_cbor_map(&cbor_pkts, &cbor, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateSeconds", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_double(&cbor, (double)ts.tv_sec + ( (double)ts.tv_usec / 1000000 ), &should_flush); /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateNanoFractions", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ts.tv_usec * 1000, &should_flush);*/ if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ip", &should_flush); /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, proto, &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourceIpAddress", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(from), &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourcePort", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, sport, &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationIpAddress", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(to), &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationPort", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, dport, &should_flush);*/ if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &ip, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, proto, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(from), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, sport, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(to), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, dport, &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &ip, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ID", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_id(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QR", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_qr(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "Opcode", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_opcode(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AA", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_aa(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "TC", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_tc(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_rd(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RA", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ra(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ad(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "CD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_cd(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RCODE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_rcode(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QDCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_qdcount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ANCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_ancount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "NSCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_nscount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ARCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_arcount(pkt), &should_flush); /* questionRRs */ if (ldns_pkt_qdcount(pkt) > 0) { ldns_rr_list *list = ldns_pkt_question(pkt); ldns_rr *rr; size_t n, qdcount = ldns_pkt_qdcount(pkt); ldns_buffer *dname; char *dname_str; if (!list) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } rr = ldns_rr_list_rr(list, 0); if (!rr) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } if (!(dname = ldns_buffer_new(512))) { ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QNAME", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, dname_str, &should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QCLASS", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_class(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QTYPE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_type(rr), &should_flush); if (qdcount > 1) { CborEncoder queries; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "questionRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &queries, CborIndefiniteLength, &should_flush); for (n = 1; cbor_err == CborNoError && n < qdcount; n++) { CborEncoder query; rr = ldns_rr_list_rr(list, n); if (!rr) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } if (!(dname = ldns_buffer_new(512))) { ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (cbor_err == CborNoError) cbor_err = append_cbor_map(&queries, &query, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "NAME", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, dname_str, &should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "CLASS", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_class(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "TYPE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_type(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&queries, &query, &should_flush); } if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &queries, &should_flush); } } /* answerRRs */ if (ldns_pkt_ancount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "answerRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_answer(pkt), ldns_pkt_ancount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } /* authorityRRs */ if (ldns_pkt_nscount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "authorityRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_authority(pkt), ldns_pkt_nscount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } /* additionalRRs */ if (ldns_pkt_arcount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "additionalRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_additional(pkt), ldns_pkt_arcount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } ldns_pkt_free(pkt); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_pkts, &cbor, &should_flush); if (cbor_err != CborNoError) { fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } if (should_flush) { if ((cbor_err = cbor_encoder_close_container_checked(&cbor_root, &cbor_pkts)) != CborNoError) { fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } fprintf(stderr, "cbor output: %lu bytes\n", cbor_encoder_get_buffer_size(&cbor_root, cbor_buf)); cbor_flushed = 1; return DUMP_CBOR_FLUSH; } return DUMP_CBOR_OK; }