1bc892140SDag-Erling Smørgrav /* 2bc892140SDag-Erling Smørgrav * services/view.c - named views containing local zones authority service. 3bc892140SDag-Erling Smørgrav * 4bc892140SDag-Erling Smørgrav * Copyright (c) 2016, NLnet Labs. All rights reserved. 5bc892140SDag-Erling Smørgrav * 6bc892140SDag-Erling Smørgrav * This software is open source. 7bc892140SDag-Erling Smørgrav * 8bc892140SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9bc892140SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10bc892140SDag-Erling Smørgrav * are met: 11bc892140SDag-Erling Smørgrav * 12bc892140SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13bc892140SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14bc892140SDag-Erling Smørgrav * 15bc892140SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16bc892140SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17bc892140SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18bc892140SDag-Erling Smørgrav * 19bc892140SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20bc892140SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21bc892140SDag-Erling Smørgrav * specific prior written permission. 22bc892140SDag-Erling Smørgrav * 23bc892140SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24bc892140SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25bc892140SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26bc892140SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27bc892140SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28bc892140SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29bc892140SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30bc892140SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31bc892140SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32bc892140SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33bc892140SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34bc892140SDag-Erling Smørgrav */ 35bc892140SDag-Erling Smørgrav 36bc892140SDag-Erling Smørgrav /** 37bc892140SDag-Erling Smørgrav * \file 38bc892140SDag-Erling Smørgrav * 39bc892140SDag-Erling Smørgrav * This file contains functions to enable named views that can hold local zone 40bc892140SDag-Erling Smørgrav * authority service. 41bc892140SDag-Erling Smørgrav */ 42bc892140SDag-Erling Smørgrav #include "config.h" 43bc892140SDag-Erling Smørgrav #include "services/view.h" 44bc892140SDag-Erling Smørgrav #include "services/localzone.h" 45bc892140SDag-Erling Smørgrav #include "util/config_file.h" 46*be771a7bSCy Schubert #include "respip/respip.h" 47bc892140SDag-Erling Smørgrav 48bc892140SDag-Erling Smørgrav int 49bc892140SDag-Erling Smørgrav view_cmp(const void* v1, const void* v2) 50bc892140SDag-Erling Smørgrav { 51bc892140SDag-Erling Smørgrav struct view* a = (struct view*)v1; 52bc892140SDag-Erling Smørgrav struct view* b = (struct view*)v2; 53bc892140SDag-Erling Smørgrav 54bc892140SDag-Erling Smørgrav return strcmp(a->name, b->name); 55bc892140SDag-Erling Smørgrav } 56bc892140SDag-Erling Smørgrav 57bc892140SDag-Erling Smørgrav struct views* 58bc892140SDag-Erling Smørgrav views_create(void) 59bc892140SDag-Erling Smørgrav { 60bc892140SDag-Erling Smørgrav struct views* v = (struct views*)calloc(1, 61bc892140SDag-Erling Smørgrav sizeof(*v)); 62bc892140SDag-Erling Smørgrav if(!v) 63bc892140SDag-Erling Smørgrav return NULL; 64bc892140SDag-Erling Smørgrav rbtree_init(&v->vtree, &view_cmp); 65bc892140SDag-Erling Smørgrav lock_rw_init(&v->lock); 66bc892140SDag-Erling Smørgrav lock_protect(&v->lock, &v->vtree, sizeof(v->vtree)); 67bc892140SDag-Erling Smørgrav return v; 68bc892140SDag-Erling Smørgrav } 69bc892140SDag-Erling Smørgrav 70bc892140SDag-Erling Smørgrav void 71bc892140SDag-Erling Smørgrav view_delete(struct view* v) 72bc892140SDag-Erling Smørgrav { 73bc892140SDag-Erling Smørgrav if(!v) 74bc892140SDag-Erling Smørgrav return; 75bc892140SDag-Erling Smørgrav lock_rw_destroy(&v->lock); 76bc892140SDag-Erling Smørgrav local_zones_delete(v->local_zones); 7765b390aaSDag-Erling Smørgrav respip_set_delete(v->respip_set); 78bc892140SDag-Erling Smørgrav free(v->name); 79bc892140SDag-Erling Smørgrav free(v); 80bc892140SDag-Erling Smørgrav } 81bc892140SDag-Erling Smørgrav 82bc892140SDag-Erling Smørgrav static void 833005e0a3SDag-Erling Smørgrav delviewnode(rbnode_type* n, void* ATTR_UNUSED(arg)) 84bc892140SDag-Erling Smørgrav { 85bc892140SDag-Erling Smørgrav struct view* v = (struct view*)n; 86bc892140SDag-Erling Smørgrav view_delete(v); 87bc892140SDag-Erling Smørgrav } 88bc892140SDag-Erling Smørgrav 89bc892140SDag-Erling Smørgrav void 90bc892140SDag-Erling Smørgrav views_delete(struct views* v) 91bc892140SDag-Erling Smørgrav { 92bc892140SDag-Erling Smørgrav if(!v) 93bc892140SDag-Erling Smørgrav return; 94bc892140SDag-Erling Smørgrav lock_rw_destroy(&v->lock); 95bc892140SDag-Erling Smørgrav traverse_postorder(&v->vtree, delviewnode, NULL); 96bc892140SDag-Erling Smørgrav free(v); 97bc892140SDag-Erling Smørgrav } 98bc892140SDag-Erling Smørgrav 99bc892140SDag-Erling Smørgrav /** create a new view */ 100bc892140SDag-Erling Smørgrav static struct view* 101bc892140SDag-Erling Smørgrav view_create(char* name) 102bc892140SDag-Erling Smørgrav { 103bc892140SDag-Erling Smørgrav struct view* v = (struct view*)calloc(1, sizeof(*v)); 104bc892140SDag-Erling Smørgrav if(!v) 105bc892140SDag-Erling Smørgrav return NULL; 106bc892140SDag-Erling Smørgrav v->node.key = v; 107bc892140SDag-Erling Smørgrav if(!(v->name = strdup(name))) { 108bc892140SDag-Erling Smørgrav free(v); 109bc892140SDag-Erling Smørgrav return NULL; 110bc892140SDag-Erling Smørgrav } 111bc892140SDag-Erling Smørgrav lock_rw_init(&v->lock); 1123005e0a3SDag-Erling Smørgrav lock_protect(&v->lock, &v->name, sizeof(*v)-sizeof(rbnode_type)); 113bc892140SDag-Erling Smørgrav return v; 114bc892140SDag-Erling Smørgrav } 115bc892140SDag-Erling Smørgrav 116bc892140SDag-Erling Smørgrav /** enter a new view returns with WRlock */ 117bc892140SDag-Erling Smørgrav static struct view* 118bc892140SDag-Erling Smørgrav views_enter_view_name(struct views* vs, char* name) 119bc892140SDag-Erling Smørgrav { 120bc892140SDag-Erling Smørgrav struct view* v = view_create(name); 121bc892140SDag-Erling Smørgrav if(!v) { 122bc892140SDag-Erling Smørgrav log_err("out of memory"); 123bc892140SDag-Erling Smørgrav return NULL; 124bc892140SDag-Erling Smørgrav } 125bc892140SDag-Erling Smørgrav 126bc892140SDag-Erling Smørgrav /* add to rbtree */ 127bc892140SDag-Erling Smørgrav lock_rw_wrlock(&vs->lock); 128bc892140SDag-Erling Smørgrav lock_rw_wrlock(&v->lock); 129bc892140SDag-Erling Smørgrav if(!rbtree_insert(&vs->vtree, &v->node)) { 130bc892140SDag-Erling Smørgrav log_warn("duplicate view: %s", name); 131bc892140SDag-Erling Smørgrav lock_rw_unlock(&v->lock); 132bc892140SDag-Erling Smørgrav view_delete(v); 133bc892140SDag-Erling Smørgrav lock_rw_unlock(&vs->lock); 134bc892140SDag-Erling Smørgrav return NULL; 135bc892140SDag-Erling Smørgrav } 136bc892140SDag-Erling Smørgrav lock_rw_unlock(&vs->lock); 137bc892140SDag-Erling Smørgrav return v; 138bc892140SDag-Erling Smørgrav } 139bc892140SDag-Erling Smørgrav 140bc892140SDag-Erling Smørgrav int 141bc892140SDag-Erling Smørgrav views_apply_cfg(struct views* vs, struct config_file* cfg) 142bc892140SDag-Erling Smørgrav { 143bc892140SDag-Erling Smørgrav struct config_view* cv; 144bc892140SDag-Erling Smørgrav struct view* v; 145bc892140SDag-Erling Smørgrav struct config_file lz_cfg; 146bc892140SDag-Erling Smørgrav /* Check existence of name in first view (last in config). Rest of 147bc892140SDag-Erling Smørgrav * views are already checked when parsing config. */ 148bc892140SDag-Erling Smørgrav if(cfg->views && !cfg->views->name) { 149bc892140SDag-Erling Smørgrav log_err("view without a name"); 150bc892140SDag-Erling Smørgrav return 0; 151bc892140SDag-Erling Smørgrav } 152bc892140SDag-Erling Smørgrav for(cv = cfg->views; cv; cv = cv->next) { 153bc892140SDag-Erling Smørgrav /* create and enter view */ 154bc892140SDag-Erling Smørgrav if(!(v = views_enter_view_name(vs, cv->name))) 155bc892140SDag-Erling Smørgrav return 0; 156bc892140SDag-Erling Smørgrav v->isfirst = cv->isfirst; 157bc892140SDag-Erling Smørgrav if(cv->local_zones || cv->local_data) { 158bc892140SDag-Erling Smørgrav if(!(v->local_zones = local_zones_create())){ 159bc892140SDag-Erling Smørgrav lock_rw_unlock(&v->lock); 160bc892140SDag-Erling Smørgrav return 0; 161bc892140SDag-Erling Smørgrav } 162bc892140SDag-Erling Smørgrav memset(&lz_cfg, 0, sizeof(lz_cfg)); 163bc892140SDag-Erling Smørgrav lz_cfg.local_zones = cv->local_zones; 164bc892140SDag-Erling Smørgrav lz_cfg.local_data = cv->local_data; 165bc892140SDag-Erling Smørgrav lz_cfg.local_zones_nodefault = 166bc892140SDag-Erling Smørgrav cv->local_zones_nodefault; 167c7f4d7adSDag-Erling Smørgrav if(v->isfirst) { 168c7f4d7adSDag-Erling Smørgrav /* Do not add defaults to view-specific 169c7f4d7adSDag-Erling Smørgrav * local-zone when global local zone will be 170c7f4d7adSDag-Erling Smørgrav * used. */ 171c7f4d7adSDag-Erling Smørgrav struct config_strlist* nd; 172c7f4d7adSDag-Erling Smørgrav lz_cfg.local_zones_disable_default = 1; 173c7f4d7adSDag-Erling Smørgrav /* Add nodefault zones to list of zones to add, 174c7f4d7adSDag-Erling Smørgrav * so they will be used as if they are 175c7f4d7adSDag-Erling Smørgrav * configured as type transparent */ 176c7f4d7adSDag-Erling Smørgrav for(nd = cv->local_zones_nodefault; nd; 177c7f4d7adSDag-Erling Smørgrav nd = nd->next) { 178c7f4d7adSDag-Erling Smørgrav char* nd_str, *nd_type; 179c7f4d7adSDag-Erling Smørgrav nd_str = strdup(nd->str); 180c7f4d7adSDag-Erling Smørgrav if(!nd_str) { 181c7f4d7adSDag-Erling Smørgrav log_err("out of memory"); 182c7f4d7adSDag-Erling Smørgrav lock_rw_unlock(&v->lock); 183c7f4d7adSDag-Erling Smørgrav return 0; 184c7f4d7adSDag-Erling Smørgrav } 185c7f4d7adSDag-Erling Smørgrav nd_type = strdup("nodefault"); 186c7f4d7adSDag-Erling Smørgrav if(!nd_type) { 187c7f4d7adSDag-Erling Smørgrav log_err("out of memory"); 188c7f4d7adSDag-Erling Smørgrav free(nd_str); 189c7f4d7adSDag-Erling Smørgrav lock_rw_unlock(&v->lock); 190c7f4d7adSDag-Erling Smørgrav return 0; 191c7f4d7adSDag-Erling Smørgrav } 192c7f4d7adSDag-Erling Smørgrav if(!cfg_str2list_insert( 193c7f4d7adSDag-Erling Smørgrav &lz_cfg.local_zones, nd_str, 194c7f4d7adSDag-Erling Smørgrav nd_type)) { 195c7f4d7adSDag-Erling Smørgrav log_err("failed to insert " 196c7f4d7adSDag-Erling Smørgrav "default zones into " 197c7f4d7adSDag-Erling Smørgrav "local-zone list"); 198c7f4d7adSDag-Erling Smørgrav lock_rw_unlock(&v->lock); 199c7f4d7adSDag-Erling Smørgrav return 0; 200c7f4d7adSDag-Erling Smørgrav } 201c7f4d7adSDag-Erling Smørgrav } 202c7f4d7adSDag-Erling Smørgrav } 203bc892140SDag-Erling Smørgrav if(!local_zones_apply_cfg(v->local_zones, &lz_cfg)){ 204bc892140SDag-Erling Smørgrav lock_rw_unlock(&v->lock); 205bc892140SDag-Erling Smørgrav return 0; 206bc892140SDag-Erling Smørgrav } 207bc892140SDag-Erling Smørgrav /* local_zones, local_zones_nodefault and local_data 208bc892140SDag-Erling Smørgrav * are free'd from config_view by local_zones_apply_cfg. 209bc892140SDag-Erling Smørgrav * Set pointers to NULL. */ 210bc892140SDag-Erling Smørgrav cv->local_zones = NULL; 211bc892140SDag-Erling Smørgrav cv->local_data = NULL; 212bc892140SDag-Erling Smørgrav cv->local_zones_nodefault = NULL; 213bc892140SDag-Erling Smørgrav } 214bc892140SDag-Erling Smørgrav lock_rw_unlock(&v->lock); 215bc892140SDag-Erling Smørgrav } 216bc892140SDag-Erling Smørgrav return 1; 217bc892140SDag-Erling Smørgrav } 218bc892140SDag-Erling Smørgrav 219bc892140SDag-Erling Smørgrav /** find a view by name */ 220bc892140SDag-Erling Smørgrav struct view* 221bc892140SDag-Erling Smørgrav views_find_view(struct views* vs, const char* name, int write) 222bc892140SDag-Erling Smørgrav { 223bc892140SDag-Erling Smørgrav struct view* v; 224bc892140SDag-Erling Smørgrav struct view key; 225bc892140SDag-Erling Smørgrav key.node.key = &v; 226bc892140SDag-Erling Smørgrav key.name = (char *)name; 227bc892140SDag-Erling Smørgrav lock_rw_rdlock(&vs->lock); 228bc892140SDag-Erling Smørgrav if(!(v = (struct view*)rbtree_search(&vs->vtree, &key.node))) { 229bc892140SDag-Erling Smørgrav lock_rw_unlock(&vs->lock); 230bc892140SDag-Erling Smørgrav return 0; 231bc892140SDag-Erling Smørgrav } 232bc892140SDag-Erling Smørgrav if(write) { 233bc892140SDag-Erling Smørgrav lock_rw_wrlock(&v->lock); 234bc892140SDag-Erling Smørgrav } else { 235bc892140SDag-Erling Smørgrav lock_rw_rdlock(&v->lock); 236bc892140SDag-Erling Smørgrav } 237bc892140SDag-Erling Smørgrav lock_rw_unlock(&vs->lock); 238bc892140SDag-Erling Smørgrav return v; 239bc892140SDag-Erling Smørgrav } 240bc892140SDag-Erling Smørgrav 241bc892140SDag-Erling Smørgrav void views_print(struct views* v) 242bc892140SDag-Erling Smørgrav { 243bc892140SDag-Erling Smørgrav /* TODO implement print */ 244bc892140SDag-Erling Smørgrav (void)v; 245bc892140SDag-Erling Smørgrav } 246*be771a7bSCy Schubert 247*be771a7bSCy Schubert size_t views_get_mem(struct views* vs) 248*be771a7bSCy Schubert { 249*be771a7bSCy Schubert struct view* v; 250*be771a7bSCy Schubert size_t m; 251*be771a7bSCy Schubert if(!vs) return 0; 252*be771a7bSCy Schubert m = sizeof(struct views); 253*be771a7bSCy Schubert lock_rw_rdlock(&vs->lock); 254*be771a7bSCy Schubert RBTREE_FOR(v, struct view*, &vs->vtree) { 255*be771a7bSCy Schubert m += view_get_mem(v); 256*be771a7bSCy Schubert } 257*be771a7bSCy Schubert lock_rw_unlock(&vs->lock); 258*be771a7bSCy Schubert return m; 259*be771a7bSCy Schubert } 260*be771a7bSCy Schubert 261*be771a7bSCy Schubert size_t view_get_mem(struct view* v) 262*be771a7bSCy Schubert { 263*be771a7bSCy Schubert size_t m = sizeof(*v); 264*be771a7bSCy Schubert lock_rw_rdlock(&v->lock); 265*be771a7bSCy Schubert m += getmem_str(v->name); 266*be771a7bSCy Schubert m += local_zones_get_mem(v->local_zones); 267*be771a7bSCy Schubert m += respip_set_get_mem(v->respip_set); 268*be771a7bSCy Schubert lock_rw_unlock(&v->lock); 269*be771a7bSCy Schubert return m; 270*be771a7bSCy Schubert } 271*be771a7bSCy Schubert 272*be771a7bSCy Schubert void views_swap_tree(struct views* vs, struct views* data) 273*be771a7bSCy Schubert { 274*be771a7bSCy Schubert rbnode_type* oldroot = vs->vtree.root; 275*be771a7bSCy Schubert size_t oldcount = vs->vtree.count; 276*be771a7bSCy Schubert vs->vtree.root = data->vtree.root; 277*be771a7bSCy Schubert vs->vtree.count = data->vtree.count; 278*be771a7bSCy Schubert data->vtree.root = oldroot; 279*be771a7bSCy Schubert data->vtree.count = oldcount; 280*be771a7bSCy Schubert } 281