1 /* 2 * daemon/acl_list.h - client access control storage for the server. 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /** 37 * \file 38 * 39 * This file helps the server keep out queries from outside sources, that 40 * should not be answered. 41 */ 42 #include "config.h" 43 #include "daemon/acl_list.h" 44 #include "util/regional.h" 45 #include "util/log.h" 46 #include "util/config_file.h" 47 #include "util/net_help.h" 48 #include "services/localzone.h" 49 #include "services/listen_dnsport.h" 50 #include "sldns/str2wire.h" 51 52 struct acl_list* 53 acl_list_create(void) 54 { 55 struct acl_list* acl = (struct acl_list*)calloc(1, 56 sizeof(struct acl_list)); 57 if(!acl) 58 return NULL; 59 acl->region = regional_create(); 60 if(!acl->region) { 61 acl_list_delete(acl); 62 return NULL; 63 } 64 return acl; 65 } 66 67 void 68 acl_list_delete(struct acl_list* acl) 69 { 70 if(!acl) 71 return; 72 regional_destroy(acl->region); 73 free(acl); 74 } 75 76 /** insert new address into acl_list structure */ 77 static struct acl_addr* 78 acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr, 79 socklen_t addrlen, int net, enum acl_access control, 80 int complain_duplicates) 81 { 82 struct acl_addr* node = regional_alloc_zero(acl->region, 83 sizeof(struct acl_addr)); 84 if(!node) 85 return NULL; 86 node->control = control; 87 if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) { 88 if(complain_duplicates) 89 verbose(VERB_QUERY, "duplicate acl address ignored."); 90 } 91 return node; 92 } 93 94 /** parse str to acl_access enum */ 95 static int 96 parse_acl_access(const char* str, enum acl_access* control) 97 { 98 if(strcmp(str, "allow") == 0) 99 *control = acl_allow; 100 else if(strcmp(str, "deny") == 0) 101 *control = acl_deny; 102 else if(strcmp(str, "refuse") == 0) 103 *control = acl_refuse; 104 else if(strcmp(str, "deny_non_local") == 0) 105 *control = acl_deny_non_local; 106 else if(strcmp(str, "refuse_non_local") == 0) 107 *control = acl_refuse_non_local; 108 else if(strcmp(str, "allow_snoop") == 0) 109 *control = acl_allow_snoop; 110 else if(strcmp(str, "allow_setrd") == 0) 111 *control = acl_allow_setrd; 112 else { 113 log_err("access control type %s unknown", str); 114 return 0; 115 } 116 return 1; 117 } 118 119 /** apply acl_list string */ 120 static int 121 acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2, 122 int complain_duplicates) 123 { 124 struct sockaddr_storage addr; 125 int net; 126 socklen_t addrlen; 127 enum acl_access control; 128 if(!parse_acl_access(s2, &control)) { 129 return 0; 130 } 131 if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { 132 log_err("cannot parse access control: %s %s", str, s2); 133 return 0; 134 } 135 if(!acl_list_insert(acl, &addr, addrlen, net, control, 136 complain_duplicates)) { 137 log_err("out of memory"); 138 return 0; 139 } 140 return 1; 141 } 142 143 /** find or create node (NULL on parse or error) */ 144 static struct acl_addr* 145 acl_find_or_create_str2addr(struct acl_list* acl, const char* str, 146 int is_interface, int port) 147 { 148 struct acl_addr* node; 149 struct sockaddr_storage addr; 150 socklen_t addrlen; 151 int net = (str_is_ip6(str)?128:32); 152 if(is_interface) { 153 if(!extstrtoaddr(str, &addr, &addrlen, port)) { 154 log_err("cannot parse interface: %s", str); 155 return NULL; 156 } 157 } else { 158 if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { 159 log_err("cannot parse netblock: %s", str); 160 return NULL; 161 } 162 } 163 /* find or create node */ 164 if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr, 165 addrlen, net)) && !is_interface) { 166 /* create node, type 'allow' since otherwise tags are 167 * pointless, can override with specific access-control: cfg */ 168 if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr, 169 addrlen, net, acl_allow, 1))) { 170 log_err("out of memory"); 171 return NULL; 172 } 173 } 174 return node; 175 } 176 177 /** find or create node (NULL on error) */ 178 static struct acl_addr* 179 acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr, 180 socklen_t addrlen, enum acl_access control) 181 { 182 struct acl_addr* node; 183 int net = (addr_is_ip6(addr, addrlen)?128:32); 184 /* find or create node */ 185 if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr, 186 addrlen, net))) { 187 /* create node; 188 * can override with specific access-control: cfg */ 189 if(!(node=(struct acl_addr*)acl_list_insert(acl, addr, 190 addrlen, net, control, 1))) { 191 log_err("out of memory"); 192 return NULL; 193 } 194 } 195 return node; 196 } 197 198 /** apply acl_interface string */ 199 static int 200 acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface, 201 const char* s2, int port) 202 { 203 struct acl_addr* node; 204 enum acl_access control; 205 if(!parse_acl_access(s2, &control)) { 206 return 0; 207 } 208 if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) { 209 log_err("cannot update ACL on non-configured interface: %s %d", 210 iface, port); 211 return 0; 212 } 213 node->control = control; 214 return 1; 215 } 216 217 struct acl_addr* 218 acl_interface_insert(struct acl_list* acl_interface, 219 struct sockaddr_storage* addr, socklen_t addrlen, 220 enum acl_access control) 221 { 222 return acl_find_or_create(acl_interface, addr, addrlen, control); 223 } 224 225 /** apply acl_tag string */ 226 static int 227 acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap, 228 size_t bitmaplen, int is_interface, int port) 229 { 230 struct acl_addr* node; 231 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 232 if(is_interface) 233 log_err("non-configured interface: %s", str); 234 return 0; 235 } 236 node->taglen = bitmaplen; 237 node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen); 238 if(!node->taglist) { 239 log_err("out of memory"); 240 return 0; 241 } 242 return 1; 243 } 244 245 /** apply acl_view string */ 246 static int 247 acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2, 248 struct views* vs, int is_interface, int port) 249 { 250 struct acl_addr* node; 251 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 252 if(is_interface) 253 log_err("non-configured interface: %s", str); 254 return 0; 255 } 256 node->view = views_find_view(vs, str2, 0 /* get read lock*/); 257 if(!node->view) { 258 log_err("no view with name: %s", str2); 259 return 0; 260 } 261 lock_rw_unlock(&node->view->lock); 262 return 1; 263 } 264 265 /** apply acl_tag_action string */ 266 static int 267 acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg, 268 const char* str, const char* tag, const char* action, 269 int is_interface, int port) 270 { 271 struct acl_addr* node; 272 int tagid; 273 enum localzone_type t; 274 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 275 if(is_interface) 276 log_err("non-configured interface: %s", str); 277 return 0; 278 } 279 /* allocate array if not yet */ 280 if(!node->tag_actions) { 281 node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region, 282 sizeof(*node->tag_actions)*cfg->num_tags); 283 if(!node->tag_actions) { 284 log_err("out of memory"); 285 return 0; 286 } 287 node->tag_actions_size = (size_t)cfg->num_tags; 288 } 289 /* parse tag */ 290 if((tagid=find_tag_id(cfg, tag)) == -1) { 291 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 292 return 0; 293 } 294 if((size_t)tagid >= node->tag_actions_size) { 295 log_err("tagid too large for array %s %s", str, tag); 296 return 0; 297 } 298 if(!local_zone_str2type(action, &t)) { 299 log_err("cannot parse access control action type: %s %s %s", 300 str, tag, action); 301 return 0; 302 } 303 node->tag_actions[tagid] = (uint8_t)t; 304 return 1; 305 } 306 307 /** check wire data parse */ 308 static int 309 check_data(const char* data, const struct config_strlist* head) 310 { 311 char buf[65536]; 312 uint8_t rr[LDNS_RR_BUF_SIZE]; 313 size_t len = sizeof(rr); 314 int res; 315 /* '.' is sufficient for validation, and it makes the call to 316 * sldns_wirerr_get_type() simpler below. */ 317 snprintf(buf, sizeof(buf), "%s %s", ".", data); 318 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0, 319 NULL, 0); 320 321 /* Reject it if we would end up having CNAME and other data (including 322 * another CNAME) for the same tag. */ 323 if(res == 0 && head) { 324 const char* err_data = NULL; 325 326 if(sldns_wirerr_get_type(rr, len, 1) == LDNS_RR_TYPE_CNAME) { 327 /* adding CNAME while other data already exists. */ 328 err_data = data; 329 } else { 330 snprintf(buf, sizeof(buf), "%s %s", ".", head->str); 331 len = sizeof(rr); 332 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, 333 NULL, 0, NULL, 0); 334 if(res != 0) { 335 /* This should be impossible here as head->str 336 * has been validated, but we check it just in 337 * case. */ 338 return 0; 339 } 340 if(sldns_wirerr_get_type(rr, len, 1) == 341 LDNS_RR_TYPE_CNAME) /* already have CNAME */ 342 err_data = head->str; 343 } 344 if(err_data) { 345 log_err("redirect tag data '%s' must not coexist with " 346 "other data.", err_data); 347 return 0; 348 } 349 } 350 if(res == 0) 351 return 1; 352 log_err("rr data [char %d] parse error %s", 353 (int)LDNS_WIREPARSE_OFFSET(res)-2, 354 sldns_get_errorstr_parse(res)); 355 return 0; 356 } 357 358 /** apply acl_tag_data string */ 359 static int 360 acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg, 361 const char* str, const char* tag, const char* data, 362 int is_interface, int port) 363 { 364 struct acl_addr* node; 365 int tagid; 366 char* dupdata; 367 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 368 if(is_interface) 369 log_err("non-configured interface: %s", str); 370 return 0; 371 } 372 /* allocate array if not yet */ 373 if(!node->tag_datas) { 374 node->tag_datas = (struct config_strlist**)regional_alloc_zero( 375 acl->region, sizeof(*node->tag_datas)*cfg->num_tags); 376 if(!node->tag_datas) { 377 log_err("out of memory"); 378 return 0; 379 } 380 node->tag_datas_size = (size_t)cfg->num_tags; 381 } 382 /* parse tag */ 383 if((tagid=find_tag_id(cfg, tag)) == -1) { 384 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 385 return 0; 386 } 387 if((size_t)tagid >= node->tag_datas_size) { 388 log_err("tagid too large for array %s %s", str, tag); 389 return 0; 390 } 391 392 /* check data? */ 393 if(!check_data(data, node->tag_datas[tagid])) { 394 log_err("cannot parse access-control-tag data: %s %s '%s'", 395 str, tag, data); 396 return 0; 397 } 398 399 dupdata = regional_strdup(acl->region, data); 400 if(!dupdata) { 401 log_err("out of memory"); 402 return 0; 403 } 404 if(!cfg_region_strlist_insert(acl->region, 405 &(node->tag_datas[tagid]), dupdata)) { 406 log_err("out of memory"); 407 return 0; 408 } 409 return 1; 410 } 411 412 /** read acl_list config */ 413 static int 414 read_acl_list(struct acl_list* acl, struct config_str2list* acls) 415 { 416 struct config_str2list* p; 417 for(p = acls; p; p = p->next) { 418 log_assert(p->str && p->str2); 419 if(!acl_list_str_cfg(acl, p->str, p->str2, 1)) 420 return 0; 421 } 422 return 1; 423 } 424 425 /** read acl view config */ 426 static int 427 read_acl_view(struct acl_list* acl, struct config_str2list** acl_view, 428 struct views* v) 429 { 430 struct config_str2list* np, *p = *acl_view; 431 *acl_view = NULL; 432 while(p) { 433 log_assert(p->str && p->str2); 434 if(!acl_list_view_cfg(acl, p->str, p->str2, v, 0, 0)) { 435 config_deldblstrlist(p); 436 return 0; 437 } 438 /* free the items as we go to free up memory */ 439 np = p->next; 440 free(p->str); 441 free(p->str2); 442 free(p); 443 p = np; 444 } 445 return 1; 446 } 447 448 /** read acl tags config */ 449 static int 450 read_acl_tags(struct acl_list* acl, struct config_strbytelist** acl_tags) 451 { 452 struct config_strbytelist* np, *p = *acl_tags; 453 *acl_tags = NULL; 454 while(p) { 455 log_assert(p->str && p->str2); 456 if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len, 0, 0)) { 457 config_del_strbytelist(p); 458 return 0; 459 } 460 /* free the items as we go to free up memory */ 461 np = p->next; 462 free(p->str); 463 free(p->str2); 464 free(p); 465 p = np; 466 } 467 return 1; 468 } 469 470 /** read acl tag actions config */ 471 static int 472 read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg, 473 struct config_str3list** acl_tag_actions) 474 { 475 struct config_str3list* p, *np; 476 p = *acl_tag_actions; 477 *acl_tag_actions = NULL; 478 while(p) { 479 log_assert(p->str && p->str2 && p->str3); 480 if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2, 481 p->str3, 0, 0)) { 482 config_deltrplstrlist(p); 483 return 0; 484 } 485 /* free the items as we go to free up memory */ 486 np = p->next; 487 free(p->str); 488 free(p->str2); 489 free(p->str3); 490 free(p); 491 p = np; 492 } 493 return 1; 494 } 495 496 /** read acl tag datas config */ 497 static int 498 read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg, 499 struct config_str3list** acl_tag_datas) 500 { 501 struct config_str3list* p, *np; 502 p = *acl_tag_datas; 503 *acl_tag_datas = NULL; 504 while(p) { 505 log_assert(p->str && p->str2 && p->str3); 506 if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3, 507 0, 0)) { 508 config_deltrplstrlist(p); 509 return 0; 510 } 511 /* free the items as we go to free up memory */ 512 np = p->next; 513 free(p->str); 514 free(p->str2); 515 free(p->str3); 516 free(p); 517 p = np; 518 } 519 return 1; 520 } 521 522 int 523 acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, 524 struct views* v) 525 { 526 regional_free_all(acl->region); 527 addr_tree_init(&acl->tree); 528 if(!read_acl_list(acl, cfg->acls)) 529 return 0; 530 if(!read_acl_view(acl, &cfg->acl_view, v)) 531 return 0; 532 if(!read_acl_tags(acl, &cfg->acl_tags)) 533 return 0; 534 if(!read_acl_tag_actions(acl, cfg, &cfg->acl_tag_actions)) 535 return 0; 536 if(!read_acl_tag_datas(acl, cfg, &cfg->acl_tag_datas)) 537 return 0; 538 /* insert defaults, with '0' to ignore them if they are duplicates */ 539 /* the 'refuse' defaults for /0 are now done per interface instead */ 540 if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) 541 return 0; 542 if(cfg->do_ip6) { 543 if(!acl_list_str_cfg(acl, "::1", "allow", 0)) 544 return 0; 545 if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) 546 return 0; 547 } 548 addr_tree_init_parents(&acl->tree); 549 return 1; 550 } 551 552 int 553 acl_interface_compare(const void* k1, const void* k2) 554 { 555 struct addr_tree_node* n1 = (struct addr_tree_node*)k1; 556 struct addr_tree_node* n2 = (struct addr_tree_node*)k2; 557 return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, 558 n2->addrlen); 559 /* We don't care about comparing node->net. All addresses in the 560 * acl_interface tree have either 32 (ipv4) or 128 (ipv6). */ 561 } 562 563 void 564 acl_interface_init(struct acl_list* acl_interface) 565 { 566 regional_free_all(acl_interface->region); 567 /* We want comparison in the tree to include only address and port. 568 * We don't care about comparing node->net. All addresses in the 569 * acl_interface->tree should have either 32 (ipv4) or 128 (ipv6). 570 * Initialise with the appropriate compare function but keep treating 571 * it as an addr_tree. */ 572 addr_tree_addrport_init(&acl_interface->tree); 573 } 574 575 static int 576 read_acl_interface_action(struct acl_list* acl_interface, 577 struct config_str2list* acls, int port) 578 { 579 struct config_str2list* p; 580 for(p = acls; p; p = p->next) { 581 char** resif = NULL; 582 int num_resif = 0; 583 int i; 584 log_assert(p->str && p->str2); 585 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) 586 return 0; 587 for(i = 0; i<num_resif; i++) { 588 if(!acl_interface_str_cfg(acl_interface, resif[i], p->str2, port)){ 589 config_del_strarray(resif, num_resif); 590 return 0; 591 } 592 } 593 config_del_strarray(resif, num_resif); 594 } 595 return 1; 596 } 597 598 /** read acl view config for interface */ 599 static int 600 read_acl_interface_view(struct acl_list* acl_interface, 601 struct config_str2list** acl_view, 602 struct views* v, int port) 603 { 604 struct config_str2list* np, *p = *acl_view; 605 *acl_view = NULL; 606 while(p) { 607 char** resif = NULL; 608 int num_resif = 0; 609 int i; 610 log_assert(p->str && p->str2); 611 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 612 config_deldblstrlist(p); 613 return 0; 614 } 615 for(i = 0; i<num_resif; i++) { 616 if(!acl_list_view_cfg(acl_interface, resif[i], p->str2, 617 v, 1, port)) { 618 config_del_strarray(resif, num_resif); 619 config_deldblstrlist(p); 620 return 0; 621 } 622 } 623 config_del_strarray(resif, num_resif); 624 /* free the items as we go to free up memory */ 625 np = p->next; 626 free(p->str); 627 free(p->str2); 628 free(p); 629 p = np; 630 } 631 return 1; 632 } 633 634 /** read acl tags config for interface */ 635 static int 636 read_acl_interface_tags(struct acl_list* acl_interface, 637 struct config_strbytelist** acl_tags, int port) 638 { 639 struct config_strbytelist* np, *p = *acl_tags; 640 *acl_tags = NULL; 641 while(p) { 642 char** resif = NULL; 643 int num_resif = 0; 644 int i; 645 log_assert(p->str && p->str2); 646 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 647 config_del_strbytelist(p); 648 return 0; 649 } 650 for(i = 0; i<num_resif; i++) { 651 if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2, 652 p->str2len, 1, port)) { 653 config_del_strbytelist(p); 654 config_del_strarray(resif, num_resif); 655 return 0; 656 } 657 } 658 config_del_strarray(resif, num_resif); 659 /* free the items as we go to free up memory */ 660 np = p->next; 661 free(p->str); 662 free(p->str2); 663 free(p); 664 p = np; 665 } 666 return 1; 667 } 668 669 /** read acl tag actions config for interface*/ 670 static int 671 read_acl_interface_tag_actions(struct acl_list* acl_interface, 672 struct config_file* cfg, 673 struct config_str3list** acl_tag_actions, int port) 674 { 675 struct config_str3list* p, *np; 676 p = *acl_tag_actions; 677 *acl_tag_actions = NULL; 678 while(p) { 679 char** resif = NULL; 680 int num_resif = 0; 681 int i; 682 log_assert(p->str && p->str2 && p->str3); 683 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 684 config_deltrplstrlist(p); 685 return 0; 686 } 687 for(i = 0; i<num_resif; i++) { 688 if(!acl_list_tag_action_cfg(acl_interface, cfg, 689 resif[i], p->str2, p->str3, 1, port)) { 690 config_deltrplstrlist(p); 691 config_del_strarray(resif, num_resif); 692 return 0; 693 } 694 } 695 config_del_strarray(resif, num_resif); 696 /* free the items as we go to free up memory */ 697 np = p->next; 698 free(p->str); 699 free(p->str2); 700 free(p->str3); 701 free(p); 702 p = np; 703 } 704 return 1; 705 } 706 707 /** read acl tag datas config for interface */ 708 static int 709 read_acl_interface_tag_datas(struct acl_list* acl_interface, 710 struct config_file* cfg, 711 struct config_str3list** acl_tag_datas, int port) 712 { 713 struct config_str3list* p, *np; 714 p = *acl_tag_datas; 715 *acl_tag_datas = NULL; 716 while(p) { 717 char** resif = NULL; 718 int num_resif = 0; 719 int i; 720 log_assert(p->str && p->str2 && p->str3); 721 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 722 config_deltrplstrlist(p); 723 return 0; 724 } 725 for(i = 0; i<num_resif; i++) { 726 if(!acl_list_tag_data_cfg(acl_interface, cfg, 727 resif[i], p->str2, p->str3, 1, port)) { 728 config_deltrplstrlist(p); 729 config_del_strarray(resif, num_resif); 730 return 0; 731 } 732 } 733 config_del_strarray(resif, num_resif); 734 /* free the items as we go to free up memory */ 735 np = p->next; 736 free(p->str); 737 free(p->str2); 738 free(p->str3); 739 free(p); 740 p = np; 741 } 742 return 1; 743 } 744 745 int 746 acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg, 747 struct views* v) 748 { 749 if(!read_acl_interface_action(acl_interface, cfg->interface_actions, 750 cfg->port)) 751 return 0; 752 if(!read_acl_interface_view(acl_interface, &cfg->interface_view, v, 753 cfg->port)) 754 return 0; 755 if(!read_acl_interface_tags(acl_interface, &cfg->interface_tags, 756 cfg->port)) 757 return 0; 758 if(!read_acl_interface_tag_actions(acl_interface, cfg, 759 &cfg->interface_tag_actions, cfg->port)) 760 return 0; 761 if(!read_acl_interface_tag_datas(acl_interface, cfg, 762 &cfg->interface_tag_datas, cfg->port)) 763 return 0; 764 addr_tree_init_parents(&acl_interface->tree); 765 return 1; 766 } 767 768 enum acl_access 769 acl_get_control(struct acl_addr* acl) 770 { 771 if(acl) return acl->control; 772 return acl_deny; 773 } 774 775 struct acl_addr* 776 acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr, 777 socklen_t addrlen) 778 { 779 return (struct acl_addr*)addr_tree_lookup(&acl->tree, 780 addr, addrlen); 781 } 782 783 size_t 784 acl_list_get_mem(struct acl_list* acl) 785 { 786 if(!acl) return 0; 787 return sizeof(*acl) + regional_get_mem(acl->region); 788 } 789 790 const char* acl_access_to_str(enum acl_access acl) 791 { 792 switch(acl) { 793 case acl_deny: return "deny"; 794 case acl_refuse: return "refuse"; 795 case acl_deny_non_local: return "deny_non_local"; 796 case acl_refuse_non_local: return "refuse_non_local"; 797 case acl_allow: return "allow"; 798 case acl_allow_snoop: return "allow_snoop"; 799 case acl_allow_setrd: return "allow_setrd"; 800 default: break; 801 } 802 return "unknown"; 803 } 804 805 void 806 log_acl_action(const char* action, struct sockaddr_storage* addr, 807 socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr) 808 { 809 char a[128], n[128]; 810 uint16_t port; 811 addr_to_str(addr, addrlen, a, sizeof(a)); 812 port = ntohs(((struct sockaddr_in*)addr)->sin_port); 813 if(acladdr) { 814 addr_to_str(&acladdr->node.addr, acladdr->node.addrlen, 815 n, sizeof(n)); 816 verbose(VERB_ALGO, "%s query from %s port %d because of " 817 "%s/%d %s", action, a, (int)port, n, acladdr->node.net, 818 acl_access_to_str(acl)); 819 } else { 820 verbose(VERB_ALGO, "%s query from %s port %d", action, a, 821 (int)port); 822 } 823 } 824