mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-25 09:09:40 -05:00
auth zone unit test extra_packet moves multipe tcp packets on stream
git-svn-id: file:///svn/unbound/trunk@4485 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
6a0b5aa8e3
commit
61d431e44f
4 changed files with 130 additions and 37 deletions
|
|
@ -504,7 +504,6 @@ auth_zones_find_or_add_xfer(struct auth_zones* az, struct auth_zone* z)
|
|||
if(!x) {
|
||||
/* not found, create the zone */
|
||||
x = auth_xfer_create(az, z);
|
||||
lock_basic_lock(&x->lock);
|
||||
} else {
|
||||
lock_basic_lock(&x->lock);
|
||||
}
|
||||
|
|
@ -920,7 +919,6 @@ rrset_moveover_rrsigs(struct auth_data* node, uint16_t rr_type,
|
|||
/* 0 rrsigs to move over, done */
|
||||
return 1;
|
||||
}
|
||||
log_info("moveover %d sigs size %d", (int)sigs, (int)sigsz);
|
||||
|
||||
/* allocate rrset sigsz larger for extra sigs elements, and
|
||||
* allocate rrsig sigsz smaller for less sigs elements. */
|
||||
|
|
@ -1323,7 +1321,7 @@ decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt,
|
|||
case LDNS_RDF_TYPE_DNAME:
|
||||
sldns_buffer_set_position(&pktbuf,
|
||||
(size_t)(rd -
|
||||
sldns_buffer_current(&pktbuf)));
|
||||
sldns_buffer_begin(&pktbuf)));
|
||||
oldpos = sldns_buffer_position(&pktbuf);
|
||||
/* moves pktbuf to right after the
|
||||
* compressed dname, and returns uncompressed
|
||||
|
|
@ -1367,11 +1365,10 @@ decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt,
|
|||
if(!sldns_buffer_available(buf, rdlen)) return 0;
|
||||
sldns_buffer_write(buf, rd, rdlen);
|
||||
}
|
||||
sldns_buffer_flip(buf);
|
||||
|
||||
/* fixup rdlength */
|
||||
sldns_buffer_write_u16_at(buf, rdlenpos,
|
||||
sldns_buffer_position(buf)-rdlenpos-2);
|
||||
sldns_buffer_flip(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -1393,6 +1390,9 @@ az_insert_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
|
|||
}
|
||||
rr = sldns_buffer_begin(scratch_buffer);
|
||||
rr_len = sldns_buffer_limit(scratch_buffer);
|
||||
char buf[512];
|
||||
(void)sldns_wire2str_rr_buf(rr, rr_len, buf, sizeof(buf));
|
||||
log_info("decompress is %s", buf);
|
||||
dname_len = dname_valid(rr, rr_len);
|
||||
return az_insert_rr(z, rr, rr_len, dname_len, duplicate);
|
||||
}
|
||||
|
|
@ -2830,7 +2830,6 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
|
|||
char wcname[256];
|
||||
sldns_wire2str_dname_buf(wildcard->name, wildcard->namelen,
|
||||
wcname, sizeof(wcname));
|
||||
log_info("wildcard %s", wcname);
|
||||
}
|
||||
if((rrset=az_domain_rrset(wildcard, qinfo->qtype)) != NULL) {
|
||||
/* wildcard has type, add it */
|
||||
|
|
@ -3113,6 +3112,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
|||
lock_rw_unlock(&az->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lock_rw_unlock(&az->lock);
|
||||
if(!z->for_downstream) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
|
|
@ -3422,10 +3422,8 @@ xfr_create_ixfr_packet(struct auth_xfer* xfr, sldns_buffer* buf, uint16_t id)
|
|||
struct query_info qinfo;
|
||||
uint32_t serial;
|
||||
int have_zone;
|
||||
lock_basic_lock(&xfr->lock);
|
||||
have_zone = xfr->have_zone;
|
||||
serial = xfr->serial;
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
|
||||
memset(&qinfo, 0, sizeof(qinfo));
|
||||
qinfo.qname = xfr->name;
|
||||
|
|
@ -3601,20 +3599,25 @@ chunk_rrlist_gonext(struct auth_chunk** rr_chunk, int* rr_num,
|
|||
/* already at end of chunks? */
|
||||
if(!*rr_chunk)
|
||||
return;
|
||||
while(*rr_chunk) {
|
||||
/* move within this chunk */
|
||||
if((*rr_chunk)->len >= LDNS_HEADER_SIZE &&
|
||||
(*rr_num)+1 < (int)LDNS_ANCOUNT((*rr_chunk)->data)) {
|
||||
(*rr_num) += 1;
|
||||
*rr_pos = rr_nextpos;
|
||||
return ;
|
||||
}
|
||||
|
||||
/* no more RRs in this chunk */
|
||||
/* continue with next chunk, see if it has RRs */
|
||||
/* move within this chunk */
|
||||
if((*rr_chunk)->len >= LDNS_HEADER_SIZE &&
|
||||
(*rr_num)+1 < (int)LDNS_ANCOUNT((*rr_chunk)->data)) {
|
||||
(*rr_num) += 1;
|
||||
*rr_pos = rr_nextpos;
|
||||
return;
|
||||
}
|
||||
/* no more RRs in this chunk */
|
||||
/* continue with next chunk, see if it has RRs */
|
||||
if(*rr_chunk)
|
||||
*rr_chunk = (*rr_chunk)->next;
|
||||
while(*rr_chunk) {
|
||||
*rr_num = 0;
|
||||
*rr_pos = 0;
|
||||
if((*rr_chunk)->len >= LDNS_HEADER_SIZE &&
|
||||
LDNS_ANCOUNT((*rr_chunk)->data) > 0) {
|
||||
return;
|
||||
}
|
||||
*rr_chunk = (*rr_chunk)->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3634,7 +3637,18 @@ chunk_rrlist_get_current(struct auth_chunk* rr_chunk, int rr_num,
|
|||
|
||||
/* fetch rr information */
|
||||
sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len);
|
||||
sldns_buffer_set_position(&pkt, rr_pos);
|
||||
if(rr_pos == 0) {
|
||||
size_t i;
|
||||
/* skip question section */
|
||||
sldns_buffer_set_position(&pkt, LDNS_HEADER_SIZE);
|
||||
for(i=0; i<LDNS_QDCOUNT(rr_chunk->data); i++) {
|
||||
if(pkt_dname_len(&pkt) ==0) return 0;
|
||||
if(sldns_buffer_remaining(&pkt) < 4) return 0;
|
||||
sldns_buffer_skip(&pkt, 4); /* type and class */
|
||||
}
|
||||
} else {
|
||||
sldns_buffer_set_position(&pkt, rr_pos);
|
||||
}
|
||||
*rr_dname = sldns_buffer_current(&pkt);
|
||||
if(pkt_dname_len(&pkt) == 0) return 0;
|
||||
if(sldns_buffer_remaining(&pkt) < 10) return 0;
|
||||
|
|
@ -3649,6 +3663,28 @@ chunk_rrlist_get_current(struct auth_chunk* rr_chunk, int rr_num,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** print log message where we are in parsing the zone transfer */
|
||||
static void
|
||||
log_rrlist_position(const char* label, struct auth_chunk* rr_chunk,
|
||||
uint8_t* rr_dname, uint16_t rr_type, size_t rr_counter)
|
||||
{
|
||||
sldns_buffer pkt;
|
||||
size_t dlen;
|
||||
uint8_t buf[256];
|
||||
char str[256];
|
||||
char typestr[32];
|
||||
sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len);
|
||||
sldns_buffer_set_position(&pkt, (size_t)(rr_dname -
|
||||
sldns_buffer_begin(&pkt)));
|
||||
if((dlen=pkt_dname_len(&pkt)) == 0) return;
|
||||
if(dlen >= sizeof(buf)) return;
|
||||
dname_pkt_copy(&pkt, buf, rr_dname);
|
||||
dname_str(buf, str);
|
||||
(void)sldns_wire2str_type_buf(rr_type, typestr, sizeof(typestr));
|
||||
verbose(VERB_ALGO, "%s at[%d] %s %s", label, (int)rr_counter,
|
||||
str, typestr);
|
||||
}
|
||||
|
||||
/** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */
|
||||
static int
|
||||
apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
|
|
@ -3676,6 +3712,8 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
|||
/* failed to parse RR */
|
||||
return 0;
|
||||
}
|
||||
if(verbosity>=VERB_ALGO) log_rrlist_position("apply_ixfr",
|
||||
rr_chunk, rr_dname, rr_type, rr_counter);
|
||||
/* twiddle add/del mode and check for start and end */
|
||||
if(rr_counter == 0 && rr_type != LDNS_RR_TYPE_SOA)
|
||||
return 0;
|
||||
|
|
@ -3777,6 +3815,7 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
|
|||
uint32_t serial = 0;
|
||||
size_t rr_nextpos;
|
||||
size_t rr_counter = 0;
|
||||
int have_end_soa = 0;
|
||||
|
||||
/* clear the data tree */
|
||||
traverse_postorder(&z->data, auth_data_del, NULL);
|
||||
|
|
@ -3795,9 +3834,12 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
|
|||
/* failed to parse RR */
|
||||
return 0;
|
||||
}
|
||||
if(verbosity>=VERB_ALGO) log_rrlist_position("apply_axfr",
|
||||
rr_chunk, rr_dname, rr_type, rr_counter);
|
||||
if(rr_type == LDNS_RR_TYPE_SOA) {
|
||||
if(rr_counter != 0) {
|
||||
/* end of the axfr */
|
||||
have_end_soa = 1;
|
||||
break;
|
||||
}
|
||||
if(rr_rdlen < 22) return 0; /* bad SOA rdlen */
|
||||
|
|
@ -3815,6 +3857,10 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
|
|||
rr_counter++;
|
||||
chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos);
|
||||
}
|
||||
if(!have_end_soa) {
|
||||
log_err("no end SOA record for AXFR");
|
||||
return 0;
|
||||
}
|
||||
|
||||
xfr->serial = serial;
|
||||
xfr->have_zone = 1;
|
||||
|
|
@ -4068,6 +4114,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
|
|||
* and we may then get an instant cache response,
|
||||
* and that calls the callback just like a full
|
||||
* lookup and lookup failures also call callback */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
xfr_transfer_move_to_next_lookup(xfr, env);
|
||||
|
|
@ -4079,13 +4126,13 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
|
|||
xfr->task_transfer->master = xfr_transfer_current_master(xfr);
|
||||
if(xfr_transfer_init_fetch(xfr, env)) {
|
||||
/* successfully started, wait for callback */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
/* failed to fetch, next master */
|
||||
xfr_transfer_nextmaster(xfr);
|
||||
}
|
||||
|
||||
lock_basic_lock(&xfr->lock);
|
||||
/* we failed to fetch the zone, move to wait task
|
||||
* use the shorter retry timeout */
|
||||
xfr_transfer_disown(xfr);
|
||||
|
|
@ -4148,6 +4195,7 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
|||
struct module_env* env;
|
||||
log_assert(xfr->task_transfer);
|
||||
env = xfr->task_transfer->env;
|
||||
lock_basic_lock(&xfr->lock);
|
||||
|
||||
/* process result */
|
||||
if(rcode == LDNS_RCODE_NOERROR) {
|
||||
|
|
@ -4507,7 +4555,6 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
|
|||
/* it worked! */
|
||||
auth_chunks_delete(xfr->task_transfer);
|
||||
|
||||
lock_basic_lock(&xfr->lock);
|
||||
/* we fetched the zone, move to wait task */
|
||||
xfr_transfer_disown(xfr);
|
||||
|
||||
|
|
@ -4596,7 +4643,6 @@ xfr_start_transfer(struct auth_xfer* xfr, struct module_env* env,
|
|||
log_assert(xfr->task_transfer->chunks_last == NULL);
|
||||
xfr->task_transfer->worker = env->worker;
|
||||
xfr->task_transfer->env = env;
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
|
||||
/* init transfer process */
|
||||
/* find that master in the transfer's list of masters? */
|
||||
|
|
@ -4759,7 +4805,6 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
|||
xfr_probe_disown(xfr);
|
||||
xfr_start_transfer(xfr, env,
|
||||
xfr_probe_current_master(xfr));
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
@ -5147,6 +5192,7 @@ auth_xfer_new(struct auth_zone* z)
|
|||
sizeof(xfr->task_probe->worker));
|
||||
lock_protect(&xfr->lock, &xfr->task_transfer->worker,
|
||||
sizeof(xfr->task_transfer->worker));
|
||||
lock_basic_lock(&xfr->lock);
|
||||
return xfr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -268,6 +268,11 @@ 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) {
|
||||
if(p->tcp_pkt_counter != 0) {
|
||||
/* continue tcp transfer */
|
||||
*pend = p;
|
||||
return 1;
|
||||
}
|
||||
if(pending_find_match(runtime, entry, p)) {
|
||||
*pend = p;
|
||||
return 1;
|
||||
|
|
@ -298,24 +303,45 @@ pending_list_delete(struct replay_runtime* runtime, struct fake_pending* pend)
|
|||
}
|
||||
}
|
||||
|
||||
/** number of replies in entry */
|
||||
static int
|
||||
count_reply_packets(struct entry* entry)
|
||||
{
|
||||
int count = 0;
|
||||
struct reply_packet* reppkt = entry->reply_list;
|
||||
while(reppkt) {
|
||||
count++;
|
||||
reppkt = reppkt->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill buffer with reply from the entry.
|
||||
*/
|
||||
static void
|
||||
fill_buffer_with_reply(sldns_buffer* buffer, struct entry* entry, uint8_t* q,
|
||||
size_t qlen)
|
||||
size_t qlen, int tcp_pkt_counter)
|
||||
{
|
||||
struct reply_packet* reppkt;
|
||||
uint8_t* c;
|
||||
size_t clen;
|
||||
log_assert(entry && entry->reply_list);
|
||||
sldns_buffer_clear(buffer);
|
||||
if(entry->reply_list->reply_from_hex) {
|
||||
c = sldns_buffer_begin(entry->reply_list->reply_from_hex);
|
||||
clen = sldns_buffer_limit(entry->reply_list->reply_from_hex);
|
||||
reppkt = entry->reply_list;
|
||||
if(tcp_pkt_counter > 0) {
|
||||
int i = tcp_pkt_counter;
|
||||
while(reppkt && i--)
|
||||
reppkt = reppkt->next;
|
||||
log_pkt("extra_packet ", reppkt->reply_pkt, reppkt->reply_len);
|
||||
}
|
||||
if(reppkt->reply_from_hex) {
|
||||
c = sldns_buffer_begin(reppkt->reply_from_hex);
|
||||
clen = sldns_buffer_limit(reppkt->reply_from_hex);
|
||||
if(!c) fatal_exit("out of memory");
|
||||
} else {
|
||||
c = entry->reply_list->reply_pkt;
|
||||
clen = entry->reply_list->reply_len;
|
||||
c = reppkt->reply_pkt;
|
||||
clen = reppkt->reply_len;
|
||||
}
|
||||
if(c) {
|
||||
if(q) adjust_packet(entry, &c, &clen, q, qlen);
|
||||
|
|
@ -346,12 +372,20 @@ answer_callback_from_entry(struct replay_runtime* runtime,
|
|||
c.type = comm_udp;
|
||||
if(pend->transport == transport_tcp)
|
||||
c.type = comm_tcp;
|
||||
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len);
|
||||
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
|
||||
pend->tcp_pkt_counter);
|
||||
repinfo.c = &c;
|
||||
repinfo.addrlen = pend->addrlen;
|
||||
memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
|
||||
if(!pend->serviced)
|
||||
pending_list_delete(runtime, pend);
|
||||
if(!pend->serviced) {
|
||||
if(entry->reply_list->next &&
|
||||
pend->tcp_pkt_counter < count_reply_packets(entry)) {
|
||||
/* go to next packet next time */
|
||||
pend->tcp_pkt_counter++;
|
||||
} else {
|
||||
pending_list_delete(runtime, pend);
|
||||
}
|
||||
}
|
||||
if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) {
|
||||
fatal_exit("testbound: unexpected: callback returned 1");
|
||||
}
|
||||
|
|
@ -417,7 +451,7 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
|
|||
if(todo->match->match_transport == transport_tcp)
|
||||
repinfo.c->type = comm_tcp;
|
||||
else repinfo.c->type = comm_udp;
|
||||
fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0);
|
||||
fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0, 0);
|
||||
log_info("testbound: incoming QUERY");
|
||||
log_pkt("query pkt", todo->match->reply_list->reply_pkt,
|
||||
todo->match->reply_list->reply_len);
|
||||
|
|
@ -454,13 +488,20 @@ fake_pending_callback(struct replay_runtime* runtime,
|
|||
c.type = comm_tcp;
|
||||
if(todo->evt_type == repevt_back_reply && todo->match) {
|
||||
fill_buffer_with_reply(c.buffer, todo->match, p->pkt,
|
||||
p->pkt_len);
|
||||
p->pkt_len, p->tcp_pkt_counter);
|
||||
}
|
||||
repinfo.c = &c;
|
||||
repinfo.addrlen = p->addrlen;
|
||||
memcpy(&repinfo.addr, &p->addr, p->addrlen);
|
||||
if(!p->serviced)
|
||||
pending_list_delete(runtime, p);
|
||||
if(!p->serviced) {
|
||||
if(todo->match->reply_list->next && !error &&
|
||||
p->tcp_pkt_counter < count_reply_packets(todo->match)) {
|
||||
/* go to next packet next time */
|
||||
p->tcp_pkt_counter++;
|
||||
} else {
|
||||
pending_list_delete(runtime, p);
|
||||
}
|
||||
}
|
||||
if((*cb)(&c, cb_arg, error, &repinfo)) {
|
||||
fatal_exit("unexpected: pending callback returned 1");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -348,6 +348,8 @@ struct fake_pending {
|
|||
enum transport_type transport;
|
||||
/** if this is a serviced query */
|
||||
int serviced;
|
||||
/** if we are handling a multi pkt tcp stream, non 0 and the pkt nr*/
|
||||
int tcp_pkt_counter;
|
||||
/** the runtime structure this is part of */
|
||||
struct replay_runtime* runtime;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -572,11 +572,15 @@ 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")) {
|
||||
/* copy current packet into buffer */
|
||||
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);
|
||||
/* clear for next packet */
|
||||
pktlen = LDNS_HEADER_SIZE;
|
||||
memset(pktbuf, 0, pktlen); /* ID = 0, FLAGS="", and rr counts 0 */
|
||||
} else if(str_keyword(&parse, "SECTION")) {
|
||||
if(str_keyword(&parse, "QUESTION"))
|
||||
add_section = LDNS_SECTION_QUESTION;
|
||||
|
|
|
|||
Loading…
Reference in a new issue