diff --git a/src/tests/dnslib/dnslib_edns_tests.c b/src/tests/dnslib/dnslib_edns_tests.c new file mode 100644 index 0000000000000000000000000000000000000000..94c6447fdddb88d7f076df78b191a48ea368b483 --- /dev/null +++ b/src/tests/dnslib/dnslib_edns_tests.c @@ -0,0 +1,194 @@ +/*! + * \file dnslib_ends_tests.c + * + * \author Jan Kadlec <jan.kadlec@nic.cz> + * + * Contains unit tests for ENDS API + * + * Contains tests for: + * - ENDS API + */ + +#include "tap_unit.h" + +#include "dnslib/edns.h" + +static int dnslib_edns_tests_count(int argc, char *argv[]); +static int dnslib_edns_tests_run(int argc, char *argv[]); + +/*! Exported unit API. + */ +unit_api dnslib_ends_tests_api = { + "DNS library - EDNS", //! Unit name + &dnslib_edns_tests_count, //! Count scheduled tests + &dnslib_edns_tests_run //! Run scheduled tests +}; + +/* + * Unit implementation. + */ + +dnslib_dname_t root_domain = { (uint8_t *)"0", 1, (uint8_t *)"0" , 1, NULL }; + +enum { TEST_EDNS = 1 }; + +struct edns { + dnslib_dname_t *owner; + uint16_t type; + uint16_t payload; + uint8_t ext_rcode; + uint8_t version; +}; + +typedef struct edns edns_t; + +static edns_t test_edns[TEST_EDNS] = { +{ &root_domain, + DNSLIB_RRTYPE_OPT, + 4096, + 0, + 0 } +}; + +uint8_t wire[7] = +{ 0x00, /* root */ + 0x00, 0x29, /* type OPT */ + 0x10, 0x00, /* UDP payload size */ + 0x00, /* higher bits in extended rcode */ + 0x00 }; /* ENDS version */ + +static uint8_t *edns_wire[TEST_EDNS] = { wire }; + +static int test_edns_get_payload() +{ + int errors = 0; + + for (int i = 0; i < TEST_EDNS; i++) { + if (dnslib_edns_get_payload(edns_wire[i]) != test_edns[i].payload) { + diag("Got wrong payload from wire"); + errors++; + } + } + return (errors == 0); +} + +static int test_edns_get_ext_rcode() +{ + int errors = 0; + + for (int i = 0; i < TEST_EDNS; i++) { + if (dnslib_edns_get_ext_rcode(edns_wire[i]) != test_edns[i].ext_rcode) { + diag("Got wrong extended rcode from wire"); + errors++; + } + } + return (errors == 0); +} + +static int test_edns_get_version() +{ + int errors = 0; + + for (int i = 0; i < TEST_EDNS; i++) { + if (dnslib_edns_get_version(edns_wire[i]) != test_edns[i].version) { + diag("Got wrong version from wire"); + errors++; + } + } + return (errors == 0); +} + +static int test_edns_set_payload() +{ + int errors = 0; + + uint16_t payload = 1024; + + for (int i = 0; i < TEST_EDNS; i++) { + dnslib_edns_set_payload(edns_wire[i], payload); + + if (dnslib_edns_get_payload(edns_wire[i]) != payload) { + diag("Set wrong payload"); + errors++; + } + } + return (errors == 0); +} + +static int test_edns_set_ext_rcode() +{ + int errors = 0; + + uint8_t rcode = 0x12; + + for (int i = 0; i < TEST_EDNS; i++) { + dnslib_edns_set_ext_rcode(edns_wire[i], rcode); + + if (dnslib_edns_get_ext_rcode(edns_wire[i]) != rcode) { + diag("Set wrong rcode"); + errors++; + } + } + return (errors == 0); +} + +static int test_edns_set_version() +{ + int errors = 0; + + uint8_t version = 1; + + for (int i = 0; i < TEST_EDNS; i++) { + dnslib_edns_set_version(edns_wire[i], version); + + if (dnslib_edns_get_version(edns_wire[i]) != version) { + diag("Set wrong version"); + errors++; + } + } + return (errors == 0); +} + +static const int DNSLIB_EDNS_TESTS_COUNT = 6; + +/*! This helper routine should report number of + * scheduled tests for given parameters. + */ +static int dnslib_edns_tests_count(int argc, char *argv[]) +{ + return DNSLIB_EDNS_TESTS_COUNT; +} + +/*! Run all scheduled tests for given parameters. + */ +static int dnslib_edns_tests_run(int argc, char *argv[]) +{ + int res = 0; + int res_final = 1; + + res = test_edns_get_payload(); + ok(res, "ends: get payload"); + res_final *= res; + + res = test_edns_get_ext_rcode(); + ok(res, "ends: get ext. rcode"); + res_final *= res; + + res = test_edns_get_version(); + ok(res, "ends: get version"); + res_final *= res; + + res = test_edns_set_payload(); + ok(res, "ends: set payload"); + res_final *= res; + + res = test_edns_set_ext_rcode(); + ok(res, "ends: set ext. rcode"); + res_final *= res; + + res = test_edns_set_version(); + ok(res, "ends: set version"); + res_final *= res; + + return res_final; +} diff --git a/src/tests/dnslib/dnslib_response_tests.c b/src/tests/dnslib/dnslib_response_tests.c index cf9cf45f85ad680a8eeae179e984507486f27840..5ee9685169266c11b43af5a74a2269bd54e604df 100644 --- a/src/tests/dnslib/dnslib_response_tests.c +++ b/src/tests/dnslib/dnslib_response_tests.c @@ -18,9 +18,7 @@ #include "rdata.h" #include "rrset.h" #include "dname.h" - -#include "ldns/ldns.h" -#include <stdbool.h> +#include "packet.h" static int dnslib_response_tests_count(int argc, char *argv[]); static int dnslib_response_tests_run(int argc, char *argv[]); @@ -48,9 +46,11 @@ struct test_response { uint16_t ancount; uint16_t nscount; uint16_t arcount; - dnslib_rrset_t *answer; - dnslib_rrset_t *authority; - dnslib_rrset_t *additional; + +/* XXX dnslib_rrset_t *question; */ + dnslib_rrset_t **answer; + dnslib_rrset_t **authority; + dnslib_rrset_t **additional; short size; @@ -69,6 +69,8 @@ struct test_raw_packet { typedef struct test_raw_packet test_raw_packet_t; +enum { DNAME_MAX_WIRE_LENGTH = 256 }; + enum { DNAMES_COUNT = 2, ITEMS_COUNT = 2, @@ -96,39 +98,12 @@ static dnslib_rdata_item_t ITEMS[ITEMS_COUNT] = static dnslib_rdata_t RDATA[RDATA_COUNT] = { {&ITEMS[0], 1, &RDATA[0]} }; static dnslib_rrset_t RESPONSE_RRSETS[RRSETS_COUNT] = - { {&DNAMES[0],1 ,1 ,3600, &RDATA[0], NULL} }; + { {&DNAMES[0], 1, 1, 3600, &RDATA[0], NULL} }; static test_response_t RESPONSES[RESPONSE_COUNT] = { {&DNAMES[0], 1, 1, 12345, 0, 0, 1, 0, 0, 0, NULL, - RESPONSE_RRSETS, NULL, 29} }; - -/* ************************* LDNS DATA ************************* */ - -/* XXX ENDIANESS ??? */ -static ldns_rdf LDNS_RDFS_TEMP[LDNS_RDF_TEMP_COUNT] = - { {LDNS_RDF_TYPE_DNAME, 13, (void *)"\7example\3com"}, - {LDNS_RDF_TYPE_DNAME, 16, (void *)"\2ns\7example\3com"} }; - -static ldns_rdf *LDNS_RDF_ARRAYS[LDNS_RDFS_COUNT] = - { &LDNS_RDFS_TEMP[0], &LDNS_RDFS_TEMP[1] } ; - -static ldns_rr LDNS_RRS[LDNS_RR_COUNT] = - { {&LDNS_RDFS_TEMP[0], 3600, 1, LDNS_RR_TYPE_NS, - LDNS_RR_CLASS_IN, &LDNS_RDF_ARRAYS[1], false} }; - -static ldns_rr *tmp = &LDNS_RRS[0]; - -static ldns_rr_list LDNS_RRLISTS[LDNS_RRLIST_COUNT] = - { {1, 1, &tmp} }; + (dnslib_rrset_t **)&RESPONSE_RRSETS, NULL, 29} }; -static ldns_hdr LDNS_HEADERS[LDNS_HEADER_COUNT] = - { {12345, false, false, false, false, false, false, false, - LDNS_PACKET_QUERY, 0, 0, 1, 0, 0} }; - -/* XXX what is response code in our response */ -static ldns_pkt LDNS_PACKETS[LDNS_PACKET_COUNT] =/*I have to put 65535 smwh*/ - { {&LDNS_HEADERS[0], NULL, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, - NULL, NULL, &LDNS_RRLISTS[0] , NULL} }; static int load_raw_packets(test_raw_packet_t ***raw_packets, uint8_t *count, const char *filename) @@ -171,7 +146,260 @@ static int load_raw_packets(test_raw_packet_t ***raw_packets, uint8_t *count, return 0; } -static int load_parsed_packets(test_response_t ***responses, uint *count, +static dnslib_rdata_t *load_response_rdata(uint16_t type, FILE *f) +{ + dnslib_rdata_t *rdata; + + rdata = dnslib_rdata_new(); + + dnslib_rrtype_descriptor_t *desc = + dnslib_rrtype_descriptor_by_type(type); + assert(desc != NULL); + + dnslib_rdata_item_t *items = + malloc(sizeof(dnslib_rdata_item_t) * desc->length); + + uint8_t raw_data_length; /* TODO should be bigger */ + + debug_zp("Reading %d items\n", desc->length); + + debug_zp("current type: %s\n", dnslib_rrtype_to_string(type)); + + for (int i = 0; i < desc->length; i++) { + if (desc->wireformat[i] == DNSLIB_RDATA_WF_COMPRESSED_DNAME || + desc->wireformat[i] == DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME || + desc->wireformat[i] == DNSLIB_RDATA_WF_LITERAL_DNAME ) { + + /* TODO maybe this does not need to be stored this big */ + + uint8_t dname_size; + uint8_t *dname_wire = NULL; //[DNAME_MAX_WIRE_LENGTH] = { 0 }; + + fread(&dname_size, sizeof(dname_size), 1, f); + assert(dname_size < DNAME_MAX_WIRE_LENGTH); + + dname_wire = malloc(sizeof(uint8_t) * dname_size); + fread(dname_wire, sizeof(uint8_t), + dname_size, f); + + items[i].dname = + dnslib_dname_new_from_wire(dname_wire, + dname_size, + NULL); + assert(items[i].dname); + + } else { + fread(&raw_data_length, sizeof(raw_data_length), 1, f); + debug_zp("read len: %d\n", raw_data_length); + items[i].raw_data = + malloc(sizeof(uint8_t) * raw_data_length + 1); + *(items[i].raw_data) = raw_data_length; + fread(items[i].raw_data + 1, sizeof(uint8_t), + raw_data_length, f); + } + } + + if (dnslib_rdata_set_items(rdata, items, desc->length) != 0) { + fprintf(stderr, "Error: could not set items\n"); + } + + free(items); + + return rdata; +} + +/*dnslib_rrsig_set_t *dnslib_load_rrsig(FILE *f) +{ + dnslib_rrsig_set_t *rrsig; + + uint16_t rrset_type; + uint16_t rrset_class; + uint32_t rrset_ttl; + + uint8_t rdata_count; + + fread(&rrset_type, sizeof(rrset_type), 1, f); + debug_zp("rrset type: %d\n", rrset_type); + fread(&rrset_class, sizeof(rrset_class), 1, f); + debug_zp("rrset class %d\n", rrset_class); + fread(&rrset_ttl, sizeof(rrset_ttl), 1, f); + debug_zp("rrset ttl %d\n", rrset_ttl); + + fread(&rdata_count, sizeof(rdata_count), 1, f); + + rrsig = dnslib_rrsig_set_new(NULL, rrset_type, rrset_class, rrset_ttl); + + dnslib_rdata_t *tmp_rdata; + + debug_zp("loading %d rdata entries\n", rdata_count); + + for (int i = 0; i < rdata_count; i++) { + tmp_rdata = dnslib_load_rdata(DNSLIB_RRTYPE_RRSIG, f); + dnslib_rrsig_set_add_rdata(rrsig, tmp_rdata); + } + + return rrsig; +} */ + +static dnslib_rrset_t *load_response_rrset(FILE *f, char is_question) +{ + dnslib_rrset_t *rrset; + + uint16_t rrset_type; + uint16_t rrset_class; + uint32_t rrset_ttl; + + /* Each rrset will only have one rdata entry */ + /* RRSIGs will be read as separate RRSets for now */ + /* TODO probably change it in python dump so that it complies with our + * implementation + */ + +/* uint8_t rdata_count; + uint8_t rrsig_count; */ + + uint8_t dname_size; + uint8_t *dname_wire = NULL; + + fread(&dname_size, sizeof(dname_size), 1, f); + assert(dname_size < DNAME_MAX_WIRE_LENGTH); + + dname_wire = malloc(sizeof(uint8_t) * dname_size); + fread(dname_wire, sizeof(uint8_t), + dname_size, f); + + + + dnslib_dname_t *owner = + dnslib_dname_new_from_wire(dname_wire, + dname_size, + NULL); + + fread(&rrset_type, sizeof(rrset_type), 1, f); + fread(&rrset_class, sizeof(rrset_class), 1, f); + + if (!is_question) { + fread(&rrset_ttl, sizeof(rrset_ttl), 1, f); + } + + rrset = dnslib_rrset_new(owner, rrset_type, rrset_class, rrset_ttl); + + debug_zp("RRSet type: %d\n", rrset->type); + + if (is_question) { + return rrset; + } + + dnslib_rdata_t *tmp_rdata; + + tmp_rdata = load_response_rdata(rrset->type, f); + dnslib_rrset_add_rdata(rrset, tmp_rdata); + + return rrset; +} + +static test_response_t *load_parsed_response(FILE *f) +{ + test_response_t *resp = malloc(sizeof(test_response_t)); + + if (fread(&resp->id, sizeof(resp->id), 1, f) != sizeof(resp->id)) { + return NULL; + } + + if (fread(&resp->qdcount, sizeof(resp->qdcount), 1, f) != + sizeof(resp->qdcount)) { + return NULL; + } + + if (fread(&resp->qdcount, sizeof(resp->ancount), 1, f) != + sizeof(resp->qdcount)) { + return NULL; + } + + + if (fread(&resp->qdcount, sizeof(resp->nscount), 1, f) != + sizeof(resp->qdcount)) { + return NULL; + } + + + if (fread(&resp->qdcount, sizeof(resp->arcount), 1, f) != + sizeof(resp->qdcount)) { + return NULL; + } + + dnslib_rrset_t **question_rrsets; + + question_rrsets = malloc(sizeof(dnslib_rrset_t *) * resp->qdcount); + + for (int i = 0; i < resp->qdcount; i++) { + question_rrsets[i] = load_response_rrset(f, 1); + if (question_rrsets[i] == NULL) { + return NULL; + } + } + + resp->answer = malloc(sizeof(dnslib_rrset_t *) * resp->ancount); + + for (int i = 0; i < resp->ancount; i++) { + resp->answer[i] = load_response_rrset(f, 0); + if (resp->answer[i] == NULL) { + return NULL; + } + } + + resp->authority = malloc(sizeof(dnslib_rrset_t *) * resp->nscount); + + for (int i = 0; i < resp->nscount; i++) { + resp->authority[i] = load_response_rrset(f, 0); + if (resp->authority[i] == NULL) { + return NULL; + } + } + + resp->additional= malloc(sizeof(dnslib_rrset_t *) * resp->arcount); + + for (int i = 0; i < resp->arcount; i++) { + resp->additional[i] = load_response_rrset(f, 0); + if (resp->additional[i] == NULL) { + return NULL; + } + } + + return resp; +} + +static int load_parsed_responses(test_response_t ***responses, uint32_t *count, + const char *filename) +{ + assert(*responses == NULL); + + FILE *f; + + f = fopen(filename, "r"); + + if (f == NULL) { + diag("could not open file: %s", filename); + return -1; + } + + if (fread(count, sizeof(*count), 1, f) != sizeof(*count)) { + return -1; + } + + *responses = malloc(sizeof(test_response_t *) * *count); + + for (int i = 0; i < *count; i++) { + *responses[i] = load_parsed_response(f); + if (responses[i] == NULL) { + return -1; + } + } + + return 0; +} + +/*static int load_parsed_packets(test_response_t ***responses, uint *count, const char *filename) { assert(*responses == NULL); @@ -240,7 +468,7 @@ static int load_parsed_packets(test_response_t ***responses, uint *count, return 0; -} +}*/ /* \note just checking the pointers probably would suffice */ static int compare_rrsets(const dnslib_rrset_t *rrset1, @@ -404,7 +632,7 @@ static int check_response(dnslib_response_t *resp, test_response_t *test_resp, if (check_authority) { for (int i = 0; (i < resp->header.arcount) && !errors; i++) { - if (resp->authority[i]!=&(test_resp->authority[i])) { + if (resp->authority[i] != (test_resp->authority[i])) { diag("Authority rrset #%d is wrongly set.\n", i); errors++; @@ -414,7 +642,7 @@ static int check_response(dnslib_response_t *resp, test_response_t *test_resp, if (check_answer) { for (int i = 0; (i < resp->header.arcount) && !errors; i++) { - if (resp->authority[i]!=&(test_resp->authority[i])) { + if (resp->authority[i] != (test_resp->authority[i])) { diag("Authority rrset #%d is wrongly set.\n", i); errors++; @@ -424,7 +652,7 @@ static int check_response(dnslib_response_t *resp, test_response_t *test_resp, if (check_additional) { for (int i = 0; (i < resp->header.arcount) && !errors; i++) { - if (resp->authority[i]!=&(test_resp->authority[i])) { + if (resp->authority[i] != (test_resp->authority[i])) { diag("Authority rrset #%d is wrongly set.\n", i); errors++; @@ -516,20 +744,8 @@ static int test_response_to_wire() resp->size = RESPONSES[i].size; uint8_t *dnslib_wire = NULL; - uint8_t *ldns_wire = NULL; - - size_t ldns_wire_size; - size_t dnslib_wire_size; - - if (ldns_pkt2wire(&ldns_wire, &LDNS_PACKETS[i], - &ldns_wire_size) != LDNS_STATUS_OK) { - diag("Could not convert ldns packet to wire\n"); - dnslib_response_free(&resp); - return 0; - } - diag("hex dump ldns wire:"); - hex_print((char *)ldns_wire, ldns_wire_size); + uint dnslib_wire_size; if (dnslib_response_to_wire(resp, &dnslib_wire, &dnslib_wire_size) != 0) { @@ -565,12 +781,11 @@ static int test_response_to_wire() dnslib_response_free(&tmp_resp); - if (compare_wires(dnslib_wire, ldns_wire, dnslib_wire_size)) { +/* if (compare_wires(dnslib_wire, ldns_wire, dnslib_wire_size)) { diag("Resulting wires were not equal - TODO\n"); // return 0; - } + } */ - free(ldns_wire); free(dnslib_wire); dnslib_response_free(&resp); } @@ -578,7 +793,215 @@ static int test_response_to_wire() return (errors == 0); } -static const int DNSLIB_RESPONSE_TEST_COUNT = 6; +static int test_response_free() +{ + dnslib_response_t *resp = dnslib_response_new_empty(NULL, 0); + assert(resp); + + dnslib_response_free(&resp); + + return (resp == NULL); +} + +static int test_response_qname(dnslib_response_t **responses) +{ + int errors = 0; + for (int i = 0; i < RESPONSE_COUNT; i++) { + if (dnslib_dname_compare(dnslib_response_qname(responses[i]), + RESPONSES[i].owner) != 0) { + diag("Got wrong qname value from response"); + errors++; + } + } + + return errors; +} + +static int test_response_qtype(dnslib_response_t **responses) +{ + int errors = 0; + for (int i = 0; i < RESPONSE_COUNT; i++) { + if (dnslib_response_qtype(responses[i]) != + RESPONSES[i].type) { + diag("Got wrong qtype value from response"); + errors++; + } + } + + return errors; +} + +static int test_response_qclass(dnslib_response_t **responses) +{ + int errors = 0; + for (int i = 0; i < RESPONSE_COUNT; i++) { + if (dnslib_response_qclass(responses[i]) != + RESPONSES[i].rclass) { + diag("Got wrong qclass value from response"); + errors++; + } + } + + return errors; +} + +static int test_response_getters(uint type) +{ + int errors = 0; + + dnslib_response_t *responses[RESPONSE_COUNT]; + + for (int i = 0; (i < RESPONSE_COUNT); i++) { + + responses[i] = dnslib_response_new_empty(NULL, 0); + + responses[i]->header.id = RESPONSES[i].id; + //flags1? + responses[i]->header.qdcount = RESPONSES[i].qdcount; + responses[i]->header.ancount = RESPONSES[i].ancount; + responses[i]->header.nscount = RESPONSES[i].nscount; + responses[i]->header.arcount = RESPONSES[i].arcount; + + responses[i]->question.qname = RESPONSES[i].owner; + responses[i]->question.qtype = RESPONSES[i].type; + responses[i]->question.qclass = RESPONSES[i].rclass; + + for (int j = 0; j < RESPONSES[i].ancount; j++) { + if (&(RESPONSES[i].answer[j])) { + dnslib_response_add_rrset_answer(responses[i], + (RESPONSES[i].answer[j]), 0); + } + } + for (int j = 0; j < RESPONSES[i].arcount; j++) { + if (&(RESPONSES[i].additional[j])) { + dnslib_response_add_rrset_additional(responses[i], + (RESPONSES[i].additional[j]), 0); + } + } + for (int j = 0; j < RESPONSES[i].arcount; j++) { + if (&(RESPONSES[i].authority[j])) { + dnslib_response_add_rrset_authority(responses[i], + (RESPONSES[i].authority[j]), 0); + } + } + + responses[i]->size = RESPONSES[i].size; + } + + switch (type) { + case 0: { + errors += test_response_qname(responses); + break; + } + case 1: { + errors += test_response_qtype(responses); + break; + } + case 2: { + errors += test_response_qclass(responses); + break; + } + default: { + diag("Unknown type"); + return 0; + } + } /* switch */ + + return (errors == 0); +} + +static int test_response_set_rcode(dnslib_response_t **responses) +{ + int errors = 0; + short rcode = 0xA; + for (int i = 0; i < RESPONSE_COUNT; i++) { + dnslib_response_set_rcode(responses[i], rcode); + if (dnslib_packet_flags_get_rcode(responses[i]->header.flags2) != rcode) { + diag("Set wrong rcode."); + errors++; + } + } + return errors; +} + +static int test_response_set_aa(dnslib_response_t **responses) +{ + int errors = 0; + for (int i = 0; i < RESPONSE_COUNT; i++) { + dnslib_response_set_aa(responses[i]); + /* TODO this returns 4 - shouldn't it return 1? It would work, yes, + but some checks might be neccassary */ + if (!dnslib_packet_flags_get_aa(responses[i]->header.flags1)) { + printf("%d\n", dnslib_packet_flags_get_aa(responses[i]->header.flags1)); + diag("Set wrong aa bit."); + errors++; + } + } + return errors; +} + +static int test_response_setters(uint type) +{ + int errors = 0; + + dnslib_response_t *responses[RESPONSE_COUNT]; + + for (int i = 0; (i < RESPONSE_COUNT); i++) { + + responses[i] = dnslib_response_new_empty(NULL, 0); + + responses[i]->header.id = RESPONSES[i].id; + //flags1? + responses[i]->header.qdcount = RESPONSES[i].qdcount; + responses[i]->header.ancount = RESPONSES[i].ancount; + responses[i]->header.nscount = RESPONSES[i].nscount; + responses[i]->header.arcount = RESPONSES[i].arcount; + + responses[i]->question.qname = RESPONSES[i].owner; + responses[i]->question.qtype = RESPONSES[i].type; + responses[i]->question.qclass = RESPONSES[i].rclass; + + for (int j = 0; j < RESPONSES[i].ancount; j++) { + if (&(RESPONSES[i].answer[j])) { + dnslib_response_add_rrset_answer(responses[i], + (RESPONSES[i].answer[j]), 0); + } + } + for (int j = 0; j < RESPONSES[i].arcount; j++) { + if (&(RESPONSES[i].additional[j])) { + dnslib_response_add_rrset_additional(responses[i], + (RESPONSES[i].additional[j]), 0); + } + } + for (int j = 0; j < RESPONSES[i].arcount; j++) { + if (&(RESPONSES[i].authority[j])) { + dnslib_response_add_rrset_authority(responses[i], + (RESPONSES[i].authority[j]), 0); + } + } + + responses[i]->size = RESPONSES[i].size; + } + + switch (type) { + case 0: { + errors += test_response_set_rcode(responses); + break; + } + case 1: { + errors += test_response_set_aa(responses); + break; + } + default: { + diag("Unknown type"); + return 0; + } + } /* switch */ + + return (errors == 0); +} + +static const int DNSLIB_RESPONSE_TEST_COUNT = 12; /*! This helper routine should report number of * scheduled tests for given parameters. @@ -610,12 +1033,30 @@ static int dnslib_response_tests_run(int argc, char *argv[]) uint response_parsed_count = 0; uint8_t response_raw_count = 0; - load_parsed_packets(&parsed_responses, &response_parsed_count, - "src/tests/dnslib/files/parsed_packets"); + ok(test_response_getters(0), "response: get qname"); + + ok(test_response_getters(1), "response: get qtype"); + + ok(test_response_getters(2), "response: get qclass"); + + ok(test_response_setters(0), "response: set rcode"); + + ok(test_response_setters(1), "response: set aa"); + + if (load_parsed_responses(&parsed_responses, &response_parsed_count, + "files/parsed_data") != 0) { + diag("Could not load parsed responses, skipping"); + return 0; + } + diag("read %d responses\n", response_parsed_count); - load_raw_packets(&raw_queries, &response_raw_count, - "src/tests/dnslib/files/raw_packets"); + if (load_raw_packets(&raw_queries, &response_raw_count, + "files/raw_data") != 0) { + diag("Could not load raw responses, skipping"); + return 0; + } + diag("read %d responses\n", response_raw_count); assert(response_raw_count == response_parsed_count); @@ -639,5 +1080,7 @@ static int dnslib_response_tests_run(int argc, char *argv[]) endskip; + ok(test_response_free(), "response: free"); + return 0; } diff --git a/src/tests/dnslib/dnslib_rrsig_set_tests.c b/src/tests/dnslib/dnslib_rrsig_set_tests.c new file mode 100644 index 0000000000000000000000000000000000000000..7b688d0ca597a571baa7c915524971f283570d42 --- /dev/null +++ b/src/tests/dnslib/dnslib_rrsig_set_tests.c @@ -0,0 +1,552 @@ +/*! + * \file dnslib_rrsig_set_tests.c + * + * \author Jan Kadlec <jan.kadlec@nic.cz> + * + * Contains unit tests for RRSIG set (dnslib_rrsig_set_t) and its API. + * + * Contains tests for: + * - RRSIG set API + */ + +#include "tap_unit.h" + +#include "common.h" +#include "rrsig.h" +#include "dname.h" +#include "rdata.h" + +static int dnslib_rrsig_set_tests_count(int argc, char *argv[]); +static int dnslib_rrsig_set_tests_run(int argc, char *argv[]); + +/*! Exported unit API. + */ +unit_api dnslib_rrsig_set_tests_api = { + "DNS library - rrsig_set", //! Unit name + &dnslib_rrsig_set_tests_count, //! Count scheduled tests + &dnslib_rrsig_set_tests_run //! Run scheduled tests +}; + +/*----------------------------------------------------------------------------*/ +/* + * Unit implementation. + */ + +enum { TEST_RRSIG_SETS = 6 }; + +//void *RRSIG_ADDRESS = (void *)0xDEADBEEF; +//void *RRSIG_FIRST = RRSIG_ADDRESS + 10; + +struct test_rrsig_set { + char *owner; + uint16_t type; + uint16_t rclass; + uint32_t ttl; + dnslib_rdata_t *rdata; +}; + +enum { + RRS_DNAMES_COUNT = 3, + RRS_ITEMS_COUNT = 3, + RRS_RDATA_COUNT = 5, +}; + +static dnslib_dname_t RRS_DNAMES[RRS_DNAMES_COUNT] = + { {(uint8_t *)"\7example\3com", 13, NULL}, //0's at the end are added + {(uint8_t *)"\2ns1\7example\3com", 17, NULL}, + {(uint8_t *)"\2ns2\7example\3com", 17, NULL} }; + +/* 192.168.1.1 */ +//static uint8_t adress[4] = {0xc0, 0xa8, 0x01, 0x01}; + +static dnslib_rdata_item_t RRS_ITEMS[RRS_ITEMS_COUNT] = + { {.dname = &RRS_DNAMES[1]}, + {.dname = &RRS_DNAMES[2]}, + {.raw_data = adress} }; + +static dnslib_rdata_t RRS_RDATA[RRS_RDATA_COUNT] = + { {&RRS_ITEMS[0], 1, &RRS_RDATA[0]}, + {&RRS_ITEMS[1], 1, &RRS_RDATA[1]}, /* first ns */ + {&RRS_ITEMS[2], 1, &RRS_RDATA[2]}, /* second ns */ + {&RRS_ITEMS[1], 1, &RRS_RDATA[4]}, /* both in cyclic list */ + {&RRS_ITEMS[2], 1, &RRS_RDATA[3]} }; + +static struct test_rrsig_set test_rrsig_sets[TEST_RRSIG_SETS] = { + { + "example.com.", + 2, + DNSLIB_CLASS_IN, + 3600, + NULL, + }, + { + "example2.com.", + 2, + DNSLIB_CLASS_IN, + 3600, + NULL, + }, + { + "example3.com.", + 2, + DNSLIB_CLASS_IN, + 3600, + NULL, + }, + { "example.com.", DNSLIB_RRTYPE_NS, DNSLIB_CLASS_IN, + 3600, &RRS_RDATA[1] }, + { "example.com.", DNSLIB_RRTYPE_NS, DNSLIB_CLASS_IN, + 3600, &RRS_RDATA[2] }, + { "example.com.", DNSLIB_RRTYPE_NS, DNSLIB_CLASS_IN, + 3600, &RRS_RDATA[3] }, +}; + +/* fills test_rrsig_sets with random rdata */ +static void rrs_create_rdata() +{ + dnslib_rdata_t *r; + for (int i = 0; i < TEST_RRSIG_SETS - 3; i++) { + r = dnslib_rdata_new(); + dnslib_rdata_item_t item; + item.raw_data = RDATA_ITEM_PTR; + + dnslib_rdata_set_item(r, 0, item); + + uint8_t data[DNSLIB_MAX_RDATA_WIRE_SIZE]; + generate_rdata(data, DNSLIB_MAX_RDATA_WIRE_SIZE); + + // from dnslib_rdata_tests.c + fill_rdata(data, DNSLIB_MAX_RDATA_WIRE_SIZE, + DNSLIB_RRTYPE_RRSIG, r); + test_rrsig_sets[i].rdata = r; + } +} + +static int check_rrsig_set(const dnslib_rrsig_set_t *rrsig_set, int i, + int check_rdata, int check_items) +{ + int errors = 0; + + if (rrsig_set == NULL) { + diag("RRSet not created!"); + return 1; + } + + char *owner = dnslib_dname_to_str(rrsig_set->owner); + if (strcmp(owner, test_rrsig_sets[i].owner) != 0) { + diag("OWNER domain name wrong: '%s' (should be '%s')", + owner, test_rrsig_sets[i].owner); + ++errors; + } + free(owner); + + if (rrsig_set->type != test_rrsig_sets[i].type) { + diag("TYPE wrong: %u (should be: %u)", rrsig_set->type, + test_rrsig_sets[i].type); + ++errors; + } + + if (rrsig_set->rclass != test_rrsig_sets[i].rclass) { + diag("CLASS wrong: %u (should be: %u)", rrsig_set->rclass, + test_rrsig_sets[i].rclass); + ++errors; + } + + if (rrsig_set->ttl != test_rrsig_sets[i].ttl) { + diag("TTL wrong: %u (should be: %u)", rrsig_set->ttl, + test_rrsig_sets[i].ttl); + ++errors; + } + + if (check_rdata) { + dnslib_rdata_t *rdata = rrsig_set->rdata; + + if (rdata == NULL) { + diag("There are no RDATAs in the RRSet"); + ++errors; + } + if (rdata != NULL) { + while (rdata->next != NULL && + rdata->next != rrsig_set->rdata) { + rdata = rdata->next; + } + if (rdata->next == NULL) { + diag("The list of RDATAs is not cyclical!"); + ++errors; + } else { + assert(rdata == rrsig_set->rdata); + } + } + } + + if (check_items) { + dnslib_rrtype_descriptor_t *desc = + dnslib_rrtype_descriptor_by_type(rrsig_set->type); + if (dnslib_rdata_compare(rrsig_set->rdata, + test_rrsig_sets[i].rdata, + desc->wireformat)) { + diag("Rdata items do not match."); + errors++; + } + } + + return errors; +} + +/*! + * \brief Tests dnslib_rrsig_set_new(). + * + * \retval > 0 on success. + * \retval 0 otherwise. + */ +static int test_rrsig_set_create() +{ + int errors = 0; + + for (int i = 0; i < TEST_RRSIG_SETS; ++i) { + dnslib_dname_t *owner = dnslib_dname_new_from_str( + test_rrsig_sets[i].owner, + strlen(test_rrsig_sets[i].owner), + NODE_ADDRESS); + if (owner == NULL) { + diag("Error creating owner domain name!"); + return 0; + } + dnslib_rrsig_set_t *rrsig_set = dnslib_rrsig_set_new(owner, + test_rrsig_sets[i].type, + test_rrsig_sets[i].rclass, + test_rrsig_sets[i].ttl); + + errors += check_rrsig_set(rrsig_set, i, 0, 0); + + dnslib_rrsig_set_free(&rrsig_set); + dnslib_dname_free(&owner); + } + + //diag("Total errors: %d", errors); + + return (errors == 0); +} + +/*! + * \brief Tests dnslib_rrsig_set_free(). + * + * \retval > 0 on success. + * \retval 0 otherwise. + * + * \todo How to test this? + */ +static int test_rrsig_set_delete() +{ + return 0; +} + +static int test_rrsig_set_rdata() +{ + /* rdata add */ + int errors = 0; + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + dnslib_dname_t *owner = dnslib_dname_new_from_str( + test_rrsig_sets[i].owner, + strlen(test_rrsig_sets[i].owner), + NODE_ADDRESS); + if (owner == NULL) { + diag("Error creating owner domain name!"); + return 0; + } + dnslib_rrsig_set_t *rrsig_set = dnslib_rrsig_set_new(owner, + test_rrsig_sets[i].type, + test_rrsig_sets[i].rclass, + test_rrsig_sets[i].ttl); + + dnslib_rrsig_set_add_rdata(rrsig_set, test_rrsig_sets[i].rdata); + + errors += check_rrsig_set(rrsig_set, i, 1, 0); + + dnslib_rrsig_set_free(&rrsig_set); + dnslib_dname_free(&owner); + } + + //test whether adding works properly = keeps order of added elements + + dnslib_rrsig_set_t *rrsig_set = dnslib_rrsig_set_new(NULL, 0, 0, 0); + + dnslib_rdata_t *r; + + dnslib_rdata_item_t *item; + + char *test_strings[10] = + { "-2", "9", "2", "10", "1", "5", "8", "4", "6", "7" }; + + for (int i = 0; i < 10; i++) { + r = dnslib_rdata_new(); + item = malloc(sizeof(dnslib_rdata_item_t)); + item->raw_data = (uint8_t *)test_strings[i]; + //following statement creates a copy + dnslib_rdata_set_items(r, item, 1); + dnslib_rrsig_set_add_rdata(rrsig_set, r); + free(item); + } + + dnslib_rdata_t *tmp = rrsig_set->rdata; + + int i = 0; + while (tmp->next != rrsig_set->rdata && !errors) { + if (strcmp(test_strings[i], (char *)tmp->items[0].raw_data)) { + diag("Adding RDATA error!, is %s should be %s", + tmp->items[0].raw_data, test_strings[i]); + errors++; + } + i++; + tmp = tmp->next; + } + + tmp = rrsig_set->rdata; + + dnslib_rdata_t *next; + + while (tmp->next != rrsig_set->rdata) { + next = tmp->next; + dnslib_rdata_free(&tmp); + tmp = next; + } + + dnslib_rdata_free(&tmp); + + dnslib_rrsig_set_free(&rrsig_set); + + return (errors == 0); +} + +static int test_rrsig_set_merge() +{ + dnslib_rrsig_set_t *merger1; + dnslib_rrsig_set_t *merger2; + + dnslib_dname_t *owner1 = + dnslib_dname_new_from_str(test_rrsig_sets[3].owner, + strlen(test_rrsig_sets[3].owner), NULL); + merger1 = dnslib_rrsig_set_new(owner1, test_rrsig_sets[3].type, + test_rrsig_sets[3].rclass, + test_rrsig_sets[3].ttl); + + dnslib_rrsig_set_add_rdata(merger1, test_rrsig_sets[3].rdata); + + dnslib_dname_t *owner2 = + dnslib_dname_new_from_str(test_rrsig_sets[4].owner, + strlen(test_rrsig_sets[4].owner), NULL); + merger2 = dnslib_rrsig_set_new(owner2, test_rrsig_sets[4].type, + test_rrsig_sets[4].rclass, + test_rrsig_sets[4].ttl); + + dnslib_rrsig_set_add_rdata(merger2, test_rrsig_sets[4].rdata); + + dnslib_rrsig_set_merge((void **)&merger1, (void **)&merger2); + + if (check_rrsig_set(merger1, 5, 0, 1)) { + diag("Merged rdata are wrongly set."); + return 0; + } + + dnslib_dname_free(&owner1); + dnslib_dname_free(&owner2); + dnslib_rrsig_set_free(&merger1); + dnslib_rrsig_set_free(&merger2); + + return 1; +} + +static int test_rrsig_set_type(dnslib_rrsig_set_t **rrsig_sets) +{ + int errors = 0; + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + if (dnslib_rrsig_set_type(rrsig_sets[i]) != test_rrsig_sets[i].type) { + errors++; + diag("Got wrong value for type from rrsig_set."); + } + } + return errors; +} + +static int test_rrsig_set_class(dnslib_rrsig_set_t **rrsig_sets) +{ + int errors = 0; + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + if (dnslib_rrsig_set_class(rrsig_sets[i]) != test_rrsig_sets[i].rclass) { + errors++; + diag("Got wrong value for class from rrsig_set."); + } + } + + return errors; +} + +static int test_rrsig_set_ttl(dnslib_rrsig_set_t **rrsig_sets) +{ + int errors = 0; + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + if (dnslib_rrsig_set_ttl(rrsig_sets[i]) != test_rrsig_sets[i].ttl) { + errors++; + diag("Got wrong value for ttl from rrsig_set."); + } + } + return errors; +} + +static int test_rrsig_set_getters(uint type) +{ + int errors = 0; + + dnslib_rrsig_set_t *rrsig_sets[TEST_RRSIG_SETS]; + + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + dnslib_dname_t *owner = dnslib_dname_new_from_str( + test_rrsig_sets[i].owner, + strlen(test_rrsig_sets[i].owner), + NODE_ADDRESS); + if (owner == NULL) { + diag("Error creating owner domain name!"); + return 0; + } + rrsig_sets[i] = dnslib_rrsig_set_new(owner, + test_rrsig_sets[i].type, + test_rrsig_sets[i].rclass, + test_rrsig_sets[i].ttl); + + dnslib_rrsig_set_add_rdata(rrsig_sets[i], test_rrsig_sets[i].rdata); + } + + switch (type) { + case 0: { + errors += test_rrsig_set_type(rrsig_sets); + break; + } + case 1: { + errors += test_rrsig_set_class(rrsig_sets); + break; + } + case 2: { + errors += test_rrsig_set_ttl(rrsig_sets); + break; + } + } /* switch */ + + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + dnslib_dname_free(&rrsig_sets[i]->owner); + dnslib_rrsig_set_free(&rrsig_sets[i]); + } + + + return (errors == 0); +} + +static int test_rrsig_set_deep_free() +{ + int errors = 0; +/* \note this cannot be tested, because some of the rdata are on stack */ +/* dnslib_rrsig_set_t *tmp_rrsig_set; + dnslib_dname_t *owner; + for (int i = 0; i < TEST_RRSIG_SETS - 3; i++) { + owner = dnslib_dname_new_from_str( + test_rrsig_sets[i].owner, + strlen(test_rrsig_sets[i].owner), + NODE_ADDRESS); + if (owner == NULL) { + diag("Error creating owner domain name!"); + return 0; + } + + tmp_rrsig_set = dnslib_rrsig_set_new(owner, + test_rrsig_sets[i].type, + test_rrsig_sets[i].rclass, + test_rrsig_sets[i].ttl); + + dnslib_rrsig_set_add_rdata(tmp_rrsig_set, test_rrsig_sets[i].rdata); + + dnslib_rrsig_set_deep_free(&tmp_rrsig_set, 1, 0); + + errors += (tmp_rrsig_set != NULL); + } */ + + return (errors == 0); +} + +/*----------------------------------------------------------------------------*/ + +static const int DNSLIB_RRSIG_SET_TEST_COUNT = 8; + +/*! This helper routine should report number of + * scheduled tests for given parameters. + */ +static int dnslib_rrsig_set_tests_count(int argc, char *argv[]) +{ + return DNSLIB_RRSIG_SET_TEST_COUNT; +} + +/*! Run all scheduled tests for given parameters. + */ +static int dnslib_rrsig_set_tests_run(int argc, char *argv[]) +{ + int res = 0, + res_final = 1; + + rrs_create_rdata(); + + res = test_rrsig_set_create(); + ok(res, "rrsig_set: create"); + res_final *= res; + + skip(!res, 11); + + todo(); + + ok(res = test_rrsig_set_delete(), "rrsig_set: delete"); + //res_final *= res; + + endtodo; + + ok(res = test_rrsig_set_getters(0), "rrsig_set: type"); + res_final *= res; + + ok(res = test_rrsig_set_getters(1), "rrsig_set: class"); + res_final *= res; + + ok(res = test_rrsig_set_getters(2), "rrsig_set: ttl"); + res_final *= res; + + ok(res = test_rrsig_set_rdata(), "rrsig_set: rdata manipulation"); + res_final *= res; + + ok(res = test_rrsig_set_merge(), "rrsig_set: rdata merging"); + res_final *= res; + + todo(); + + ok(res = test_rrsig_set_deep_free(), "rrsig_set: deep free"); + res_final *= res; + + endtodo; + + endskip; /* !res_create */ + + +/* dnslib_rrtype_descriptor_t *desc; + + for (int i = 0; i < TEST_RRSIG_SETS; i++) { + desc = dnslib_rrtype_descriptor_by_type(test_rrsig_sets[i].type); + for (int x = 0; x < test_rrsig_sets[i].rdata->count; x++) { + if ( + desc->wireformat[x] == + DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME || + desc->wireformat[x] == + DNSLIB_RDATA_WF_COMPRESSED_DNAME || + desc->wireformat[x] == DNSLIB_RDATA_WF_LITERAL_DNAME) { + dnslib_dname_free( + &(test_rrsig_sets[i].rdata->items[x].dname)); + } + } + dnslib_rdata_free(&test_rrsig_sets[i].rdata); + } */ + + return res_final; +} diff --git a/src/tests/dnslib_tests.c b/src/tests/dnslib_tests.c index 3765f951a4c12fdabc724f302bddca127869d098..1d3e772d3f72ea9d80325a6e96e1a464b588a934 100644 --- a/src/tests/dnslib_tests.c +++ b/src/tests/dnslib_tests.c @@ -4,8 +4,10 @@ #include "dnslib/dnslib_rdata_tests.c" #include "dnslib/dnslib_node_tests.c" #include "dnslib/dnslib_rrset_tests.c" +#include "dnslib/dnslib_rrsig_set_tests.c" #include "dnslib/dnslib_zone_tests.c" #include "dnslib/dnslib_response_tests.c" +#include "dnslib/dnslib_edns_tests.c" static int dnslib_tests_count(int argc, char *argv[]); static int dnslib_tests_run(int argc, char *argv[]); @@ -29,9 +31,11 @@ static int dnslib_tests_count(int argc, char *argv[]) return dnslib_dname_tests_count(argc, argv) + dnslib_rdata_tests_count(argc, argv) + dnslib_rrset_tests_count(argc, argv) + + dnslib_rrsig_set_tests_count(argc, argv) + dnslib_node_tests_count(argc, argv) + dnslib_zone_tests_count(argc, argv) - + dnslib_response_tests_count(argc, argv); + + dnslib_response_tests_count(argc, argv) + + dnslib_edns_tests_count(argc, argv); } /*! Run all scheduled tests for given parameters. @@ -55,6 +59,9 @@ static int dnslib_tests_run(int argc, char *argv[]) note("Testing module: rrset"); res = dnslib_rrset_tests_run(argc, argv); + note("Testing module: rrsig set"); + res = dnslib_rrsig_set_tests_run(argc, argv); + skip(!res, node_tests + zone_tests); note("Testing module: node"); @@ -68,6 +75,8 @@ static int dnslib_tests_run(int argc, char *argv[]) note("Testing module: response"); res = dnslib_response_tests_run(argc, argv); + note("Testing module: ends"); + res = dnslib_edns_tests_run(argc, argv); endskip; // skipped zone