1 /* 2 * services/view.c - named views containing local zones authority service. 3 * 4 * Copyright (c) 2016, 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 contains functions to enable named views that can hold local zone 40 * authority service. 41 */ 42 #include "config.h" 43 #include "services/view.h" 44 #include "services/localzone.h" 45 #include "util/config_file.h" 46 47 int 48 view_cmp(const void* v1, const void* v2) 49 { 50 struct view* a = (struct view*)v1; 51 struct view* b = (struct view*)v2; 52 53 return strcmp(a->name, b->name); 54 } 55 56 struct views* 57 views_create(void) 58 { 59 struct views* v = (struct views*)calloc(1, 60 sizeof(*v)); 61 if(!v) 62 return NULL; 63 rbtree_init(&v->vtree, &view_cmp); 64 lock_rw_init(&v->lock); 65 lock_protect(&v->lock, &v->vtree, sizeof(v->vtree)); 66 return v; 67 } 68 69 /** This prototype is defined in in respip.h, but we want to avoid 70 * unnecessary dependencies */ 71 void respip_set_delete(struct respip_set *set); 72 73 void 74 view_delete(struct view* v) 75 { 76 if(!v) 77 return; 78 lock_rw_destroy(&v->lock); 79 local_zones_delete(v->local_zones); 80 respip_set_delete(v->respip_set); 81 free(v->name); 82 free(v); 83 } 84 85 static void 86 delviewnode(rbnode_type* n, void* ATTR_UNUSED(arg)) 87 { 88 struct view* v = (struct view*)n; 89 view_delete(v); 90 } 91 92 void 93 views_delete(struct views* v) 94 { 95 if(!v) 96 return; 97 lock_rw_destroy(&v->lock); 98 traverse_postorder(&v->vtree, delviewnode, NULL); 99 free(v); 100 } 101 102 /** create a new view */ 103 static struct view* 104 view_create(char* name) 105 { 106 struct view* v = (struct view*)calloc(1, sizeof(*v)); 107 if(!v) 108 return NULL; 109 v->node.key = v; 110 if(!(v->name = strdup(name))) { 111 free(v); 112 return NULL; 113 } 114 lock_rw_init(&v->lock); 115 lock_protect(&v->lock, &v->name, sizeof(*v)-sizeof(rbnode_type)); 116 return v; 117 } 118 119 /** enter a new view returns with WRlock */ 120 static struct view* 121 views_enter_view_name(struct views* vs, char* name) 122 { 123 struct view* v = view_create(name); 124 if(!v) { 125 log_err("out of memory"); 126 return NULL; 127 } 128 129 /* add to rbtree */ 130 lock_rw_wrlock(&vs->lock); 131 lock_rw_wrlock(&v->lock); 132 if(!rbtree_insert(&vs->vtree, &v->node)) { 133 log_warn("duplicate view: %s", name); 134 lock_rw_unlock(&v->lock); 135 view_delete(v); 136 lock_rw_unlock(&vs->lock); 137 return NULL; 138 } 139 lock_rw_unlock(&vs->lock); 140 return v; 141 } 142 143 int 144 views_apply_cfg(struct views* vs, struct config_file* cfg) 145 { 146 struct config_view* cv; 147 struct view* v; 148 struct config_file lz_cfg; 149 /* Check existence of name in first view (last in config). Rest of 150 * views are already checked when parsing config. */ 151 if(cfg->views && !cfg->views->name) { 152 log_err("view without a name"); 153 return 0; 154 } 155 for(cv = cfg->views; cv; cv = cv->next) { 156 /* create and enter view */ 157 if(!(v = views_enter_view_name(vs, cv->name))) 158 return 0; 159 v->isfirst = cv->isfirst; 160 if(cv->local_zones || cv->local_data) { 161 if(!(v->local_zones = local_zones_create())){ 162 lock_rw_unlock(&v->lock); 163 return 0; 164 } 165 memset(&lz_cfg, 0, sizeof(lz_cfg)); 166 lz_cfg.local_zones = cv->local_zones; 167 lz_cfg.local_data = cv->local_data; 168 lz_cfg.local_zones_nodefault = 169 cv->local_zones_nodefault; 170 if(v->isfirst) { 171 /* Do not add defaults to view-specific 172 * local-zone when global local zone will be 173 * used. */ 174 struct config_strlist* nd; 175 lz_cfg.local_zones_disable_default = 1; 176 /* Add nodefault zones to list of zones to add, 177 * so they will be used as if they are 178 * configured as type transparent */ 179 for(nd = cv->local_zones_nodefault; nd; 180 nd = nd->next) { 181 char* nd_str, *nd_type; 182 nd_str = strdup(nd->str); 183 if(!nd_str) { 184 log_err("out of memory"); 185 lock_rw_unlock(&v->lock); 186 return 0; 187 } 188 nd_type = strdup("nodefault"); 189 if(!nd_type) { 190 log_err("out of memory"); 191 free(nd_str); 192 lock_rw_unlock(&v->lock); 193 return 0; 194 } 195 if(!cfg_str2list_insert( 196 &lz_cfg.local_zones, nd_str, 197 nd_type)) { 198 log_err("failed to insert " 199 "default zones into " 200 "local-zone list"); 201 lock_rw_unlock(&v->lock); 202 return 0; 203 } 204 } 205 } 206 if(!local_zones_apply_cfg(v->local_zones, &lz_cfg)){ 207 lock_rw_unlock(&v->lock); 208 return 0; 209 } 210 /* local_zones, local_zones_nodefault and local_data 211 * are free'd from config_view by local_zones_apply_cfg. 212 * Set pointers to NULL. */ 213 cv->local_zones = NULL; 214 cv->local_data = NULL; 215 cv->local_zones_nodefault = NULL; 216 } 217 lock_rw_unlock(&v->lock); 218 } 219 return 1; 220 } 221 222 /** find a view by name */ 223 struct view* 224 views_find_view(struct views* vs, const char* name, int write) 225 { 226 struct view* v; 227 struct view key; 228 key.node.key = &v; 229 key.name = (char *)name; 230 lock_rw_rdlock(&vs->lock); 231 if(!(v = (struct view*)rbtree_search(&vs->vtree, &key.node))) { 232 lock_rw_unlock(&vs->lock); 233 return 0; 234 } 235 if(write) { 236 lock_rw_wrlock(&v->lock); 237 } else { 238 lock_rw_rdlock(&v->lock); 239 } 240 lock_rw_unlock(&vs->lock); 241 return v; 242 } 243 244 void views_print(struct views* v) 245 { 246 /* TODO implement print */ 247 (void)v; 248 } 249