]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
test for msgparse.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Apr 2007 14:03:33 +0000 (14:03 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Apr 2007 14:03:33 +0000 (14:03 +0000)
git-svn-id: file:///svn/unbound/trunk@246 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testcode/fake_event.c
testcode/unitmain.c
testcode/unitmain.h
testcode/unitmsgparse.c [new file with mode: 0644]
util/data/dname.c
util/data/msgparse.c
util/data/msgparse.h
util/data/msgreply.c
util/net_help.c
util/net_help.h

index 2cbdd84d00e4c550bf9d6abecf760b6791afb107..75835db878c02ef4dfba88a20bfe1e64345181d9 100644 (file)
@@ -3,6 +3,10 @@
        - store calculated hash value too.
        - routine to create message out of stored information.
        - util/data/msgparse.c for message parsing code.
+       - unit test, and first fixes because of test.
+               * forgot rrset_count addition.
+               * did & of ptr on stack for memory position calculation.
+               * dname_pkt_copy forgot to read next label length.
 
 16 April 2007: Wouter
        - following a small change in LDNS, parsing code calculates the
index f5f9863b532bb8753cb4ad1c7493a3899beb3ba8..989846574b09471ca31fa8d448764ac5cd3be076 100644 (file)
@@ -47,6 +47,7 @@
 #include "config.h"
 #include "testcode/fake_event.h"
 #include "util/netevent.h"
+#include "util/net_help.h"
 #include "services/listen_dnsport.h"
 #include "services/outside_network.h"
 #include "testcode/replay.h"
@@ -613,12 +614,7 @@ void
 comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
         size_t iovlen)
 {
-       size_t i;
-       ldns_buffer_clear(repinfo->c->buffer);
-       for(i=1; i<iovlen; i++)
-               ldns_buffer_write(repinfo->c->buffer, iov[i].iov_base,
-                       iov[i].iov_len);
-       ldns_buffer_flip(repinfo->c->buffer);
+       write_iov_buffer(repinfo->c->buffer, iov, iovlen);
        comm_point_send_reply(repinfo);
 }
 
index a5d294f2064e58d8066882584a9be1c2c274184a..26ef8da5e247b3eef4f5864c783eaf0d9e9194f0 100644 (file)
@@ -216,6 +216,7 @@ main(int argc, char* argv[])
        msgreply_test();
        lruhash_test();
        slabhash_test();
+       msgparse_test();
        checklock_stop();
        printf("%d tests succeeded\n", testcount);
        return 0;
index 220d757de9431a2b91fc2ae147ebd7ca36eda38c..3f60d68ea70c278cd6a4c4c58ac7decbafedaa17 100644 (file)
@@ -51,5 +51,7 @@ extern int testcount;
 void lruhash_test();
 /** unit test slabhashtable implementation */
 void slabhash_test();
+/** unit test for msgreply and msgparse */
+void msgparse_test();
 
 #endif /* TESTCODE_UNITMAIN_H */
