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;
}
Exemple #2
0
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);
		}
		
	}
	
}
Exemple #3
0
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;
}
Exemple #9
0
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;
}
Exemple #11
0
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);
}
Exemple #14
0
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;
}
Exemple #15
0
/** 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;
	}
}
Exemple #16
0
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;
}
Exemple #20
0
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;
}
Exemple #21
0
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);
    }
}
Exemple #23
0
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);
    
}
Exemple #24
0
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;
}
Exemple #28
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);
}
Exemple #29
0
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;
}
Exemple #30
0
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);
}