00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022 #include <atf-c.h>
00023 #include <isc/mem.h>
00024 #include <isc/random.h>
00025 #include <isc/string.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 #include <sys/mman.h>
00029
00030 #ifdef HAVE_INTTYPES_H
00031 #include <inttypes.h>
00032 #endif
00033
00034 #include <dns/rbt.h>
00035 #include <dns/fixedname.h>
00036 #include <dns/result.h>
00037 #include <dns/compress.h>
00038 #include "dnstest.h"
00039
00040 #include <isc/app.h>
00041 #include <isc/buffer.h>
00042 #include <isc/entropy.h>
00043 #include <isc/file.h>
00044 #include <isc/hash.h>
00045 #include <isc/mem.h>
00046 #include <isc/os.h>
00047 #include <isc/string.h>
00048 #include <isc/socket.h>
00049 #include <isc/stdio.h>
00050 #include <isc/task.h>
00051 #include <isc/timer.h>
00052 #include <isc/util.h>
00053
00054 #include <dns/log.h>
00055 #include <dns/name.h>
00056 #include <dns/result.h>
00057
00058 #include <dst/dst.h>
00059
00060 #ifndef MAP_FILE
00061 #define MAP_FILE 0
00062 #endif
00063
00064 typedef struct data_holder {
00065 int len;
00066 const char *data;
00067 } data_holder_t;
00068
00069 typedef struct rbt_testdata {
00070 const char *name;
00071 size_t name_len;
00072 data_holder_t data;
00073 } rbt_testdata_t;
00074
00075 #define DATA_ITEM(name) { (name), sizeof(name) - 1, { sizeof(name), (name) } }
00076
00077 rbt_testdata_t testdata[] = {
00078 DATA_ITEM("first.com."),
00079 DATA_ITEM("one.net."),
00080 DATA_ITEM("two.com."),
00081 DATA_ITEM("three.org."),
00082 DATA_ITEM("asdf.com."),
00083 DATA_ITEM("ghjkl.com."),
00084 DATA_ITEM("1.edu."),
00085 DATA_ITEM("2.edu."),
00086 DATA_ITEM("3.edu."),
00087 DATA_ITEM("123.edu."),
00088 DATA_ITEM("1236.com."),
00089 DATA_ITEM("and_so_forth.com."),
00090 DATA_ITEM("thisisalongname.com."),
00091 DATA_ITEM("a.b."),
00092 DATA_ITEM("test.net."),
00093 DATA_ITEM("whoknows.org."),
00094 DATA_ITEM("blargh.com."),
00095 DATA_ITEM("www.joe.com."),
00096 DATA_ITEM("test.com."),
00097 DATA_ITEM("isc.org."),
00098 DATA_ITEM("uiop.mil."),
00099 DATA_ITEM("last.fm."),
00100 { NULL, 0, { 0, NULL } }
00101 };
00102
00103 static void
00104 delete_data(void *data, void *arg) {
00105 UNUSED(arg);
00106 UNUSED(data);
00107 }
00108
00109 static isc_result_t
00110 write_data(FILE *file, unsigned char *datap, void *arg, isc_uint64_t *crc) {
00111 isc_result_t result;
00112 size_t ret = 0;
00113 data_holder_t *data = (data_holder_t *)datap;
00114 data_holder_t temp;
00115 off_t where;
00116
00117 UNUSED(arg);
00118
00119 REQUIRE(file != NULL);
00120 REQUIRE(crc != NULL);
00121 REQUIRE(data != NULL);
00122 REQUIRE((data->len == 0 && data->data == NULL) ||
00123 (data->len != 0 && data->data != NULL));
00124
00125 result = isc_stdio_tell(file, &where);
00126 if (result != ISC_R_SUCCESS)
00127 return (result);
00128
00129 temp = *data;
00130 temp.data = (data->len == 0
00131 ? NULL
00132 : (char *)((uintptr_t)where + sizeof(data_holder_t)));
00133
00134 isc_crc64_update(crc, (void *)&temp, sizeof(temp));
00135 ret = fwrite(&temp, sizeof(data_holder_t), 1, file);
00136 if (ret != 1)
00137 return (ISC_R_FAILURE);
00138 if (data->len > 0) {
00139 isc_crc64_update(crc, (const void *)data->data, data->len);
00140 ret = fwrite(data->data, data->len, 1, file);
00141 if (ret != 1)
00142 return (ISC_R_FAILURE);
00143 }
00144
00145 return (ISC_R_SUCCESS);
00146 }
00147
00148 static isc_result_t
00149 fix_data(dns_rbtnode_t *p, void *base, size_t max, void *arg,
00150 isc_uint64_t *crc)
00151 {
00152 data_holder_t *data = p->data;
00153 size_t size;
00154
00155 UNUSED(base);
00156 UNUSED(max);
00157 UNUSED(arg);
00158
00159 REQUIRE(crc != NULL);
00160 REQUIRE(p != NULL);
00161
00162
00163 if (data == NULL)
00164 printf("fixing data: data NULL\n");
00165 else
00166 printf("fixing data: len %d, data %p\n", data->len, data->data);
00167
00168 if (data == NULL ||
00169 (data->len == 0 && data->data != NULL) ||
00170 (data->len != 0 && data->data == NULL))
00171 return (ISC_R_INVALIDFILE);
00172
00173 size = max - ((char *)p - (char *)base);
00174
00175 if (data->len > (int) size || data->data > (const char *) max) {
00176 printf("data invalid\n");
00177 return (ISC_R_INVALIDFILE);
00178 }
00179
00180 isc_crc64_update(crc, (void *)data, sizeof(*data));
00181
00182 data->data = (data->len == 0)
00183 ? NULL
00184 : (char *)data + sizeof(data_holder_t);
00185
00186 if (data->len > 0)
00187 isc_crc64_update(crc, (const void *)data->data, data->len);
00188
00189 return (ISC_R_SUCCESS);
00190 }
00191
00192
00193
00194
00195 static void
00196 add_test_data(isc_mem_t *mymctx, dns_rbt_t *rbt) {
00197 char buffer[1024];
00198 isc_buffer_t b;
00199 isc_result_t result;
00200 dns_fixedname_t fname;
00201 dns_name_t *name;
00202 dns_compress_t cctx;
00203 rbt_testdata_t *testdatap = testdata;
00204
00205 dns_compress_init(&cctx, -1, mymctx);
00206
00207 while (testdatap->name != NULL && testdatap->data.data != NULL) {
00208 memmove(buffer, testdatap->name, testdatap->name_len);
00209
00210 isc_buffer_init(&b, buffer, testdatap->name_len);
00211 isc_buffer_add(&b, testdatap->name_len);
00212 dns_fixedname_init(&fname);
00213 name = dns_fixedname_name(&fname);
00214 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
00215 if (result != ISC_R_SUCCESS) {
00216 testdatap++;
00217 continue;
00218 }
00219
00220 if (name != NULL) {
00221 result = dns_rbt_addname(rbt, name, &testdatap->data);
00222 ATF_CHECK_STREQ(dns_result_totext(result), "success");
00223 }
00224 testdatap++;
00225 }
00226
00227 dns_compress_invalidate(&cctx);
00228 }
00229
00230
00231
00232
00233 static void
00234 check_test_data(dns_rbt_t *rbt) {
00235 char buffer[1024];
00236 char *arg;
00237 dns_fixedname_t fname;
00238 dns_fixedname_t fixed;
00239 dns_name_t *name;
00240 isc_buffer_t b;
00241 data_holder_t *data;
00242 isc_result_t result;
00243 dns_name_t *foundname;
00244 rbt_testdata_t *testdatap = testdata;
00245
00246 dns_fixedname_init(&fixed);
00247 foundname = dns_fixedname_name(&fixed);
00248
00249 while (testdatap->name != NULL && testdatap->data.data != NULL) {
00250 memmove(buffer, testdatap->name, testdatap->name_len + 1);
00251 arg = buffer;
00252
00253 isc_buffer_init(&b, arg, testdatap->name_len);
00254 isc_buffer_add(&b, testdatap->name_len);
00255 dns_fixedname_init(&fname);
00256 name = dns_fixedname_name(&fname);
00257 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
00258 if (result != ISC_R_SUCCESS) {
00259 testdatap++;
00260 continue;
00261 }
00262
00263 data = NULL;
00264 result = dns_rbt_findname(rbt, name, 0, foundname,
00265 (void *) &data);
00266 ATF_CHECK_STREQ(dns_result_totext(result), "success");
00267
00268 testdatap++;
00269 }
00270 }
00271
00272 static void
00273 data_printer(FILE *out, void *datap)
00274 {
00275 data_holder_t *data = (data_holder_t *)datap;
00276
00277 fprintf(out, "%d bytes, %s", data->len, data->data);
00278 }
00279
00280 ATF_TC(serialize);
00281 ATF_TC_HEAD(serialize, tc) {
00282 atf_tc_set_md_var(tc, "descr", "Test writing an rbt to file");
00283 }
00284 ATF_TC_BODY(serialize, tc) {
00285 dns_rbt_t *rbt = NULL;
00286 isc_result_t result;
00287 FILE *rbtfile = NULL;
00288 dns_rbt_t *rbt_deserialized = NULL;
00289 off_t offset;
00290 int fd;
00291 off_t filesize = 0;
00292 char *base;
00293
00294 UNUSED(tc);
00295
00296 isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00297
00298 result = dns_test_begin(NULL, ISC_TRUE);
00299 ATF_CHECK_STREQ(dns_result_totext(result), "success");
00300 result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
00301 ATF_CHECK_STREQ(dns_result_totext(result), "success");
00302
00303 add_test_data(mctx, rbt);
00304
00305 dns_rbt_printtext(rbt, data_printer, stdout);
00306
00307
00308
00309
00310 printf("serialization begins.\n");
00311 rbtfile = fopen("./zone.bin", "w+b");
00312 ATF_REQUIRE(rbtfile != NULL);
00313 result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL,
00314 &offset);
00315 ATF_REQUIRE(result == ISC_R_SUCCESS);
00316 dns_rbt_destroy(&rbt);
00317
00318
00319
00320
00321 printf("deserialization begins.\n");
00322
00323
00324
00325
00326 fd = open("zone.bin", O_RDWR);
00327 isc_file_getsizefd(fd, &filesize);
00328 base = mmap(NULL, filesize,
00329 PROT_READ|PROT_WRITE,
00330 MAP_FILE|MAP_PRIVATE, fd, 0);
00331 ATF_REQUIRE(base != NULL && base != MAP_FAILED);
00332 close(fd);
00333
00334 result = dns_rbt_deserialize_tree(base, filesize, 0, mctx,
00335 delete_data, NULL, fix_data, NULL,
00336 NULL, &rbt_deserialized);
00337
00338
00339 ATF_REQUIRE(result == ISC_R_SUCCESS);
00340 if (rbt_deserialized == NULL)
00341 atf_tc_fail("deserialized rbt is null!");
00342
00343 check_test_data(rbt_deserialized);
00344
00345 dns_rbt_printtext(rbt_deserialized, data_printer, stdout);
00346
00347 dns_rbt_destroy(&rbt_deserialized);
00348 munmap(base, filesize);
00349 unlink("zone.bin");
00350 dns_test_end();
00351 }
00352
00353 ATF_TC(deserialize_corrupt);
00354 ATF_TC_HEAD(deserialize_corrupt, tc) {
00355 atf_tc_set_md_var(tc, "descr", "Test reading a corrupt map file");
00356 }
00357 ATF_TC_BODY(deserialize_corrupt, tc) {
00358 dns_rbt_t *rbt = NULL;
00359 isc_result_t result;
00360 FILE *rbtfile = NULL;
00361 off_t offset;
00362 int fd;
00363 off_t filesize = 0;
00364 char *base, *p, *q;
00365 isc_uint32_t r;
00366 int i;
00367
00368 UNUSED(tc);
00369
00370 isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00371
00372 result = dns_test_begin(NULL, ISC_TRUE);
00373 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00374
00375
00376 result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
00377 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00378
00379 add_test_data(mctx, rbt);
00380 rbtfile = fopen("./zone.bin", "w+b");
00381 ATF_REQUIRE(rbtfile != NULL);
00382 result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL,
00383 &offset);
00384 ATF_REQUIRE(result == ISC_R_SUCCESS);
00385 dns_rbt_destroy(&rbt);
00386
00387
00388 for (i = 0; i < 256; i++) {
00389 dns_rbt_t *rbt_deserialized = NULL;
00390
00391 fd = open("zone.bin", O_RDWR);
00392 isc_file_getsizefd(fd, &filesize);
00393 base = mmap(NULL, filesize,
00394 PROT_READ|PROT_WRITE,
00395 MAP_FILE|MAP_PRIVATE, fd, 0);
00396 ATF_REQUIRE(base != NULL && base != MAP_FAILED);
00397 close(fd);
00398
00399
00400 isc_random_get(&r);
00401 p = base + (r % filesize);
00402 q = base + filesize;
00403 isc_random_get(&r);
00404 q -= (r % (q - p));
00405 while (p++ < q) {
00406 isc_random_get(&r);
00407 *p = r & 0xff;
00408 }
00409
00410 result = dns_rbt_deserialize_tree(base, filesize, 0, mctx,
00411 delete_data, NULL,
00412 fix_data, NULL,
00413 NULL, &rbt_deserialized);
00414 printf("%d: %s\n", i, isc_result_totext(result));
00415
00416
00417 ATF_REQUIRE(result == ISC_R_SUCCESS ||
00418 result == ISC_R_INVALIDFILE);
00419 if (result != ISC_R_SUCCESS)
00420 ATF_REQUIRE(rbt_deserialized == NULL);
00421
00422 if (rbt_deserialized != NULL)
00423 dns_rbt_destroy(&rbt_deserialized);
00424
00425 munmap(base, filesize);
00426 }
00427
00428 unlink("zone.bin");
00429 dns_test_end();
00430 }
00431
00432
00433 ATF_TC(serialize_align);
00434 ATF_TC_HEAD(serialize_align, tc) {
00435 atf_tc_set_md_var(tc, "descr",
00436 "Test the dns_rbt_serialize_align() function.");
00437 }
00438 ATF_TC_BODY(serialize_align, tc) {
00439 UNUSED(tc);
00440
00441 ATF_CHECK(dns_rbt_serialize_align(0) == 0);
00442 ATF_CHECK(dns_rbt_serialize_align(1) == 8);
00443 ATF_CHECK(dns_rbt_serialize_align(2) == 8);
00444 ATF_CHECK(dns_rbt_serialize_align(3) == 8);
00445 ATF_CHECK(dns_rbt_serialize_align(4) == 8);
00446 ATF_CHECK(dns_rbt_serialize_align(5) == 8);
00447 ATF_CHECK(dns_rbt_serialize_align(6) == 8);
00448 ATF_CHECK(dns_rbt_serialize_align(7) == 8);
00449 ATF_CHECK(dns_rbt_serialize_align(8) == 8);
00450 ATF_CHECK(dns_rbt_serialize_align(9) == 16);
00451 ATF_CHECK(dns_rbt_serialize_align(0xff) == 0x100);
00452 ATF_CHECK(dns_rbt_serialize_align(0x301) == 0x308);
00453 }
00454
00455
00456
00457
00458 ATF_TP_ADD_TCS(tp) {
00459 ATF_TP_ADD_TC(tp, serialize);
00460 ATF_TP_ADD_TC(tp, deserialize_corrupt);
00461 ATF_TP_ADD_TC(tp, serialize_align);
00462
00463 return (atf_no_error());
00464 }