OpenDNSSEC-signer  2.1.7
zonelistparser.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
32 #include "adapter/adapter.h"
33 #include "parser/zonelistparser.h"
34 #include "file.h"
35 #include "log.h"
36 #include "status.h"
37 #include "signer/zonelist.h"
38 #include "signer/zone.h"
39 
40 #include <libxml/xpath.h>
41 #include <libxml/xmlreader.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 static const char* parser_str = "parser";
46 
47 
52 static const char*
53 parse_zonelist_element(xmlXPathContextPtr xpathCtx, xmlChar* expr)
54 {
55  xmlXPathObjectPtr xpathObj = NULL;
56  const char* str = NULL;
57 
58  ods_log_assert(xpathCtx);
59  ods_log_assert(expr);
60 
61  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
62  if (xpathObj == NULL) {
63  ods_log_error("[%s] unable to evaluate xpath expression %s",
64  parser_str, expr);
65  return NULL;
66  }
67  str = (const char*) xmlXPathCastToString(xpathObj);
68  xmlXPathFreeObject(xpathObj);
69  return str;
70 }
71 
72 
77 static adapter_type*
78 zlp_adapter(xmlNode* curNode, adapter_mode type, unsigned inbound)
79 {
80  const char* file = NULL;
81  adapter_type* adapter = NULL;
82  file = (const char*) xmlNodeGetContent(curNode);
83  if (!file) {
84  ods_log_error("[%s] unable to read %s adapter", parser_str,
85  inbound?"input":"output");
86  return NULL;
87  }
88  adapter = adapter_create(file, type, inbound);
89  free((void*)file);
90  return adapter;
91 }
92 
93 
98 static adapter_type*
99 parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar* expr,
100  int inbound)
101 {
102  xmlXPathObjectPtr xpathObj = NULL;
103  xmlNode* curNode = NULL;
104  xmlChar* type = NULL;
105  adapter_type* adapter = NULL;
106  int i = 0;
107 
108  if (!xpathCtx || !expr) {
109  return NULL;
110  }
111  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
112  if (xpathObj == NULL) {
113  ods_log_error("[%s] unable to parse adapter: xmlPathEvalExpression() "
114  "failed (expr %s)", parser_str, expr);
115  return NULL;
116  }
117  if (xpathObj->nodesetval) {
118  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
119  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
120  while (curNode) {
121  if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) {
122  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
123  } else if (xmlStrEqual(curNode->name,
124  (const xmlChar*)"Adapter")) {
125  type = xmlGetProp(curNode, (const xmlChar*)"type");
126  if (xmlStrEqual(type, (const xmlChar*)"File")) {
127  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
128  } else if (xmlStrEqual(type, (const xmlChar*)"DNS")) {
129  adapter = zlp_adapter(curNode, ADAPTER_DNS, inbound);
130  } else {
131  ods_log_error("[%s] unable to parse %s adapter: "
132  "unknown type", parser_str, (const char*) type);
133  }
134  free((void*)type);
135  type = NULL;
136  }
137  if (adapter) {
138  xmlXPathFreeObject(xpathObj);
139  return adapter;
140  }
141  curNode = curNode->next;
142  }
143  }
144  }
145  xmlXPathFreeObject(xpathObj);
146  return NULL;
147 }
148 
149 
154 static void
155 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone)
156 {
157  xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input";
158  xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output";
159 
160  if (!xpathCtx || !zone) {
161  return;
162  }
163  zone->adinbound = parse_zonelist_adapter(xpathCtx, i_expr, 1);
164  zone->adoutbound = parse_zonelist_adapter(xpathCtx, o_expr, 0);
165 }
166 
167 
172 ods_status
173 parse_zonelist_zones(void* zlist, const char* zlfile)
174 {
175  char* tag_name = NULL;
176  char* zone_name = NULL;
177  zone_type* new_zone = NULL;
178  int ret = 0;
179  int error = 0;
180  xmlTextReaderPtr reader = NULL;
181  xmlDocPtr doc = NULL;
182  xmlXPathContextPtr xpathCtx = NULL;
183  xmlChar* name_expr = (unsigned char*) "name";
184  xmlChar* policy_expr = (unsigned char*) "//Zone/Policy";
185  xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration";
186 
187  if (!zlist || !zlfile) {
188  ods_log_error("[%s] unable to parse zonelist: no storage or no filename",
189  parser_str);
190  return ODS_STATUS_ASSERT_ERR;
191  }
192  reader = xmlNewTextReaderFilename(zlfile);
193  if (!reader) {
194  ods_log_error("[%s] unable to parse zonelist: failed to open file %s",
195  parser_str, zlfile);
196  return ODS_STATUS_XML_ERR;
197  }
198  ret = xmlTextReaderRead(reader);
199  while (ret == XML_READER_TYPE_ELEMENT) {
200  tag_name = (char*) xmlTextReaderLocalName(reader);
201  if (ods_strcmp(tag_name, "Zone") == 0 &&
202  ods_strcmp(tag_name, "ZoneList") != 0 &&
203  xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
204  /* Found a zone */
205  zone_name = (char*) xmlTextReaderGetAttribute(reader,
206  name_expr);
207  if (!zone_name || strlen(zone_name) <= 0) {
208  ods_log_alert("[%s] unable to extract zone name from "
209  "zonelist %s, skipping...", parser_str, zlfile);
210  if (zone_name) {
211  free((void*) zone_name);
212  }
213  free((void*) tag_name);
214  ret = xmlTextReaderRead(reader);
215  continue;
216  }
217  /* Expand this node to get the rest of the info */
218  xmlTextReaderExpand(reader);
219  doc = xmlTextReaderCurrentDoc(reader);
220  if (doc) {
221  xpathCtx = xmlXPathNewContext(doc);
222  }
223  if (doc == NULL || xpathCtx == NULL) {
224  ods_log_alert("[%s] unable to read zone %s, skipping...",
225  parser_str, zone_name);
226  ret = xmlTextReaderRead(reader);
227  free((void*) zone_name);
228  free((void*) tag_name);
229  continue;
230  }
231  /* That worked, now read out the contents... */
232  new_zone = zone_create(zone_name, LDNS_RR_CLASS_IN);
233  if (new_zone) {
234  new_zone->policy_name = parse_zonelist_element(xpathCtx,
235  policy_expr);
236  new_zone->signconf_filename = parse_zonelist_element(xpathCtx,
237  signconf_expr);
238  parse_zonelist_adapters(xpathCtx, new_zone);
239  if (!new_zone->policy_name || !new_zone->signconf_filename ||
240  !new_zone->adinbound || !new_zone->adoutbound) {
241  zone_cleanup(new_zone);
242  new_zone = NULL;
243  ods_log_crit("[%s] unable to create zone %s", parser_str,
244  zone_name);
245  error = 1;
246  } else if (zonelist_add_zone((zonelist_type*) zlist, new_zone)
247  == NULL) {
248  ods_log_crit("[%s] unable to add zone %s", parser_str,
249  zone_name);
250  zone_cleanup(new_zone);
251  new_zone = NULL;
252  error = 1;
253  }
254  } else {
255  ods_log_crit("[%s] unable to create zone %s", parser_str,
256  zone_name);
257  error = 1;
258  }
259  xmlXPathFreeContext(xpathCtx);
260  xpathCtx = NULL;
261  free((void*) zone_name);
262  if (error) {
263  free((void*) tag_name);
264  tag_name = NULL;
265  ret = 1;
266  break;
267  }
268  ods_log_debug("[%s] zone %s added", parser_str, new_zone->name);
269  }
270  free((void*) tag_name);
271  ret = xmlTextReaderRead(reader);
272  }
273  /* no more zones */
274  ods_log_debug("[%s] no more zones", parser_str);
275  xmlFreeTextReader(reader);
276  if (doc) {
277  xmlFreeDoc(doc);
278  }
279  if (ret != 0) {
280  ods_log_error("[%s] unable to parse zonelist: parse error in %s",
281  parser_str, zlfile);
282  return ODS_STATUS_PARSE_ERR;
283  }
284  return ODS_STATUS_OK;
285 }
ADAPTER_DNS
@ ADAPTER_DNS
Definition: adapter.h:42
parse_zonelist_zones
ods_status parse_zonelist_zones(void *zlist, const char *zlfile)
Definition: zonelistparser.c:173
zonelistparser.h
zone_struct
Definition: zone.h:60
adapter_struct
Definition: adapter.h:57
zone_struct::signconf_filename
const char * signconf_filename
Definition: zone.h:71
zone.h
zonelist.h
zone_struct::name
const char * name
Definition: zone.h:69
adapter_mode
enum adapter_mode_enum adapter_mode
Definition: adapter.h:44
adapter_create
adapter_type * adapter_create(const char *str, adapter_mode type, unsigned in)
Definition: adapter.c:48
zonelist_add_zone
zone_type * zonelist_add_zone(zonelist_type *zlist, zone_type *zone)
Definition: zonelist.c:201
zone_struct::policy_name
const char * policy_name
Definition: zone.h:70
zone_create
zone_type * zone_create(char *name, ldns_rr_class klass)
Definition: zone.c:55
adapter.h
zonelist_struct
Definition: zonelist.h:44
zone_struct::adoutbound
adapter_type * adoutbound
Definition: zone.h:75
ADAPTER_FILE
@ ADAPTER_FILE
Definition: adapter.h:41
zone_cleanup
void zone_cleanup(zone_type *zone)
Definition: zone.c:761
zone_struct::adinbound
adapter_type * adinbound
Definition: zone.h:74