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