/** setup parent pointers, so that a lookup can be done for closest match */ static void init_parents(struct local_zones* zones) { struct local_zone* node, *prev = NULL, *p; int m; lock_rw_wrlock(&zones->lock); RBTREE_FOR(node, struct local_zone*, &zones->ztree) { lock_rw_wrlock(&node->lock); node->parent = NULL; if(!prev || prev->dclass != node->dclass) { prev = node; lock_rw_unlock(&node->lock); continue; } (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, node->namelabs, &m); /* we know prev is smaller */ /* sort order like: . com. bla.com. zwb.com. net. */ /* find the previous, or parent-parent-parent */ for(p = prev; p; p = p->parent) /* looking for name with few labels, a parent */ if(p->namelabs <= m) { /* ==: since prev matched m, this is closest*/ /* <: prev matches more, but is not a parent, * this one is a (grand)parent */ node->parent = p; break; } prev = node; if(node->override_tree) addr_tree_init_parents(node->override_tree); lock_rw_unlock(&node->lock); } lock_rw_unlock(&zones->lock); }
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg) { regional_free_all(acl->region); addr_tree_init(&acl->tree); if(!read_acl_list(acl, cfg)) return 0; /* insert defaults, with '0' to ignore them if they are duplicates */ if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0)) return 0; if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) return 0; if(cfg->do_ip6) { if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0)) return 0; if(!acl_list_str_cfg(acl, "::1", "allow", 0)) return 0; if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) return 0; } addr_tree_init_parents(&acl->tree); return 1; }