1 /* $NetBSD: soa_6.c,v 1.6 2014/12/10 04:37:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2007, 2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1998-2002 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id */ 21 22 /* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */ 23 24 #ifndef RDATA_GENERIC_SOA_6_C 25 #define RDATA_GENERIC_SOA_6_C 26 27 #define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON) 28 29 static inline isc_result_t 30 fromtext_soa(ARGS_FROMTEXT) { 31 isc_token_t token; 32 dns_name_t name; 33 isc_buffer_t buffer; 34 int i; 35 isc_uint32_t n; 36 isc_boolean_t ok; 37 38 REQUIRE(type == 6); 39 40 UNUSED(type); 41 UNUSED(rdclass); 42 UNUSED(callbacks); 43 44 origin = (origin != NULL) ? origin : dns_rootname; 45 46 for (i = 0; i < 2; i++) { 47 RETERR(isc_lex_getmastertoken(lexer, &token, 48 isc_tokentype_string, 49 ISC_FALSE)); 50 51 dns_name_init(&name, NULL); 52 buffer_fromregion(&buffer, &token.value.as_region); 53 RETTOK(dns_name_fromtext(&name, &buffer, origin, 54 options, target)); 55 ok = ISC_TRUE; 56 if ((options & DNS_RDATA_CHECKNAMES) != 0) 57 switch (i) { 58 case 0: 59 ok = dns_name_ishostname(&name, ISC_FALSE); 60 break; 61 case 1: 62 ok = dns_name_ismailbox(&name); 63 break; 64 65 } 66 if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) 67 RETTOK(DNS_R_BADNAME); 68 if (!ok && callbacks != NULL) 69 warn_badname(&name, lexer, callbacks); 70 } 71 72 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 73 ISC_FALSE)); 74 RETERR(uint32_tobuffer(token.value.as_ulong, target)); 75 76 for (i = 0; i < 4; i++) { 77 RETERR(isc_lex_getmastertoken(lexer, &token, 78 isc_tokentype_string, 79 ISC_FALSE)); 80 RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n)); 81 RETERR(uint32_tobuffer(n, target)); 82 } 83 84 return (ISC_R_SUCCESS); 85 } 86 87 static const char *soa_fieldnames[5] = { 88 "serial", "refresh", "retry", "expire", "minimum" 89 }; 90 91 static inline isc_result_t 92 totext_soa(ARGS_TOTEXT) { 93 isc_region_t dregion; 94 dns_name_t mname; 95 dns_name_t rname; 96 dns_name_t prefix; 97 isc_boolean_t sub; 98 int i; 99 isc_boolean_t multiline; 100 isc_boolean_t comment; 101 102 REQUIRE(rdata->type == 6); 103 REQUIRE(rdata->length != 0); 104 105 multiline = ISC_TF((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0); 106 if (multiline) 107 comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0); 108 else 109 comment = ISC_FALSE; 110 111 112 dns_name_init(&mname, NULL); 113 dns_name_init(&rname, NULL); 114 dns_name_init(&prefix, NULL); 115 116 dns_rdata_toregion(rdata, &dregion); 117 118 dns_name_fromregion(&mname, &dregion); 119 isc_region_consume(&dregion, name_length(&mname)); 120 121 dns_name_fromregion(&rname, &dregion); 122 isc_region_consume(&dregion, name_length(&rname)); 123 124 sub = name_prefix(&mname, tctx->origin, &prefix); 125 RETERR(dns_name_totext(&prefix, sub, target)); 126 127 RETERR(str_totext(" ", target)); 128 129 sub = name_prefix(&rname, tctx->origin, &prefix); 130 RETERR(dns_name_totext(&prefix, sub, target)); 131 132 if (multiline) 133 RETERR(str_totext(" (" , target)); 134 RETERR(str_totext(tctx->linebreak, target)); 135 136 for (i = 0; i < 5; i++) { 137 char buf[sizeof("0123456789 ; ")]; 138 unsigned long num; 139 num = uint32_fromregion(&dregion); 140 isc_region_consume(&dregion, 4); 141 sprintf(buf, comment ? "%-10lu ; " : "%lu", num); 142 RETERR(str_totext(buf, target)); 143 if (comment) { 144 RETERR(str_totext(soa_fieldnames[i], target)); 145 /* Print times in week/day/hour/minute/second form */ 146 if (i >= 1) { 147 RETERR(str_totext(" (", target)); 148 RETERR(dns_ttl_totext(num, ISC_TRUE, target)); 149 RETERR(str_totext(")", target)); 150 } 151 RETERR(str_totext(tctx->linebreak, target)); 152 } else if (i < 4) { 153 RETERR(str_totext(tctx->linebreak, target)); 154 } 155 } 156 157 if (multiline) 158 RETERR(str_totext(")", target)); 159 160 return (ISC_R_SUCCESS); 161 } 162 163 static inline isc_result_t 164 fromwire_soa(ARGS_FROMWIRE) { 165 dns_name_t mname; 166 dns_name_t rname; 167 isc_region_t sregion; 168 isc_region_t tregion; 169 170 REQUIRE(type == 6); 171 172 UNUSED(type); 173 UNUSED(rdclass); 174 175 dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14); 176 177 dns_name_init(&mname, NULL); 178 dns_name_init(&rname, NULL); 179 180 RETERR(dns_name_fromwire(&mname, source, dctx, options, target)); 181 RETERR(dns_name_fromwire(&rname, source, dctx, options, target)); 182 183 isc_buffer_activeregion(source, &sregion); 184 isc_buffer_availableregion(target, &tregion); 185 186 if (sregion.length < 20) 187 return (ISC_R_UNEXPECTEDEND); 188 if (tregion.length < 20) 189 return (ISC_R_NOSPACE); 190 191 memmove(tregion.base, sregion.base, 20); 192 isc_buffer_forward(source, 20); 193 isc_buffer_add(target, 20); 194 195 return (ISC_R_SUCCESS); 196 } 197 198 static inline isc_result_t 199 towire_soa(ARGS_TOWIRE) { 200 isc_region_t sregion; 201 isc_region_t tregion; 202 dns_name_t mname; 203 dns_name_t rname; 204 dns_offsets_t moffsets; 205 dns_offsets_t roffsets; 206 207 REQUIRE(rdata->type == 6); 208 REQUIRE(rdata->length != 0); 209 210 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14); 211 212 dns_name_init(&mname, moffsets); 213 dns_name_init(&rname, roffsets); 214 215 dns_rdata_toregion(rdata, &sregion); 216 217 dns_name_fromregion(&mname, &sregion); 218 isc_region_consume(&sregion, name_length(&mname)); 219 RETERR(dns_name_towire(&mname, cctx, target)); 220 221 dns_name_fromregion(&rname, &sregion); 222 isc_region_consume(&sregion, name_length(&rname)); 223 RETERR(dns_name_towire(&rname, cctx, target)); 224 225 isc_buffer_availableregion(target, &tregion); 226 if (tregion.length < 20) 227 return (ISC_R_NOSPACE); 228 229 memmove(tregion.base, sregion.base, 20); 230 isc_buffer_add(target, 20); 231 return (ISC_R_SUCCESS); 232 } 233 234 static inline int 235 compare_soa(ARGS_COMPARE) { 236 isc_region_t region1; 237 isc_region_t region2; 238 dns_name_t name1; 239 dns_name_t name2; 240 int order; 241 242 REQUIRE(rdata1->type == rdata2->type); 243 REQUIRE(rdata1->rdclass == rdata2->rdclass); 244 REQUIRE(rdata1->type == 6); 245 REQUIRE(rdata1->length != 0); 246 REQUIRE(rdata2->length != 0); 247 248 dns_name_init(&name1, NULL); 249 dns_name_init(&name2, NULL); 250 251 dns_rdata_toregion(rdata1, ®ion1); 252 dns_rdata_toregion(rdata2, ®ion2); 253 254 dns_name_fromregion(&name1, ®ion1); 255 dns_name_fromregion(&name2, ®ion2); 256 257 order = dns_name_rdatacompare(&name1, &name2); 258 if (order != 0) 259 return (order); 260 261 isc_region_consume(®ion1, name_length(&name1)); 262 isc_region_consume(®ion2, name_length(&name2)); 263 264 dns_name_init(&name1, NULL); 265 dns_name_init(&name2, NULL); 266 267 dns_name_fromregion(&name1, ®ion1); 268 dns_name_fromregion(&name2, ®ion2); 269 270 order = dns_name_rdatacompare(&name1, &name2); 271 if (order != 0) 272 return (order); 273 274 isc_region_consume(®ion1, name_length(&name1)); 275 isc_region_consume(®ion2, name_length(&name2)); 276 277 return (isc_region_compare(®ion1, ®ion2)); 278 } 279 280 static inline isc_result_t 281 fromstruct_soa(ARGS_FROMSTRUCT) { 282 dns_rdata_soa_t *soa = source; 283 isc_region_t region; 284 285 REQUIRE(type == 6); 286 REQUIRE(source != NULL); 287 REQUIRE(soa->common.rdtype == type); 288 REQUIRE(soa->common.rdclass == rdclass); 289 290 UNUSED(type); 291 UNUSED(rdclass); 292 293 dns_name_toregion(&soa->origin, ®ion); 294 RETERR(isc_buffer_copyregion(target, ®ion)); 295 dns_name_toregion(&soa->contact, ®ion); 296 RETERR(isc_buffer_copyregion(target, ®ion)); 297 RETERR(uint32_tobuffer(soa->serial, target)); 298 RETERR(uint32_tobuffer(soa->refresh, target)); 299 RETERR(uint32_tobuffer(soa->retry, target)); 300 RETERR(uint32_tobuffer(soa->expire, target)); 301 return (uint32_tobuffer(soa->minimum, target)); 302 } 303 304 static inline isc_result_t 305 tostruct_soa(ARGS_TOSTRUCT) { 306 isc_region_t region; 307 dns_rdata_soa_t *soa = target; 308 dns_name_t name; 309 isc_result_t result; 310 311 REQUIRE(rdata->type == 6); 312 REQUIRE(target != NULL); 313 REQUIRE(rdata->length != 0); 314 315 soa->common.rdclass = rdata->rdclass; 316 soa->common.rdtype = rdata->type; 317 ISC_LINK_INIT(&soa->common, link); 318 319 320 dns_rdata_toregion(rdata, ®ion); 321 322 dns_name_init(&name, NULL); 323 dns_name_fromregion(&name, ®ion); 324 isc_region_consume(®ion, name_length(&name)); 325 dns_name_init(&soa->origin, NULL); 326 RETERR(name_duporclone(&name, mctx, &soa->origin)); 327 328 dns_name_fromregion(&name, ®ion); 329 isc_region_consume(®ion, name_length(&name)); 330 dns_name_init(&soa->contact, NULL); 331 result = name_duporclone(&name, mctx, &soa->contact); 332 if (result != ISC_R_SUCCESS) 333 goto cleanup; 334 335 soa->serial = uint32_fromregion(®ion); 336 isc_region_consume(®ion, 4); 337 338 soa->refresh = uint32_fromregion(®ion); 339 isc_region_consume(®ion, 4); 340 341 soa->retry = uint32_fromregion(®ion); 342 isc_region_consume(®ion, 4); 343 344 soa->expire = uint32_fromregion(®ion); 345 isc_region_consume(®ion, 4); 346 347 soa->minimum = uint32_fromregion(®ion); 348 349 soa->mctx = mctx; 350 return (ISC_R_SUCCESS); 351 352 cleanup: 353 if (mctx != NULL) 354 dns_name_free(&soa->origin, mctx); 355 return (ISC_R_NOMEMORY); 356 } 357 358 static inline void 359 freestruct_soa(ARGS_FREESTRUCT) { 360 dns_rdata_soa_t *soa = source; 361 362 REQUIRE(source != NULL); 363 REQUIRE(soa->common.rdtype == 6); 364 365 if (soa->mctx == NULL) 366 return; 367 368 dns_name_free(&soa->origin, soa->mctx); 369 dns_name_free(&soa->contact, soa->mctx); 370 soa->mctx = NULL; 371 } 372 373 static inline isc_result_t 374 additionaldata_soa(ARGS_ADDLDATA) { 375 UNUSED(rdata); 376 UNUSED(add); 377 UNUSED(arg); 378 379 REQUIRE(rdata->type == 6); 380 381 return (ISC_R_SUCCESS); 382 } 383 384 static inline isc_result_t 385 digest_soa(ARGS_DIGEST) { 386 isc_region_t r; 387 dns_name_t name; 388 389 REQUIRE(rdata->type == 6); 390 391 dns_rdata_toregion(rdata, &r); 392 393 dns_name_init(&name, NULL); 394 dns_name_fromregion(&name, &r); 395 RETERR(dns_name_digest(&name, digest, arg)); 396 isc_region_consume(&r, name_length(&name)); 397 398 dns_name_init(&name, NULL); 399 dns_name_fromregion(&name, &r); 400 RETERR(dns_name_digest(&name, digest, arg)); 401 isc_region_consume(&r, name_length(&name)); 402 403 return ((digest)(arg, &r)); 404 } 405 406 static inline isc_boolean_t 407 checkowner_soa(ARGS_CHECKOWNER) { 408 409 REQUIRE(type == 6); 410 411 UNUSED(name); 412 UNUSED(type); 413 UNUSED(rdclass); 414 UNUSED(wildcard); 415 416 return (ISC_TRUE); 417 } 418 419 static inline isc_boolean_t 420 checknames_soa(ARGS_CHECKNAMES) { 421 isc_region_t region; 422 dns_name_t name; 423 424 REQUIRE(rdata->type == 6); 425 426 UNUSED(owner); 427 428 dns_rdata_toregion(rdata, ®ion); 429 dns_name_init(&name, NULL); 430 dns_name_fromregion(&name, ®ion); 431 if (!dns_name_ishostname(&name, ISC_FALSE)) { 432 if (bad != NULL) 433 dns_name_clone(&name, bad); 434 return (ISC_FALSE); 435 } 436 isc_region_consume(®ion, name_length(&name)); 437 dns_name_fromregion(&name, ®ion); 438 if (!dns_name_ismailbox(&name)) { 439 if (bad != NULL) 440 dns_name_clone(&name, bad); 441 return (ISC_FALSE); 442 } 443 return (ISC_TRUE); 444 } 445 446 static inline int 447 casecompare_soa(ARGS_COMPARE) { 448 return (compare_soa(rdata1, rdata2)); 449 } 450 451 #endif /* RDATA_GENERIC_SOA_6_C */ 452