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:
Wouter Wijngaards 2018-02-01 10:38:05 +00:00
parent 392be1e787
commit 6a0b5aa8e3
6 changed files with 255 additions and 41 deletions

View file

@ -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);

View file

@ -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)
{

View file

@ -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

View file

@ -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;
}

View file

@ -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
View file

@ -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