OpenDNSSEC-signer  1.4.1
zonelistparser.c
Go to the documentation of this file.
1 /*
2  * $Id: zonelistparser.c 7041 2013-02-15 09:09:02Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "adapter/adapter.h"
35 #include "parser/zonelistparser.h"
36 #include "shared/file.h"
37 #include "shared/log.h"
38 #include "shared/status.h"
39 #include "signer/zonelist.h"
40 #include "signer/zone.h"
41 
42 #include <libxml/xpath.h>
43 #include <libxml/xmlreader.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 static const char* parser_str = "parser";
48 
49 
54 static const char*
55 parse_zonelist_element(xmlXPathContextPtr xpathCtx, xmlChar* expr)
56 {
57  xmlXPathObjectPtr xpathObj = NULL;
58  const char* str = NULL;
59 
60  ods_log_assert(xpathCtx);
61  ods_log_assert(expr);
62 
63  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
64  if (xpathObj == NULL) {
65  ods_log_error("[%s] unable to evaluate xpath expression %s",
66  parser_str, expr);
67  return NULL;
68  }
69  str = (const char*) xmlXPathCastToString(xpathObj);
70  xmlXPathFreeObject(xpathObj);
71  return str;
72 }
73 
74 
79 static adapter_type*
80 zlp_adapter(xmlNode* curNode, adapter_mode type, unsigned inbound)
81 {
82  const char* file = NULL;
83  adapter_type* adapter = NULL;
84  file = (const char*) xmlNodeGetContent(curNode);
85  if (!file) {
86  ods_log_error("[%s] unable to read %s adapter", parser_str,
87  inbound?"input":"output");
88  return NULL;
89  }
90  adapter = adapter_create(file, type, inbound);
91  free((void*)file);
92  return adapter;
93 }
94 
95 
101 parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar* expr,
102  int inbound)
103 {
104  xmlXPathObjectPtr xpathObj = NULL;
105  xmlNode* curNode = NULL;
106  xmlChar* type = NULL;
107  adapter_type* adapter = NULL;
108  int i = 0;
109 
110  if (!xpathCtx || !expr) {
111  return NULL;
112  }
113  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
114  if (xpathObj == NULL) {
115  ods_log_error("[%s] unable to parse adapter: xmlPathEvalExpression() "
116  "failed (expr %s)", parser_str, expr);
117  return NULL;
118  }
119  if (xpathObj->nodesetval) {
120  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
121  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
122  while (curNode) {
123  if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) {
124  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
125  } else if (xmlStrEqual(curNode->name,
126  (const xmlChar*)"Adapter")) {
127  type = xmlGetProp(curNode, (const xmlChar*)"type");
128  if (xmlStrEqual(type, (const xmlChar*)"File")) {
129  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
130  } else if (xmlStrEqual(type, (const xmlChar*)"DNS")) {
131  adapter = zlp_adapter(curNode, ADAPTER_DNS, inbound);
132  } else {
133  ods_log_error("[%s] unable to parse %s adapter: "
134  "unknown type", parser_str, (const char*) type);
135  }
136  free((void*)type);
137  type = NULL;
138  }
139  if (adapter) {
140  break;
141  }
142  curNode = curNode->next;
143  }
144  }
145  }
146  xmlXPathFreeObject(xpathObj);
147  return adapter;
148 }
149 
150 
155 static void
156 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone)
157 {
158  xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input";
159  xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output";
160 
161  if (!xpathCtx || !zone) {
162  return;
163  }
164  zone->adinbound = parse_zonelist_adapter(xpathCtx, i_expr, 1);
165  zone->adoutbound = parse_zonelist_adapter(xpathCtx, o_expr, 0);
166  return;
167 }
168 
169 
175 parse_zonelist_zones(void* zlist, const char* zlfile)
176 {
177  char* tag_name = NULL;
178  char* zone_name = NULL;
179  zone_type* new_zone = NULL;
180  int ret = 0;
181  int error = 0;
182  xmlTextReaderPtr reader = NULL;
183  xmlDocPtr doc = NULL;
184  xmlXPathContextPtr xpathCtx = NULL;
185  xmlChar* name_expr = (unsigned char*) "name";
186  xmlChar* policy_expr = (unsigned char*) "//Zone/Policy";
187  xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration";
188 
189  if (!zlist || !zlfile) {
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 }
void ods_log_alert(const char *format,...)
Definition: log.c:368
void zone_cleanup(zone_type *zone)
Definition: zone.c:693
void ods_log_debug(const char *format,...)
Definition: log.c:272
enum ods_enum_status ods_status
Definition: status.h:89
void ods_log_error(const char *format,...)
Definition: log.c:336
int ods_strcmp(const char *s1, const char *s2)
Definition: file.c:312
zone_type * zone_create(char *name, ldns_rr_class klass)
Definition: zone.c:56
adapter_type * adoutbound
Definition: zone.h:84
void ods_log_crit(const char *format,...)
Definition: log.c:352
zone_type * zonelist_add_zone(zonelist_type *zlist, zone_type *zone)
Definition: zonelist.c:207
adapter_type * adinbound
Definition: zone.h:83
adapter_type * adapter_create(const char *str, adapter_mode type, unsigned in)
Definition: adapter.c:51
ods_status parse_zonelist_zones(void *zlist, const char *zlfile)
const char * signconf_filename
Definition: zone.h:80
enum adapter_mode_enum adapter_mode
Definition: adapter.h:51
adapter_type * parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar *expr, int inbound)
const char * name
Definition: zone.h:78
const char * policy_name
Definition: zone.h:79
#define ods_log_assert(x)
Definition: log.h:156