DCPluginSyncFilterResult dcplugin_sync_post_filter(DCPlugin *dcplugin, DCPluginDNSPacket *dcp_packet) { Blocking *blocking = dcplugin_get_user_data(dcplugin); ldns_pkt *packet = NULL; DCPluginSyncFilterResult result = DCP_SYNC_FILTER_RESULT_OK; if (blocking->domains == NULL && blocking->ips == NULL) { return DCP_SYNC_FILTER_RESULT_OK; } if (ldns_wire2pkt(&packet, dcplugin_get_wire_data(dcp_packet), dcplugin_get_wire_data_len(dcp_packet)) != LDNS_STATUS_OK) { return DCP_SYNC_FILTER_RESULT_ERROR; } if (blocking->domains != NULL && (result = apply_block_domains(dcp_packet, blocking, packet) != DCP_SYNC_FILTER_RESULT_OK)) { ldns_pkt_free(packet); return result; } if (blocking->ips != NULL && (result = apply_block_ips(dcp_packet, blocking, packet) != DCP_SYNC_FILTER_RESULT_OK)) { ldns_pkt_free(packet); return result; } ldns_pkt_free(packet); return DCP_SYNC_FILTER_RESULT_OK; }
ldns_rr * ldns_axfr_next(ldns_resolver *resolver) { ldns_rr *cur_rr; uint8_t *packet_wire; size_t packet_wire_size; ldns_lookup_table *rcode; ldns_status status; /* check if start() has been called */ if (!resolver || resolver->_socket == 0) { return NULL; } if (resolver->_cur_axfr_pkt) { if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; return ldns_axfr_next(resolver); } cur_rr = ldns_rr_clone(ldns_rr_list_rr( ldns_pkt_answer(resolver->_cur_axfr_pkt), resolver->_axfr_i)); resolver->_axfr_i++; if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { resolver->_axfr_soa_count++; if (resolver->_axfr_soa_count >= 2) { close(resolver->_socket); resolver->_socket = 0; ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; } } return cur_rr; } else { packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); if(!packet_wire) return NULL; status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, packet_wire_size); free(packet_wire); resolver->_axfr_i = 0; if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); fprintf(stderr, "Error in AXFR: %s\n", rcode->name); return NULL; } else { return ldns_axfr_next(resolver); } } }
ldns_pkt * ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type type, ldns_rr_class c, uint16_t flags) { ldns_rdf *newname; ldns_pkt *pkt; ldns_status status; pkt = NULL; if (!ldns_resolver_defnames(r)) { status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, type, c, flags); if (status == LDNS_STATUS_OK) { return pkt; } else { if (pkt) { ldns_pkt_free(pkt); } fprintf(stderr, "error: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } } if (!ldns_resolver_domain(r)) { /* _defnames is set, but the domain is not....?? */ status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, type, c, flags); if (status == LDNS_STATUS_OK) { return pkt; } else { if (pkt) { ldns_pkt_free(pkt); } return NULL; } } newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); if (!newname) { if (pkt) { ldns_pkt_free(pkt); } return NULL; } status = ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, type, c, flags); ldns_rdf_free(newname); return pkt; }
DCPluginSyncFilterResult dcplugin_sync_pre_filter(DCPlugin *dcplugin, DCPluginDNSPacket *dcp_packet) { uint8_t *new_packet; ldns_rdf *edns_data; ldns_pkt *packet; size_t new_packet_size; ldns_wire2pkt(&packet, dcplugin_get_wire_data(dcp_packet), dcplugin_get_wire_data_len(dcp_packet)); edns_data = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX, dcplugin_get_user_data(dcplugin)); ldns_pkt_set_edns_data(packet, edns_data); ldns_pkt2wire(&new_packet, packet, &new_packet_size); if (dcplugin_get_wire_data_max_len(dcp_packet) >= new_packet_size) { dcplugin_set_wire_data(dcp_packet, new_packet, new_packet_size); } free(new_packet); ldns_pkt_free(packet); return DCP_SYNC_FILTER_RESULT_OK; }
/** * Fill buffer with reply from the entry. */ static void fill_buffer_with_reply(ldns_buffer* buffer, struct entry* entry, ldns_pkt* q) { ldns_status status; ldns_pkt* answer_pkt = NULL; log_assert(entry && entry->reply_list); ldns_buffer_clear(buffer); if(entry->reply_list->reply_from_hex) { status = ldns_buffer2pkt_wire(&answer_pkt, entry->reply_list->reply_from_hex); if(status != LDNS_STATUS_OK) { log_err("testbound: hex packet unparsable, used asis."); ldns_buffer_write(buffer, ldns_buffer_begin(entry->reply_list->reply_from_hex), ldns_buffer_limit(entry->reply_list->reply_from_hex)); } } else { answer_pkt = ldns_pkt_clone(entry->reply_list->reply); } if(answer_pkt) { if(q) adjust_packet(entry, answer_pkt, q); status = ldns_pkt2buffer_wire(buffer, answer_pkt); if(status != LDNS_STATUS_OK) fatal_exit("ldns: cannot pkt2buffer_wire parsed pkt"); } ldns_pkt_free(answer_pkt); ldns_buffer_flip(buffer); }
ldns_rr_list* mrb_getrr_list(mrb_state *mrb, ldns_resolver *resolver, char *name, uint32_t rrtype,uint32_t rrclass, uint32_t opt, uint32_t rrsection) { ldns_pkt *pkt = NULL; ldns_rr_list *records= NULL; ldns_rdf *domain = NULL; domain = ldns_dname_new_frm_str(name); if(!domain) { return NULL; } pkt = ldns_resolver_query(resolver, domain, rrtype, rrclass, opt); ldns_rdf_deep_free(domain); if(!pkt) { return NULL; } records =ldns_pkt_rr_list_by_type(pkt, rrtype, rrsection); ldns_pkt_free(pkt); if(!records) { return NULL; } return records; }
ldns_rr_list *mrb_getaddress_rr_list(mrb_state *mrb, ldns_resolver *resolver, char *name) { ldns_pkt *pkt = NULL; ldns_rr_list *records= NULL; ldns_rdf *domain = NULL; domain = ldns_dname_new_frm_str(name); if(!domain) { return NULL; } pkt = ldns_resolver_query(resolver, domain, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, LDNS_RD); ldns_rdf_deep_free(domain); if(!pkt) { return NULL; } records =ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); ldns_pkt_free(pkt); if(!records) { return NULL; } return records; }
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; }
void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) { /* not particularly fast but flexible, make wireformat and print */ ldns_buffer* buf = ldns_buffer_new(65535); struct regional* region = regional_create(); if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, region, 65535, 1)) { log_info("%s: log_dns_msg: out of memory", str); } else { ldns_status s; ldns_pkt* pkt = NULL; s = ldns_buffer2pkt_wire(&pkt, buf); if(s != LDNS_STATUS_OK) { log_info("%s: log_dns_msg: ldns parse gave: %s", str, ldns_get_errorstr_by_id(s)); } else { ldns_buffer_clear(buf); s = ldns_pkt2buffer_str(buf, pkt); if(s != LDNS_STATUS_OK) { log_info("%s: log_dns_msg: ldns tostr gave: %s", str, ldns_get_errorstr_by_id(s)); } else { log_info("%s %s", str, (char*)ldns_buffer_begin(buf)); } } ldns_pkt_free(pkt); } ldns_buffer_free(buf); regional_destroy(region); }
ldns_pkt * ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { char *str_dname; ldns_rdf *new_name; ldns_rdf **search_list; size_t i; ldns_pkt *p; str_dname = ldns_rdf2str(name); if (ldns_dname_str_absolute(str_dname)) { /* query as-is */ return ldns_resolver_query(r, name, t, c, flags); } else if (ldns_resolver_dnsrch(r)) { search_list = ldns_resolver_searchlist(r); for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { new_name = ldns_dname_cat_clone(name, search_list[i]); p = ldns_resolver_query(r, new_name, t, c, flags); ldns_rdf_free(new_name); if (p) { if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { return p; } else { ldns_pkt_free(p); p = NULL; } } } } return NULL; }
static char * get_dns_string(netresolve_query_t query) { #ifdef USE_LDNS const uint8_t *answer; size_t length; if (!(answer = netresolve_query_get_dns_answer(query, &length))) return NULL; ldns_pkt *pkt; int status = ldns_wire2pkt(&pkt, answer, length); if (status) { fprintf(stderr, "ldns: %s", ldns_get_errorstr_by_id(status)); return NULL; } char *result = ldns_pkt2str(pkt); ldns_pkt_free(pkt); return result; #else return NULL; #endif }
/** check the packet and make sure that EDNS and DO and the type and RRSIG */ static int check_packet(uint8_t* wire, size_t len, int tp) { ldns_pkt *p = NULL; ldns_status s; if( (s=ldns_wire2pkt(&p, wire, len)) != LDNS_STATUS_OK) { if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s)); goto failed; } if(!p) { if(verb) printf("error: out of memory\n"); goto failed; } /* does DNS work? */ if(ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { char* r = ldns_pkt_rcode2str(ldns_pkt_get_rcode(p)); if(verb) printf("no answer, %s\n", r?r:"(out of memory)"); LDNS_FREE(r); goto failed; } /* test EDNS0 presence, of OPT record */ /* LDNS forgets during pkt parse, but we test the ARCOUNT; * 0 additionals means no EDNS(on the wire), and after parsing the * same additional RRs as before means no EDNS OPT */ if(LDNS_ARCOUNT(wire) == 0 || ldns_pkt_arcount(p) == LDNS_ARCOUNT(wire)) { if(verb) printf("no EDNS\n"); goto failed; } /* test if the type, RRSIG present */ if(!check_type_in_answer(p, tp) || !check_type_in_answer(p, LDNS_RR_TYPE_RRSIG)) { goto failed; } LDNS_FREE(wire); ldns_pkt_free(p); return 1; failed: LDNS_FREE(wire); ldns_pkt_free(p); return 0; }
/** delete a fake pending */ static void delete_fake_pending(struct fake_pending* pend) { if(!pend) return; ldns_buffer_free(pend->buffer); ldns_pkt_free(pend->pkt); free(pend); }
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; }
/** delete the list of reply packets */ void delete_replylist(struct reply_packet* replist) { struct reply_packet *p=replist, *np; while(p) { np = p->next; ldns_pkt_free(p->reply); ldns_buffer_free(p->reply_from_hex); free(p); p=np; } }
void network_req_free(getdns_network_req * net_req) { if (!net_req) { return; } if (net_req->result) { ldns_pkt_free(net_req->result); } GETDNS_FREE(net_req->owner->my_mf, net_req); }
/** delete a replay answer */ static void delete_replay_answer(struct replay_answer* a) { if(!a) return; if(a->repinfo.c) { ldns_buffer_free(a->repinfo.c->buffer); free(a->repinfo.c); } ldns_pkt_free(a->pkt); free(a); }
/** create a query to test */ static ldns_buffer* make_query(char* nm, int tp) { /* with EDNS DO and CDFLAG */ ldns_buffer* b = ldns_buffer_new(512); ldns_pkt* p; ldns_status s; if(!b) { if(verb) printf("error: out of memory\n"); return NULL; } s = ldns_pkt_query_new_frm_str(&p, nm, tp, LDNS_RR_CLASS_IN, (uint16_t)(LDNS_RD|LDNS_CD)); if(s != LDNS_STATUS_OK) { if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s)); ldns_buffer_free(b); return NULL; } if(!p) { if(verb) printf("error: out of memory\n"); ldns_buffer_free(b); return NULL; } ldns_pkt_set_edns_do(p, 1); ldns_pkt_set_edns_udp_size(p, 4096); ldns_pkt_set_id(p, ldns_get_random()); if( (s=ldns_pkt2buffer_wire(b, p)) != LDNS_STATUS_OK) { if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s)); ldns_pkt_free(p); ldns_buffer_free(b); return NULL; } ldns_pkt_free(p); return b; }
DCPluginSyncFilterResult dcplugin_sync_post_filter(DCPlugin *dcplugin, DCPluginDNSPacket *dcp_packet) { Context *context = dcplugin_get_user_data(dcplugin); ldns_pkt *packet; DCPluginSyncFilterResult result = DCP_SYNC_FILTER_RESULT_OK; if (context->blacklist == NULL) { return DCP_SYNC_FILTER_RESULT_OK; } if (ldns_wire2pkt(&packet, dcplugin_get_wire_data(dcp_packet), dcplugin_get_wire_data_len(dcp_packet)) != LDNS_STATUS_OK) { return DCP_SYNC_FILTER_RESULT_ERROR; } if ((result = apply_block_ips(dcp_packet, context, packet) != DCP_SYNC_FILTER_RESULT_OK)) { ldns_pkt_free(packet); return result; } ldns_pkt_free(packet); return DCP_SYNC_FILTER_RESULT_OK; }
bool handle_domain(void *k, void *l, void *c) { lookup_t *lookup = (lookup_t *) l; lookup_context_t *context = (lookup_context_t *) c; struct timeval now; gettimeofday(&now, NULL); if (timediff(&now, &lookup->next_lookup) < 0) { uint16_t query_flags = 0; if (!context->cmd_args.norecurse) { query_flags |= LDNS_RD; } ldns_pkt *packet; if(LDNS_STATUS_OK != ldns_pkt_query_new_frm_str(&packet, lookup->domain, context->cmd_args.record_types, LDNS_RR_CLASS_IN, query_flags)) { abort(); } ldns_pkt_set_id(packet, lookup->transaction); uint8_t *buf = NULL; size_t packet_size = 0; if(LDNS_STATUS_OK != ldns_pkt2wire(&buf, packet, &packet_size)) { abort(); } ldns_pkt_free(packet); packet = NULL; sockaddr_in_t *resolver = massdns_get_resolver((size_t) rand(), &context->resolvers); ssize_t n = -1; while (n < 0) { n = sendto(context->sock, buf, packet_size, 0, (sockaddr_t *) resolver, sizeof(*resolver)); } free(buf); long addusec = context->cmd_args.interval_ms * 1000; addusec += rand() % (addusec / 5); // Avoid congestion by adding some randomness lookup->next_lookup.tv_usec = (now.tv_usec + addusec) % 1000000; lookup->next_lookup.tv_sec = now.tv_sec + (now.tv_usec + addusec) / 1000000; lookup->tries++; if (lookup->tries == context->cmd_args.resolve_count) { hashmapRemove(context->map, lookup->domain); free(lookup->domain); free(lookup); } } return true; }
ldns_rr_list *mrb_getname_rr_list(mrb_state *mrb, ldns_resolver *resolver,char *addr) { char *rev = NULL, *query = NULL; const char *arpa = "in-addr.arpa"; ldns_rdf *domain = NULL ; ldns_pkt *pkt = NULL; ldns_rr_list *records = NULL; rev = reverse_addr(addr); if(!rev) { return NULL; } query = (char *)malloc( strlen(rev) + strlen(arpa) + sizeof(char) * 4); strcpy(query, rev); strcat(query,"."); strcat(query,arpa); domain = ldns_dname_new_frm_str(query); free(query); if(!domain) { return NULL; } pkt = ldns_resolver_query(resolver, domain, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN, LDNS_RD); ldns_rdf_deep_free(domain); if(!pkt) { return NULL; } records = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN); ldns_pkt_free(pkt); if(!records) { return NULL; } return records; }
void ldns_resolver_deep_free(ldns_resolver *res) { size_t i; if (res) { if (res->_searchlist) { for (i = 0; i < ldns_resolver_searchlist_count(res); i++) { ldns_rdf_deep_free(res->_searchlist[i]); } LDNS_FREE(res->_searchlist); } if (res->_nameservers) { for (i = 0; i < res->_nameserver_count; i++) { ldns_rdf_deep_free(res->_nameservers[i]); } LDNS_FREE(res->_nameservers); } if (ldns_resolver_domain(res)) { ldns_rdf_deep_free(ldns_resolver_domain(res)); } if (res->_tsig_keyname) { LDNS_FREE(res->_tsig_keyname); } if (res->_tsig_keydata) { LDNS_FREE(res->_tsig_keydata); } if (res->_tsig_algorithm) { LDNS_FREE(res->_tsig_algorithm); } if (res->_cur_axfr_pkt) { ldns_pkt_free(res->_cur_axfr_pkt); } if (res->_rtt) { LDNS_FREE(res->_rtt); } if (res->_dnssec_anchors) { ldns_rr_list_deep_free(res->_dnssec_anchors); } LDNS_FREE(res); } }
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); }
int massdns_receive_packet(int socket, void (*handle_packet)(ldns_pkt *, struct sockaddr_storage, void *), void *ctx) { uint8_t recvbuf[0xFFFF]; struct sockaddr_storage recvaddr; socklen_t fromlen = sizeof(recvaddr); ssize_t num_received = recvfrom(socket, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *) &recvaddr, &fromlen); if (num_received > 0) { ldns_pkt *packet; if(LDNS_STATUS_OK != ldns_wire2pkt(&packet, recvbuf, (size_t)num_received)) { // We have received a packet with an invalid format return 1; } handle_packet(packet, recvaddr, ctx); ldns_pkt_free(packet); return 1; } return 0; }
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) { struct fake_pending* pend = (struct fake_pending*)sq; struct replay_runtime* runtime = pend->runtime; /* delete from the list */ struct fake_pending* p = runtime->pending_list, *prev=NULL; while(p) { if(p == pend) { log_assert(p->cb_arg == cb_arg); log_info("serviced pending delete"); if(prev) prev->next = p->next; else runtime->pending_list = p->next; ldns_buffer_free(p->buffer); ldns_pkt_free(p->pkt); free(p); return; } prev = p; p = p->next; } log_info("double delete of pending serviced query"); }
switch_status_t ldns_lookup(const char *number, const char *root, char *server_name[ENUM_MAXNAMESERVERS] , enum_record_t **results) { ldns_resolver *res = NULL; ldns_rdf *domain = NULL; ldns_pkt *p = NULL; ldns_rr_list *naptr = NULL; ldns_status s = LDNS_STATUS_ERR; ldns_rdf *serv_rdf; switch_status_t status = SWITCH_STATUS_FALSE; char *name = NULL; struct timeval to = { 0, 0}; int inameserver = 0; int added_server = 0; if (!(name = reverse_number(number, root))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parse Error!\n"); goto end; } if (!(domain = ldns_dname_new_frm_str(name))) { goto end; } if (server_name) { res = ldns_resolver_new(); switch_assert(res); for(inameserver=0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) { if ( server_name[inameserver] != NULL ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding Nameserver [%s]\n", server_name[inameserver]); if ((serv_rdf = ldns_rdf_new_addr_frm_str( server_name[inameserver] ))) { s = ldns_resolver_push_nameserver(res, serv_rdf); ldns_rdf_deep_free(serv_rdf); added_server = 1; } } } } if (!added_server) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No Nameservers specified, using host default\n"); /* create a new resolver from /etc/resolv.conf */ s = ldns_resolver_new_frm_file(&res, NULL); } if (s != LDNS_STATUS_OK) { goto end; } to.tv_sec = globals.timeout / 1000; to.tv_usec = (globals.timeout % 1000) * 1000; ldns_resolver_set_timeout(res, to); ldns_resolver_set_retry(res, (uint8_t)globals.retries); ldns_resolver_set_random(res, globals.random); if ((p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN, LDNS_RD))) { /* retrieve the NAPTR records from the answer section of that * packet */ if ((naptr = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NAPTR, LDNS_SECTION_ANSWER))) { size_t i; ldns_rr_list_sort(naptr); for (i = 0; i < ldns_rr_list_rr_count(naptr); i++) { parse_naptr(ldns_rr_list_rr(naptr, i), number, results); } //ldns_rr_list_print(stdout, naptr); ldns_rr_list_deep_free(naptr); status = SWITCH_STATUS_SUCCESS; } } end: switch_safe_free(name); if (domain) { ldns_rdf_deep_free(domain); } if (p) { ldns_pkt_free(p); } if (res) { ldns_resolver_deep_free(res); } return status; }
int main(int argc, char *argv[]) { ldns_resolver *res; ldns_rdf *domain; ldns_pkt *p; ldns_rr_list *mx; ldns_status s; p = NULL; mx = NULL; domain = NULL; res = NULL; if (argc != 2) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } else { /* create a rdf from the command line arg */ domain = ldns_dname_new_frm_str(argv[1]); if (!domain) { usage(stdout, argv[0]); exit(EXIT_FAILURE); } } /* create a new resolver from /etc/resolv.conf */ s = ldns_resolver_new_frm_file(&res, NULL); if (s != LDNS_STATUS_OK) { exit(EXIT_FAILURE); } /* use the resolver to send a query for the mx * records of the domain given on the command line */ std::clock_t start; start = std::clock(); p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN, LDNS_RD); if(!p) std::cout << "no packet is generated" << std::endl; else{ std::clock_t current; current = std::clock(); double latency = (current-start)*1000.0/CLOCKS_PER_SEC; std::cout <<"Qurey sent to " << domain << ", latency is " << latency << " ms." <<std::endl; } ldns_rdf_deep_free(domain); //if (!p) { // exit(EXIT_FAILURE); //} else { // /* retrieve the MX records from the answer section of that // * packet // */ // mx = ldns_pkt_rr_list_by_type(p, // LDNS_RR_TYPE_MX, // LDNS_SECTION_ANSWER); // if (!mx) { // fprintf(stderr, // " *** invalid answer name %s after MX query for %s\n", // argv[1], argv[1]); // ldns_pkt_free(p); // ldns_resolver_deep_free(res); // exit(EXIT_FAILURE); // } else { // ldns_rr_list_sort(mx); // ldns_rr_list_print(stdout, mx); // ldns_rr_list_deep_free(mx); // } //} ldns_pkt_free(p); ldns_resolver_deep_free(res); 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); }
ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type type, ldns_rr_class c, uint16_t flags) { ldns_pkt *query_pkt; ldns_pkt *answer_pkt; ldns_status status; assert(r != NULL); assert(name != NULL); answer_pkt = NULL; /* do all the preprocessing here, then fire of an query to * the network */ if (0 == type) { type = LDNS_RR_TYPE_A; } if (0 == c) { c = LDNS_RR_CLASS_IN; } if (0 == ldns_resolver_nameserver_count(r)) { return LDNS_STATUS_RES_NO_NS; } if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { return LDNS_STATUS_RES_QUERY; } status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name, type, c, flags); if (status != LDNS_STATUS_OK) { return status; } /* if tsig values are set, tsign it */ /* TODO: make last 3 arguments optional too? maybe make complete rr instead of seperate values in resolver (and packet) Jelte should this go in pkt_prepare? */ #ifdef HAVE_SSL if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) { status = ldns_pkt_tsig_sign(query_pkt, ldns_resolver_tsig_keyname(r), ldns_resolver_tsig_keydata(r), 300, ldns_resolver_tsig_algorithm(r), NULL); if (status != LDNS_STATUS_OK) { return LDNS_STATUS_CRYPTO_TSIG_ERR; } } #endif /* HAVE_SSL */ status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt); ldns_pkt_free(query_pkt); /* allows answer to be NULL when not interested in return value */ if (answer) { *answer = answer_pkt; } return status; }
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); }