diff --git a/testcode/unitmsgparse.c b/testcode/unitmsgparse.c
new file mode 100644 (file)
index 0000000..4311069
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * testcode/unitmsgparse.c - unit test for msg parse routines.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * \file
+ * Unit test main program. Calls all the other unit tests.
+ * Exits with code 1 on a failure. 0 if all unit tests are successfull.
+ */
+
+#include "config.h"
+#include "util/log.h"
+#include "testcode/unitmain.h"
+#include "util/data/msgparse.h"
+#include "util/data/msgreply.h"
+#include "util/alloc.h"
+#include "util/region-allocator.h"
+#include "util/net_help.h"
+
+/** skip whitespace */
+static void
+skip_whites(const char** p)
+{
+       while(1) {
+               while(isspace(**p))
+                       (*p)++;
+               if(**p == ';') {
+                       /* comment, skip until newline */
+                       while(**p && **p != '\n')
+                               (*p)++;
+                       if(**p == '\n')
+                               (*p)++;
+               } else return;
+       }
+}
+
+/** takes a hex string and puts into buffer */
+static void hex_to_buf(ldns_buffer* pkt, const char* hex)
+{
+       const char* p = hex;
+       int val;
+       ldns_buffer_clear(pkt);
+       while(*p) {
+               skip_whites(&p);
+               if(ldns_buffer_position(pkt) == ldns_buffer_limit(pkt))
+                       fatal_exit("hex_to_buf: buffer too small");
+               if(!isalnum(*p))
+                       break;
+               val = ldns_hexdigit_to_int(*p++) << 4;
+               skip_whites(&p);
+               log_assert(*p && isalnum(*p));
+               val |= ldns_hexdigit_to_int(*p++);
+               ldns_buffer_write_u8(pkt, (uint8_t)val);
+               skip_whites(&p);
+       }
+       ldns_buffer_flip(pkt);
+       if(0) printf("packet size %u\n", (unsigned)ldns_buffer_limit(pkt));
+}
+
+/** match two rr lists */
+static int
+match_list(ldns_rr_list* q, ldns_rr_list *p)
+{
+       size_t i;
+       if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p))
+               return 0;
+       for(i=0; i<ldns_rr_list_rr_count(q); i++)
+       {
+               if(ldns_rr_compare(ldns_rr_list_rr(q, i),
+                       ldns_rr_list_rr(p, i)) != 0) {
+                       verbose(3, "rr %d different", i);
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/** compare two booleans */
+static int
+cmp_bool(int x, int y)
+{
+       if(!x && !y) return 0;
+       if(x && y) return 0;
+       if(!x) return -1;
+       return 1;
+}
+
+/** match all of the packet */
+static int
+match_all(ldns_pkt* q, ldns_pkt* p)
+{
+       if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p))
+       { verbose(3, "allmatch: opcode different"); return 0;}
+       if(ldns_pkt_get_rcode(q) != ldns_pkt_get_rcode(p))
+       { verbose(3, "allmatch: rcode different"); return 0;}
+       if(ldns_pkt_id(q) != ldns_pkt_id(p))
+       { verbose(3, "allmatch: id different"); return 0;}
+       if(cmp_bool(ldns_pkt_qr(q), ldns_pkt_qr(p)) != 0)
+       { verbose(3, "allmatch: qr different"); return 0;}
+       if(cmp_bool(ldns_pkt_aa(q), ldns_pkt_aa(p)) != 0)
+       { verbose(3, "allmatch: aa different"); return 0;}
+       if(cmp_bool(ldns_pkt_tc(q), ldns_pkt_tc(p)) != 0)
+       { verbose(3, "allmatch: tc different"); return 0;}
+       if(cmp_bool(ldns_pkt_rd(q), ldns_pkt_rd(p)) != 0)
+       { verbose(3, "allmatch: rd different"); return 0;}
+       if(cmp_bool(ldns_pkt_cd(q), ldns_pkt_cd(p)) != 0)
+       { verbose(3, "allmatch: cd different"); return 0;}
+       if(cmp_bool(ldns_pkt_ra(q), ldns_pkt_ra(p)) != 0)
+       { verbose(3, "allmatch: ra different"); return 0;}
+       if(cmp_bool(ldns_pkt_ad(q), ldns_pkt_ad(p)) != 0)
+       { verbose(3, "allmatch: ad different"); return 0;}
+       if(ldns_pkt_qdcount(q) != ldns_pkt_qdcount(p))
+       { verbose(3, "allmatch: qdcount different"); return 0;}
+       if(ldns_pkt_ancount(q) != ldns_pkt_ancount(p))
+       { verbose(3, "allmatch: ancount different"); return 0;}
+       if(ldns_pkt_nscount(q) != ldns_pkt_nscount(p))
+       { verbose(3, "allmatch: nscount different"); return 0;}
+       if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p))
+       { verbose(3, "allmatch: arcount different"); return 0;}
+       if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p)))
+       { verbose(3, "allmatch: qd section different"); return 0;}
+       if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p)))
+       { verbose(3, "allmatch: an section different"); return 0;}
+       if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p)))
+       { verbose(3, "allmatch: ar section different"); return 0;}
+       if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p)))
+       { verbose(3, "allmatch: ns section different"); return 0;}
+       return 1;
+}
+
+/** see if buffers contain the same packet */
+static int
+test_buffers(ldns_buffer* pkt, ldns_buffer* out)
+{
+       ldns_pkt* p1=0, *p2=0;
+       ldns_status s1, s2;
+       /* check binary same */
+       if(ldns_buffer_limit(pkt) == ldns_buffer_limit(out) &&
+               memcmp(ldns_buffer_begin(pkt), ldns_buffer_begin(out),
+                       ldns_buffer_limit(pkt)) == 0)
+               return 1;
+       /* check if it 'means the same' */
+       s1 = ldns_buffer2pkt_wire(&p1, pkt);
+       s2 = ldns_buffer2pkt_wire(&p2, pkt);
+       if(s1 != s2) {
+               /* oops! */
+               printf("input ldns parse: %s, output ldns parse: %s.\n",
+                       ldns_get_errorstr_by_id(s1), 
+                       ldns_get_errorstr_by_id(s2));
+               unit_assert(0);
+       }
+       /* compare packets */
+       unit_assert(match_all(p1, p2));
+       ldns_pkt_free(p1);
+       ldns_pkt_free(p2);
+       return 0;
+}
+
+/** test a packet */
+static void
+testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out, 
+       const char* hex)
+{
+       struct query_info qi;
+       struct reply_info* rep = 0;
+       size_t sz;
+       int ret;
+       uint16_t id;
+       uint16_t flags;
+       uint32_t timenow = 0;
+       region_type *region = region_create(malloc, free);
+       struct iovec iov[1024];
+       size_t maxiov = 1024;
+
+       hex_to_buf(pkt, hex);
+       memmove(&id, ldns_buffer_begin(pkt), sizeof(id));
+       memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags));
+       ret = reply_info_parse(pkt, alloc, &qi, &rep);
+       if(ret != 0) {
+               printf("exit code %d: %s", ret, 
+                       ldns_lookup_by_id(ldns_rcodes, ret)->name);
+               unit_assert(ret == 0);
+       }
+       sz = reply_info_iov_regen(&qi, rep, id, flags, iov, maxiov,
+               timenow, region);
+       unit_assert(sz != 0); /* udp packets should fit in 1024 iov */
+       write_iov_buffer(out, iov, sz);
+
+       test_buffers(pkt, out);
+
+       query_info_clear(&qi);
+       reply_info_parsedelete(rep, alloc);
+       region_destroy(region);
+}
+
+/** simple test of parsing. */
+static void
+simpletest(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out)
+{
+       /* a root query  drill -q - */
+       testpkt(pkt, alloc, out, 
+               " c5 40 01 00 00 01 00 00 00 00 00 00 00 00 02 00 01 ");
+       
+       /* a root reply  drill -w - */
+       testpkt(pkt, alloc, out, 
+       " ; 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19\n"
+       " ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n"
+       " 97 3f 81 80 00 01 00 0d 00 00 00 02 00 00 02 00 01 00 00 02    ;          1-  20\n"
+       " 00 01 00 06 6d 38 00 14 01 49 0c 52 4f 4f 54 2d 53 45 52 56    ;         21-  40\n"
+       " 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01    ;         41-  60\n"
+       " 4a 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00    ;         61-  80\n"
+       " 00 02 00 01 00 06 6d 38 00 14 01 4b 0c 52 4f 4f 54 2d 53 45    ;         81- 100\n"
+       " 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00    ;        101- 120\n"
+       " 14 01 4c 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54    ;        121- 140\n"
+       " 00 00 00 02 00 01 00 06 6d 38 00 14 01 4d 0c 52 4f 4f 54 2d    ;        141- 160\n"
+       " 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d    ;        161- 180\n"
+       " 38 00 14 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e    ;        181- 200\n"
+       " 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 42 0c 52 4f 4f    ;        201- 220\n"
+       " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00    ;        221- 240\n"
+       " 06 6d 38 00 14 01 43 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53    ;        241- 260\n"
+       " 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 44 0c 52    ;        261- 280\n"
+       " 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00    ;        281- 300\n"
+       " 01 00 06 6d 38 00 14 01 45 0c 52 4f 4f 54 2d 53 45 52 56 45    ;        301- 320\n"
+       " 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 46    ;        321- 340\n"
+       " 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00    ;        341- 360\n"
+       " 02 00 01 00 06 6d 38 00 14 01 47 0c 52 4f 4f 54 2d 53 45 52    ;        361- 380\n"
+       " 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14    ;        381- 400\n"
+       " 01 48 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00    ;        401- 420\n"
+       " 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00    ;        421- 440\n"
+       " 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f    ;        441- 460\n"
+       " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02    ;        461- 480\n"
+       " 64 b9 00 04 c0 3a 80 1e  ");
+}
+
+void msgparse_test()
+{
+       ldns_buffer* pkt = ldns_buffer_new(65553);
+       ldns_buffer* out = ldns_buffer_new(65553);
+       struct alloc_cache super_a, alloc;
+       /* init */
+       alloc_init(&super_a, NULL, 0);
+       alloc_init(&alloc, &super_a, 2);
+
+       simpletest(pkt, &alloc, out);
+
+       /* cleanup */
+       alloc_clear(&alloc);
+       alloc_clear(&super_a);
+       ldns_buffer_free(pkt);
+       ldns_buffer_free(out);
+}
index a3ae1062d00036404c1a01366b9e7b1514b33dbf..005dc543e1b9219d31dc25bffeaf507d9a242bcf 100644 (file)
@@ -296,6 +296,7 @@ void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname)
                memmove(to, dname, lablen);
                dname += lablen;
                to += lablen;
