]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
auth zone test, udp and tcp answered from unit test
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 1 Feb 2018 10:38:05 +0000 (10:38 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 1 Feb 2018 10:38:05 +0000 (10:38 +0000)
git-svn-id: file:///svn/unbound/trunk@4484 be551aaa-1e26-0410-a405-d3ace91eadb9

services/authzone.c
sldns/wire2str.c
sldns/wire2str.h
testcode/fake_event.c
testcode/testpkts.c
testdata/auth_xfr.rpl

index 6efe2e1f8acd62b1597acda2351918f4da137d61..b53f2bc58081ee156be8ce0f53aad8205e57f532 100644 (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);
index 861b7648adecf0c5db8908f70b5e5d0939e9466d..832239f9b76a2439dd3cc8530600e103e19e0ac6 100644 (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)
 {
index aac13c548acd7617280bfc90393b1cc848359923..a64f5807269ce65010197c3e1680cb444dcd4235 100644 (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
index e999896ece8bb4daf37522f05ceb32574f45275f..f5481c22de35f6d3e96ce80d4add1d7debe6c6f9 100644 (file)
 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;
 }
 
index e1a7768abed0a361bd01f05a76bf5ed9c18c3f81..401f8afd1542a87641ab597c3cd8cff90527df01 100644 (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.
index 60b85668ec43521560fba9775f152777d76d8398..b1610202c71c7cb70e5839e0579d33e1ab7b2288 100644 (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