Home | History | Annotate | Line # | Download | only in daemon
      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