1/* 2 * Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1998-2001, 2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: t_master.c,v 1.39.346.2 2011/03/12 04:59:14 tbox Exp $ */ 19 20#include <config.h> 21 22#include <ctype.h> 23#include <stdlib.h> 24 25#include <isc/buffer.h> 26#include <isc/mem.h> 27#include <isc/string.h> /* Required for HP/UX (and others?) */ 28#include <isc/util.h> 29 30#include <dns/callbacks.h> 31#include <dns/master.h> 32#include <dns/name.h> 33#include <dns/rdataclass.h> 34#include <dns/rdataset.h> 35#include <dns/result.h> 36 37#include <tests/t_api.h> 38 39#define BUFLEN 255 40#define BIGBUFLEN (64 * 1024) 41 42static isc_result_t 43t1_add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset); 44 45isc_mem_t *T1_mctx; 46char *Tokens[T_MAXTOKS + 1]; 47 48static isc_result_t 49t1_add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) { 50 char buf[BIGBUFLEN]; 51 isc_buffer_t target; 52 isc_result_t result; 53 54 UNUSED(arg); 55 56 isc_buffer_init(&target, buf, BIGBUFLEN); 57 result = dns_rdataset_totext(dataset, owner, ISC_FALSE, ISC_FALSE, 58 &target); 59 if (result != ISC_R_SUCCESS) 60 t_info("dns_rdataset_totext: %s\n", dns_result_totext(result)); 61 62 return(result); 63} 64 65static int 66test_master(char *testfile, char *origin, char *class, isc_result_t exp_result) 67{ 68 int result; 69 int len; 70 isc_result_t isc_result; 71 isc_result_t dns_result; 72 dns_name_t dns_origin; 73 isc_buffer_t source; 74 isc_buffer_t target; 75 unsigned char name_buf[BUFLEN]; 76 dns_rdatacallbacks_t callbacks; 77 dns_rdataclass_t rdataclass; 78 isc_textregion_t textregion; 79 80 if (T1_mctx == NULL) 81 isc_result = isc_mem_create(0, 0, &T1_mctx); 82 else 83 isc_result = ISC_R_SUCCESS; 84 if (isc_result != ISC_R_SUCCESS) { 85 t_info("isc_mem_create failed %d\n", isc_result); 86 return(T_UNRESOLVED); 87 } 88 89 len = strlen(origin); 90 isc_buffer_init(&source, origin, len); 91 isc_buffer_add(&source, len); 92 isc_buffer_setactive(&source, len); 93 isc_buffer_init(&target, name_buf, BUFLEN); 94 dns_name_init(&dns_origin, NULL); 95 dns_result = dns_name_fromtext(&dns_origin, &source, dns_rootname, 96 0, &target); 97 if (dns_result != ISC_R_SUCCESS) { 98 t_info("dns_name_fromtext failed %s\n", 99 dns_result_totext(dns_result)); 100 return(T_UNRESOLVED); 101 } 102 103 dns_rdatacallbacks_init_stdio(&callbacks); 104 callbacks.add = t1_add_callback; 105 106 textregion.base = class; 107 textregion.length = strlen(class); 108 109 dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion); 110 if (dns_result != ISC_R_SUCCESS) { 111 t_info("dns_rdataclass_fromtext failed %s\n", 112 dns_result_totext(dns_result)); 113 return(T_UNRESOLVED); 114 } 115 116 dns_result = dns_master_loadfile( testfile, 117 &dns_origin, 118 &dns_origin, 119 rdataclass, 120 ISC_TRUE, 121 &callbacks, 122 T1_mctx); 123 124 if (dns_result == exp_result) 125 result = T_PASS; 126 else { 127 t_info("dns_master_loadfile: got %s, expected %s\n", 128 dns_result_totext(dns_result), 129 dns_result_totext(exp_result)); 130 result = T_FAIL; 131 } 132 return(result); 133} 134 135static int 136test_master_x(const char *filename) { 137 FILE *fp; 138 char *p; 139 int line; 140 int cnt; 141 int result; 142 143 result = T_UNRESOLVED; 144 145 fp = fopen(filename, "r"); 146 if (fp != NULL) { 147 line = 0; 148 while ((p = t_fgetbs(fp)) != NULL) { 149 150 ++line; 151 152 /* 153 * Skip comment lines. 154 */ 155 if ((isspace(*p & 0xff)) || (*p == '#')) { 156 (void)free(p); 157 continue; 158 } 159 160 /* 161 * Name of data file, origin, zclass, expected result. 162 */ 163 cnt = t_bustline(p, Tokens); 164 if (cnt == 4) { 165 result = test_master(Tokens[0], Tokens[1], 166 Tokens[2], 167 t_dns_result_fromtext(Tokens[3])); 168 } else { 169 t_info("bad format in %s at line %d\n", 170 filename, line); 171 } 172 173 (void)free(p); 174 } 175 (void)fclose(fp); 176 } else { 177 t_info("Missing datafile %s\n", filename); 178 } 179 return(result); 180} 181 182static const char *a1 = "dns_master_loadfile loads a valid master file and " 183 "returns ISC_R_SUCCESS"; 184static void 185t1(void) { 186 int result; 187 t_assert("dns_master_loadfile", 1, T_REQUIRED, "%s", a1); 188 result = test_master_x("dns_master_load_1_data"); 189 t_result(result); 190} 191 192static const char *a2 = 193 "dns_master_loadfile returns ISC_R_UNEXPECTEDEND when the " 194 "masterfile input ends unexpectedly"; 195 196static void 197t2(void) { 198 int result; 199 t_assert("dns_master_loadfile", 2, T_REQUIRED, "%s", a2); 200 result = test_master_x("dns_master_load_2_data"); 201 t_result(result); 202} 203 204static const char *a3 = "dns_master_loadfile returns DNS_R_NOOWNER when the " 205 "an ownername is not specified"; 206 207static void 208t3() { 209 int result; 210 t_assert("dns_master_loadfile", 3, T_REQUIRED, "%s", a3); 211 result = test_master_x("dns_master_load_3_data"); 212 t_result(result); 213} 214 215static const char *a4 = "dns_master_loadfile accepts broken zone files " 216 "where the first record has an undefined TTL, " 217 "as long as it is a SOA"; 218 219static void 220t4() { 221 int result; 222 t_assert("dns_master_loadfile", 4, T_REQUIRED, "%s", a4); 223 result = test_master_x("dns_master_load_4_data"); 224 t_result(result); 225} 226 227static const char *a5 = "dns_master_loadfile returns DNS_R_BADCLASS when the " 228 "the record class did not match the zone class"; 229 230static void 231t5() { 232 int result; 233 234 t_assert("dns_master_loadfile", 5, T_REQUIRED, "%s", a5); 235 result = test_master_x("dns_master_load_5_data"); 236 237 t_result(result); 238} 239 240static const char *a6 = 241 "dns_master_loadfile understands DNSKEY RR specifications " 242 "containing key material"; 243 244static void 245t6() { 246 int result; 247 248 t_assert("dns_master_loadfile", 6, T_REQUIRED, "%s", a6); 249 result = test_master_x("dns_master_load_6_data"); 250 251 t_result(result); 252} 253 254static const char *a7 = 255 "dns_master_loadfile understands DNSKEY RR specifications " 256 "containing no key material"; 257 258static void 259t7() { 260 int result; 261 262 t_assert("dns_master_loadfile", 7, T_REQUIRED, "%s", a7); 263 result = test_master_x("dns_master_load_7_data"); 264 265 t_result(result); 266} 267 268static const char *a8 = 269 "dns_master_loadfile understands $INCLUDE"; 270 271static void 272t8() { 273 int result; 274 275 t_assert("dns_master_loadfile", 8, T_REQUIRED, "%s", a8); 276 result = test_master_x("dns_master_load_8_data"); 277 278 t_result(result); 279} 280 281static const char *a9 = 282 "dns_master_loadfile understands $INCLUDE with failure"; 283 284static void 285t9() { 286 int result; 287 288 t_assert("dns_master_loadfile", 9, T_REQUIRED, "%s", a9); 289 result = test_master_x("dns_master_load_9_data"); 290 291 t_result(result); 292} 293 294static const char *a10 = 295 "dns_master_loadfile non-empty blank lines"; 296 297static void 298t10() { 299 int result; 300 301 t_assert("dns_master_loadfile", 10, T_REQUIRED, "%s", a10); 302 result = test_master_x("dns_master_load_10_data"); 303 304 t_result(result); 305} 306 307static const char *a11 = 308 "dns_master_loadfile allow leading zeros in SOA"; 309 310static void 311t11() { 312 int result; 313 314 t_assert("dns_master_loadfile", 11, T_REQUIRED, "%s", a11); 315 result = test_master_x("dns_master_load_11_data"); 316 317 t_result(result); 318} 319 320 321testspec_t T_testlist[] = { 322 { t1, "ISC_R_SUCCESS" }, 323 { t2, "ISC_R_UNEXPECTEDEND" }, 324 { t3, "DNS_NOOWNER" }, 325 { t4, "DNS_NOTTL" }, 326 { t5, "DNS_BADCLASS" }, 327 { t6, "DNSKEY RR 1" }, 328 { t7, "DNSKEY RR 2" }, 329 { t8, "$INCLUDE" }, 330 { t9, "$INCLUDE w/ DNS_BADCLASS" }, 331 { t10, "non empty blank lines" }, 332 { t11, "leading zeros in serial" }, 333 { NULL, NULL } 334}; 335 336