ssu.c revision 1.3
1/* $NetBSD: ssu.c,v 1.3 2019/01/09 16:55:12 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14/*! \file */ 15 16#include <config.h> 17 18#include <stdbool.h> 19 20#include <isc/magic.h> 21#include <isc/mem.h> 22#include <isc/netaddr.h> 23#include <isc/print.h> 24#include <isc/result.h> 25#include <isc/string.h> 26#include <isc/util.h> 27 28#include <dns/dlz.h> 29#include <dns/fixedname.h> 30#include <dns/name.h> 31#include <dns/ssu.h> 32 33#include <dst/gssapi.h> 34#include <dst/dst.h> 35 36#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T') 37#define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC) 38 39#define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R') 40#define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC) 41 42struct dns_ssurule { 43 unsigned int magic; 44 bool grant; /*%< is this a grant or a deny? */ 45 dns_ssumatchtype_t matchtype; /*%< which type of pattern match? */ 46 dns_name_t *identity; /*%< the identity to match */ 47 dns_name_t *name; /*%< the name being updated */ 48 unsigned int ntypes; /*%< number of data types covered */ 49 dns_rdatatype_t *types; /*%< the data types. Can include */ 50 /* ANY. if NULL, defaults to all */ 51 /* types except SIG, SOA, and NS */ 52 ISC_LINK(dns_ssurule_t) link; 53}; 54 55struct dns_ssutable { 56 unsigned int magic; 57 isc_mem_t *mctx; 58 unsigned int references; 59 isc_mutex_t lock; 60 dns_dlzdb_t *dlzdatabase; 61 ISC_LIST(dns_ssurule_t) rules; 62}; 63 64isc_result_t 65dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) { 66 dns_ssutable_t *table; 67 68 REQUIRE(tablep != NULL && *tablep == NULL); 69 REQUIRE(mctx != NULL); 70 71 table = isc_mem_get(mctx, sizeof(dns_ssutable_t)); 72 if (table == NULL) 73 return (ISC_R_NOMEMORY); 74 isc_mutex_init(&table->lock); 75 table->references = 1; 76 table->mctx = NULL; 77 isc_mem_attach(mctx, &table->mctx); 78 ISC_LIST_INIT(table->rules); 79 table->magic = SSUTABLEMAGIC; 80 *tablep = table; 81 return (ISC_R_SUCCESS); 82} 83 84static inline void 85destroy(dns_ssutable_t *table) { 86 isc_mem_t *mctx; 87 88 REQUIRE(VALID_SSUTABLE(table)); 89 90 mctx = table->mctx; 91 while (!ISC_LIST_EMPTY(table->rules)) { 92 dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules); 93 if (rule->identity != NULL) { 94 dns_name_free(rule->identity, mctx); 95 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t)); 96 } 97 if (rule->name != NULL) { 98 dns_name_free(rule->name, mctx); 99 isc_mem_put(mctx, rule->name, sizeof(dns_name_t)); 100 } 101 if (rule->types != NULL) 102 isc_mem_put(mctx, rule->types, 103 rule->ntypes * sizeof(dns_rdatatype_t)); 104 ISC_LIST_UNLINK(table->rules, rule, link); 105 rule->magic = 0; 106 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t)); 107 } 108 isc_mutex_destroy(&table->lock); 109 table->magic = 0; 110 isc_mem_putanddetach(&table->mctx, table, sizeof(dns_ssutable_t)); 111} 112 113void 114dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) { 115 REQUIRE(VALID_SSUTABLE(source)); 116 REQUIRE(targetp != NULL && *targetp == NULL); 117 118 LOCK(&source->lock); 119 120 INSIST(source->references > 0); 121 source->references++; 122 INSIST(source->references != 0); 123 124 UNLOCK(&source->lock); 125 126 *targetp = source; 127} 128 129void 130dns_ssutable_detach(dns_ssutable_t **tablep) { 131 dns_ssutable_t *table; 132 bool done = false; 133 134 REQUIRE(tablep != NULL); 135 table = *tablep; 136 REQUIRE(VALID_SSUTABLE(table)); 137 138 LOCK(&table->lock); 139 140 INSIST(table->references > 0); 141 if (--table->references == 0) 142 done = true; 143 UNLOCK(&table->lock); 144 145 *tablep = NULL; 146 147 if (done) 148 destroy(table); 149} 150 151isc_result_t 152dns_ssutable_addrule(dns_ssutable_t *table, bool grant, 153 const dns_name_t *identity, dns_ssumatchtype_t matchtype, 154 const dns_name_t *name, unsigned int ntypes, 155 dns_rdatatype_t *types) 156{ 157 dns_ssurule_t *rule; 158 isc_mem_t *mctx; 159 isc_result_t result; 160 161 REQUIRE(VALID_SSUTABLE(table)); 162 REQUIRE(dns_name_isabsolute(identity)); 163 REQUIRE(dns_name_isabsolute(name)); 164 REQUIRE(matchtype <= dns_ssumatchtype_max); 165 if (matchtype == dns_ssumatchtype_wildcard) 166 REQUIRE(dns_name_iswildcard(name)); 167 if (ntypes > 0) 168 REQUIRE(types != NULL); 169 170 mctx = table->mctx; 171 rule = isc_mem_get(mctx, sizeof(dns_ssurule_t)); 172 if (rule == NULL) 173 return (ISC_R_NOMEMORY); 174 175 rule->identity = NULL; 176 rule->name = NULL; 177 rule->types = NULL; 178 179 rule->grant = grant; 180 181 rule->identity = isc_mem_get(mctx, sizeof(dns_name_t)); 182 if (rule->identity == NULL) { 183 result = ISC_R_NOMEMORY; 184 goto failure; 185 } 186 dns_name_init(rule->identity, NULL); 187 result = dns_name_dup(identity, mctx, rule->identity); 188 if (result != ISC_R_SUCCESS) 189 goto failure; 190 191 rule->name = isc_mem_get(mctx, sizeof(dns_name_t)); 192 if (rule->name == NULL) { 193 result = ISC_R_NOMEMORY; 194 goto failure; 195 } 196 dns_name_init(rule->name, NULL); 197 result = dns_name_dup(name, mctx, rule->name); 198 if (result != ISC_R_SUCCESS) 199 goto failure; 200 201 rule->matchtype = matchtype; 202 203 rule->ntypes = ntypes; 204 if (ntypes > 0) { 205 rule->types = isc_mem_get(mctx, 206 ntypes * sizeof(dns_rdatatype_t)); 207 if (rule->types == NULL) { 208 result = ISC_R_NOMEMORY; 209 goto failure; 210 } 211 memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t)); 212 } else 213 rule->types = NULL; 214 215 rule->magic = SSURULEMAGIC; 216 ISC_LIST_INITANDAPPEND(table->rules, rule, link); 217 218 return (ISC_R_SUCCESS); 219 220 failure: 221 if (rule->identity != NULL) { 222 if (dns_name_dynamic(rule->identity)) 223 dns_name_free(rule->identity, mctx); 224 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t)); 225 } 226 if (rule->name != NULL) { 227 if (dns_name_dynamic(rule->name)) 228 dns_name_free(rule->name, mctx); 229 isc_mem_put(mctx, rule->name, sizeof(dns_name_t)); 230 } 231 if (rule->types != NULL) 232 isc_mem_put(mctx, rule->types, 233 ntypes * sizeof(dns_rdatatype_t)); 234 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t)); 235 236 return (result); 237} 238 239static inline bool 240isusertype(dns_rdatatype_t type) { 241 return (type != dns_rdatatype_ns && 242 type != dns_rdatatype_soa && 243 type != dns_rdatatype_rrsig); 244} 245 246static void 247reverse_from_address(dns_name_t *tcpself, const isc_netaddr_t *tcpaddr) { 248 char buf[16 * 4 + sizeof("IP6.ARPA.")]; 249 isc_result_t result; 250 const unsigned char *ap; 251 isc_buffer_t b; 252 unsigned long l; 253 254 switch (tcpaddr->family) { 255 case AF_INET: 256 l = ntohl(tcpaddr->type.in.s_addr); 257 result = snprintf(buf, sizeof(buf), 258 "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.", 259 (l >> 0) & 0xff, (l >> 8) & 0xff, 260 (l >> 16) & 0xff, (l >> 24) & 0xff); 261 RUNTIME_CHECK(result < sizeof(buf)); 262 break; 263 case AF_INET6: 264 ap = tcpaddr->type.in6.s6_addr; 265 result = snprintf(buf, sizeof(buf), 266 "%x.%x.%x.%x.%x.%x.%x.%x." 267 "%x.%x.%x.%x.%x.%x.%x.%x." 268 "%x.%x.%x.%x.%x.%x.%x.%x." 269 "%x.%x.%x.%x.%x.%x.%x.%x." 270 "IP6.ARPA.", 271 ap[15] & 0x0f, (ap[15] >> 4) & 0x0f, 272 ap[14] & 0x0f, (ap[14] >> 4) & 0x0f, 273 ap[13] & 0x0f, (ap[13] >> 4) & 0x0f, 274 ap[12] & 0x0f, (ap[12] >> 4) & 0x0f, 275 ap[11] & 0x0f, (ap[11] >> 4) & 0x0f, 276 ap[10] & 0x0f, (ap[10] >> 4) & 0x0f, 277 ap[9] & 0x0f, (ap[9] >> 4) & 0x0f, 278 ap[8] & 0x0f, (ap[8] >> 4) & 0x0f, 279 ap[7] & 0x0f, (ap[7] >> 4) & 0x0f, 280 ap[6] & 0x0f, (ap[6] >> 4) & 0x0f, 281 ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, 282 ap[4] & 0x0f, (ap[4] >> 4) & 0x0f, 283 ap[3] & 0x0f, (ap[3] >> 4) & 0x0f, 284 ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, 285 ap[1] & 0x0f, (ap[1] >> 4) & 0x0f, 286 ap[0] & 0x0f, (ap[0] >> 4) & 0x0f); 287 RUNTIME_CHECK(result < sizeof(buf)); 288 break; 289 default: 290 INSIST(0); 291 ISC_UNREACHABLE(); 292 } 293 isc_buffer_init(&b, buf, strlen(buf)); 294 isc_buffer_add(&b, strlen(buf)); 295 result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL); 296 RUNTIME_CHECK(result == ISC_R_SUCCESS); 297} 298 299static void 300stf_from_address(dns_name_t *stfself, const isc_netaddr_t *tcpaddr) { 301 char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")]; 302 isc_result_t result; 303 const unsigned char *ap; 304 isc_buffer_t b; 305 unsigned long l; 306 307 switch(tcpaddr->family) { 308 case AF_INET: 309 l = ntohl(tcpaddr->type.in.s_addr); 310 result = snprintf(buf, sizeof(buf), 311 "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx" 312 "2.0.0.2.IP6.ARPA.", 313 l & 0xf, (l >> 4) & 0xf, 314 (l >> 8) & 0xf, (l >> 12) & 0xf, 315 (l >> 16) & 0xf, (l >> 20) & 0xf, 316 (l >> 24) & 0xf, (l >> 28) & 0xf); 317 RUNTIME_CHECK(result < sizeof(buf)); 318 break; 319 case AF_INET6: 320 ap = tcpaddr->type.in6.s6_addr; 321 result = snprintf(buf, sizeof(buf), 322 "%x.%x.%x.%x.%x.%x.%x.%x." 323 "%x.%x.%x.%x.IP6.ARPA.", 324 ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, 325 ap[4] & 0x0f, (ap[4] >> 4) & 0x0f, 326 ap[3] & 0x0f, (ap[3] >> 4) & 0x0f, 327 ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, 328 ap[1] & 0x0f, (ap[1] >> 4) & 0x0f, 329 ap[0] & 0x0f, (ap[0] >> 4) & 0x0f); 330 RUNTIME_CHECK(result < sizeof(buf)); 331 break; 332 default: 333 INSIST(0); 334 ISC_UNREACHABLE(); 335 } 336 isc_buffer_init(&b, buf, strlen(buf)); 337 isc_buffer_add(&b, strlen(buf)); 338 result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL); 339 RUNTIME_CHECK(result == ISC_R_SUCCESS); 340} 341 342bool 343dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer, 344 const dns_name_t *name, const isc_netaddr_t *addr, 345 bool tcp, const dns_aclenv_t *env, 346 dns_rdatatype_t type, const dst_key_t *key) 347{ 348 dns_ssurule_t *rule; 349 unsigned int i; 350 dns_fixedname_t fixed; 351 dns_name_t *wildcard; 352 dns_name_t *tcpself; 353 dns_name_t *stfself; 354 isc_result_t result; 355 int match; 356 357 REQUIRE(VALID_SSUTABLE(table)); 358 REQUIRE(signer == NULL || dns_name_isabsolute(signer)); 359 REQUIRE(dns_name_isabsolute(name)); 360 REQUIRE(addr == NULL || env != NULL); 361 362 if (signer == NULL && addr == NULL) 363 return (false); 364 365 for (rule = ISC_LIST_HEAD(table->rules); 366 rule != NULL; 367 rule = ISC_LIST_NEXT(rule, link)) 368 { 369 switch (rule->matchtype) { 370 case dns_ssumatchtype_name: 371 case dns_ssumatchtype_local: 372 case dns_ssumatchtype_subdomain: 373 case dns_ssumatchtype_wildcard: 374 case dns_ssumatchtype_self: 375 case dns_ssumatchtype_selfsub: 376 case dns_ssumatchtype_selfwild: 377 if (signer == NULL) 378 continue; 379 if (dns_name_iswildcard(rule->identity)) { 380 if (!dns_name_matcheswildcard(signer, 381 rule->identity)) 382 continue; 383 } else { 384 if (!dns_name_equal(signer, rule->identity)) 385 continue; 386 } 387 break; 388 case dns_ssumatchtype_selfkrb5: 389 case dns_ssumatchtype_selfms: 390 case dns_ssumatchtype_selfsubkrb5: 391 case dns_ssumatchtype_selfsubms: 392 case dns_ssumatchtype_subdomainkrb5: 393 case dns_ssumatchtype_subdomainms: 394 if (signer == NULL) 395 continue; 396 break; 397 case dns_ssumatchtype_tcpself: 398 case dns_ssumatchtype_6to4self: 399 if (!tcp || addr == NULL) 400 continue; 401 break; 402 case dns_ssumatchtype_external: 403 case dns_ssumatchtype_dlz: 404 break; 405 } 406 407 switch (rule->matchtype) { 408 case dns_ssumatchtype_name: 409 if (!dns_name_equal(name, rule->name)) 410 continue; 411 break; 412 case dns_ssumatchtype_subdomain: 413 if (!dns_name_issubdomain(name, rule->name)) 414 continue; 415 break; 416 case dns_ssumatchtype_local: 417 if (addr == NULL) { 418 continue; 419 } 420 if (!dns_name_issubdomain(name, rule->name)) { 421 continue; 422 } 423 dns_acl_match(addr, NULL, env->localhost, 424 NULL, &match, NULL); 425 if (match == 0) { 426 if (signer != NULL) { 427 isc_log_write(dns_lctx, 428 DNS_LOGCATEGORY_GENERAL, 429 DNS_LOGMODULE_SSU, 430 ISC_LOG_WARNING, 431 "update-policy local: " 432 "match on session " 433 "key not from " 434 "localhost"); 435 } 436 continue; 437 } 438 break; 439 case dns_ssumatchtype_wildcard: 440 if (!dns_name_matcheswildcard(name, rule->name)) 441 continue; 442 break; 443 case dns_ssumatchtype_self: 444 if (!dns_name_equal(signer, name)) 445 continue; 446 break; 447 case dns_ssumatchtype_selfsub: 448 if (!dns_name_issubdomain(name, signer)) 449 continue; 450 break; 451 case dns_ssumatchtype_selfwild: 452 wildcard = dns_fixedname_initname(&fixed); 453 result = dns_name_concatenate(dns_wildcardname, signer, 454 wildcard, NULL); 455 if (result != ISC_R_SUCCESS) 456 continue; 457 if (!dns_name_matcheswildcard(name, wildcard)) 458 continue; 459 break; 460 case dns_ssumatchtype_selfkrb5: 461 if (dst_gssapi_identitymatchesrealmkrb5(signer, name, 462 rule->identity, 463 false)) 464 { 465 break; 466 } 467 continue; 468 case dns_ssumatchtype_selfms: 469 if (dst_gssapi_identitymatchesrealmms(signer, name, 470 rule->identity, 471 false)) 472 { 473 break; 474 } 475 continue; 476 case dns_ssumatchtype_selfsubkrb5: 477 if (dst_gssapi_identitymatchesrealmkrb5(signer, name, 478 rule->identity, 479 true)) 480 { 481 break; 482 } 483 continue; 484 case dns_ssumatchtype_selfsubms: 485 if (dst_gssapi_identitymatchesrealmms(signer, name, 486 rule->identity, 487 true)) 488 break; 489 continue; 490 case dns_ssumatchtype_subdomainkrb5: 491 if (!dns_name_issubdomain(name, rule->name)) 492 continue; 493 if (dst_gssapi_identitymatchesrealmkrb5(signer, NULL, 494 rule->identity, 495 false)) 496 { 497 break; 498 } 499 continue; 500 case dns_ssumatchtype_subdomainms: 501 if (!dns_name_issubdomain(name, rule->name)) 502 continue; 503 if (dst_gssapi_identitymatchesrealmms(signer, NULL, 504 rule->identity, 505 false)) 506 { 507 break; 508 } 509 continue; 510 case dns_ssumatchtype_tcpself: 511 tcpself = dns_fixedname_initname(&fixed); 512 reverse_from_address(tcpself, addr); 513 if (dns_name_iswildcard(rule->identity)) { 514 if (!dns_name_matcheswildcard(tcpself, 515 rule->identity)) 516 continue; 517 } else { 518 if (!dns_name_equal(tcpself, rule->identity)) 519 continue; 520 } 521 if (!dns_name_equal(tcpself, name)) 522 continue; 523 break; 524 case dns_ssumatchtype_6to4self: 525 stfself = dns_fixedname_initname(&fixed); 526 stf_from_address(stfself, addr); 527 if (dns_name_iswildcard(rule->identity)) { 528 if (!dns_name_matcheswildcard(stfself, 529 rule->identity)) 530 continue; 531 } else { 532 if (!dns_name_equal(stfself, rule->identity)) 533 continue; 534 } 535 if (!dns_name_equal(stfself, name)) 536 continue; 537 break; 538 case dns_ssumatchtype_external: 539 if (!dns_ssu_external_match(rule->identity, signer, 540 name, addr, type, key, 541 table->mctx)) 542 continue; 543 break; 544 case dns_ssumatchtype_dlz: 545 if (!dns_dlz_ssumatch(table->dlzdatabase, signer, 546 name, addr, type, key)) 547 continue; 548 break; 549 } 550 551 if (rule->ntypes == 0) { 552 /* 553 * If this is a DLZ rule, then the DLZ ssu 554 * checks will have already checked 555 * the type. 556 */ 557 if (rule->matchtype != dns_ssumatchtype_dlz && 558 !isusertype(type)) 559 continue; 560 } else { 561 for (i = 0; i < rule->ntypes; i++) { 562 if (rule->types[i] == dns_rdatatype_any || 563 rule->types[i] == type) 564 break; 565 } 566 if (i == rule->ntypes) 567 continue; 568 } 569 return (rule->grant); 570 } 571 572 return (false); 573} 574 575bool 576dns_ssurule_isgrant(const dns_ssurule_t *rule) { 577 REQUIRE(VALID_SSURULE(rule)); 578 return (rule->grant); 579} 580 581dns_name_t * 582dns_ssurule_identity(const dns_ssurule_t *rule) { 583 REQUIRE(VALID_SSURULE(rule)); 584 return (rule->identity); 585} 586 587unsigned int 588dns_ssurule_matchtype(const dns_ssurule_t *rule) { 589 REQUIRE(VALID_SSURULE(rule)); 590 return (rule->matchtype); 591} 592 593dns_name_t * 594dns_ssurule_name(const dns_ssurule_t *rule) { 595 REQUIRE(VALID_SSURULE(rule)); 596 return (rule->name); 597} 598 599unsigned int 600dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) { 601 REQUIRE(VALID_SSURULE(rule)); 602 REQUIRE(types != NULL && *types != NULL); 603 *types = rule->types; 604 return (rule->ntypes); 605} 606 607isc_result_t 608dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) { 609 REQUIRE(VALID_SSUTABLE(table)); 610 REQUIRE(rule != NULL && *rule == NULL); 611 *rule = ISC_LIST_HEAD(table->rules); 612 return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE); 613} 614 615isc_result_t 616dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) { 617 REQUIRE(VALID_SSURULE(rule)); 618 REQUIRE(nextrule != NULL && *nextrule == NULL); 619 *nextrule = ISC_LIST_NEXT(rule, link); 620 return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE); 621} 622 623/* 624 * Create a specialised SSU table that points at an external DLZ database 625 */ 626isc_result_t 627dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, 628 dns_dlzdb_t *dlzdatabase) 629{ 630 isc_result_t result; 631 dns_ssurule_t *rule; 632 dns_ssutable_t *table = NULL; 633 634 REQUIRE(tablep != NULL && *tablep == NULL); 635 636 result = dns_ssutable_create(mctx, &table); 637 if (result != ISC_R_SUCCESS) 638 return (result); 639 640 table->dlzdatabase = dlzdatabase; 641 642 rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t)); 643 if (rule == NULL) { 644 dns_ssutable_detach(&table); 645 return (ISC_R_NOMEMORY); 646 } 647 648 rule->identity = NULL; 649 rule->name = NULL; 650 rule->types = NULL; 651 rule->grant = true; 652 rule->matchtype = dns_ssumatchtype_dlz; 653 rule->ntypes = 0; 654 rule->types = NULL; 655 rule->magic = SSURULEMAGIC; 656 657 ISC_LIST_INITANDAPPEND(table->rules, rule, link); 658 *tablep = table; 659 return (ISC_R_SUCCESS); 660} 661 662isc_result_t 663dns_ssu_mtypefromstring(const char *str, dns_ssumatchtype_t *mtype) { 664 665 REQUIRE(str != NULL); 666 REQUIRE(mtype != NULL); 667 668 if (strcasecmp(str, "name") == 0) { 669 *mtype = dns_ssumatchtype_name; 670 } else if (strcasecmp(str, "subdomain") == 0) { 671 *mtype = dns_ssumatchtype_subdomain; 672 } else if (strcasecmp(str, "wildcard") == 0) { 673 *mtype = dns_ssumatchtype_wildcard; 674 } else if (strcasecmp(str, "self") == 0) { 675 *mtype = dns_ssumatchtype_self; 676 } else if (strcasecmp(str, "selfsub") == 0) { 677 *mtype = dns_ssumatchtype_selfsub; 678 } else if (strcasecmp(str, "selfwild") == 0) { 679 *mtype = dns_ssumatchtype_selfwild; 680 } else if (strcasecmp(str, "ms-self") == 0) { 681 *mtype = dns_ssumatchtype_selfms; 682 } else if (strcasecmp(str, "ms-selfsub") == 0) { 683 *mtype = dns_ssumatchtype_selfsubms; 684 } else if (strcasecmp(str, "krb5-self") == 0) { 685 *mtype = dns_ssumatchtype_selfkrb5; 686 } else if (strcasecmp(str, "krb5-selfsub") == 0) { 687 *mtype = dns_ssumatchtype_selfsubkrb5; 688 } else if (strcasecmp(str, "ms-subdomain") == 0) { 689 *mtype = dns_ssumatchtype_subdomainms; 690 } else if (strcasecmp(str, "krb5-subdomain") == 0) { 691 *mtype = dns_ssumatchtype_subdomainkrb5; 692 } else if (strcasecmp(str, "tcp-self") == 0) { 693 *mtype = dns_ssumatchtype_tcpself; 694 } else if (strcasecmp(str, "6to4-self") == 0) { 695 *mtype = dns_ssumatchtype_6to4self; 696 } else if (strcasecmp(str, "zonesub") == 0) { 697 *mtype = dns_ssumatchtype_subdomain; 698 } else if (strcasecmp(str, "external") == 0) { 699 *mtype = dns_ssumatchtype_external; 700 } else { 701 return (ISC_R_NOTFOUND); 702 } 703 return (ISC_R_SUCCESS); 704} 705