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