ATF_TC_BODY(hip, tc) { unsigned char hipwire[DNS_RDATA_MAXLENGTH] = { 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x41, 0x42, 0x43, 0x44, 0x00 }; unsigned char buf[1024*1024]; isc_buffer_t source, target; dns_rdata_t rdata; dns_decompress_t dctx; isc_result_t result; size_t i; UNUSED(tc); /* * Fill the rest of input buffer with compression pointers. */ for (i = 12; i < sizeof(hipwire) - 2; i += 2) { hipwire[i] = 0xc0; hipwire[i+1] = 0x06; } isc_buffer_init(&source, hipwire, sizeof(hipwire)); isc_buffer_add(&source, sizeof(hipwire)); isc_buffer_setactive(&source, i); isc_buffer_init(&target, buf, sizeof(buf)); dns_rdata_init(&rdata); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, dns_rdatatype_hip, &source, &dctx, 0, &target); dns_decompress_invalidate(&dctx); ATF_REQUIRE_EQ(result, DNS_R_FORMERR); }
ATF_TC_BODY(edns_client_subnet, tc) { struct { unsigned char data[64]; size_t len; isc_boolean_t ok; } test_data[] = { { /* option code with no content */ { 0x00, 0x08, 0x0, 0x00 }, 4, ISC_FALSE }, { /* Option code family 0, source 0, scope 0 */ { 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 }, 8, ISC_TRUE }, { /* Option code family 1 (ipv4), source 0, scope 0 */ { 0x00, 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00 }, 8, ISC_TRUE }, { /* Option code family 2 (ipv6) , source 0, scope 0 */ { 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00 }, 8, ISC_TRUE }, { /* extra octet */ { 0x00, 0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }, 9, ISC_FALSE }, { /* source too long for IPv4 */ { 0x00, 0x08, 0x00, 8, 0x00, 0x01, 33, 0x00, 0x00, 0x00, 0x00, 0x00 }, 12, ISC_FALSE }, { /* source too long for IPv6 */ { 0x00, 0x08, 0x00, 20, 0x00, 0x02, 129, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 24, ISC_FALSE }, { /* scope too long for IPv4 */ { 0x00, 0x08, 0x00, 8, 0x00, 0x01, 0x00, 33, 0x00, 0x00, 0x00, 0x00 }, 12, ISC_FALSE }, { /* scope too long for IPv6 */ { 0x00, 0x08, 0x00, 20, 0x00, 0x02, 0x00, 129, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 24, ISC_FALSE }, { /* length too short for source generic */ { 0x00, 0x08, 0x00, 5, 0x00, 0x00, 17, 0x00, 0x00, 0x00, }, 19, ISC_FALSE }, { /* length too short for source ipv4 */ { 0x00, 0x08, 0x00, 7, 0x00, 0x01, 32, 0x00, 0x00, 0x00, 0x00, 0x00 }, 11, ISC_FALSE }, { /* length too short for source ipv6 */ { 0x00, 0x08, 0x00, 19, 0x00, 0x02, 128, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, 23, ISC_FALSE }, { /* sentinal */ { 0x00 }, 0, ISC_FALSE } }; unsigned char buf[1024*1024]; isc_buffer_t source, target1; dns_rdata_t rdata; dns_decompress_t dctx; isc_result_t result; size_t i; UNUSED(tc); for (i = 0; test_data[i].len != 0; i++) { isc_buffer_init(&source, test_data[i].data, test_data[i].len); isc_buffer_add(&source, test_data[i].len); isc_buffer_setactive(&source, test_data[i].len); isc_buffer_init(&target1, buf, sizeof(buf)); dns_rdata_init(&rdata); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, dns_rdatatype_opt, &source, &dctx, 0, &target1); dns_decompress_invalidate(&dctx); if (test_data[i].ok) ATF_CHECK_EQ(result, ISC_R_SUCCESS); else ATF_CHECK(result != ISC_R_SUCCESS); } }
ATF_TC_BODY(csync, tc) { struct { const char *data; isc_boolean_t ok; } text_data[] = { { "", ISC_FALSE }, { "0", ISC_FALSE }, { "0 0", ISC_TRUE }, { "0 0 A", ISC_TRUE }, { "0 0 NS", ISC_TRUE }, { "0 0 AAAA", ISC_TRUE }, { "0 0 A AAAA", ISC_TRUE }, { "0 0 A NS AAAA", ISC_TRUE }, { "0 0 A NS AAAA BOGUS", ISC_FALSE }, { NULL, ISC_FALSE }, }; struct { unsigned char data[64]; size_t len; isc_boolean_t ok; } wire_data[] = { /* short */ { { 0x00 }, 0, ISC_FALSE }, /* short */ { { 0x00 }, 1, ISC_FALSE }, /* short */ { { 0x00, 0x00 }, 2, ISC_FALSE }, /* short */ { { 0x00, 0x00, 0x00 }, 3, ISC_FALSE }, /* short */ { { 0x00, 0x00, 0x00, 0x00 }, 4, ISC_FALSE }, /* short */ { { 0x00, 0x00, 0x00, 0x00, 0x00 }, 5, ISC_FALSE }, /* serial + flags only */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 6, ISC_TRUE }, /* bad type map */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 7, ISC_FALSE }, /* bad type map */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 8, ISC_FALSE }, /* good type map */ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02 }, 9, ISC_TRUE } }; unsigned char buf1[1024]; unsigned char buf2[1024]; isc_buffer_t source, target1, target2; isc_result_t result; size_t i; dns_rdataclass_t rdclass = dns_rdataclass_in; dns_rdatatype_t type = dns_rdatatype_csync; isc_lex_t *lex = NULL; dns_rdatacallbacks_t callbacks; dns_rdata_csync_t csync; dns_decompress_t dctx; UNUSED(tc); result = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = isc_lex_create(mctx, 64, &lex); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); dns_rdatacallbacks_init(&callbacks); callbacks.error = error_callback; callbacks.warn = warn_callback; for (i = 0; text_data[i].data != NULL; i++) { size_t length = strlen(text_data[i].data); isc_buffer_constinit(&source, text_data[i].data, length); isc_buffer_add(&source, length); result = isc_lex_openbuffer(lex, &source); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); isc_buffer_init(&target1, buf1, sizeof(buf1)); result = dns_rdata_fromtext(NULL, rdclass, type, lex, dns_rootname, 0, NULL, &target1, &callbacks); if (text_data[i].ok) ATF_CHECK_EQ(result, ISC_R_SUCCESS); else ATF_CHECK(result != ISC_R_SUCCESS); } isc_lex_destroy(&lex); for (i = 0; i < sizeof(wire_data)/sizeof(wire_data[0]); i++) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_init(&source, wire_data[i].data, wire_data[i].len); isc_buffer_add(&source, wire_data[i].len); isc_buffer_setactive(&source, wire_data[i].len); isc_buffer_init(&target1, buf1, sizeof(buf1)); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, rdclass, type, &source, &dctx, 0, &target1); dns_decompress_invalidate(&dctx); if (wire_data[i].ok) ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); else ATF_REQUIRE(result != ISC_R_SUCCESS); if (result != ISC_R_SUCCESS) continue; result = dns_rdata_tostruct(&rdata, &csync, NULL); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); isc_buffer_init(&target2, buf2, sizeof(buf2)); dns_rdata_reset(&rdata); result = dns_rdata_fromstruct(&rdata, rdclass, type, &csync, &target2); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), wire_data[i].len); ATF_REQUIRE_EQ(memcmp(buf2, wire_data[i].data, wire_data[i].len), 0); } }
ATF_TC_BODY(isdn, tc) { struct { unsigned char data[64]; size_t len; isc_boolean_t ok; } test_data[] = { { /* "" */ { 0x00 }, 1, ISC_TRUE }, { /* "\001" */ { 0x1, 0x01 }, 2, ISC_TRUE }, { /* "\001" "" */ { 0x1, 0x01, 0x00 }, 3, ISC_TRUE }, { /* "\000" "\001" */ { 0x1, 0x01, 0x01, 0x01 }, 4, ISC_TRUE }, { /* sentinal */ { 0x00 }, 0, ISC_FALSE } }; unsigned char buf1[1024]; unsigned char buf2[1024]; isc_buffer_t source, target1, target2; dns_rdata_t rdata; dns_decompress_t dctx; isc_result_t result; size_t i; dns_rdata_isdn_t isdn; UNUSED(tc); for (i = 0; test_data[i].len != 0; i++) { isc_buffer_init(&source, test_data[i].data, test_data[i].len); isc_buffer_add(&source, test_data[i].len); isc_buffer_setactive(&source, test_data[i].len); isc_buffer_init(&target1, buf1, sizeof(buf1)); dns_rdata_init(&rdata); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); result = dns_rdata_fromwire(&rdata, dns_rdataclass_in, dns_rdatatype_isdn, &source, &dctx, 0, &target1); dns_decompress_invalidate(&dctx); if (test_data[i].ok) ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); else ATF_REQUIRE(result != ISC_R_SUCCESS); if (result != ISC_R_SUCCESS) continue; result = dns_rdata_tostruct(&rdata, &isdn, NULL); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); isc_buffer_init(&target2, buf2, sizeof(buf2)); dns_rdata_reset(&rdata); result = dns_rdata_fromstruct(&rdata, dns_rdataclass_in, dns_rdatatype_isdn, &isdn, &target2); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(isc_buffer_usedlength(&target2), test_data[i].len); ATF_REQUIRE_EQ(memcmp(buf2, test_data[i].data, test_data[i].len), 0); } }
static void print_yaml(dns_dtdata_t *dt) { Dnstap__Dnstap *frame = dt->frame; Dnstap__Message *m = frame->message; const ProtobufCEnumValue *ftype, *mtype; static isc_boolean_t first = ISC_TRUE; ftype = protobuf_c_enum_descriptor_get_value( &dnstap__dnstap__type__descriptor, frame->type); if (ftype == NULL) return; if (!first) printf("---\n"); else first = ISC_FALSE; printf("type: %s\n", ftype->name); if (frame->has_identity) printf("identity: %.*s\n", (int) frame->identity.len, frame->identity.data); if (frame->has_version) printf("version: %.*s\n", (int) frame->version.len, frame->version.data); if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE) return; printf("message:\n"); mtype = protobuf_c_enum_descriptor_get_value( &dnstap__message__type__descriptor, m->type); if (mtype == NULL) return; printf(" type: %s\n", mtype->name); if (!isc_time_isepoch(&dt->qtime)) { char buf[100]; isc_time_formatISO8601(&dt->qtime, buf, sizeof(buf)); printf(" query_time: !!timestamp %s\n", buf); } if (!isc_time_isepoch(&dt->rtime)) { char buf[100]; isc_time_formatISO8601(&dt->rtime, buf, sizeof(buf)); printf(" response_time: !!timestamp %s\n", buf); } if (dt->msgdata.base != NULL) { printf(" message_size: %zdb\n", (size_t) dt->msgdata.length); } else printf(" message_size: 0b\n"); if (m->has_socket_family) { const ProtobufCEnumValue *type = protobuf_c_enum_descriptor_get_value( &dnstap__socket_family__descriptor, m->socket_family); if (type != NULL) printf(" socket_family: %s\n", type->name); } printf(" socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP"); if (m->has_query_address) { ProtobufCBinaryData *ip = &m->query_address; char buf[100]; (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data, buf, sizeof(buf)); printf(" query_address: %s\n", buf); } if (m->has_response_address) { ProtobufCBinaryData *ip = &m->response_address; char buf[100]; (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data, buf, sizeof(buf)); printf(" response_address: %s\n", buf); } if (m->has_query_port) printf(" query_port: %u\n", m->query_port); if (m->has_response_port) printf(" response_port: %u\n", m->response_port); if (m->has_query_zone) { isc_result_t result; dns_fixedname_t fn; dns_name_t *name; isc_buffer_t b; dns_decompress_t dctx; dns_fixedname_init(&fn); name = dns_fixedname_name(&fn); isc_buffer_init(&b, m->query_zone.data, m->query_zone.len); isc_buffer_add(&b, m->query_zone.len); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); result = dns_name_fromwire(name, &b, &dctx, 0, NULL); if (result == ISC_R_SUCCESS) { printf(" query_zone: "); dns_name_print(name, stdout); printf("\n"); } } if (dt->msg != NULL) { printf(" %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0) ? "query_message_data" : "response_message_data"); print_packet(dt, &dns_master_style_yaml); printf(" %s: |\n", ((dt->type & DNS_DTTYPE_QUERY) != 0) ? "query_message" : "response_message"); print_packet(dt, &dns_master_style_indent); } };
void test(unsigned int allowed, dns_name_t *name1, dns_name_t *name2, dns_name_t *name3, unsigned char *result, unsigned int length) { isc_mem_t *mctx = NULL; dns_compress_t cctx; dns_decompress_t dctx; isc_buffer_t source; isc_buffer_t target; dns_name_t name; unsigned char buf1[1024]; unsigned char buf2[1024]; if (verbose) { const char *s; switch (allowed) { case DNS_COMPRESS_NONE: s = "DNS_COMPRESS_NONE"; break; case DNS_COMPRESS_GLOBAL14: s = "DNS_COMPRESS_GLOBAL14"; break; /* case DNS_COMPRESS_ALL: s = "DNS_COMPRESS_ALL"; break; */ default: s = "UNKNOWN"; break; } fprintf(stdout, "Allowed = %s\n", s); } RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); isc_buffer_init(&source, buf1, sizeof(buf1)); RUNTIME_CHECK(dns_compress_init(&cctx, -1, mctx) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_name_towire(name1, &cctx, &source) == ISC_R_SUCCESS); /* RUNTIME_CHECK(dns_compress_localinit(&cctx, name1, &source) == ISC_R_SUCCESS); */ dns_compress_setmethods(&cctx, allowed); RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_name_towire(name3, &cctx, &source) == ISC_R_SUCCESS); /* dns_compress_localinvalidate(&cctx); */ dns_compress_rollback(&cctx, 0); /* testing only */ dns_compress_invalidate(&cctx); if (raw) { unsigned int i; for (i = 0; i < source.used; /* */ ) { fprintf(stdout, "%02x", ((unsigned char *)source.base)[i]); if ((++i % 20) == 0) fputs("\n", stdout); else if (i == source.used) fputs("\n", stdout); else fputs(" ", stdout); } } isc_buffer_setactive(&source, source.used); isc_buffer_init(&target, buf2, sizeof(buf2)); dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT); dns_name_init(&name, NULL); RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE, &target) == ISC_R_SUCCESS); dns_decompress_setmethods(&dctx, allowed); /* dns_decompress_localinit(&dctx, &name, &source); */ RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE, &target) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE, &target) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE, &target) == ISC_R_SUCCESS); /* dns_decompress_localinvalidate(&dctx); */ dns_decompress_invalidate(&dctx); if (raw) { unsigned int i; for (i = 0; i < target.used; /* */ ) { fprintf(stdout, "%02x", ((unsigned char *)target.base)[i]); if ((++i % 20) == 0) fputs("\n", stdout); else if (i == target.used) fputs("\n", stdout); else fputs(" ", stdout); } fputs("\n", stdout); fflush(stdout); } RUNTIME_CHECK(target.used == length); RUNTIME_CHECK(memcmp(target.base, result, target.used) == 0); isc_mem_destroy(&mctx); }