+               lablen = *dname++;
        }
        /* copy last \0 */
        *to = 0;
index af9b91a5a93c86ff362bf0a0349ce05f0def411f..2b0aecd789898853bfe587c7cd408b89b2172e8e 100644 (file)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+/**
+ * \file
+ * Routines for message parsing a packet buffer to a descriptive structure.
+ */
 #include "config.h"
 #include "util/data/msgparse.h"
 #include "util/net_help.h"
@@ -403,5 +407,6 @@ parse_packet(ldns_buffer* pkt, struct msg_parse* msg, region_type* region)
                /* spurious data at end of packet. ignore */
                verbose(VERB_DETAIL, "spurious data at end of packet ignored");
        }
+       msg->rrset_count = msg->an_rrsets + msg->ns_rrsets + msg->ar_rrsets;
        return 0;
 }
index 6fecfa4c102aab61aad5f5e6e7cf47c639048bf1..bb69d20cbb29952a1fa35cd6dd0f8f3d482d2d31 100644 (file)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+/**
+ * \file
+ * Contains message parsing data structures.
+ * These point back into the packet buffer.
+ */
 
 #ifndef UTIL_DATA_MSGPARSE_H
 #define UTIL_DATA_MSGPARSE_H
index dcac83abb6e358d9f9a70c5f969cf1ac6e431b10..5c95e4202788367f1a410c3bd51ccf6a2b9f5070 100644 (file)
@@ -93,8 +93,8 @@ parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep)
        (*rep)->ar_numrrsets = msg->ar_rrsets;
        (*rep)->rrset_count = msg->rrset_count;
        /* array starts after the refs */
