mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-02-12 15:23:41 -05:00
auth zone test, udp and tcp answered from unit test
git-svn-id: file:///svn/unbound/trunk@4484 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
392be1e787
commit
6a0b5aa8e3
6 changed files with 255 additions and 41 deletions
|
|
@ -3554,20 +3554,12 @@ check_packet_ok(sldns_buffer* pkt, uint16_t qtype, struct auth_xfer* xfr,
|
|||
static int
|
||||
xfr_serial_means_update(struct auth_xfer* xfr, uint32_t serial)
|
||||
{
|
||||
uint32_t zserial;
|
||||
int have_zone, zone_expired;
|
||||
lock_basic_lock(&xfr->lock);
|
||||
zserial = xfr->serial;
|
||||
have_zone = xfr->have_zone;
|
||||
zone_expired = xfr->zone_expired;
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
|
||||
if(!have_zone)
|
||||
if(!xfr->have_zone)
|
||||
return 1; /* no zone, anything is better */
|
||||
if(zone_expired)
|
||||
if(xfr->zone_expired)
|
||||
return 1; /* expired, the sent serial is better than expired
|
||||
data */
|
||||
if(compare_serial(zserial, serial) < 0)
|
||||
if(compare_serial(xfr->serial, serial) < 0)
|
||||
return 1; /* our serial is smaller than the sent serial,
|
||||
the data is newer, fetch it */
|
||||
return 0;
|
||||
|
|
@ -4711,10 +4703,12 @@ auth_xfer_probe_timer_callback(void* arg)
|
|||
struct module_env* env;
|
||||
log_assert(xfr->task_probe);
|
||||
env = xfr->task_probe->env;
|
||||
lock_basic_lock(&xfr->lock);
|
||||
|
||||
if(xfr->task_probe->timeout <= AUTH_PROBE_TIMEOUT_STOP) {
|
||||
/* try again with bigger timeout */
|
||||
if(xfr_probe_send_probe(xfr, env, xfr->task_probe->timeout*2)) {
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -4750,19 +4744,28 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
|||
if(check_packet_ok(c->buffer, LDNS_RR_TYPE_SOA, xfr,
|
||||
&serial)) {
|
||||
/* successful lookup */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: soa probe "
|
||||
"serial is %u", buf, (unsigned)serial);
|
||||
}
|
||||
/* see if this serial indicates that the zone has
|
||||
* to be updated */
|
||||
if(xfr_serial_means_update(xfr, serial)) {
|
||||
/* if updated, start the transfer task, if needed */
|
||||
verbose(VERB_ALGO, "auth_zone updated, start transfer");
|
||||
if(xfr->task_transfer->worker == NULL) {
|
||||
xfr_probe_disown(xfr);
|
||||
xfr_start_transfer(xfr, env,
|
||||
xfr_probe_current_master(xfr));
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return 0;
|
||||
|
||||
}
|
||||
} else {
|
||||
/* if zone not updated, start the wait timer again */
|
||||
verbose(VERB_ALGO, "auth_zone unchanged, new lease, wait");
|
||||
if(xfr->have_zone)
|
||||
xfr->lease_time = *env->now;
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
|
|
@ -4776,6 +4779,11 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
|
||||
}
|
||||
|
||||
/* failed lookup */
|
||||
/* delete commpoint so a new one is created, with a fresh port nr */
|
||||
|
|
@ -4875,7 +4883,6 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
|||
xfr_probe_nextmaster(xfr);
|
||||
}
|
||||
|
||||
lock_basic_lock(&xfr->lock);
|
||||
/* we failed to send this as well, move to the wait task,
|
||||
* use the shorter retry timeout */
|
||||
xfr_probe_disown(xfr);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,12 @@ int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
|
|||
return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0);
|
||||
}
|
||||
|
||||
int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
|
||||
{
|
||||
/* use arguments as temporary variables */
|
||||
return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0);
|
||||
}
|
||||
|
||||
int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
|
||||
size_t str_len, uint16_t rrtype)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -358,6 +358,22 @@ int sldns_wire2str_edns_option_code_print(char** str, size_t* str_len,
|
|||
int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
|
||||
size_t str_len);
|
||||
|
||||
/**
|
||||
* Convert question RR to string presentation format, on one line. User buffer.
|
||||
* @param rr: wireformat RR data
|
||||
* @param rr_len: length of the rr wire data.
|
||||
* @param str: the string buffer to write to.
|
||||
* If you pass NULL as the str, the return value of the function is
|
||||
* the str_len you need for the entire packet. It does not include
|
||||
* the 0 byte at the end.
|
||||
* @param str_len: the size of the string buffer. If more is needed, it'll
|
||||
* silently truncate the output to fit in the buffer.
|
||||
* @return the number of characters for this element, excluding zerobyte.
|
||||
* Is larger or equal than str_len if output was truncated.
|
||||
*/
|
||||
int sldns_wire2str_rrquestion_buf(uint8_t* rr, size_t rr_len, char* str,
|
||||
size_t str_len);
|
||||
|
||||
/**
|
||||
* 3597 printout of an RR in unknown rr format.
|
||||
* There are more format and comment options available for printout
|
||||
|
|
|
|||
|
|
@ -67,6 +67,27 @@
|
|||
struct worker;
|
||||
struct daemon_remote;
|
||||
|
||||
/** unique code to check that fake_commpoint is that structure */
|
||||
#define FAKE_COMMPOINT_TYPECODE 97347923
|
||||
/** fake commpoint, stores information */
|
||||
struct fake_commpoint {
|
||||
/** typecode */
|
||||
int typecode;
|
||||
/** if this is a udp outgoing type of commpoint */
|
||||
int type_udp_out;
|
||||
/** if this is a tcp outgoing tcp of commpoint */
|
||||
int type_tcp_out;
|
||||
|
||||
/** the callback, stored for usage */
|
||||
comm_point_callback_type* cb;
|
||||
/** the callback userarg, stored for usage */
|
||||
void* cb_arg;
|
||||
/** runtime ptr */
|
||||
struct replay_runtime* runtime;
|
||||
/** the pending entry for this commpoint (if any) */
|
||||
struct fake_pending* pending;
|
||||
};
|
||||
|
||||
/** Global variable: the scenario. Saved here for when event_init is done. */
|
||||
static struct replay_scenario* saved_scenario = NULL;
|
||||
|
||||
|
|
@ -247,7 +268,6 @@ pending_matches_range(struct replay_runtime* runtime,
|
|||
struct fake_pending* p = runtime->pending_list;
|
||||
/* slow, O(N*N), but it works as advertised with weird matching */
|
||||
while(p) {
|
||||
log_info("check of pending");
|
||||
if(pending_find_match(runtime, entry, p)) {
|
||||
*pend = p;
|
||||
return 1;
|
||||
|
|
@ -1168,7 +1188,11 @@ struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base),
|
|||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
void* ATTR_UNUSED(callback_arg))
|
||||
{
|
||||
return calloc(1, 1);
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
|
||||
sizeof(*fc));
|
||||
if(!fc) return NULL;
|
||||
fc->typecode = FAKE_COMMPOINT_TYPECODE;
|
||||
return (struct comm_point*)fc;
|
||||
}
|
||||
|
||||
struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
|
||||
|
|
@ -1177,7 +1201,11 @@ struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
|
|||
void* ATTR_UNUSED(callback_arg))
|
||||
{
|
||||
/* no pipe comm possible */
|
||||
return calloc(1, 1);
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
|
||||
sizeof(*fc));
|
||||
if(!fc) return NULL;
|
||||
fc->typecode = FAKE_COMMPOINT_TYPECODE;
|
||||
return (struct comm_point*)fc;
|
||||
}
|
||||
|
||||
void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c),
|
||||
|
|
@ -1194,6 +1222,13 @@ void comm_point_stop_listening(struct comm_point* ATTR_UNUSED(c))
|
|||
/* only cmd com _local gets deleted */
|
||||
void comm_point_delete(struct comm_point* c)
|
||||
{
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)c;
|
||||
if(c == NULL) return;
|
||||
log_assert(fc->typecode == FAKE_COMMPOINT_TYPECODE);
|
||||
if(fc->type_tcp_out) {
|
||||
/* remove tcp pending, so no more callbacks to it */
|
||||
pending_list_delete(fc->runtime, fc->pending);
|
||||
}
|
||||
free(c);
|
||||
}
|
||||
|
||||
|
|
@ -1437,6 +1472,7 @@ struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
|
|||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
void* ATTR_UNUSED(callback_arg))
|
||||
{
|
||||
log_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1445,21 +1481,27 @@ struct comm_point* comm_point_create_tcp_out(struct comm_base*
|
|||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
void* ATTR_UNUSED(callback_arg))
|
||||
{
|
||||
log_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
|
||||
comm_point_callback_type* cb, void* cb_arg,
|
||||
struct sockaddr_storage* to_addr, socklen_t to_addrlen)
|
||||
struct sockaddr_storage* ATTR_UNUSED(to_addr),
|
||||
socklen_t ATTR_UNUSED(to_addrlen))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)
|
||||
outnet->base;
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
|
||||
sizeof(*fc));
|
||||
if(!fc) return NULL;
|
||||
fc->typecode = FAKE_COMMPOINT_TYPECODE;
|
||||
fc->type_udp_out = 1;
|
||||
fc->cb = cb;
|
||||
fc->cb_arg = cb_arg;
|
||||
fc->runtime = runtime;
|
||||
/* used by authzone transfers */
|
||||
(void)outnet;
|
||||
(void)cb;
|
||||
(void)cb_arg;
|
||||
(void)to_addr;
|
||||
(void)to_addrlen;
|
||||
/* TODO */
|
||||
return NULL;
|
||||
return (struct comm_point*)fc;
|
||||
}
|
||||
|
||||
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
|
||||
|
|
@ -1467,35 +1509,144 @@ struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
|
|||
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
|
||||
struct sldns_buffer* query, int timeout)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)
|
||||
outnet->base;
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
|
||||
sizeof(*fc));
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
sizeof(struct fake_pending));
|
||||
if(!fc || !pend) {
|
||||
free(fc);
|
||||
free(pend);
|
||||
return NULL;
|
||||
}
|
||||
fc->typecode = FAKE_COMMPOINT_TYPECODE;
|
||||
fc->type_tcp_out = 1;
|
||||
fc->cb = cb;
|
||||
fc->cb_arg = cb_arg;
|
||||
fc->runtime = runtime;
|
||||
fc->pending = pend;
|
||||
|
||||
/* used by authzone transfers */
|
||||
(void)outnet;
|
||||
(void)cb;
|
||||
(void)cb_arg;
|
||||
(void)to_addr;
|
||||
(void)to_addrlen;
|
||||
(void)query;
|
||||
(void)timeout;
|
||||
/* TODO */
|
||||
return NULL;
|
||||
/* create pending item */
|
||||
pend->buffer = sldns_buffer_new(sldns_buffer_limit(query)+10);
|
||||
if(!pend->buffer) {
|
||||
free(fc);
|
||||
free(pend);
|
||||
return NULL;
|
||||
}
|
||||
sldns_buffer_copy(pend->buffer, query);
|
||||
memcpy(&pend->addr, to_addr, to_addrlen);
|
||||
pend->addrlen = to_addrlen;
|
||||
pend->zone = NULL;
|
||||
pend->zonelen = 0;
|
||||
if(LDNS_QDCOUNT(sldns_buffer_begin(query)) > 0) {
|
||||
char buf[512];
|
||||
char addrbuf[128];
|
||||
(void)sldns_wire2str_rrquestion_buf(sldns_buffer_at(query, LDNS_HEADER_SIZE), sldns_buffer_limit(query)-LDNS_HEADER_SIZE, buf, sizeof(buf));
|
||||
addr_to_str((struct sockaddr_storage*)to_addr, to_addrlen,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/
|
||||
log_info("tcp to %s: %s", addrbuf, buf);
|
||||
}
|
||||
log_assert(sldns_buffer_limit(query)-LDNS_HEADER_SIZE >= 2);
|
||||
pend->qtype = (int)sldns_buffer_read_u16_at(query,
|
||||
LDNS_HEADER_SIZE+
|
||||
dname_valid(sldns_buffer_at(query, LDNS_HEADER_SIZE),
|
||||
sldns_buffer_limit(query)-LDNS_HEADER_SIZE));
|
||||
}
|
||||
pend->callback = cb;
|
||||
pend->cb_arg = cb_arg;
|
||||
pend->timeout = timeout;
|
||||
pend->transport = transport_tcp;
|
||||
pend->pkt = NULL;
|
||||
pend->runtime = runtime;
|
||||
pend->serviced = 0;
|
||||
pend->pkt_len = sldns_buffer_limit(pend->buffer);
|
||||
pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len);
|
||||
if(!pend->pkt) fatal_exit("out of memory");
|
||||
|
||||
log_info("testbound: created fake pending for tcp_out");
|
||||
|
||||
/* add to list */
|
||||
pend->next = runtime->pending_list;
|
||||
runtime->pending_list = pend;
|
||||
|
||||
return (struct comm_point*)fc;
|
||||
}
|
||||
|
||||
int comm_point_send_udp_msg(struct comm_point *ATTR_UNUSED(c),
|
||||
sldns_buffer* ATTR_UNUSED(packet), struct sockaddr* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen))
|
||||
int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||
struct sockaddr* addr, socklen_t addrlen)
|
||||
{
|
||||
/* could create a test framework; and intercept eg. authzone probes */
|
||||
return 0;
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)c;
|
||||
struct replay_runtime* runtime = fc->runtime;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
sizeof(struct fake_pending));
|
||||
if(!pend) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
fc->pending = pend;
|
||||
/* used by authzone transfers */
|
||||
/* create pending item */
|
||||
pend->buffer = sldns_buffer_new(sldns_buffer_limit(packet) + 10);
|
||||
if(!pend->buffer) {
|
||||
free(pend);
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_copy(pend->buffer, packet);
|
||||
memcpy(&pend->addr, addr, addrlen);
|
||||
pend->addrlen = addrlen;
|
||||
pend->zone = NULL;
|
||||
pend->zonelen = 0;
|
||||
if(LDNS_QDCOUNT(sldns_buffer_begin(packet)) > 0) {
|
||||
char buf[512];
|
||||
char addrbuf[128];
|
||||
(void)sldns_wire2str_rrquestion_buf(sldns_buffer_at(packet, LDNS_HEADER_SIZE), sldns_buffer_limit(packet)-LDNS_HEADER_SIZE, buf, sizeof(buf));
|
||||
addr_to_str((struct sockaddr_storage*)addr, addrlen,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/
|
||||
log_info("udp to %s: %s", addrbuf, buf);
|
||||
}
|
||||
log_assert(sldns_buffer_limit(packet)-LDNS_HEADER_SIZE >= 2);
|
||||
pend->qtype = (int)sldns_buffer_read_u16_at(packet,
|
||||
LDNS_HEADER_SIZE+
|
||||
dname_valid(sldns_buffer_at(packet, LDNS_HEADER_SIZE),
|
||||
sldns_buffer_limit(packet)-LDNS_HEADER_SIZE));
|
||||
}
|
||||
pend->callback = fc->cb;
|
||||
pend->cb_arg = fc->cb_arg;
|
||||
pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
|
||||
pend->transport = transport_udp;
|
||||
pend->pkt = NULL;
|
||||
pend->runtime = runtime;
|
||||
pend->serviced = 0;
|
||||
pend->pkt_len = sldns_buffer_limit(pend->buffer);
|
||||
pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len);
|
||||
if(!pend->pkt) fatal_exit("out of memory");
|
||||
|
||||
log_info("testbound: created fake pending for send_udp_msg");
|
||||
|
||||
/* add to list */
|
||||
pend->next = runtime->pending_list;
|
||||
runtime->pending_list = pend;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss))
|
||||
{
|
||||
log_assert(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int outnet_tcp_connect(int ATTR_UNUSED(s), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -572,6 +572,10 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
|||
} else if(str_keyword(&parse, "ADJUST")) {
|
||||
adjustline(parse, current, cur_reply);
|
||||
} else if(str_keyword(&parse, "EXTRA_PACKET")) {
|
||||
cur_reply->reply_pkt = memdup(pktbuf, pktlen);
|
||||
cur_reply->reply_len = pktlen;
|
||||
if(!cur_reply->reply_pkt)
|
||||
error("out of memory");
|
||||
cur_reply = entry_add_reply(current);
|
||||
} else if(str_keyword(&parse, "SECTION")) {
|
||||
if(str_keyword(&parse, "QUESTION"))
|
||||
|
|
@ -1558,10 +1562,10 @@ adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
|
|||
return;
|
||||
}
|
||||
/* copy the ID */
|
||||
if(match->copy_id && reslen >= 2)
|
||||
res[1] = orig[1];
|
||||
if(match->copy_id && reslen >= 1)
|
||||
res[0] = orig[0];
|
||||
if(match->copy_id && reslen >= 2 && query_len >= 2)
|
||||
res[1] = query_pkt[1];
|
||||
if(match->copy_id && reslen >= 1 && query_len >= 1)
|
||||
res[0] = query_pkt[0];
|
||||
|
||||
if(match->copy_ednsdata_assume_clientsubnet) {
|
||||
/** Assume there is only one EDNS option, which is ECS.
|
||||
|
|
|
|||
30
testdata/auth_xfr.rpl
vendored
30
testdata/auth_xfr.rpl
vendored
|
|
@ -152,6 +152,35 @@ www.example.com. IN A
|
|||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN SOA
|
||||
SECTION ANSWER
|
||||
; serial, refresh, retry, expire, minimum
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN AXFR
|
||||
SECTION ANSWER
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||
example.com. IN NS ns.example.net.
|
||||
EXTRA_PACKET
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN AXFR
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 1.2.3.4
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
|
|
@ -172,5 +201,6 @@ SECTION ANSWER
|
|||
ENTRY_END
|
||||
|
||||
STEP 30 TIME_PASSES ELAPSE 10
|
||||
STEP 40 TRAFFIC
|
||||
|
||||
SCENARIO_END
|
||||
|
|
|
|||
Loading…
Reference in a new issue