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 if (strcmp(str, "allow_cookie") == 0) 113 *control = acl_allow_cookie; 114 else { 115 log_err("access control type %s unknown", str); 116 return 0; 117 } 118 return 1; 119 } 120 121 /** apply acl_list string */ 122 static int 123 acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2, 124 int complain_duplicates) 125 { 126 struct sockaddr_storage addr; 127 int net; 128 socklen_t addrlen; 129 enum acl_access control; 130 if(!parse_acl_access(s2, &control)) { 131 return 0; 132 } 133 if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { 134 log_err("cannot parse access control: %s %s", str, s2); 135 return 0; 136 } 137 if(!acl_list_insert(acl, &addr, addrlen, net, control, 138 complain_duplicates)) { 139 log_err("out of memory"); 140 return 0; 141 } 142 return 1; 143 } 144 145 /** find or create node (NULL on parse or error) */ 146 static struct acl_addr* 147 acl_find_or_create_str2addr(struct acl_list* acl, const char* str, 148 int is_interface, int port) 149 { 150 struct acl_addr* node; 151 struct sockaddr_storage addr; 152 socklen_t addrlen; 153 int net = (str_is_ip6(str)?128:32); 154 if(is_interface) { 155 if(!extstrtoaddr(str, &addr, &addrlen, port)) { 156 log_err("cannot parse interface: %s", str); 157 return NULL; 158 } 159 } else { 160 if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { 161 log_err("cannot parse netblock: %s", str); 162 return NULL; 163 } 164 } 165 /* find or create node */ 166 if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr, 167 addrlen, net)) && !is_interface) { 168 /* create node, type 'allow' since otherwise tags are 169 * pointless, can override with specific access-control: cfg */ 170 if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr, 171 addrlen, net, acl_allow, 1))) { 172 log_err("out of memory"); 173 return NULL; 174 } 175 } 176 return node; 177 } 178 179 /** find or create node (NULL on error) */ 180 static struct acl_addr* 181 acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr, 182 socklen_t addrlen, enum acl_access control) 183 { 184 struct acl_addr* node; 185 int net = (addr_is_ip6(addr, addrlen)?128:32); 186 /* find or create node */ 187 if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr, 188 addrlen, net))) { 189 /* create node; 190 * can override with specific access-control: cfg */ 191 if(!(node=(struct acl_addr*)acl_list_insert(acl, addr, 192 addrlen, net, control, 1))) { 193 log_err("out of memory"); 194 return NULL; 195 } 196 } 197 return node; 198 } 199 200 /** apply acl_interface string */ 201 static int 202 acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface, 203 const char* s2, int port) 204 { 205 struct acl_addr* node; 206 enum acl_access control; 207 if(!parse_acl_access(s2, &control)) { 208 return 0; 209 } 210 if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) { 211 log_err("cannot update ACL on non-configured interface: %s %d", 212 iface, port); 213 return 0; 214 } 215 node->control = control; 216 return 1; 217 } 218 219 struct acl_addr* 220 acl_interface_insert(struct acl_list* acl_interface, 221 struct sockaddr_storage* addr, socklen_t addrlen, 222 enum acl_access control) 223 { 224 return acl_find_or_create(acl_interface, addr, addrlen, control); 225 } 226 227 /** apply acl_tag string */ 228 static int 229 acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap, 230 size_t bitmaplen, int is_interface, int port) 231 { 232 struct acl_addr* node; 233 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 234 if(is_interface) 235 log_err("non-configured interface: %s", str); 236 return 0; 237 } 238 node->taglen = bitmaplen; 239 node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen); 240 if(!node->taglist) { 241 log_err("out of memory"); 242 return 0; 243 } 244 return 1; 245 } 246 247 /** apply acl_view string */ 248 static int 249 acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2, 250 struct views* vs, int is_interface, int port) 251 { 252 struct acl_addr* node; 253 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 254 if(is_interface) 255 log_err("non-configured interface: %s", str); 256 return 0; 257 } 258 node->view = views_find_view(vs, str2, 0 /* get read lock*/); 259 if(!node->view) { 260 log_err("no view with name: %s", str2); 261 return 0; 262 } 263 lock_rw_unlock(&node->view->lock); 264 return 1; 265 } 266 267 /** apply acl_tag_action string */ 268 static int 269 acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg, 270 const char* str, const char* tag, const char* action, 271 int is_interface, int port) 272 { 273 struct acl_addr* node; 274 int tagid; 275 enum localzone_type t; 276 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 277 if(is_interface) 278 log_err("non-configured interface: %s", str); 279 return 0; 280 } 281 /* allocate array if not yet */ 282 if(!node->tag_actions) { 283 node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region, 284 sizeof(*node->tag_actions)*cfg->num_tags); 285 if(!node->tag_actions) { 286 log_err("out of memory"); 287 return 0; 288 } 289 node->tag_actions_size = (size_t)cfg->num_tags; 290 } 291 /* parse tag */ 292 if((tagid=find_tag_id(cfg, tag)) == -1) { 293 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 294 return 0; 295 } 296 if((size_t)tagid >= node->tag_actions_size) { 297 log_err("tagid too large for array %s %s", str, tag); 298 return 0; 299 } 300 if(!local_zone_str2type(action, &t)) { 301 log_err("cannot parse access control action type: %s %s %s", 302 str, tag, action); 303 return 0; 304 } 305 node->tag_actions[tagid] = (uint8_t)t; 306 return 1; 307 } 308 309 /** check wire data parse */ 310 static int 311 check_data(const char* data, const struct config_strlist* head) 312 { 313 char buf[65536]; 314 uint8_t rr[LDNS_RR_BUF_SIZE]; 315 size_t len = sizeof(rr); 316 int res; 317 /* '.' is sufficient for validation, and it makes the call to 318 * sldns_wirerr_get_type() simpler below. */ 319 snprintf(buf, sizeof(buf), "%s %s", ".", data); 320 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0, 321 NULL, 0); 322 323 /* Reject it if we would end up having CNAME and other data (including 324 * another CNAME) for the same tag. */ 325 if(res == 0 && head) { 326 const char* err_data = NULL; 327 328 if(sldns_wirerr_get_type(rr, len, 1) == LDNS_RR_TYPE_CNAME) { 329 /* adding CNAME while other data already exists. */ 330 err_data = data; 331 } else { 332 snprintf(buf, sizeof(buf), "%s %s", ".", head->str); 333 len = sizeof(rr); 334 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, 335 NULL, 0, NULL, 0); 336 if(res != 0) { 337 /* This should be impossible here as head->str 338 * has been validated, but we check it just in 339 * case. */ 340 return 0; 341 } 342 if(sldns_wirerr_get_type(rr, len, 1) == 343 LDNS_RR_TYPE_CNAME) /* already have CNAME */ 344 err_data = head->str; 345 } 346 if(err_data) { 347 log_err("redirect tag data '%s' must not coexist with " 348 "other data.", err_data); 349 return 0; 350 } 351 } 352 if(res == 0) 353 return 1; 354 log_err("rr data [char %d] parse error %s", 355 (int)LDNS_WIREPARSE_OFFSET(res)-2, 356 sldns_get_errorstr_parse(res)); 357 return 0; 358 } 359 360 /** apply acl_tag_data string */ 361 static int 362 acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg, 363 const char* str, const char* tag, const char* data, 364 int is_interface, int port) 365 { 366 struct acl_addr* node; 367 int tagid; 368 char* dupdata; 369 if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) { 370 if(is_interface) 371 log_err("non-configured interface: %s", str); 372 return 0; 373 } 374 /* allocate array if not yet */ 375 if(!node->tag_datas) { 376 node->tag_datas = (struct config_strlist**)regional_alloc_zero( 377 acl->region, sizeof(*node->tag_datas)*cfg->num_tags); 378 if(!node->tag_datas) { 379 log_err("out of memory"); 380 return 0; 381 } 382 node->tag_datas_size = (size_t)cfg->num_tags; 383 } 384 /* parse tag */ 385 if((tagid=find_tag_id(cfg, tag)) == -1) { 386 log_err("cannot parse tag (define-tag it): %s %s", str, tag); 387 return 0; 388 } 389 if((size_t)tagid >= node->tag_datas_size) { 390 log_err("tagid too large for array %s %s", str, tag); 391 return 0; 392 } 393 394 /* check data? */ 395 if(!check_data(data, node->tag_datas[tagid])) { 396 log_err("cannot parse access-control-tag data: %s %s '%s'", 397 str, tag, data); 398 return 0; 399 } 400 401 dupdata = regional_strdup(acl->region, data); 402 if(!dupdata) { 403 log_err("out of memory"); 404 return 0; 405 } 406 if(!cfg_region_strlist_insert(acl->region, 407 &(node->tag_datas[tagid]), dupdata)) { 408 log_err("out of memory"); 409 return 0; 410 } 411 return 1; 412 } 413 414 /** read acl_list config */ 415 static int 416 read_acl_list(struct acl_list* acl, struct config_str2list* acls) 417 { 418 struct config_str2list* p; 419 for(p = acls; p; p = p->next) { 420 log_assert(p->str && p->str2); 421 if(!acl_list_str_cfg(acl, p->str, p->str2, 1)) 422 return 0; 423 } 424 return 1; 425 } 426 427 /** read acl view config */ 428 static int 429 read_acl_view(struct acl_list* acl, struct config_str2list** acl_view, 430 struct views* v) 431 { 432 struct config_str2list* np, *p = *acl_view; 433 *acl_view = NULL; 434 while(p) { 435 log_assert(p->str && p->str2); 436 if(!acl_list_view_cfg(acl, p->str, p->str2, v, 0, 0)) { 437 config_deldblstrlist(p); 438 return 0; 439 } 440 /* free the items as we go to free up memory */ 441 np = p->next; 442 free(p->str); 443 free(p->str2); 444 free(p); 445 p = np; 446 } 447 return 1; 448 } 449 450 /** read acl tags config */ 451 static int 452 read_acl_tags(struct acl_list* acl, struct config_strbytelist** acl_tags) 453 { 454 struct config_strbytelist* np, *p = *acl_tags; 455 *acl_tags = NULL; 456 while(p) { 457 log_assert(p->str && p->str2); 458 if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len, 0, 0)) { 459 config_del_strbytelist(p); 460 return 0; 461 } 462 /* free the items as we go to free up memory */ 463 np = p->next; 464 free(p->str); 465 free(p->str2); 466 free(p); 467 p = np; 468 } 469 return 1; 470 } 471 472 /** read acl tag actions config */ 473 static int 474 read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg, 475 struct config_str3list** acl_tag_actions) 476 { 477 struct config_str3list* p, *np; 478 p = *acl_tag_actions; 479 *acl_tag_actions = NULL; 480 while(p) { 481 log_assert(p->str && p->str2 && p->str3); 482 if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2, 483 p->str3, 0, 0)) { 484 config_deltrplstrlist(p); 485 return 0; 486 } 487 /* free the items as we go to free up memory */ 488 np = p->next; 489 free(p->str); 490 free(p->str2); 491 free(p->str3); 492 free(p); 493 p = np; 494 } 495 return 1; 496 } 497 498 /** read acl tag datas config */ 499 static int 500 read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg, 501 struct config_str3list** acl_tag_datas) 502 { 503 struct config_str3list* p, *np; 504 p = *acl_tag_datas; 505 *acl_tag_datas = NULL; 506 while(p) { 507 log_assert(p->str && p->str2 && p->str3); 508 if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3, 509 0, 0)) { 510 config_deltrplstrlist(p); 511 return 0; 512 } 513 /* free the items as we go to free up memory */ 514 np = p->next; 515 free(p->str); 516 free(p->str2); 517 free(p->str3); 518 free(p); 519 p = np; 520 } 521 return 1; 522 } 523 524 int 525 acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg, 526 struct views* v) 527 { 528 regional_free_all(acl->region); 529 addr_tree_init(&acl->tree); 530 if(!read_acl_list(acl, cfg->acls)) 531 return 0; 532 if(!read_acl_view(acl, &cfg->acl_view, v)) 533 return 0; 534 if(!read_acl_tags(acl, &cfg->acl_tags)) 535 return 0; 536 if(!read_acl_tag_actions(acl, cfg, &cfg->acl_tag_actions)) 537 return 0; 538 if(!read_acl_tag_datas(acl, cfg, &cfg->acl_tag_datas)) 539 return 0; 540 /* insert defaults, with '0' to ignore them if they are duplicates */ 541 /* the 'refuse' defaults for /0 are now done per interface instead */ 542 if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) 543 return 0; 544 if(cfg->do_ip6) { 545 if(!acl_list_str_cfg(acl, "::1", "allow", 0)) 546 return 0; 547 if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) 548 return 0; 549 } 550 addr_tree_init_parents(&acl->tree); 551 return 1; 552 } 553 554 int 555 acl_interface_compare(const void* k1, const void* k2) 556 { 557 struct addr_tree_node* n1 = (struct addr_tree_node*)k1; 558 struct addr_tree_node* n2 = (struct addr_tree_node*)k2; 559 return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, 560 n2->addrlen); 561 /* We don't care about comparing node->net. All addresses in the 562 * acl_interface tree have either 32 (ipv4) or 128 (ipv6). */ 563 } 564 565 void 566 acl_interface_init(struct acl_list* acl_interface) 567 { 568 regional_free_all(acl_interface->region); 569 /* We want comparison in the tree to include only address and port. 570 * We don't care about comparing node->net. All addresses in the 571 * acl_interface->tree should have either 32 (ipv4) or 128 (ipv6). 572 * Initialise with the appropriate compare function but keep treating 573 * it as an addr_tree. */ 574 addr_tree_addrport_init(&acl_interface->tree); 575 } 576 577 static int 578 read_acl_interface_action(struct acl_list* acl_interface, 579 struct config_str2list* acls, int port) 580 { 581 struct config_str2list* p; 582 for(p = acls; p; p = p->next) { 583 char** resif = NULL; 584 int num_resif = 0; 585 int i; 586 log_assert(p->str && p->str2); 587 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) 588 return 0; 589 for(i = 0; i<num_resif; i++) { 590 if(!acl_interface_str_cfg(acl_interface, resif[i], p->str2, port)){ 591 config_del_strarray(resif, num_resif); 592 return 0; 593 } 594 } 595 config_del_strarray(resif, num_resif); 596 } 597 return 1; 598 } 599 600 /** read acl view config for interface */ 601 static int 602 read_acl_interface_view(struct acl_list* acl_interface, 603 struct config_str2list** acl_view, 604 struct views* v, int port) 605 { 606 struct config_str2list* np, *p = *acl_view; 607 *acl_view = NULL; 608 while(p) { 609 char** resif = NULL; 610 int num_resif = 0; 611 int i; 612 log_assert(p->str && p->str2); 613 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 614 config_deldblstrlist(p); 615 return 0; 616 } 617 for(i = 0; i<num_resif; i++) { 618 if(!acl_list_view_cfg(acl_interface, resif[i], p->str2, 619 v, 1, port)) { 620 config_del_strarray(resif, num_resif); 621 config_deldblstrlist(p); 622 return 0; 623 } 624 } 625 config_del_strarray(resif, num_resif); 626 /* free the items as we go to free up memory */ 627 np = p->next; 628 free(p->str); 629 free(p->str2); 630 free(p); 631 p = np; 632 } 633 return 1; 634 } 635 636 /** read acl tags config for interface */ 637 static int 638 read_acl_interface_tags(struct acl_list* acl_interface, 639 struct config_strbytelist** acl_tags, int port) 640 { 641 struct config_strbytelist* np, *p = *acl_tags; 642 *acl_tags = NULL; 643 while(p) { 644 char** resif = NULL; 645 int num_resif = 0; 646 int i; 647 log_assert(p->str && p->str2); 648 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 649 config_del_strbytelist(p); 650 return 0; 651 } 652 for(i = 0; i<num_resif; i++) { 653 if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2, 654 p->str2len, 1, port)) { 655 config_del_strbytelist(p); 656 config_del_strarray(resif, num_resif); 657 return 0; 658 } 659 } 660 config_del_strarray(resif, num_resif); 661 /* free the items as we go to free up memory */ 662 np = p->next; 663 free(p->str); 664 free(p->str2); 665 free(p); 666 p = np; 667 } 668 return 1; 669 } 670 671 /** read acl tag actions config for interface*/ 672 static int 673 read_acl_interface_tag_actions(struct acl_list* acl_interface, 674 struct config_file* cfg, 675 struct config_str3list** acl_tag_actions, int port) 676 { 677 struct config_str3list* p, *np; 678 p = *acl_tag_actions; 679 *acl_tag_actions = NULL; 680 while(p) { 681 char** resif = NULL; 682 int num_resif = 0; 683 int i; 684 log_assert(p->str && p->str2 && p->str3); 685 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 686 config_deltrplstrlist(p); 687 return 0; 688 } 689 for(i = 0; i<num_resif; i++) { 690 if(!acl_list_tag_action_cfg(acl_interface, cfg, 691 resif[i], p->str2, p->str3, 1, port)) { 692 config_deltrplstrlist(p); 693 config_del_strarray(resif, num_resif); 694 return 0; 695 } 696 } 697 config_del_strarray(resif, num_resif); 698 /* free the items as we go to free up memory */ 699 np = p->next; 700 free(p->str); 701 free(p->str2); 702 free(p->str3); 703 free(p); 704 p = np; 705 } 706 return 1; 707 } 708 709 /** read acl tag datas config for interface */ 710 static int 711 read_acl_interface_tag_datas(struct acl_list* acl_interface, 712 struct config_file* cfg, 713 struct config_str3list** acl_tag_datas, int port) 714 { 715 struct config_str3list* p, *np; 716 p = *acl_tag_datas; 717 *acl_tag_datas = NULL; 718 while(p) { 719 char** resif = NULL; 720 int num_resif = 0; 721 int i; 722 log_assert(p->str && p->str2 && p->str3); 723 if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) { 724 config_deltrplstrlist(p); 725 return 0; 726 } 727 for(i = 0; i<num_resif; i++) { 728 if(!acl_list_tag_data_cfg(acl_interface, cfg, 729 resif[i], p->str2, p->str3, 1, port)) { 730 config_deltrplstrlist(p); 731 config_del_strarray(resif, num_resif); 732 return 0; 733 } 734 } 735 config_del_strarray(resif, num_resif); 736 /* free the items as we go to free up memory */ 737 np = p->next; 738 free(p->str); 739 free(p->str2); 740 free(p->str3); 741 free(p); 742 p = np; 743 } 744 return 1; 745 } 746 747 int 748 acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg, 749 struct views* v) 750 { 751 if(!read_acl_interface_action(acl_interface, cfg->interface_actions, 752 cfg->port)) 753 return 0; 754 if(!read_acl_interface_view(acl_interface, &cfg->interface_view, v, 755 cfg->port)) 756 return 0; 757 if(!read_acl_interface_tags(acl_interface, &cfg->interface_tags, 758 cfg->port)) 759 return 0; 760 if(!read_acl_interface_tag_actions(acl_interface, cfg, 761 &cfg->interface_tag_actions, cfg->port)) 762 return 0; 763 if(!read_acl_interface_tag_datas(acl_interface, cfg, 764 &cfg->interface_tag_datas, cfg->port)) 765 return 0; 766 addr_tree_init_parents(&acl_interface->tree); 767 return 1; 768 } 769 770 enum acl_access 771 acl_get_control(struct acl_addr* acl) 772 { 773 if(acl) return acl->control; 774 return acl_deny; 775 } 776 777 struct acl_addr* 778 acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr, 779 socklen_t addrlen) 780 { 781 return (struct acl_addr*)addr_tree_lookup(&acl->tree, 782 addr, addrlen); 783 } 784 785 size_t 786 acl_list_get_mem(struct acl_list* acl) 787 { 788 if(!acl) return 0; 789 return sizeof(*acl) + regional_get_mem(acl->region); 790 } 791 792 const char* acl_access_to_str(enum acl_access acl) 793 { 794 switch(acl) { 795 case acl_deny: return "deny"; 796 case acl_refuse: return "refuse"; 797 case acl_deny_non_local: return "deny_non_local"; 798 case acl_refuse_non_local: return "refuse_non_local"; 799 case acl_allow: return "allow"; 800 case acl_allow_snoop: return "allow_snoop"; 801 case acl_allow_setrd: return "allow_setrd"; 802 default: break; 803 } 804 return "unknown"; 805 } 806 807 void 808 log_acl_action(const char* action, struct sockaddr_storage* addr, 809 socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr) 810 { 811 char a[128], n[128]; 812 uint16_t port; 813 addr_to_str(addr, addrlen, a, sizeof(a)); 814 port = ntohs(((struct sockaddr_in*)addr)->sin_port); 815 if(acladdr) { 816 addr_to_str(&acladdr->node.addr, acladdr->node.addrlen, 817 n, sizeof(n)); 818 verbose(VERB_ALGO, "%s query from %s port %d because of " 819 "%s/%d %s", action, a, (int)port, n, acladdr->node.net, 820 acl_access_to_str(acl)); 821 } else { 822 verbose(VERB_ALGO, "%s query from %s port %d", action, a, 823 (int)port); 824 } 825 } 826