static DCPluginSyncFilterResult empty_aaa_sync_pre(DCPlugin *dcplugin, DCPluginDNSPacket *dcp_packet) { ldns_pkt *packet; ldns_rr_list *questions; uint8_t *wire_data; DCPluginSyncFilterResult result = DCP_SYNC_FILTER_RESULT_OK; wire_data = dcplugin_get_wire_data(dcp_packet); ldns_wire2pkt(&packet, wire_data, dcplugin_get_wire_data_len(dcp_packet)); if (packet == NULL) { return DCP_SYNC_FILTER_RESULT_ERROR; } questions = ldns_pkt_question(packet); if (ldns_rr_list_rr_count(questions) == (size_t) 1U && ldns_rr_get_type(ldns_rr_list_rr(questions, (size_t) 0U)) == LDNS_RR_TYPE_AAAA) { LDNS_QR_SET(wire_data); LDNS_RA_SET(wire_data); result = DCP_SYNC_FILTER_RESULT_DIRECT; } ldns_pkt_free(packet); return result; }
int process_dns_answer(packetinfo *pi, ldns_pkt *dns_pkt) { int rrcount_query; int j; ldns_rr_list *dns_query_domains; ldns_buffer *dns_buff; dns_query_domains = ldns_pkt_question(dns_pkt); rrcount_query = ldns_rr_list_rr_count(dns_query_domains); dns_buff = ldns_buffer_new(LDNS_MIN_BUFLEN); dlog("[*] rrcount_query: %d\n", rrcount_query); // Do we ever have more than one Question? // If we do - are we handling it correct ? for (j = 0; j < rrcount_query; j++) { ldns_rdf *rdf_data; rdf_data = ldns_rr_owner(ldns_rr_list_rr(dns_query_domains, j)); dlog("[D] rdf_data: %p\n", rdf_data); if ( cache_dns_objects(pi, rdf_data, dns_buff, dns_pkt) != 0 ) { dlog("[D] cache_dns_objects() returned error\n"); } } ldns_buffer_free(dns_buff); update_dns_stats(pi,SUCCESS); return(0); }
static DCPluginSyncFilterResult apply_block_domains(DCPluginDNSPacket *dcp_packet, Blocking * const blocking, ldns_pkt * const packet) { StrList *scanned; ldns_rr *question; char *owner_str; size_t owner_str_len; scanned = blocking->domains; question = ldns_rr_list_rr(ldns_pkt_question(packet), 0U); if ((owner_str = ldns_rdf2str(ldns_rr_owner(question))) == NULL) { return DCP_SYNC_FILTER_RESULT_FATAL; } owner_str_len = strlen(owner_str); if (owner_str_len > (size_t) 1U && owner_str[--owner_str_len] == '.') { owner_str[owner_str_len] = 0; } do { if (wildcard_match(owner_str, scanned->str)) { LDNS_RCODE_SET(dcplugin_get_wire_data(dcp_packet), LDNS_RCODE_REFUSED); break; } } while ((scanned = scanned->next) != NULL); free(owner_str); return DCP_SYNC_FILTER_RESULT_OK; }
/** 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 adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt) { /* copy & adjust packet */ if(match->copy_id) ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt)); if(match->copy_query) { ldns_rr_list* list = ldns_pkt_get_section_clone(query_pkt, LDNS_SECTION_QUESTION); ldns_rr_list_deep_free(ldns_pkt_question(answer_pkt)); ldns_pkt_set_question(answer_pkt, list); } if(match->sleeptime > 0) { verbose(3, "sleeping for %d seconds\n", match->sleeptime); #ifdef HAVE_SLEEP sleep(match->sleeptime); #else Sleep(match->sleeptime * 1000); #endif } }
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"); } }
int main(int argc, char **argv) { /* arguments */ int port; const char *zone_file; /* network */ int sock; ssize_t nb; struct sockaddr addr_me; struct sockaddr addr_him; socklen_t hislen = (socklen_t) sizeof(addr_him); uint8_t inbuf[INBUF_SIZE]; uint8_t *outbuf; /* dns */ ldns_status status; ldns_pkt *query_pkt; ldns_pkt *answer_pkt; size_t answer_size; ldns_rr *query_rr; ldns_rr_list *answer_qr; ldns_rr_list *answer_an; ldns_rr_list *answer_ns; ldns_rr_list *answer_ad; ldns_rdf *origin = NULL; /* zone */ ldns_zone *zone; int line_nr; FILE *zone_fp; /* use this to listen on specified interfaces later? */ char *my_address = NULL; if (argc < 5) { usage(stderr); exit(EXIT_FAILURE); } else { my_address = argv[1]; port = atoi(argv[2]); if (port < 1) { usage(stderr); exit(EXIT_FAILURE); } if (ldns_str2rdf_dname(&origin, argv[3]) != LDNS_STATUS_OK) { fprintf(stderr, "Bad origin, not a correct domain name\n"); usage(stderr); exit(EXIT_FAILURE); } zone_file = argv[4]; } printf("Reading zone file %s\n", zone_file); zone_fp = fopen(zone_file, "r"); if (!zone_fp) { fprintf(stderr, "Unable to open %s: %s\n", zone_file, strerror(errno)); exit(EXIT_FAILURE); } line_nr = 0; status = ldns_zone_new_frm_fp_l(&zone, zone_fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr); if (status != LDNS_STATUS_OK) { printf("Zone reader failed, aborting\n"); exit(EXIT_FAILURE); } else { printf("Read %u resource records in zone file\n", (unsigned int) ldns_zone_rr_count(zone)); } fclose(zone_fp); printf("Listening on port %d\n", port); sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno)); exit(1); } memset(&addr_me, 0, sizeof(addr_me)); /* bind: try all ports in that range */ if (udp_bind(sock, port, my_address)) { fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno)); exit(errno); } /* Done. Now receive */ while (1) { nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, &addr_him, &hislen); if (nb < 1) { fprintf(stderr, "%s: recvfrom(): %s\n", argv[0], strerror(errno)); exit(1); } /* show(inbuf, nb, nn, hp, sp, ip, bp); */ printf("Got query of %u bytes\n", (unsigned int) nb); status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb); if (status != LDNS_STATUS_OK) { printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); } else { ldns_pkt_print(stdout, query_pkt); } query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); printf("QUERY RR: \n"); ldns_rr_print(stdout, query_rr); answer_qr = ldns_rr_list_new(); ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr)); answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr)); answer_pkt = ldns_pkt_new(); answer_ns = ldns_rr_list_new(); answer_ad = ldns_rr_list_new(); ldns_pkt_set_qr(answer_pkt, 1); ldns_pkt_set_aa(answer_pkt, 1); ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt)); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size); if (status != LDNS_STATUS_OK) { printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); } else { nb = sendto(sock, (void*)outbuf, answer_size, 0, &addr_him, hislen); } ldns_pkt_free(query_pkt); ldns_pkt_free(answer_pkt); LDNS_FREE(outbuf); ldns_rr_list_free(answer_qr); ldns_rr_list_free(answer_an); ldns_rr_list_free(answer_ns); ldns_rr_list_free(answer_ad); } /* No cleanup because of the infinite loop * * ldns_rdf_deep_free(origin); * ldns_zone_deep_free(zone); * return 0; */ }
ldns_status ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) { ldns_rr_list *rr_list; uint16_t i; /* edns tmp vars */ ldns_rr *edns_rr; uint8_t edata[4]; (void) ldns_hdr2buffer_wire(buffer, packet); rr_list = ldns_pkt_question(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION); } } rr_list = ldns_pkt_answer(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER); } } rr_list = ldns_pkt_authority(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY); } } rr_list = ldns_pkt_additional(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL); } } /* add EDNS to additional if it is needed */ if (ldns_pkt_edns(packet)) { edns_rr = ldns_rr_new(); ldns_rr_set_owner(edns_rr, ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".")); ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT); ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet)); edata[0] = ldns_pkt_edns_extended_rcode(packet); edata[1] = ldns_pkt_edns_version(packet); ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet)); ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata)); (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL); ldns_rr_free(edns_rr); } /* add TSIG to additional if it is there */ if (ldns_pkt_tsig(packet)) { (void) ldns_rr2buffer_wire(buffer, ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL); } return LDNS_STATUS_OK; }
/** * Process query. * */ query_state query_process(query_type* q, void* engine) { ldns_status status = LDNS_STATUS_OK; ldns_pkt* pkt = NULL; ldns_rr* rr = NULL; ldns_pkt_rcode rcode = LDNS_RCODE_NOERROR; ldns_pkt_opcode opcode = LDNS_PACKET_QUERY; ldns_rr_type qtype = LDNS_RR_TYPE_SOA; engine_type* e = (engine_type*) engine; ods_log_assert(e); ods_log_assert(q); ods_log_assert(q->buffer); if (!e || !q || !q->buffer) { ods_log_error("[%s] drop query: assertion error", query_str); return QUERY_DISCARDED; /* should not happen */ } if (buffer_limit(q->buffer) < BUFFER_PKT_HEADER_SIZE) { ods_log_debug("[%s] drop query: packet too small", query_str); return QUERY_DISCARDED; /* too small */ } if (buffer_pkt_qr(q->buffer)) { ods_log_debug("[%s] drop query: qr bit set", query_str); return QUERY_DISCARDED; /* not a query */ } /* parse packet */ status = ldns_wire2pkt(&pkt, buffer_current(q->buffer), buffer_remaining(q->buffer)); if (status != LDNS_STATUS_OK) { ods_log_debug("[%s] got bad packet: %s", query_str, ldns_get_errorstr_by_id(status)); return query_formerr(q); } rr = ldns_rr_list_rr(ldns_pkt_question(pkt), 0); lock_basic_lock(&e->zonelist->zl_lock); /* we can just lookup the zone, because we will only handle SOA queries, zone transfers, updates and notifies */ q->zone = zonelist_lookup_zone_by_dname(e->zonelist, ldns_rr_owner(rr), ldns_rr_get_class(rr)); /* don't answer for zones that are just added */ if (q->zone && q->zone->zl_status == ZONE_ZL_ADDED) { ods_log_warning("[%s] zone %s just added, don't answer for now", query_str, q->zone->name); q->zone = NULL; } lock_basic_unlock(&e->zonelist->zl_lock); if (!q->zone) { ods_log_debug("[%s] zone not found", query_str); return query_servfail(q); } /* see if it is tsig signed */ if (!query_find_tsig(q)) { return query_formerr(q); } /* else: valid tsig, or no tsig present */ ods_log_debug("[%s] tsig %s", query_str, tsig_status2str(q->tsig_rr->status)); rcode = query_process_tsig(q); if (rcode != LDNS_RCODE_NOERROR) { return query_error(q, rcode); } /* process edns */ rcode = query_process_edns(q); if (rcode != LDNS_RCODE_NOERROR) { /* We should not return FORMERR, but BADVERS (=16). * BADVERS is created with Ext. RCODE, followed by RCODE. * Ext. RCODE is set to 1, RCODE must be 0 (getting 0x10 = 16). * Thus RCODE = NOERROR = NSD_RC_OK. */ return query_error(q, LDNS_RCODE_NOERROR); } /* handle incoming request */ opcode = ldns_pkt_get_opcode(pkt); qtype = ldns_rr_get_type(rr); ldns_pkt_free(pkt); switch (opcode) { case LDNS_PACKET_NOTIFY: return query_process_notify(q, qtype, engine); case LDNS_PACKET_QUERY: return query_process_query(q, qtype, engine); case LDNS_PACKET_UPDATE: return query_process_update(q); default: break; } return query_notimpl(q); }
ldns_status output_packet(ldns_buffer *output, const ldns_pkt *pkt, struct sockaddr_storage sa, lookup_context_t* context) { const ldns_output_format *fmt = ldns_output_format_nocomments; uint16_t i; ldns_status status = LDNS_STATUS_OK; time_t now = time(NULL); char nsbuffer[INET6_ADDRSTRLEN]; char* ip_prefix = ""; char* ip_suffix = ""; switch (((struct sockaddr *) &sa)->sa_family) { case AF_INET: inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa)->sin_addr), nsbuffer, INET_ADDRSTRLEN); break; case AF_INET6: inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa)->sin6_addr), nsbuffer, INET6_ADDRSTRLEN); ip_prefix = "["; ip_suffix = "]"; break; default: exit(1); } if (!pkt) { if(0 > ldns_buffer_printf(output, "")) { abort(); } return LDNS_STATUS_OK; } if(!context->cmd_args.only_responses) { if(0 > ldns_buffer_printf(output, "%s%s%s:%u %ld ", ip_prefix, ip_suffix, nsbuffer, ntohs(((struct sockaddr_in *) &sa)->sin_port), now)) { abort(); } for (i = 0; i < ldns_pkt_qdcount(pkt); i++) { status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_question(pkt), i)); if (status != LDNS_STATUS_OK) { return status; } } } if (ldns_buffer_status_ok(output)) { for (i = 0; i < ldns_pkt_ancount(pkt); i++) { if(!context->cmd_args.only_responses) { if(0 > ldns_buffer_printf(output, "\t")) { abort(); } } status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_answer(pkt), i)); if (status != LDNS_STATUS_OK) { return status; } } if(!context->cmd_args.no_authority) { if(0 > ldns_buffer_printf(output, "\n")) { abort(); } for (i = 0; i < ldns_pkt_nscount(pkt); i++) { if(!context->cmd_args.only_responses) { ldns_buffer_printf(output, "\t"); } status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_authority(pkt), i)); if (status != LDNS_STATUS_OK) { return status; } } } if(context->cmd_args.additional) { for (i = 0; i < ldns_pkt_arcount(pkt); i++) { if(!context->cmd_args.only_responses) { ldns_buffer_printf(output, "\t"); } status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_additional(pkt), i)); if (status != LDNS_STATUS_OK) { return status; } } } } else { return ldns_buffer_status(output); } return status; }
int cache_dns_objects(packetinfo *pi, ldns_rdf *rdf_data, ldns_buffer *buff, ldns_pkt *dns_pkt) { int j; int dns_answer_domain_cnt; uint64_t dnshash; ldns_status status; pdns_record *pr = NULL; ldns_rr_list *dns_answer_domains; unsigned char *domain_name = 0; ldns_buffer_clear(buff); status = ldns_rdf2buffer_str(buff, rdf_data); if (status != LDNS_STATUS_OK) { dlog("[D] Error in ldns_rdf2buffer_str(): %d\n", status); return(-1); } dns_answer_domains = ldns_pkt_answer(dns_pkt); dns_answer_domain_cnt = ldns_rr_list_rr_count(dns_answer_domains); domain_name = (unsigned char *) ldns_buffer2str(buff); if (domain_name == NULL) { dlog("[D] Error in ldns_buffer2str(%p)\n", buff); return(-1); } else { dlog("[D] domain_name: %s\n", domain_name); dlog("[D] dns_answer_domain_cnt: %d\n",dns_answer_domain_cnt); } if (dns_answer_domain_cnt == 0 && ldns_pkt_get_rcode(dns_pkt) != 0) { uint16_t rcode = ldns_pkt_get_rcode(dns_pkt); dlog("[D] Error return code: %d\n", rcode); /* PROBLEM: * As there is no valid ldns_rr here and we cant fake one that will * be very unique, we cant push this to the normal * bucket[hash->linked_list]. We should probably allocate a static * bucket[MAX_NXDOMAIN] to hold NXDOMAINS, and when that is full, pop * out the oldest (LRU). A simple script quering for random non existing * domains could easly put stress on passivedns (think conficker etc.) * if the bucket is to big or non efficient. We would still store data * such as: fistseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN */ if (config.dnsfe & (pdns_chk_dnsfe(rcode))) { ldns_rr_list *dns_query_domains; ldns_rr_class class; ldns_rr_type type; ldns_rr *rr; dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); /* Check if the node exists, if not, make it */ pr = get_pdns_record(dnshash, pi, domain_name); /* Set the SRC flag: */ //lname_node->srcflag |= pdns_chk_dnsfe(rcode); dns_query_domains = ldns_pkt_question(dns_pkt); rr = ldns_rr_list_rr(dns_query_domains, 0); class = ldns_rr_get_class(rr); type = ldns_rr_get_type(rr); if ((pr->last_seen.tv_sec - pr->last_print.tv_sec) >= config.dnsprinttime) { /* Print the SRC Error record */ print_passet_err(pr, rdf_data, rr, rcode); } } else {
/* * Parses data buffer to a query, finds the correct answer * and calls the given function for every packet to send. */ void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count, enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*), void* userdata, FILE* verbose_out) { ldns_status status; ldns_pkt *query_pkt = NULL; ldns_pkt *answer_pkt = NULL; struct reply_packet *p; ldns_rr *query_rr = NULL; uint8_t *outbuf = NULL; size_t answer_size = 0; struct entry* entry = NULL; ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop."); status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen); if (status != LDNS_STATUS_OK) { verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); ldns_rdf_free(stop_command); return; } query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), (transport==transport_tcp)?"TCP":"UDP", (int)inlen); if(verbose_out) ldns_rr_print(verbose_out, query_rr); if(verbose_out) ldns_pkt_print(verbose_out, query_pkt); if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT && ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH && ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) { exit(0); } /* fill up answer packet */ entry = find_match(entries, query_pkt, transport); if(!entry || !entry->reply_list) { verbose(1, "no answer packet for this query, no reply.\n"); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } for(p = entry->reply_list; p; p = p->next) { verbose(3, "Answer pkt:\n"); if (p->reply_from_hex) { /* try to parse the hex packet, if it can be * parsed, we can use adjust rules. if not, * send packet literally */ status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex); if (status == LDNS_STATUS_OK) { adjust_packet(entry, answer_pkt, query_pkt); if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); if (status != LDNS_STATUS_OK) { verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } ldns_pkt_free(answer_pkt); answer_pkt = NULL; } else { verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status)); /* still try to adjust ID */ answer_size = ldns_buffer_capacity(p->reply_from_hex); outbuf = LDNS_XMALLOC(uint8_t, answer_size); memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size); if(entry->copy_id) { ldns_write_uint16(outbuf, ldns_pkt_id(query_pkt)); } } } else { answer_pkt = ldns_pkt_clone(p->reply); adjust_packet(entry, answer_pkt, query_pkt); if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); if (status != LDNS_STATUS_OK) { verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } ldns_pkt_free(answer_pkt); answer_pkt = NULL; } if(p->packet_sleep) { verbose(3, "sleeping for next packet %d secs\n", p->packet_sleep); #ifdef HAVE_SLEEP sleep(p->packet_sleep); #else Sleep(p->packet_sleep * 1000); #endif verbose(3, "wakeup for next packet " "(slept %d secs)\n", p->packet_sleep); } sendfunc(outbuf, answer_size, userdata); LDNS_FREE(outbuf); outbuf = NULL; answer_size = 0; } ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); }
/** returns owner from rr */ static ldns_rdf* get_owner(ldns_pkt* p) { if(!ldns_rr_list_rr(ldns_pkt_question(p), 0)) return NULL; return ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(p), 0)); }
/** get qtype from rr */ static ldns_rr_type get_qtype(ldns_pkt* p) { if(!ldns_rr_list_rr(ldns_pkt_question(p), 0)) return 0; return ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(p), 0)); }
int main(int argc, char **argv) { /* arguments */ int port; int soa; ldns_rdf *zone_name; size_t count; size_t maxcount; /* network */ int sock; ssize_t nb; struct sockaddr addr_me; struct sockaddr addr_him; socklen_t hislen = sizeof(addr_him); const char *my_address; uint8_t inbuf[INBUF_SIZE]; uint8_t *outbuf; /* dns */ ldns_status status; ldns_pkt *query_pkt; ldns_pkt *answer_pkt; size_t answer_size; ldns_rr *query_rr; ldns_rr *rr; char rr_string[MAX_LEN + 1]; ldns_rr *soa_rr; char soa_string[MAX_LEN + 1]; /* use this to listen on specified interfaces later? */ my_address = NULL; if(argc == 5) { /* -# num given */ if (argv[1][0] == '-') { maxcount = atoi(argv[1] + 1); if (maxcount == 0) { usage(stdout); exit(EXIT_FAILURE); } else { fprintf(stderr, "quiting after %d qs\n", (int)maxcount); } } else { fprintf(stderr, "Use -Number for max count\n"); exit(EXIT_FAILURE); } argc--; argv++; } else { maxcount = 0; } if (argc != 4) { usage(stdout); exit(EXIT_FAILURE); } else { port = atoi(argv[1]); if (port < 1) { fprintf(stderr, "Use a number for the port\n"); usage(stdout); exit(EXIT_FAILURE); } zone_name = ldns_dname_new_frm_str(argv[2]); if (!zone_name) { fprintf(stderr, "Illegal domain name: %s\n", argv[2]); usage(stdout); exit(EXIT_FAILURE); } soa = atoi(argv[3]); if (soa < 1) { fprintf(stderr, "Illegal soa number\n"); usage(stdout); exit(EXIT_FAILURE); } } printf("Listening on port %d\n", port); sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } memset(&addr_me, 0, sizeof(addr_me)); /* bind: try all ports in that range */ if (udp_bind(sock, port, my_address)) { fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno)); } /* create our ixfr answer */ answer_pkt = ldns_pkt_new(); snprintf(rr_string, MAX_LEN, "%s IN IXFR", argv[2]); (void)ldns_rr_new_frm_str(&rr, rr_string , 0, NULL, NULL); (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_QUESTION, rr); /* next add some rrs, with SOA stuff so that we mimic or ixfr reply */ snprintf(soa_string, MAX_LEN, "%s IN SOA miek.miek.nl elektron.atoom.net %d 1 2 3000 4", argv[2], soa); (void)ldns_rr_new_frm_str(&soa_rr, soa_string, 0, NULL, NULL); snprintf(rr_string, MAX_LEN, "%s IN A 127.0.0.1", argv[2]); (void)ldns_rr_new_frm_str(&rr, rr_string , 0, NULL, NULL); /* compose the ixfr pkt */ (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, soa_rr); (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, rr); (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, soa_rr); /* Done. Now receive */ count = 0; while (1) { nb = recvfrom(sock, inbuf, INBUF_SIZE, 0, &addr_him, &hislen); if (nb < 1) { fprintf(stderr, "%s: recvfrom(): %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } printf("Got query of %d bytes\n", (int)nb); status = ldns_wire2pkt(&query_pkt, inbuf, nb); if (status != LDNS_STATUS_OK) { printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); continue; } query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); printf("%d QUERY RR +%d: \n", (int)++count, ldns_pkt_id(query_pkt)); ldns_rr_print(stdout, query_rr); ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt)); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size); if (status != LDNS_STATUS_OK) { printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); } else { nb = (size_t) sendto(sock, outbuf, answer_size, 0, &addr_him, hislen); } if (maxcount > 0 && count >= maxcount) { fprintf(stderr, "%d queries seen... goodbye\n", (int)count); exit(EXIT_SUCCESS); } } return 0; }
void massdns_handle_packet(ldns_pkt *packet, struct sockaddr_storage ns, void *ctx) { if (!packet || ldns_pkt_qdcount(packet) != 1) { return; } struct timeval now; gettimeofday(&now, NULL); lookup_context_t *context = (lookup_context_t *) ctx; ldns_pkt_rcode response_code = ldns_pkt_get_rcode(packet); ldns_rr_list l = ldns_pkt_question(packet)[0]; ldns_rr *question = ldns_rr_list_rr(&l, 0); ldns_rdf* owner = ldns_rr_owner(question); char* name = ldns_rdf2str(owner); size_t name_len = strlen(name); if(name_len > 0 && name[name_len - 1] == '.') { name[name_len - 1] = 0; } lookup_t *lookup = hashmapGet(context->map, name); free(name); if (lookup == NULL) { return; } if (response_code == LDNS_RCODE_NOERROR || response_code == LDNS_RCODE_NXDOMAIN || lookup->tries == context->cmd_args.resolve_count) { switch (response_code) { case LDNS_RCODE_NOERROR: stats.noerr++; break; case LDNS_RCODE_FORMERR: stats.formerr++; break; case LDNS_RCODE_SERVFAIL: stats.servfail++; break; case LDNS_RCODE_NXDOMAIN: stats.nxdomain++; break; case LDNS_RCODE_NOTIMPL: stats.notimp++; break; case LDNS_RCODE_REFUSED: stats.refused++; break; default: stats.other++; break; } context->current_rate++; ldns_buffer *buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); if(buf == NULL) { abort(); } if(LDNS_STATUS_OK != output_packet(buf, packet, ns, context)) { abort(); } char* packetstr = ldns_buffer_export2str(buf); if(packetstr == NULL) { abort(); } fprintf(stdout, "%s", packetstr); free(packetstr); if (timediff(&now, &context->next_update) <= 0) { print_stats(context); } ldns_buffer_free(buf); hashmapRemove(context->map, lookup->domain); free(lookup->domain); free(lookup); } }
void compare(struct dns_info *d1, struct dns_info *d2) { ldns_pkt *p1, *p2, *pq; bool diff = false; char *pstr1, *pstr2; struct timeval now; char *compare_result; size_t file_nr; gettimeofday(&now, NULL); if (verbosity > 0) { printf("Id: %u\n", (unsigned int) d1->seq); } if (strcmp(d1->qdata, d2->qdata) != 0) { fprintf(stderr, "Query differs!\n"); fprintf(stdout, "q: %d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->qdata, d2->qdata); } else { if (strcmp(d1->adata, d2->adata) != 0) { if (advanced_match) { /* try to read the packet and sort the sections */ p1 = read_hex_pkt(d1->adata); p2 = read_hex_pkt(d2->adata); if (p1) { ldns_pkt_set_timestamp(p1, now); } if (p2) { ldns_pkt_set_timestamp(p2, now); } if (p1 && ldns_pkt_qdcount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_question(p1)); ldns_rr_list_sort(ldns_pkt_question(p1)); } if (p1 && ldns_pkt_ancount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_answer(p1)); ldns_rr_list_sort(ldns_pkt_answer(p1)); } if (p1 && ldns_pkt_nscount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_authority(p1)); ldns_rr_list_sort(ldns_pkt_authority(p1)); } if (p1 && ldns_pkt_arcount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_additional(p1)); ldns_rr_list_sort(ldns_pkt_additional(p1)); } if (p2 && ldns_pkt_qdcount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_question(p2)); ldns_rr_list_sort(ldns_pkt_question(p2)); } if (p2 && ldns_pkt_ancount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_answer(p2)); ldns_rr_list_sort(ldns_pkt_answer(p2)); } if (p2 && ldns_pkt_nscount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_authority(p2)); ldns_rr_list_sort(ldns_pkt_authority(p2)); } if (p2 && ldns_pkt_arcount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_additional(p2)); ldns_rr_list_sort(ldns_pkt_additional(p2)); } /* simply do string comparison first */ pstr1 = ldns_pkt2str(p1); pstr2 = ldns_pkt2str(p2); if ((!p1 && !p2) || strcmp(pstr1, pstr2) != 0) { /* okay strings still differ, get the query and do a match for the match files */ pq = read_hex_pkt(d1->qdata); compare_result = compare_to_file(pq, p1, p2); if (compare_result != NULL) { /*fprintf(stderr, compare_result);*/ if (compare_result[strlen(compare_result)-1] == '\n') { compare_result[strlen(compare_result)-1] = 0; } file_nr = add_known_difference(compare_result); if (store_known_differences) { fprintf(known_differences[file_nr].file, "q: %d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->adata, d2->adata); } free(compare_result); diff = false; } else { diff=false; printf("Error: Unknown difference in packet number %u:\n", (unsigned int) total_nr_of_packets); ldns_pkt_print(stdout, pq); printf("\n"); ldns_pkt_print(stdout, p1); printf("\n"); ldns_pkt_print(stdout, p2); printf("Quitting at packet %u\n", (unsigned int) d1->seq); exit(1); } ldns_pkt_free(pq); } else { sames++; } if (diff) { if (show_originals) { fprintf(stdout, "%d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->adata, d2->adata); } else { fprintf(stdout, "%d:%d\n", (int)d1->seq, (int)d2->seq); if (!dump_hex(stdout, p1)) { fprintf(stdout, "%s", d1->adata); } fprintf(stdout, "\n"); if (!dump_hex(stdout, p2)) { fprintf(stdout, "%s", d2->adata); } fprintf(stdout, "\n"); } } LDNS_FREE(pstr1); LDNS_FREE(pstr2); ldns_pkt_free(p1); ldns_pkt_free(p2); } else { fprintf(stdout, "%d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->adata, d2->adata); } } else { sames++; bytesames++; } } }
int cache_dns_objects(packetinfo *pi, ldns_rdf *rdf_data, ldns_buffer *buff, ldns_pkt *dns_pkt) { int j; int dns_answer_domain_cnt; uint64_t dnshash; ldns_status status; pdns_record *pr = NULL; ldns_rr_list *dns_answer_domains; unsigned char *domain_name = 0; ldns_buffer_clear(buff); status = ldns_rdf2buffer_str(buff, rdf_data); if (status != LDNS_STATUS_OK) { dlog("[D] Error in ldns_rdf2buffer_str(): %d\n", status); return -1; } dns_answer_domains = ldns_pkt_answer(dns_pkt); dns_answer_domain_cnt = ldns_rr_list_rr_count(dns_answer_domains); domain_name = (unsigned char *) ldns_buffer2str(buff); if (domain_name == NULL) { dlog("[D] Error in ldns_buffer2str(%p)\n", buff); return -1; } else { dlog("[D] domain_name: %s\n", domain_name); dlog("[D] dns_answer_domain_cnt: %d\n",dns_answer_domain_cnt); } if (dns_answer_domain_cnt == 0 && ldns_pkt_get_rcode(dns_pkt) != 0) { uint16_t rcode = ldns_pkt_get_rcode(dns_pkt); dlog("[D] Error return code: %d\n", rcode); /* PROBLEM: * As there is no valid ldns_rr here and we can't fake one that will * be very unique, we cant push this to the normal * bucket[hash->linked_list]. We should probably allocate a static * bucket[MAX_NXDOMAIN] to hold NXDOMAINS, and when that is full, pop * out the oldest (LRU). A simple script querying for random non-existing * domains could easily put stress on passivedns (think conficker etc.) * if the bucket is to big or non-efficient. We would still store data * such as: firstseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN */ if (config.dnsfe & (pdns_chk_dnsfe(rcode))) { ldns_rr_list *dns_query_domains; ldns_rr *rr; dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); /* Check if the node exists, if not, make it */ pr = get_pdns_record(dnshash, pi, domain_name); /* Set the SRC flag: */ //lname_node->srcflag |= pdns_chk_dnsfe(rcode); dns_query_domains = ldns_pkt_question(dns_pkt); rr = ldns_rr_list_rr(dns_query_domains, 0); if ((pr->last_seen.tv_sec - pr->last_print.tv_sec) >= config.dnsprinttime) { /* Print the SRC Error record */ print_passet(pr, NULL, rr, rdf_data, rcode); } } else { dlog("[D] Error return code %d was not processed:%d\n", pdns_chk_dnsfe(rcode), config.dnsfe); } free(domain_name); return 0; } for (j = 0; j < dns_answer_domain_cnt; j++) { int offset = -1; ldns_rr *rr; ldns_rdf *rname; unsigned char *rdomain_name = 0; rr = ldns_rr_list_rr(dns_answer_domains, j); switch (ldns_rr_get_type(rr)) { case LDNS_RR_TYPE_AAAA: if (config.dnsf & DNS_CHK_AAAA) offset = 0; break; case LDNS_RR_TYPE_A: if (config.dnsf & DNS_CHK_A) offset = 0; break; case LDNS_RR_TYPE_PTR: if (config.dnsf & DNS_CHK_PTR) offset = 0; break; case LDNS_RR_TYPE_CNAME: if (config.dnsf & DNS_CHK_CNAME) offset = 0; break; case LDNS_RR_TYPE_DNAME: if (config.dnsf & DNS_CHK_DNAME) offset = 0; break; case LDNS_RR_TYPE_NAPTR: if (config.dnsf & DNS_CHK_NAPTR) offset = 0; break; case LDNS_RR_TYPE_RP: if (config.dnsf & DNS_CHK_RP) offset = 0; break; case LDNS_RR_TYPE_SRV: if (config.dnsf & DNS_CHK_SRV) offset = 3; break; case LDNS_RR_TYPE_TXT: if (config.dnsf & DNS_CHK_TXT) offset = 0; break; case LDNS_RR_TYPE_SOA: if (config.dnsf & DNS_CHK_SOA) offset = 0; break; case LDNS_RR_TYPE_MX: if (config.dnsf & DNS_CHK_MX) offset = 1; break; case LDNS_RR_TYPE_NS: if (config.dnsf & DNS_CHK_NS) offset = 0; break; default: offset = -1; dlog("[D] ldns_rr_get_type: %d\n", ldns_rr_get_type(rr)); break; } if (offset == -1) { dlog("[D] LDNS_RR_TYPE not enabled/supported: %d\n", ldns_rr_get_type(rr)); //data_offset = 0; continue; } /* Get the rdf data from the rr */ rname = ldns_rr_rdf(rr, offset); if (rname == NULL) { dlog("[D] ldns_rr_rdf returned: NULL\n"); continue; } ldns_buffer_clear(buff); ldns_rdf2buffer_str(buff, rname); rdomain_name = (unsigned char *) ldns_buffer2str(buff); if (rdomain_name == NULL) { dlog("[D] ldns_buffer2str returned: NULL\n"); continue; } dlog("[D] rdomain_name: %s\n", rdomain_name); if (pr == NULL) { dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); /* Check if the node exists, if not, make it */ pr = get_pdns_record(dnshash, pi, domain_name); } /* Update the pdns record with the pdns asset */ update_pdns_record_asset(pi, pr, rr, rdomain_name); /* If CNAME, free domain_name, and cp rdomain_name to domain_name */ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_CNAME) { if (config.dnsf & DNS_CHK_CNAME) { int len; free(domain_name); len = strlen((char *)rdomain_name); domain_name = calloc(1, (len + 1)); strncpy((char *)domain_name, (char *)rdomain_name, len); dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); pr = get_pdns_record(dnshash, pi, domain_name); } } /* Free the rdomain_name */ free(rdomain_name); } free(domain_name); return 0; }
void zkdns_start(const char* my_address, int port, const char* my_zone) { rp_handle = rp_initialize(my_zone); /* network */ int sock; ssize_t nb; struct sockaddr addr_me; struct sockaddr addr_him; socklen_t hislen = (socklen_t) sizeof(addr_him); uint8_t inbuf[INBUF_SIZE]; uint8_t *outbuf; /* dns */ ldns_status status; ldns_pkt *query_pkt; ldns_pkt *answer_pkt; size_t answer_size; ldns_rr *query_rr; ldns_rr_list *answer_qr; ldns_rr_list *answer_an; ldns_rr_list *answer_ns; ldns_rr_list *answer_ad; ldns_rdf *origin = NULL; /* zone */ ldns_zone *zone; int line_nr; FILE *zone_fp; if (ldns_str2rdf_dname(&origin, my_zone) != LDNS_STATUS_OK) { fprintf(stderr, "Bad origin, not a correct domain name\n"); exit(EXIT_FAILURE); } printf("Listening on port %d\n", port); sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { fprintf(stderr, "socket(): %s\n", strerror(errno)); exit(1); } memset(&addr_me, 0, sizeof(addr_me)); /* bind: try all ports in that range */ if (udp_bind(sock, port, my_address)) { fprintf(stderr, "cannot bind(): %s\n", strerror(errno)); exit(errno); } /* Done. Now receive */ while (1) { nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, &addr_him, &hislen); if (nb < 1) { fprintf(stderr, "recvfrom(): %s\n", strerror(errno)); exit(1); } /* show(inbuf, nb, nn, hp, sp, ip, bp); */ status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb); if (status != LDNS_STATUS_OK) { printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); } query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); answer_qr = ldns_rr_list_new(); ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr)); answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr)); answer_pkt = ldns_pkt_new(); answer_ns = ldns_rr_list_new(); answer_ad = ldns_rr_list_new(); ldns_pkt_set_qr(answer_pkt, 1); ldns_pkt_set_aa(answer_pkt, 1); ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt)); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns); ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); if (status != LDNS_STATUS_OK) { printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); } else { nb = sendto(sock, (void*)outbuf, answer_size, 0, &addr_him, hislen); } ldns_pkt_free(query_pkt); ldns_pkt_free(answer_pkt); LDNS_FREE(outbuf); ldns_rr_list_free(answer_qr); ldns_rr_list_free(answer_an); ldns_rr_list_free(answer_ns); ldns_rr_list_free(answer_ad); } ldns_rdf_deep_free(origin); ldns_zone_deep_free(zone); rp_shutdown(rp_handle); }
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; }