OpenDNSSEC-signer  1.3.15
zone_fetcher.c
Go to the documentation of this file.
1 /*
2  * $Id: zone_fetcher.c 5408 2011-08-16 08:15:16Z 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 #include "config.h"
29 #include "shared/log.h"
30 #include "shared/privdrop.h"
31 #include "tools/toolutil.h"
32 #include "tools/zone_fetcher.h"
33 
34 #include <arpa/inet.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <getopt.h>
38 #include <signal.h>
39 #include <syslog.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 
44 #include <libxml/tree.h>
45 #include <libxml/parser.h>
46 #include <libxml/xpath.h>
47 #include <libxml/xpathInternals.h>
48 #include <libxml/relaxng.h>
49 #include <libxml/xmlreader.h>
50 #include <libxml/xmlsave.h>
51 
52 #define DNS_SERIAL_GT(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) > 0)
53 
54 static int sig_quit = 0;
55 static int sig_reload = 0;
56 
57 ldns_resolver*
59 {
60  serverlist_type* servers;
61  ldns_rdf* ns = NULL;
62  ldns_status status = LDNS_STATUS_OK;
63 
64  ldns_resolver* xfrd = ldns_resolver_new();
65  if (config) {
66  if (config->use_tsig) {
67  ldns_resolver_set_tsig_keyname(xfrd, config->tsig_name);
68  if (strncmp(config->tsig_algo, "hmac-md5", 8) == 0) {
69  ldns_resolver_set_tsig_algorithm(xfrd, "hmac-md5.sig-alg.reg.int.");
70  } else {
71  ldns_resolver_set_tsig_algorithm(xfrd, config->tsig_algo);
72  }
73  ldns_resolver_set_tsig_keydata(xfrd, config->tsig_secret);
74  }
75  if (config->serverlist && config->serverlist->port)
76  ldns_resolver_set_port(xfrd, atoi(config->serverlist->port));
77  else
78  ldns_resolver_set_port(xfrd, atoi(DNS_PORT_STRING));
79  ldns_resolver_set_recursive(xfrd, 0);
80 
81  servers = config->serverlist;
82  while (servers) {
83  if (servers->family == AF_INET6)
84  ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, servers->ipaddr);
85  else
86  ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, servers->ipaddr);
87  if (ns) {
88  status = ldns_resolver_push_nameserver(xfrd, ns);
89  ldns_rdf_deep_free(ns);
90  ns = NULL;
91  } else {
92  ods_log_error("zone fetcher could not use %s for transfer "
93  "request: could not parse ip address", servers->ipaddr);
94  }
95  if (status != LDNS_STATUS_OK) {
96  ods_log_error("zone fetcher could not use %s for transfer "
97  "request: %s", servers->ipaddr,
98  ldns_get_errorstr_by_id(status));
99  }
100  servers = servers->next;
101  }
102  if (ldns_resolver_nameserver_count(xfrd) <= 0) {
103  ods_log_error("zone fetcher could not find any valid name "
104  "servers");
105  }
106 
107  }
108  return xfrd;
109 }
110 
111 static zfzonelist_type*
112 new_zone(char* zone_name, char* input_file)
113 {
114  zfzonelist_type* zlt = (zfzonelist_type*) malloc(sizeof(zfzonelist_type));
115  zlt->name = strdup(zone_name);
116  zlt->dname = ldns_dname_new_frm_str(zone_name);
117  zlt->input_file = strdup(input_file);
118  zlt->next = NULL;
119  return zlt;
120 }
121 
122 static void
123 free_zonelist(zfzonelist_type* zlt)
124 {
125  zfzonelist_type* next = NULL;
126 
127  while (zlt) {
128  next = zlt->next;
129  free((void*) zlt->name);
130  if (zlt->dname) {
131  ldns_rdf_deep_free(zlt->dname);
132  }
133  free((void*) zlt->input_file);
134  free((void*) zlt);
135  zlt = next;
136  }
137 }
138 
139 static serverlist_type*
140 new_server(char* ipv4, char* ipv6, char* port)
141 {
142  serverlist_type* slt = (serverlist_type*) malloc(sizeof(serverlist_type));
143  slt->family = AF_UNSPEC;
144  if (ipv4) {
145  slt->family = AF_INET;
146  slt->ipaddr = strdup(ipv4);
147  }
148  else if (ipv6) {
149  slt->family = AF_INET6;
150  slt->ipaddr = strdup(ipv6);
151  }
152  if (port)
153  slt->port = strdup(port);
154  else
155  slt->port = NULL;
156  memset(&slt->addr, 0, sizeof(union acl_addr_storage));
157 
158  if (slt->family == AF_INET6 && strlen(slt->ipaddr) > 0) {
159  if (inet_pton(slt->family, slt->ipaddr, &slt->addr.addr6) != 1) {
160  ods_log_error("zone fetcher encountered bad ip address '%s'",
161  slt->ipaddr);
162  }
163  }
164  else if (slt->family == AF_INET && strlen(slt->ipaddr) > 0) {
165  if (inet_pton(slt->family, slt->ipaddr, &slt->addr.addr) != 1) {
166  ods_log_error("zone fetcher encountered bad ip address '%s'",
167  slt->ipaddr);
168  }
169  }
170 
171  slt->next = NULL;
172  return slt;
173 }
174 
175 static void
176 free_serverlist(serverlist_type* slt)
177 {
178  if (slt) {
179  free_serverlist(slt->next);
180  if (slt->port) free((void*) slt->port);
181  if (slt->ipaddr) free((void*) slt->ipaddr);
182  free((void*) slt);
183  }
184 }
185 
186 static config_type*
187 new_config(void)
188 {
189  config_type* cfg = (config_type*) malloc(sizeof(config_type)); /* not freed */
190  cfg->use_tsig = 0;
191  cfg->pidfile = NULL;
192  cfg->tsig_name = NULL;
193  cfg->tsig_algo = NULL;
194  cfg->tsig_secret = NULL;
195  cfg->serverlist = NULL;
196  cfg->notifylist = NULL;
197  cfg->zonelist_file = NULL;
198  cfg->zonelist = NULL;
199  return cfg;
200 }
201 
202 static void
203 free_config(config_type* cfg)
204 {
205  if (cfg) {
206  if (cfg->tsig_name) free((void*) cfg->tsig_name);
207  if (cfg->tsig_algo) free((void*) cfg->tsig_algo);
208  if (cfg->tsig_secret) free((void*) cfg->tsig_secret);
209  if (cfg->pidfile) free((void*) cfg->pidfile);
210  if (cfg->zonelist_file) free((void*) cfg->zonelist_file);
211  free_zonelist(cfg->zonelist);
212  free_serverlist(cfg->serverlist);
213  free_serverlist(cfg->notifylist);
214  free((void*) cfg);
215  }
216 }
217 
218 static int
219 read_axfr_config(const char* filename, config_type* cfg)
220 {
221  int ret, i, use_tsig = 0;
222  char* tag_name, *tsig_name, *tsig_algo, *tsig_secret, *ipv4, *ipv6, *port;
223  serverlist_type* serverlist = NULL;
224  serverlist_type* notifylist = NULL;
225 
226  xmlTextReaderPtr reader = NULL;
227  xmlDocPtr doc = NULL;
228  xmlXPathContextPtr xpathCtx = NULL;
229  xmlXPathObjectPtr xpathObj = NULL;
230  xmlNode *curNode = NULL;
231  xmlChar *tsig_expr = (unsigned char*) "//ZoneFetch/Default/TSIG";
232  xmlChar *server_expr = (unsigned char*) "//ZoneFetch/Default/RequestTransfer";
233  xmlChar *notify_expr = (unsigned char*) "//ZoneFetch/NotifyListen";
234 
235  if (filename == NULL) {
236  ods_log_alert("no zone fetcher configfile provided");
237  ods_log_info("zone fetcher exiting...");
238  exit(EXIT_FAILURE);
239  }
240 
241  /* In case zonelist is huge use the XmlTextReader API so that we don't
242  * hold the whole file in memory */
243  reader = xmlNewTextReaderFilename(filename); /* not properly freed */
244  if (reader != NULL) {
245  ret = xmlTextReaderRead(reader);
246  while (ret == 1) {
247  tag_name = (char*) xmlTextReaderLocalName(reader);
248  /* Found <ZoneFetch> */
249  if (strncmp(tag_name, "ZoneFetch", 8) == 0 &&
250  xmlTextReaderNodeType(reader) == 1) {
251 
252  /* Expand this node and get the rest of the info with XPath */
253  xmlTextReaderExpand(reader);
254  doc = xmlTextReaderCurrentDoc(reader);
255  if (doc == NULL) {
256  ods_log_error("can not read zone fetcher configfile "
257  "%s", filename?filename:"(null)");
258  ods_log_info("zone fetcher exiting...");
259  exit(EXIT_FAILURE);
260  }
261  xpathCtx = xmlXPathNewContext(doc);
262  if (xpathCtx == NULL) {
263  ods_log_error("zone fetcher can not create XPath "
264  "context for %s", filename?filename:"(null)");
265  ods_log_info("zone fetcher exiting...");
266  exit(EXIT_FAILURE);
267  }
268 
269  /* Extract the master server address */
270  xpathObj = xmlXPathEvalExpression(server_expr, xpathCtx);
271  if (xpathObj == NULL || !xpathObj->nodesetval) {
272  ods_log_error("zone fetcher can not locate master "
273  "server(s) in %s", filename?filename:"(null)");
274  ods_log_info("zone fetcher exiting...");
275  exit(EXIT_FAILURE);
276  }
277  else {
278  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
279  ipv4 = NULL;
280  ipv6 = NULL;
281  port = NULL;
282  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
283  while (curNode) {
284  if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv4"))
285  ipv4 = (char *) xmlNodeGetContent(curNode);
286  if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv6"))
287  ipv6 = (char *) xmlNodeGetContent(curNode);
288  if (xmlStrEqual(curNode->name, (const xmlChar *)"Port"))
289  port = (char *) xmlNodeGetContent(curNode);
290  curNode = curNode->next;
291  }
292  if (ipv4 || ipv6) {
293  if (serverlist == NULL) {
294  serverlist = new_server(ipv4, ipv6, port); /* not freed */
295  cfg->serverlist = serverlist;
296  }
297  else {
298  serverlist->next = new_server(ipv4, ipv6, port); /* not freed */
299  serverlist = serverlist->next;
300  }
301  }
302 
303  if (ipv4) free((void*) ipv4);
304  if (ipv6) free((void*) ipv6);
305  if (port) free((void*) port);
306  }
307  xmlXPathFreeObject(xpathObj);
308  }
309 
310  /* Extract the notify listen address */
311  xpathObj = xmlXPathEvalExpression(notify_expr, xpathCtx);
312  if (xpathObj != NULL && xpathObj->nodesetval) {
313  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
314  ipv4 = NULL;
315  ipv6 = NULL;
316  port = NULL;
317  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
318  while (curNode) {
319  if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv4"))
320  ipv4 = (char *) xmlNodeGetContent(curNode);
321  if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv6"))
322  ipv6 = (char *) xmlNodeGetContent(curNode);
323  if (xmlStrEqual(curNode->name, (const xmlChar *)"Port"))
324  port = (char *) xmlNodeGetContent(curNode);
325  curNode = curNode->next;
326  }
327  if (ipv4 || ipv6 || port) {
328  if (!ipv4 && !ipv6) {
329  if (notifylist == NULL) {
330  notifylist = new_server(NULL, "", port);
331  cfg->notifylist = notifylist;
332 
333  notifylist->next = new_server("", NULL, port);
334  notifylist = notifylist->next;
335  }
336  else {
337  notifylist->next = new_server("", NULL, port);
338  notifylist = notifylist->next;
339 
340  notifylist->next = new_server(NULL, "", port);
341  notifylist = notifylist->next;
342  }
343  }
344  else if (notifylist == NULL) {
345  notifylist = new_server(ipv4, ipv6, port);
346  cfg->notifylist = notifylist;
347  }
348  else {
349  notifylist->next = new_server(ipv4, ipv6, port);
350  notifylist = notifylist->next;
351  }
352  }
353 
354  if (ipv4) free((void*) ipv4);
355  if (ipv6) free((void*) ipv6);
356  if (port) free((void*) port);
357  }
358  xmlXPathFreeObject(xpathObj);
359  }
360 
361  /* Extract the tsig credentials */
362  xpathObj = xmlXPathEvalExpression(tsig_expr, xpathCtx);
363  if (xpathObj != NULL && xpathObj->nodesetval) {
364  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
365  tsig_name = NULL;
366  tsig_algo = NULL;
367  tsig_secret = NULL;
368  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
369  while (curNode) {
370  if (xmlStrEqual(curNode->name, (const xmlChar *)"Name"))
371  tsig_name = (char *) xmlNodeGetContent(curNode);
372  if (xmlStrEqual(curNode->name, (const xmlChar *)"Algorithm"))
373  tsig_algo = (char *) xmlNodeGetContent(curNode);
374  if (xmlStrEqual(curNode->name, (const xmlChar *)"Secret"))
375  tsig_secret = (char *) xmlNodeGetContent(curNode);
376  curNode = curNode->next;
377  }
378  if (tsig_name && tsig_algo && tsig_secret) {
379  use_tsig = 1;
380  if (cfg->tsig_name) {
381  free((void*) cfg->tsig_name);
382  }
383  if (cfg->tsig_algo) {
384  free((void*) cfg->tsig_algo);
385  }
386  if (cfg->tsig_secret) {
387  free((void*) cfg->tsig_secret);
388  }
389  cfg->tsig_name = strdup(tsig_name);
390  cfg->tsig_algo = strdup(tsig_algo);
391  cfg->tsig_secret = strdup(tsig_secret);
392  }
393  if (tsig_name) {
394  free((void*) tsig_name);
395  }
396  if (tsig_algo) {
397  free((void*) tsig_algo);
398  }
399  if (tsig_secret) {
400  free((void*) tsig_secret);
401  }
402  }
403  xmlXPathFreeObject(xpathObj);
404  }
405  xmlXPathFreeContext(xpathCtx);
406  }
407 
408  /* Read the next line */
409  ret = xmlTextReaderRead(reader);
410  free((void*) tag_name);
411  }
412  xmlFreeTextReader(reader);
413  xmlFreeDoc(doc);
414  if (ret != 0) {
415  ods_log_error("zone fetcher failed to parse config file %s",
416  filename?filename:"(null)");
417  ods_log_info("zone fetcher exiting...");
418  exit(EXIT_FAILURE);
419  }
420  } else {
421  ods_log_error("zone fetcher was unable to open config file %s",
422  filename?filename:"(null)");
423  ods_log_info("zone fetcher exiting...");
424  exit(EXIT_FAILURE);
425  }
426 
427  cfg->use_tsig = use_tsig;
428  return 0;
429 }
430 
431 static zfzonelist_type*
432 read_zonelist(const char* filename)
433 {
434  zfzonelist_type* zonelist = NULL, *zonelist_start = NULL;
435  char* tag_name, *zone_name, *input_file;
436  int ret;
437 
438  xmlTextReaderPtr reader = NULL;
439  xmlDocPtr doc = NULL;
440  xmlXPathContextPtr xpathCtx = NULL;
441  xmlXPathObjectPtr xpathObj = NULL;
442  xmlChar *name_expr = (unsigned char*) "name";
443  xmlChar *adapter_expr = (unsigned char*) "//Zone/Adapters/Input/File";
444 
445  if (filename == NULL) {
446  ods_log_error("no zonelist provided for zone fetcher");
447  ods_log_info("zone fetcher exiting...");
448  exit(EXIT_FAILURE);
449  }
450 
451  /* In case zonelist is huge use the XmlTextReader API so that we don't hold the whole file in memory */
452  reader = xmlNewTextReaderFilename(filename);
453  if (reader != NULL) {
454  ret = xmlTextReaderRead(reader);
455  while (ret == 1) {
456  tag_name = (char*) xmlTextReaderLocalName(reader);
457  /* Found <Zone> */
458  if (strncmp(tag_name, "Zone", 4) == 0 &&
459  strncmp(tag_name, "ZoneList", 8) != 0 &&
460  xmlTextReaderNodeType(reader) == 1) {
461  /* Get the zone name (TODO what if this is null?) */
462  zone_name = (char*) xmlTextReaderGetAttribute(reader, name_expr);
463  /* Make sure that we got something */
464  if (zone_name == NULL) {
465  /* error */
466  ods_log_error("zone fetcher failed to extract zone "
467  "name from %s", filename?filename:"(null)");
468  /* Don't return? try to parse the rest of the zones? */
469  ret = xmlTextReaderRead(reader);
470  continue;
471  }
472  /* Expand this node and get the rest of the info with XPath */
473  xmlTextReaderExpand(reader);
474  doc = xmlTextReaderCurrentDoc(reader);
475  if (doc == NULL) {
476  ods_log_error("zone fetcher could not read zone "
477  "%s; skipping", zone_name);
478  /* Don't return? try to parse the rest of the zones? */
479  ret = xmlTextReaderRead(reader);
480  continue;
481  }
482  xpathCtx = xmlXPathNewContext(doc);
483  if (xpathCtx == NULL) {
484  ods_log_error("zone fetcher can not create XPath "
485  "context for %s; skipping zone", zone_name);
486  /* Don't return? try to parse the rest of the zones? */
487  ret = xmlTextReaderRead(reader);
488  continue;
489  }
490 
491  /* Extract the Input File Adapter filename */
492  xpathObj = xmlXPathEvalExpression(adapter_expr, xpathCtx);
493  if (xpathObj == NULL || !xpathObj->nodesetval) {
494  ods_log_error("zone fetcher was unable to evaluate "
495  "xpath expression: %s; skipping zone", adapter_expr);
496  /* Don't return? try to parse the rest of the zones? */
497  ret = xmlTextReaderRead(reader);
498  continue;
499  }
500  input_file = (char*) xmlXPathCastToString(xpathObj);
501  xmlXPathFreeObject(xpathObj);
502 
503  if (zonelist == NULL) {
504  zonelist = new_zone(zone_name, input_file); /* not freed */
505  zonelist_start = zonelist;
506  }
507  else {
508  zonelist->next = new_zone(zone_name, input_file);
509  zonelist = zonelist->next;
510  }
511  free((void*) zone_name);
512  free((void*) input_file);
513 
514  xmlXPathFreeContext(xpathCtx);
515  }
516 
517  /* Read the next line */
518  ret = xmlTextReaderRead(reader);
519  free((void*) tag_name);
520  }
521  xmlFreeTextReader(reader);
522  xmlFreeDoc(doc);
523  if (ret != 0) {
524  ods_log_error("zone fetcher failed to parse zonelist %s",
525  filename?filename:"(null)");
526  ods_log_info("zone fetcher exiting...");
527  exit(EXIT_FAILURE);
528  }
529  } else {
530  ods_log_error("zone fetcher was unable to open zonelist %s",
531  filename?filename:"(null)");
532  ods_log_info("zone fetcher exiting...");
533  exit(EXIT_FAILURE);
534  }
535 
536  return zonelist_start;
537 }
538 
540 static int
541 writepid(char* pidfile, pid_t pid)
542 {
543  FILE * fd;
544  char pidbuf[32];
545  size_t result = 0, size = 0;
546 
547  snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) pid);
548  if ((fd = fopen(pidfile, "w")) == NULL ) {
549  ods_log_error("zone fetcher could not open pidfile %s for "
550  "writing: %s", pidfile?pidfile:"(null)", strerror(errno));
551  return -1;
552  }
553  size = strlen(pidbuf);
554  if (size == 0)
555  result = 1;
556  result = fwrite((const void*) pidbuf, 1, size, fd);
557  if (result == 0) {
558  ods_log_error("zone fetcher failed to write to pidfile: %s",
559  strerror(errno));
560  } else if (result < size) {
561  ods_log_error("zone fetcher had short write to pidfile "
562  "(disk full?)");
563  result = 0;
564  } else
565  result = 1;
566  if (!result) {
567  ods_log_error("zone fetcher could not write pidfile %s: %s",
568  pidfile?pidfile:"(null)", strerror(errno));
569  fclose(fd);
570  return -1;
571  }
572  fclose(fd);
573  return 0;
574 }
575 
577 static void
578 sig_handler(int sig)
579 {
580  switch (sig)
581  {
582  case SIGTERM:
583  sig_quit = 1;
584  break;
585  case SIGHUP:
586  sig_reload = 1;
587  break;
588  default:
589  break;
590  }
591  return;
592 }
593 
594 static int
595 init_sockets(sockets_type* sockets, serverlist_type* list)
596 {
597  int ret = 0, r, ip6_support = 1, on = 0;
598  size_t i;
599  struct addrinfo hints[MAX_INTERFACES];
600  serverlist_type* walk = list;
601  serverlist_type* new_list = NULL;
602  const char* node = NULL;
603  const char* port = NULL;
604 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
605  on = 1;
606 #endif
607 
608  for (i = 0; i < MAX_INTERFACES; i++) {
609  memset(&hints[i], 0, sizeof(hints[i]));
610  hints[i].ai_family = AF_UNSPEC;
611  hints[i].ai_flags = AI_PASSIVE;
612  sockets->udp[i].s = -1;
613  sockets->tcp[i].s = -1;
614  }
615 
616  /* if no NotifyListen was provided, we create the default IPv4/IPv6
617  * address info structures */
618  if (!walk) {
619 #ifdef IPV6_V6ONLY
620  hints[0].ai_family = AF_INET6;
621  hints[1].ai_family = AF_INET;
622  new_list = new_server(NULL, "", NULL);
623  new_list->next = new_server("", NULL, NULL);
624 #else /* !IPV6_V6ONLY */
625  hints[0].ai_family = AF_INET6;
626  new_list = new_server(NULL, "", NULL);
627 #endif /* IPV6_V6ONLY */
628  walk = new_list;
629  }
630 
631  i = 0;
632  while (walk) {
633  node = strlen(walk->ipaddr) > 0 ? walk->ipaddr : NULL;
634  port = walk->port ? walk->port : DNS_PORT_STRING;
635  if (node != NULL)
636  hints[i].ai_flags |= AI_NUMERICHOST;
637  else
638  hints[i].ai_family = walk->family;
639  /* UDP */
640  hints[i].ai_socktype = SOCK_DGRAM;
641  /* getaddrinfo */
642  if ((r = getaddrinfo(node, port, &hints[i],
643  &(sockets->udp[i].addr))) != 0) {
644  if (hints[i].ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
645  ods_log_error("zone fetcher udp fallback to ipv4, no ipv6: "
646  " not supported");
647  ip6_support = 0;
648  continue;
649  }
650  ods_log_error("zone fetcher cannot parse address %s:%s: "
651  "getaddrinfo (%i): %s %s", node?node:"(null)",
652  port?port:"(null)", walk->family,
653  gai_strerror(r), r==EAI_SYSTEM?strerror(errno):"");
654  }
655 
656  /* socket */
657  if ((sockets->udp[i].s = socket(sockets->udp[i].addr->ai_family,
658  SOCK_DGRAM, 0)) == -1) {
659  if (sockets->udp[i].addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
660  ods_log_error("zone fetcher udp fallback to ipv4, no ipv6: "
661  " not supported");
662  ip6_support = 0;
663  }
664  else {
665  ods_log_error("zone fetcher can't create udp/4 socket for "
666  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
667  strerror(errno));
668  ret = -1;
669  break;
670  }
671  }
672 
673  if (sockets->udp[i].addr->ai_family == AF_INET) {
674  if (fcntl(sockets->udp[i].s, F_SETFL,
675  O_NONBLOCK) == -1) {
676  ods_log_error("zone fetcher cannot fcntl udp/4 socket for "
677  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
678  strerror(errno));
679  }
680  if (bind(sockets->udp[i].s,
681  (struct sockaddr *) sockets->udp[i].addr->ai_addr,
682  sockets->udp[i].addr->ai_addrlen) != 0)
683  {
684  ods_log_error("zone fetcher can't bind udp/4 socket for "
685  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
686  strerror(errno));
687  ret = -1;
688  break;
689  }
690  }
691  else if (ip6_support) {
692 #ifdef IPV6_V6ONLY
693 #if defined(IPPROTO_IPV6)
694  ods_log_verbose("zone fetcher setsockopt ipv6_v6only...");
695  if (setsockopt(sockets->udp[i].s, IPPROTO_IPV6, IPV6_V6ONLY, &on,
696  sizeof(on)) < 0)
697  {
698  ods_log_error("zone fetcher setsockopt(..., IPV6_V6ONLY, "
699  "...) failed for "
700  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
701  strerror(errno));
702  ret = -1;
703  break;
704  }
705 #endif
706 #endif /* IPV6_V6ONLY */
707  if (fcntl(sockets->udp[i].s, F_SETFL, O_NONBLOCK) == -1) {
708  ods_log_error("zone fetcher cannot fcntl udp/6 socket for "
709  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
710  strerror(errno));
711  }
712  if (bind(sockets->udp[i].s,
713  (struct sockaddr *) sockets->udp[i].addr->ai_addr,
714  sockets->udp[i].addr->ai_addrlen) != 0) {
715  ods_log_error("zone fetcher can't bind udp/6 socket for "
716  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
717  strerror(errno));
718  ret = -1;
719  break;
720  }
721  }
722 
723  /* TCP */
724  hints[i].ai_socktype = SOCK_STREAM;
725  /* getaddrinfo */
726  if ((r = getaddrinfo(node, port, &hints[i],
727  &(sockets->tcp[i].addr))) != 0) {
728  if (hints[i].ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
729  ods_log_error("zone fetcher tcp fallback to ipv4, no ipv6: "
730  " not supported");
731  ip6_support = 0;
732  continue;
733  }
734  ods_log_error("zone fetcher cannot parse address %s:%s: "
735  "getaddrinfo (%i): %s %s", node?node:"(null)",
736  port?port:"(null)", walk->family,
737  gai_strerror(r), r==EAI_SYSTEM?strerror(errno):"");
738  }
739  /* socket */
740  if ((sockets->tcp[i].s = socket(sockets->tcp[i].addr->ai_family,
741  SOCK_STREAM, 0)) == -1) {
742  if (sockets->tcp[i].addr->ai_family == AF_INET6 &&
743  errno == EAFNOSUPPORT) {
744  ods_log_error("zone fetcher tcp fallback to ipv4, no ipv6: "
745  " not supported");
746  ip6_support = 0;
747  }
748  else {
749  ods_log_error("zone fetcher can't create tcp socket for "
750  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
751  strerror(errno));
752  ret = -1;
753  break;
754  }
755  }
756  /* setsockopt */
757  if (sockets->tcp[i].addr->ai_family == AF_INET) {
758  if (setsockopt(sockets->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on,
759  sizeof(on)) < 0) {
760  ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) "
761  "failed for "
762  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
763  strerror(errno));
764  }
765  /* fcntl */
766  if (fcntl(sockets->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) {
767  ods_log_error("zone fetcher cannot fcntl tcp/4 for "
768  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
769  strerror(errno));
770  }
771  /* bind */
772  if (bind(sockets->tcp[i].s,
773  (struct sockaddr *) sockets->tcp[i].addr->ai_addr,
774  sockets->tcp[i].addr->ai_addrlen) != 0) {
775  ods_log_error("zone fetcher can't bind tcp/4 socket for "
776  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
777  strerror(errno));
778  ret = -1;
779  break;
780  }
781  /* listen */
782  if (listen(sockets->tcp[i].s, 5) == -1) {
783  ods_log_error("zone fetcher can't listen to tcp/4 socket for "
784  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
785  strerror(errno));
786  ret = -1;
787  break;
788  }
789  } else if (ip6_support) {
790  /* setsockopt */
791  if (sockets->tcp[i].addr->ai_family == AF_INET6 && ip6_support) {
792 #ifdef IPV6_V6ONLY
793 #if defined(IPPROTO_IPV6)
794  if (setsockopt(sockets->tcp[i].s, IPPROTO_IPV6, IPV6_V6ONLY, &on,
795  sizeof(on)) < 0)
796  {
797  ods_log_error("zone fetcher setsockopt(..., IPV6_V6ONLY, "
798  "...) failed for "
799  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
800  strerror(errno));
801  ret = -1;
802  break;
803  }
804 #endif
805 #endif /* IPV6_V6ONLY */
806  }
807  if (setsockopt(sockets->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on,
808  sizeof(on)) < 0) {
809  ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) "
810  "failed for "
811  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
812  strerror(errno));
813  }
814  /* fcntl */
815  if (fcntl(sockets->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) {
816  ods_log_error("zone fetcher cannot fcntl tcp/6 for "
817  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
818  strerror(errno));
819  }
820  /* bind */
821  if (bind(sockets->tcp[i].s,
822  (struct sockaddr *) sockets->tcp[i].addr->ai_addr,
823  sockets->tcp[i].addr->ai_addrlen) != 0) {
824  ods_log_error("zone fetcher can't bind tcp/6 socket for "
825  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
826  strerror(errno));
827  ret = -1;
828  break;
829  }
830  /* listen */
831  if (listen(sockets->tcp[i].s, 5) == -1) {
832  ods_log_error("zone fetcher can't listen to tcp/6 socket for "
833  "%s:%s (%s)", node?node:"(null)", port?port:"(null)",
834  strerror(errno));
835  ret = -1;
836  break;
837  }
838  }
839 
840  walk = walk->next;
841  i++;
842  }
843 
844  if (new_list) {
845  free_serverlist(new_list);
846  }
847 
848  return ret;
849 }
850 
851 static void
852 free_sockets(sockets_type* sockets)
853 {
854  size_t i = 0;
855 
856  for (i=0; i < MAX_INTERFACES; i++) {
857  if (sockets->udp[i].s != -1) {
858  close(sockets->udp[i].s);
859  freeaddrinfo((void*)sockets->udp[i].addr);
860  }
861  if (sockets->tcp[i].s != -1) {
862  close(sockets->tcp[i].s);
863  freeaddrinfo((void*)sockets->tcp[i].addr);
864  }
865  }
866 }
867 
868 static int
869 odd_xfer(zfzonelist_type* zone, uint32_t serial, config_type* config, int kick_signer)
870 {
871  ldns_status status = LDNS_STATUS_OK;
872  ldns_rr* axfr_rr = NULL, *soa_rr = NULL;
873  uint32_t new_serial = 0;
874  ldns_pkt* qpkt = NULL, *apkt;
875  FILE* fd = NULL;
876  char lock_ext[32];
877  char axfr_file[MAXPATHLEN];
878  char dest_file[MAXPATHLEN];
879  char lock_file[MAXPATHLEN];
880  char engine_sign_cmd[MAXPATHLEN + 1024];
881  int soa_seen = 0;
882  ldns_resolver* xfrd = NULL;
883 
884  /* soa serial query */
885  if (!zone || !zone->dname) {
886  ods_log_error("zone fetcher failed to provide a zone for AXFR ");
887  return -1;
888  }
889 /* Coverity comment:
890  Event deref_ptr: Directly dereferenced pointer "zone"
891 */
892  qpkt = ldns_pkt_query_new(ldns_rdf_clone(zone->dname),
893  LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD);
894  if (!qpkt) {
895  ods_log_error("zone fetcher failed to create SOA query. "
896  "Aborting AXFR");
897  return -1;
898  }
899 
900  /* Initialise LDNS resolver for AXFR */
901  xfrd = init_xfrd(config);
902 
903  if (!xfrd) {
904  ods_log_error("zone fetcher failed to initialise AXFR structure");
905  return -1;
906  }
907 
908  status = ldns_resolver_send_pkt(&apkt, xfrd, qpkt);
909  ldns_pkt_free(qpkt);
910 
911  if (status != LDNS_STATUS_OK) {
912  ods_log_error("zone fetcher failed to send SOA query: %s",
913  ldns_get_errorstr_by_id(status));
914  ldns_resolver_deep_free(xfrd);
915  return -1;
916  }
917  if (ldns_pkt_ancount(apkt) == 1) {
918  soa_rr = ldns_rr_list_rr(ldns_pkt_answer(apkt), 0);
919  if (soa_rr && ldns_rr_get_type(soa_rr) == LDNS_RR_TYPE_SOA) {
920  new_serial = ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2));
921  }
922  ldns_pkt_free(apkt);
923  } else {
924  ods_log_error("zone fetcher saw SOA response with ANCOUNT != 1, "
925  "Aborting AXFR");
926  /* retry? */
927  ldns_pkt_free(apkt);
928  ldns_resolver_deep_free(xfrd);
929  return -1;
930  }
931 
932  if (DNS_SERIAL_GT(new_serial, serial)) {
933  status = ldns_axfr_start(xfrd, zone->dname, LDNS_RR_CLASS_IN);
934  if (status != LDNS_STATUS_OK) {
935  ods_log_error("zone fetcher failed to start axfr: %s",
936  ldns_get_errorstr_by_id(status));
937  ldns_resolver_deep_free(xfrd);
938  return -1;
939  }
940 
941 /* Coverity comment:
942  Event check_after_deref: Pointer "zone" dereferenced before NULL check
943 */
944  if (zone && zone->input_file) {
945  snprintf(lock_ext, sizeof(lock_ext), "axfr.%lu",
946  (unsigned long) getpid());
947 
948  snprintf(axfr_file, sizeof(axfr_file), "%s.%s", zone->input_file, lock_ext);
949  fd = fopen(axfr_file, "w");
950  if (!fd) {
951  ods_log_error("zone fetcher cannot store AXFR to file %s", axfr_file);
952  ldns_resolver_deep_free(xfrd);
953  return -1;
954  }
955  }
956  assert(fd);
957 
958  axfr_rr = ldns_axfr_next(xfrd);
959  if (!axfr_rr) {
960  ods_log_error("zone fetcher AXFR for %s failed",
961  zone->name?zone->name:"(null)");
962  fclose(fd);
963  unlink(axfr_file);
964  ldns_resolver_deep_free(xfrd);
965  return -1;
966  }
967  else {
968  while (axfr_rr) {
969  if (ldns_rr_get_type(axfr_rr) == LDNS_RR_TYPE_SOA) {
970  if (!soa_seen) {
971  soa_seen = 1;
972  ldns_rr_print(fd, axfr_rr);
973  }
974  } else {
975  ldns_rr_print(fd, axfr_rr);
976  }
977  ldns_rr_free(axfr_rr);
978  axfr_rr = ldns_axfr_next(xfrd);
979  }
980 
981  /* RoRi:
982  * We MUST now check if the AXFR was successful by verifying that
983  * LDNS has seen the SOA record twice. Not doing this can result
984  * in a half-transferred zone if the AXFR is interrupted.
985  */
986  if (!ldns_axfr_complete(xfrd)) {
987  /* The AXFR was not successful, we've received only a partial zone */
988  ods_log_error("zone fetcher AXFR for %s failed, received only a partial zone", zone->name);
989  fclose(fd);
990  unlink(axfr_file);
991  ldns_resolver_deep_free(xfrd);
992  return -1;
993  }
994 
995  ods_log_info("zone fetcher transferred zone %s serial %u "
996  "successfully", zone->name?zone->name:"(null)", new_serial);
997 
998  /* Close file before moving it */
999  fclose(fd);
1000 
1001  /* moving and kicking */
1002  snprintf(lock_file, sizeof(lock_file), "%s.lock",
1003  zone->input_file?zone->input_file:"(null)");
1004 
1005 lock_axfr:
1006  if (access(lock_file, F_OK) == 0) {
1007  ods_log_deeebug("zone fetcher axfr file %s is locked, "
1008  "waiting...", dest_file);
1009  sleep(1);
1010  goto lock_axfr;
1011  } else {
1012  fd = fopen(lock_file, "w");
1013  if (!fd) {
1014  ods_log_error("zone fetcher cannot lock AXFR file %s",
1015  lock_file);
1016  ldns_resolver_deep_free(xfrd);
1017  return -1;
1018  }
1019  }
1020  assert(fd); /* locked */
1021 
1022  snprintf(dest_file, sizeof(dest_file), "%s.axfr",
1023  zone->input_file?zone->input_file:"(null)");
1024  if(rename(axfr_file, dest_file) == 0) {
1025  fclose(fd);
1026  (void) unlink(lock_file); /* unlocked */
1027 
1028  if (kick_signer) {
1029  snprintf(engine_sign_cmd, sizeof(engine_sign_cmd),
1030  "%s sign %s > /dev/null 2>&1",
1031  ODS_SE_CLI, zone->name?zone->name:"--all");
1032  if (system(engine_sign_cmd) != 0) {
1033  ods_log_error("zone fetcher could not kick "
1034  "the signer engine to sign zone %s",
1035  zone->name?zone->name:"--all");
1036  }
1037  }
1038  } else {
1039  fclose(fd);
1040  (void) unlink(lock_file); /* unlocked */
1041 
1042  ods_log_error("zone fetcher could not move AXFR to %s",
1043  dest_file);
1044  }
1045  ldns_resolver_deep_free(xfrd);
1046  return 0;
1047  }
1048  } else {
1049  ods_log_info("zone fetcher zone %s is already up to date, "
1050  "serial is %u", zone->name?zone->name:"(null)", serial);
1051  }
1052 
1053  ldns_resolver_deep_free(xfrd);
1054  return 0;
1055 }
1056 
1057 static void
1058 send_udp(uint8_t* buf, size_t len, void* data)
1059 {
1060  struct handle_udp_userdata *userdata = (struct handle_udp_userdata*)data;
1061  /* udp send reply */
1062  ssize_t nb;
1063  nb = sendto(userdata->udp_sock, buf, len, 0,
1064  (struct sockaddr*)&userdata->addr_him, userdata->hislen);
1065  if (nb == -1)
1066  ods_log_error("zone fetcher sendto() failed: %s", strerror(errno));
1067  else if ((size_t)nb != len)
1068  ods_log_error("zone fetcher sendto(): only sent %d of %d octets.",
1069  (int)nb, (int)len);
1070 }
1071 
1072 static void
1073 write_n_bytes(int sock, uint8_t* buf, size_t sz)
1074 {
1075  size_t count = 0;
1076  while(count < sz) {
1077  ssize_t nb = send(sock, buf+count, sz-count, 0);
1078  if(nb < 0) {
1079  ods_log_error("zone fetcher send() failed: %s",
1080  strerror(errno));
1081  return;
1082  }
1083  count += nb;
1084  }
1085 }
1086 
1087 static void
1088 send_tcp(uint8_t* buf, size_t len, void* data)
1089 {
1090  struct handle_tcp_userdata *userdata = (struct handle_tcp_userdata*)data;
1091  uint16_t tcplen;
1092  /* tcp send reply */
1093  tcplen = htons(len);
1094  write_n_bytes(userdata->s, (uint8_t*)&tcplen, sizeof(tcplen));
1095  write_n_bytes(userdata->s, buf, len);
1096 }
1097 
1098 static void
1099 handle_query(uint8_t* inbuf, ssize_t inlen,
1100  void (*sendfunc)(uint8_t*, size_t, void*),
1101  void* userdata, config_type* config)
1102 {
1103  zfzonelist_type* zonelist = NULL;
1104  ldns_status status = LDNS_STATUS_OK;
1105  ldns_pkt *query_pkt = NULL;
1106  ldns_rr *query_rr = NULL;
1107  uint32_t serial = 0;
1108  char* owner_name = NULL;
1109  uint8_t *outbuf = NULL;
1110  size_t answer_size = 0;
1111  char dest_file[MAXPATHLEN];
1112  FILE* fd;
1113 
1114  /* packet parsing */
1115  status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen);
1116  if (status != LDNS_STATUS_OK) {
1117  ods_log_error("zone fetcher got bad packet: %s",
1118  ldns_get_errorstr_by_id(status));
1119  return;
1120  }
1121  query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
1122 
1123  if (ldns_pkt_get_opcode(query_pkt) != LDNS_PACKET_NOTIFY ||
1124  ldns_pkt_get_rcode(query_pkt) != LDNS_RCODE_NOERROR ||
1125  ldns_pkt_qr(query_pkt) ||
1126  !ldns_pkt_aa(query_pkt) ||
1127  ldns_pkt_tc(query_pkt) ||
1128  ldns_pkt_rd(query_pkt) ||
1129  ldns_pkt_ra(query_pkt) ||
1130  ldns_pkt_cd(query_pkt) ||
1131  ldns_pkt_ad(query_pkt) ||
1132  ldns_pkt_qdcount(query_pkt) != 1 ||
1133  ldns_pkt_nscount(query_pkt) != 0 ||
1134  ldns_pkt_arcount(query_pkt) != 0 ||
1135  ldns_rr_get_type(query_rr) != LDNS_RR_TYPE_SOA ||
1136  ldns_rr_get_class(query_rr) != LDNS_RR_CLASS_IN)
1137  {
1138  ods_log_info("zone fetcher drop bad notify");
1139  return;
1140  }
1141 
1142  /* NOTIFY OK */
1143  if (config) {
1144  zonelist = config->zonelist;
1145  }
1146  ldns_pkt_set_qr(query_pkt, 1);
1147  status = ldns_pkt2wire(&outbuf, query_pkt, &answer_size);
1148  if (status != LDNS_STATUS_OK) {
1149  ods_log_error("zone fetcher error creating notify response: %s",
1150  ldns_get_errorstr_by_id(status));
1151  }
1152  sendfunc(outbuf, answer_size, userdata);
1153  LDNS_FREE(outbuf);
1154 
1155  /* send AXFR request */
1156  while (zonelist) {
1157  if (ldns_dname_compare(ldns_rr_owner(query_rr), zonelist->dname) == 0)
1158  {
1159  ods_log_info("zone fetcher received NOTIFY for zone %s",
1160  zonelist->name?zonelist->name:"(null)");
1161  /* get latest serial */
1162  snprintf(dest_file, sizeof(dest_file), "%s.axfr",
1163  zonelist->input_file?zonelist->input_file:"(null)");
1164  fd = fopen(dest_file, "r");
1165  if (!fd) {
1166  serial = 0;
1167  } else {
1168  serial = lookup_serial(fd);
1169  fclose(fd);
1170  }
1171  if (odd_xfer(zonelist, serial, config, 1) != 0) {
1172  ods_log_error("AXFR for zone %s failed",
1173  zonelist->name?zonelist->name:"(null)");
1174  }
1175  ldns_pkt_free(query_pkt);
1176  return;
1177  }
1178  /* next */
1179  zonelist = zonelist->next;
1180  }
1181  owner_name = ldns_rdf2str(ldns_rr_owner(query_rr));
1182  ods_log_warning("zone fetcher notify received for unknown zone: %s",
1183  owner_name?owner_name:"(null)");
1184  free((void*)owner_name);
1185  ldns_pkt_free(query_pkt);
1186 }
1187 
1188 static void
1189 read_n_bytes(int sock, uint8_t* buf, size_t sz)
1190 {
1191  size_t count = 0;
1192  while(count < sz) {
1193  ssize_t nb = recv(sock, buf+count, sz-count, 0);
1194  if(nb < 0) {
1195  ods_log_error("zone fetcher recv() failed: %s",
1196  strerror(errno));
1197  return;
1198  }
1199  count += nb;
1200  }
1201 }
1202 
1203 static char*
1204 addr2ip(struct sockaddr_storage addr, char* remote, size_t len)
1205 {
1206  if (addr.ss_family == AF_INET6) {
1207  if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
1208  remote, len)) {
1209  return NULL;
1210  }
1211  } else {
1212  if (!inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr,
1213  remote, len))
1214  return NULL;
1215  }
1216 
1217  return remote;
1218 }
1219 
1220 static int
1221 acl_matches(struct sockaddr_storage* addr, config_type* config)
1222 {
1223  serverlist_type* serverlist = NULL;
1224 
1225  if (config && config->serverlist) {
1226  serverlist = config->serverlist;
1227  while (serverlist) {
1228  if (serverlist->family == AF_INET6) {
1229  struct sockaddr_in6* addr6 = (struct sockaddr_in6*)addr;
1230  if (serverlist->family == addr->ss_family &&
1231  memcmp(&addr6->sin6_addr, &serverlist->addr.addr6,
1232  sizeof(struct in6_addr)) == 0)
1233  {
1234  return 1;
1235  }
1236  }
1237  else {
1238  struct sockaddr_in* addr4 = (struct sockaddr_in*)addr;
1239  if (serverlist->family == addr4->sin_family &&
1240  memcmp(&addr4->sin_addr, &serverlist->addr.addr,
1241  sizeof(struct in_addr)) == 0)
1242  {
1243  return 1;
1244  }
1245  }
1246 
1247  serverlist = serverlist->next;
1248  }
1249  }
1250  return 0;
1251 }
1252 
1253 static void
1254 handle_udp(int udp_sock, config_type* config)
1255 {
1256  ssize_t nb;
1257  uint8_t inbuf[INBUF_SIZE];
1258  struct handle_udp_userdata userdata;
1259  char* remote;
1260 
1261  userdata.udp_sock = udp_sock;
1262  userdata.hislen = (socklen_t) sizeof(userdata.addr_him);
1263  nb = recvfrom(udp_sock, inbuf, INBUF_SIZE, 0,
1264  (struct sockaddr*) &userdata.addr_him, &userdata.hislen);
1265  if (nb < 1) {
1266  ods_log_error("zone fetcher recvfrom() failed: %s",
1267  strerror(errno));
1268  return;
1269  }
1270 
1271  /* acl */
1272  if (!acl_matches(&userdata.addr_him, config)) {
1273  remote = (char*) malloc(sizeof(char)*userdata.hislen);
1274  ods_log_warning("zone fetcher refused message from "
1275  "unauthoritative source: %s",
1276  addr2ip(userdata.addr_him, remote, userdata.hislen));
1277  free((void*)remote);
1278  return;
1279  }
1280  handle_query(inbuf, nb, send_udp, &userdata, config);
1281 }
1282 
1283 static void
1284 handle_tcp(int tcp_sock, config_type* config)
1285 {
1286  int s;
1287  struct sockaddr_storage addr_him;
1288  socklen_t hislen;
1289  uint8_t inbuf[INBUF_SIZE];
1290  uint16_t tcplen;
1291  struct handle_tcp_userdata userdata;
1292  char* remote;
1293 
1294  /* accept */
1295  hislen = (socklen_t)sizeof(addr_him);
1296  if((s = accept(tcp_sock, (struct sockaddr*)&addr_him, &hislen)) < 0) {
1297  ods_log_error("zone fetcher accept() failed: %s", strerror(errno));
1298  return;
1299  }
1300  userdata.s = s;
1301 
1302  /* tcp recv */
1303  read_n_bytes(s, (uint8_t*)&tcplen, sizeof(tcplen));
1304  tcplen = ntohs(tcplen);
1305  if(tcplen >= INBUF_SIZE) {
1306  ods_log_error("zone fetcher query %d bytes too large, "
1307  "buffer %d bytes.", tcplen, INBUF_SIZE);
1308  close(s);
1309  return;
1310  }
1311  read_n_bytes(s, inbuf, tcplen);
1312 
1313  /* acl */
1314  if (!acl_matches(&addr_him, config)) {
1315  remote = (char*) malloc(sizeof(char)*hislen);
1316  ods_log_warning("zone fetcher refused message from "
1317  "unauthoritative source: %s",
1318  addr2ip(addr_him, remote, hislen));
1319  free((void*)remote);
1320  close(s);
1321  return;
1322  }
1323  handle_query(inbuf, (ssize_t) tcplen, send_tcp, &userdata, config);
1324  close(s);
1325 }
1326 
1327 
1332 static void
1333 reload_zonelist(config_type *config) {
1334  zfzonelist_type *new_zonelist, **thisp;
1335  zfzonelist_type *added_zonelist = NULL, *kept_zonelist = NULL;
1336  int added_count = 0, changed_count = 0, kept_count = 0;
1337  /* Fail softly if the zonelist cannot be accessed for reloading */
1338  if (!config->zonelist_file) {
1339  ods_log_error("zone fetcher is unable to access the zonelist");
1340  return;
1341  } else {
1342  ods_log_verbose("zone fetcher will reload the zonelist");
1343  }
1344  /* Read the zonelist file and construct a new linked list of zonelist entries */
1345  new_zonelist = read_zonelist (config->zonelist_file);
1346  /* Iterate over the new zonelist file and compare it to previously configured zonelist entries */
1347  while (new_zonelist) {
1348  zfzonelist_type *next_zonelist = new_zonelist->next;
1349  zfzonelist_type *this = config->zonelist;
1350  int found = 0;
1351  while (this && !found) {
1352  found = !strcmp (this->name, new_zonelist->name);
1353  if (!found) {
1354  this = this->next;
1355  }
1356  }
1357 
1358  /* If the zone name is found in the old zonelist, it is either a full match or a replacement */
1359  if (found) {
1360  if (strcmp (new_zonelist->input_file, this->input_file)) {
1361  /* the zonelist entry has changed -- treat as a replacement/new zonelist entry */
1362  changed_count++;
1363  new_zonelist->next = added_zonelist;
1364  added_zonelist = new_zonelist;
1365  } else {
1366  /* the zonelist entry is already configured -- treat as a kept zonelist entry */
1367  kept_count++;
1368  new_zonelist->next = kept_zonelist;
1369  kept_zonelist = new_zonelist;
1370  }
1371  } else {
1372  /* new_zonelist introduces a new zonelist entry */
1373  added_count++;
1374  new_zonelist->next = added_zonelist;
1375  added_zonelist = new_zonelist;
1376  }
1377  new_zonelist = next_zonelist;
1378  }
1379 
1380  /* Replace the configured zonelist with the added_zonelist and kept_zonelist */
1381  free_zonelist (config->zonelist);
1382  config->zonelist = kept_zonelist;
1383  thisp = &config->zonelist;
1384  while (*thisp) {
1385  thisp = &(*thisp)->next;
1386  }
1387  *thisp = added_zonelist;
1388 
1389  /* Perform an initial AXFR for the newly added zones (assume no present inputfile) */
1390  new_zonelist = added_zonelist;
1391  while (new_zonelist) {
1392  /* send the request -- assume no file is present so SOA is 0 */
1393  if (odd_xfer (new_zonelist, 0, config, 1) != 0) {
1394  ods_log_error("AXFR for new zone %s failed", new_zonelist->name);
1395  }
1396  /* next */
1397  new_zonelist = new_zonelist->next;
1398  }
1399  ods_log_verbose("Reloaded zonelist -- kept %d, changed %d and added %d zones",
1400  kept_count, changed_count, added_count);
1401  return;
1402 }
1403 
1404 
1405 static void
1406 xfrd_ns(sockets_type* sockets, config_type* cfg)
1407 {
1408  fd_set rset, wset, eset;
1409  struct timeval timeout;
1410  int count, maxfd = 0;
1411  size_t i;
1412 
1413  /* service */
1414  count = 0;
1415  timeout.tv_sec = 0;
1416  timeout.tv_usec = 0;
1417  while (!sig_quit) {
1418  if (sig_reload) {
1419  reload_zonelist(cfg);
1420  sig_reload = 0;
1421  }
1422  FD_ZERO(&rset);
1423  FD_ZERO(&wset);
1424  FD_ZERO(&eset);
1425  for (i=0; i < MAX_INTERFACES; i++) {
1426  if (sockets->udp[i].s != -1)
1427  FD_SET(sockets->udp[i].s, &rset);
1428  if (sockets->tcp[i].s != -1)
1429  FD_SET(sockets->tcp[i].s, &rset);
1430  if (sockets->udp[i].s > maxfd) maxfd = sockets->udp[i].s;
1431  if (sockets->tcp[i].s > maxfd) maxfd = sockets->tcp[i].s;
1432  }
1433 
1434  if (select(maxfd+1, &rset, &wset, &eset, NULL) < 0) {
1435  if (errno == EINTR)
1436  continue;
1437  ods_log_error("zone fetcher select(): %s", strerror(errno));
1438  }
1439 
1440  for (i=0; i < MAX_INTERFACES; i++) {
1441  if (sockets->udp[i].s != -1 && FD_ISSET(sockets->udp[i].s, &rset))
1442  handle_udp(sockets->udp[i].s, cfg);
1443  if (sockets->tcp[i].s != -1 && FD_ISSET(sockets->tcp[i].s, &rset))
1444  handle_tcp(sockets->tcp[i].s, cfg);
1445  }
1446  }
1447 }
1448 
1449 static void
1450 list_settings(FILE* out, config_type* config, const char* filename)
1451 {
1452  zfzonelist_type* zones = NULL;
1453  serverlist_type* servers = NULL;
1454 
1455  if (config) {
1456  fprintf(out, "configuration settings:\n");
1457  fprintf(out, "filename: %s\n", filename?filename:"(null)");
1458  fprintf(out, "pidfile: %s\n",
1459  config->pidfile?config->pidfile:"(null)");
1460  fprintf(out, "tsig: %s\n", config->use_tsig?"yes":"no");
1461  if (config->use_tsig) {
1462  fprintf(out, "tsig name: %s\n",
1463  config->tsig_name?config->tsig_name:"(null)");
1464  fprintf(out, "tsig algorithm: %s\n",
1465  config->tsig_algo?config->tsig_algo:"(null)");
1466  fprintf(out, "tsig secret: ?\n");
1467  }
1468  fprintf(out, "zones: %s\n", config->zonelist?"":"none");
1469  zones = config->zonelist;
1470  while (zones) {
1471  fprintf(out, "\t%s\n", zones->name?zones->name:"(null)");
1472  zones = zones->next;
1473  }
1474  fprintf(out, "master servers: %s\n", config->serverlist?"":"none");
1475  servers = config->serverlist;
1476  while (servers) {
1477  fprintf(out, "\t%s\n", servers->ipaddr?servers->ipaddr:"(null)");
1478  servers = servers->next;
1479  }
1480  fprintf(out, "interfaces: %s\n", config->notifylist?"":"none");
1481  servers = config->notifylist;
1482  while (servers) {
1483  fprintf(out, "\t%s %s:%s\n",
1484  servers->family==AF_INET6?"ipv6":"ipv4",
1485  servers->ipaddr?servers->ipaddr:"(null)",
1486  servers->port?servers->port:"(null)");
1487  servers = servers->next;
1488  }
1489  fprintf(out, "list zone fetcher settings done.\n");
1490  }
1491  else fprintf(out, "no config\n");
1492 }
1493 
1494 int
1495 tools_zone_fetcher(const char* config_file, const char* zonelist_file,
1496  const char* group, const char* user, const char* chroot, const char* log_file,
1497  int use_syslog, int verbosity)
1498 {
1499  zfzonelist_type *zonelist = NULL;
1500  config_type* config = NULL;
1501  uint32_t serial = 0;
1502  FILE* fd;
1503  sockets_type sockets;
1504  int c, info = 0;
1505  int error = 0;
1506  struct sigaction action;
1507  uid_t uid = -1;
1508  gid_t gid = -1;
1509 
1510  ods_log_init(log_file, use_syslog, verbosity);
1511 
1512  /* read transfer configuration */
1513  config = new_config();
1514  config->pidfile = strdup(ODS_ZF_PIDFILE); /* not freed */
1515  if (!config->pidfile) {
1516  ods_log_alert("zone fetcher error: no pidfile given");
1517  free_config(config);
1518  exit(EXIT_FAILURE);
1519  }
1520 
1521  c = read_axfr_config(config_file, config);
1522  config->zonelist = read_zonelist(zonelist_file);
1523  config->zonelist_file = strdup(zonelist_file);
1524 
1525  if (info) {
1526  list_settings(stdout, config, config_file);
1527  }
1528 
1529  if (config->serverlist == NULL) {
1530  ods_log_alert("zone fetcher error: no master servers configured "
1531  "with <RequestTransfer>");
1532  free_config(config);
1533  exit(EXIT_FAILURE);
1534  }
1535 
1536  /* setup signal handing */
1537  action.sa_handler = sig_handler;
1538  sigfillset(&action.sa_mask);
1539  action.sa_flags = 0;
1540  sigaction(SIGHUP, &action, NULL);
1541  sigaction(SIGTERM, &action, NULL);
1542 
1543  /* write pidfile */
1544  if (writepid(config->pidfile, getpid()) != 0) {
1545  ods_log_error("write pidfile %s failed", config->pidfile);
1546  ods_log_info("zone fetcher exiting...");
1547  exit(EXIT_FAILURE);
1548  }
1549 
1550  ods_log_info("zone fetcher started");
1551 
1552  /* foreach zone, do a single axfr request */
1553  zonelist = config->zonelist;
1554  while (zonelist != NULL) {
1555  /* get latest serial */
1556  fd = fopen(zonelist->input_file, "r");
1557  if (!fd) {
1558  serial = 0;
1559  } else {
1560  serial = lookup_serial(fd);
1561  fclose(fd);
1562  }
1563  /* send the request */
1564  if (odd_xfer(zonelist, serial, config, 1) != 0) {
1565  ods_log_error("AXFR for zone %s failed",
1566  zonelist->name?zonelist->name:"(null)");
1567  }
1568  /* next */
1569  zonelist = zonelist->next;
1570  }
1571 
1572  /* listen to NOTIFY messages */
1573  c = init_sockets(&sockets, config->notifylist);
1574  if (c == -1) {
1575  ods_log_error("zone fetcher failed to initialize sockets");
1576  if (unlink(config->pidfile) == -1) {
1577  ods_log_error("unlink pidfile %s failed: %s",
1578  config->pidfile?config->pidfile:"(null)",
1579  strerror(errno));
1580  }
1581  ods_log_info("zone fetcher exiting...");
1582  exit(EXIT_FAILURE);
1583  }
1584 
1585  /* drop privileges */
1586  error = privdrop(user, group, chroot, &uid, &gid);
1587  privclose(user, group);
1588  if (error != 0) {
1589  ods_log_error("zone fetcher failed to drop privileges");
1590  if (unlink(config->pidfile) == -1) {
1591  ods_log_error("unlink pidfile %s failed: %s",
1592  config->pidfile?config->pidfile:"(null)",
1593  strerror(errno));
1594  }
1595  free_sockets(&sockets);
1596  ods_log_info("zone fetcher exiting...");
1597  exit(EXIT_FAILURE);
1598  }
1599 
1600  xfrd_ns(&sockets, config);
1601 
1602  if (unlink(config->pidfile) == -1) {
1603  ods_log_warning("unlink pidfile %s failed: %s",
1604  config->pidfile?config->pidfile:"(null)",
1605  strerror(errno));
1606  }
1607  free_sockets(&sockets);
1608 
1609  /* done */
1610  ods_log_debug("zone fetcher done");
1611  free_config(config);
1612  ods_log_close();
1613  return 0;
1614 }