-       (*rep)->rrsets = (struct ub_packed_rrset_key**)&
-               ((*rep)->ref[msg->rrset_count]);
+       (*rep)->rrsets = (struct ub_packed_rrset_key**)
+               &((*rep)->ref[msg->rrset_count]);
        /* zero the arrays to assist cleanup in case of malloc failure */
        memset( (*rep)->rrsets, 0, 
                sizeof(struct ub_packed_rrset_key*) * msg->rrset_count);
@@ -308,10 +308,10 @@ parse_rr_copy(ldns_buffer* pkt, struct rrset_parse* pset,
        data->ttl = MAX_TTL;
        data->count = pset->rr_count;
        /* layout: struct - rr_len - rr_data - rdata - rrsig */
-       data->rr_len = (size_t*)((uint8_t*)&data + 
+       data->rr_len = (size_t*)((uint8_t*)data + 
                sizeof(struct packed_rrset_data));
-       data->rr_data = (uint8_t**)(&data->rr_len[data->count]);
-       nextrdata = (uint8_t*)(&data->rr_data[data->count]);
+       data->rr_data = (uint8_t**)&(data->rr_len[data->count]);
+       nextrdata = (uint8_t*)&(data->rr_data[data->count]);
        data->rrsig_data = 0;
        data->rrsig_len = 0;
        for(i=0; i<data->count; i++) {
index a42f2af93bcef0e6b0f32a9993cef916e33a9b52..788b414d5e34aa7486232cc76399eed051a5d40e 100644 (file)
@@ -94,3 +94,16 @@ is_pow2(size_t num)
        if(num == 0) return 1;
        return (num & (num-1)) == 0;
 }
+
+void 
+write_iov_buffer(ldns_buffer* buffer, struct iovec* iov, size_t iovlen)
+{
+       size_t i;
+       ldns_buffer_clear(buffer);
+       for(i=1; i<iovlen; i++) {
+               log_assert(ldns_buffer_position(buffer)+iov[i].iov_len
+                       <= ldns_buffer_capacity(buffer));
+               ldns_buffer_write(buffer, iov[i].iov_base, iov[i].iov_len);
+       }
+       ldns_buffer_flip(buffer);
+}
index f5d9c8037719cde6206bc1a2459f22a85af520e4..557c43d3960c7e5c976544574e4da4028a0e9dad 100644 (file)
@@ -83,4 +83,12 @@ int fd_set_nonblock(int s);
  */
 int is_pow2(size_t num);
 
+/**
+ * Write iov vector into a buffer.
+ * @param buffer: to write data into. 
+ * @param iov: iov vector
+ * @param iovlen: length of iov vector
+ */
+void write_iov_buffer(ldns_buffer* buffer, struct iovec* iov, size_t iovlen);
+
 #endif /* NET_HELP_H */