OpenDNSSEC-signer 1.3.0
|
00001 /* 00002 * $Id: zone_fetcher.c 5320 2011-07-12 10:42:26Z jakob $ 00003 * 00004 * Copyright (c) 2009 NLnet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "config.h" 00029 #include "shared/log.h" 00030 #include "shared/privdrop.h" 00031 #include "tools/toolutil.h" 00032 #include "tools/zone_fetcher.h" 00033 00034 #include <arpa/inet.h> 00035 #include <errno.h> 00036 #include <fcntl.h> 00037 #include <getopt.h> 00038 #include <signal.h> 00039 #include <syslog.h> 00040 #include <unistd.h> 00041 #include <sys/types.h> 00042 #include <sys/socket.h> 00043 00044 #include <libxml/tree.h> 00045 #include <libxml/parser.h> 00046 #include <libxml/xpath.h> 00047 #include <libxml/xpathInternals.h> 00048 #include <libxml/relaxng.h> 00049 #include <libxml/xmlreader.h> 00050 #include <libxml/xmlsave.h> 00051 00052 #define DNS_SERIAL_GT(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) > 0) 00053 00054 static int sig_quit = 0; 00055 static int sig_reload = 0; 00056 00057 ldns_resolver* 00058 init_xfrd(config_type* config) 00059 { 00060 serverlist_type* servers; 00061 ldns_rdf* ns = NULL; 00062 ldns_status status = LDNS_STATUS_OK; 00063 00064 ldns_resolver* xfrd = ldns_resolver_new(); 00065 if (config) { 00066 if (config->use_tsig) { 00067 ldns_resolver_set_tsig_keyname(xfrd, config->tsig_name); 00068 if (strncmp(config->tsig_algo, "hmac-md5", 8) == 0) { 00069 ldns_resolver_set_tsig_algorithm(xfrd, "hmac-md5.sig-alg.reg.int."); 00070 } else { 00071 ldns_resolver_set_tsig_algorithm(xfrd, config->tsig_algo); 00072 } 00073 ldns_resolver_set_tsig_keydata(xfrd, config->tsig_secret); 00074 } 00075 if (config->serverlist && config->serverlist->port) 00076 ldns_resolver_set_port(xfrd, atoi(config->serverlist->port)); 00077 else 00078 ldns_resolver_set_port(xfrd, atoi(DNS_PORT_STRING)); 00079 ldns_resolver_set_recursive(xfrd, 0); 00080 00081 servers = config->serverlist; 00082 while (servers) { 00083 if (servers->family == AF_INET6) 00084 ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, servers->ipaddr); 00085 else 00086 ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, servers->ipaddr); 00087 if (ns) { 00088 status = ldns_resolver_push_nameserver(xfrd, ns); 00089 ldns_rdf_deep_free(ns); 00090 ns = NULL; 00091 } else { 00092 ods_log_error("zone fetcher could not use %s for transfer " 00093 "request: could not parse ip address", servers->ipaddr); 00094 } 00095 if (status != LDNS_STATUS_OK) { 00096 ods_log_error("zone fetcher could not use %s for transfer " 00097 "request: %s", servers->ipaddr, 00098 ldns_get_errorstr_by_id(status)); 00099 } 00100 servers = servers->next; 00101 } 00102 if (ldns_resolver_nameserver_count(xfrd) <= 0) { 00103 ods_log_error("zone fetcher could not find any valid name " 00104 "servers"); 00105 } 00106 00107 } 00108 return xfrd; 00109 } 00110 00111 static zfzonelist_type* 00112 new_zone(char* zone_name, char* input_file) 00113 { 00114 zfzonelist_type* zlt = (zfzonelist_type*) malloc(sizeof(zfzonelist_type)); 00115 zlt->name = strdup(zone_name); 00116 zlt->dname = ldns_dname_new_frm_str(zone_name); 00117 zlt->input_file = strdup(input_file); 00118 zlt->next = NULL; 00119 return zlt; 00120 } 00121 00122 static void 00123 free_zonelist(zfzonelist_type* zlt) 00124 { 00125 zfzonelist_type* next = NULL; 00126 00127 while (zlt) { 00128 next = zlt->next; 00129 free((void*) zlt->name); 00130 if (zlt->dname) { 00131 ldns_rdf_deep_free(zlt->dname); 00132 } 00133 free((void*) zlt->input_file); 00134 free((void*) zlt); 00135 zlt = next; 00136 } 00137 } 00138 00139 static serverlist_type* 00140 new_server(char* ipv4, char* ipv6, char* port) 00141 { 00142 serverlist_type* slt = (serverlist_type*) malloc(sizeof(serverlist_type)); 00143 slt->family = AF_UNSPEC; 00144 if (ipv4) { 00145 slt->family = AF_INET; 00146 slt->ipaddr = strdup(ipv4); 00147 } 00148 else if (ipv6) { 00149 slt->family = AF_INET6; 00150 slt->ipaddr = strdup(ipv6); 00151 } 00152 if (port) 00153 slt->port = strdup(port); 00154 else 00155 slt->port = NULL; 00156 memset(&slt->addr, 0, sizeof(union acl_addr_storage)); 00157 00158 if (slt->family == AF_INET6 && strlen(slt->ipaddr) > 0) { 00159 if (inet_pton(slt->family, slt->ipaddr, &slt->addr.addr6) != 1) { 00160 ods_log_error("zone fetcher encountered bad ip address '%s'", 00161 slt->ipaddr); 00162 } 00163 } 00164 else if (slt->family == AF_INET && strlen(slt->ipaddr) > 0) { 00165 if (inet_pton(slt->family, slt->ipaddr, &slt->addr.addr) != 1) { 00166 ods_log_error("zone fetcher encountered bad ip address '%s'", 00167 slt->ipaddr); 00168 } 00169 } 00170 00171 slt->next = NULL; 00172 return slt; 00173 } 00174 00175 static void 00176 free_serverlist(serverlist_type* slt) 00177 { 00178 if (slt) { 00179 free_serverlist(slt->next); 00180 if (slt->port) free((void*) slt->port); 00181 if (slt->ipaddr) free((void*) slt->ipaddr); 00182 free((void*) slt); 00183 } 00184 } 00185 00186 static config_type* 00187 new_config(void) 00188 { 00189 config_type* cfg = (config_type*) malloc(sizeof(config_type)); /* not freed */ 00190 cfg->use_tsig = 0; 00191 cfg->pidfile = NULL; 00192 cfg->tsig_name = NULL; 00193 cfg->tsig_algo = NULL; 00194 cfg->tsig_secret = NULL; 00195 cfg->serverlist = NULL; 00196 cfg->notifylist = NULL; 00197 cfg->zonelist_file = NULL; 00198 cfg->zonelist = NULL; 00199 return cfg; 00200 } 00201 00202 static void 00203 free_config(config_type* cfg) 00204 { 00205 if (cfg) { 00206 if (cfg->tsig_name) free((void*) cfg->tsig_name); 00207 if (cfg->tsig_algo) free((void*) cfg->tsig_algo); 00208 if (cfg->tsig_secret) free((void*) cfg->tsig_secret); 00209 if (cfg->pidfile) free((void*) cfg->pidfile); 00210 if (cfg->zonelist_file) free((void*) cfg->zonelist_file); 00211 free_zonelist(cfg->zonelist); 00212 free_serverlist(cfg->serverlist); 00213 free_serverlist(cfg->notifylist); 00214 free((void*) cfg); 00215 } 00216 } 00217 00218 static int 00219 read_axfr_config(const char* filename, config_type* cfg) 00220 { 00221 int ret, i, use_tsig = 0; 00222 char* tag_name, *tsig_name, *tsig_algo, *tsig_secret, *ipv4, *ipv6, *port; 00223 serverlist_type* serverlist = NULL; 00224 serverlist_type* notifylist = NULL; 00225 00226 xmlTextReaderPtr reader = NULL; 00227 xmlDocPtr doc = NULL; 00228 xmlXPathContextPtr xpathCtx = NULL; 00229 xmlXPathObjectPtr xpathObj = NULL; 00230 xmlNode *curNode = NULL; 00231 xmlChar *tsig_expr = (unsigned char*) "//ZoneFetch/Default/TSIG"; 00232 xmlChar *server_expr = (unsigned char*) "//ZoneFetch/Default/RequestTransfer"; 00233 xmlChar *notify_expr = (unsigned char*) "//ZoneFetch/NotifyListen"; 00234 00235 if (filename == NULL) { 00236 ods_log_alert("no zone fetcher configfile provided"); 00237 ods_log_info("zone fetcher exiting..."); 00238 exit(EXIT_FAILURE); 00239 } 00240 00241 /* In case zonelist is huge use the XmlTextReader API so that we don't 00242 * hold the whole file in memory */ 00243 reader = xmlNewTextReaderFilename(filename); /* not properly freed */ 00244 if (reader != NULL) { 00245 ret = xmlTextReaderRead(reader); 00246 while (ret == 1) { 00247 tag_name = (char*) xmlTextReaderLocalName(reader); 00248 /* Found <ZoneFetch> */ 00249 if (strncmp(tag_name, "ZoneFetch", 8) == 0 && 00250 xmlTextReaderNodeType(reader) == 1) { 00251 00252 /* Expand this node and get the rest of the info with XPath */ 00253 xmlTextReaderExpand(reader); 00254 doc = xmlTextReaderCurrentDoc(reader); 00255 if (doc == NULL) { 00256 ods_log_error("can not read zone fetcher configfile " 00257 "%s", filename?filename:"(null)"); 00258 ods_log_info("zone fetcher exiting..."); 00259 exit(EXIT_FAILURE); 00260 } 00261 xpathCtx = xmlXPathNewContext(doc); 00262 if (xpathCtx == NULL) { 00263 ods_log_error("zone fetcher can not create XPath " 00264 "context for %s", filename?filename:"(null)"); 00265 ods_log_info("zone fetcher exiting..."); 00266 exit(EXIT_FAILURE); 00267 } 00268 00269 /* Extract the master server address */ 00270 xpathObj = xmlXPathEvalExpression(server_expr, xpathCtx); 00271 if (xpathObj == NULL || !xpathObj->nodesetval) { 00272 ods_log_error("zone fetcher can not locate master " 00273 "server(s) in %s", filename?filename:"(null)"); 00274 ods_log_info("zone fetcher exiting..."); 00275 exit(EXIT_FAILURE); 00276 } 00277 else { 00278 for (i=0; i < xpathObj->nodesetval->nodeNr; i++) { 00279 ipv4 = NULL; 00280 ipv6 = NULL; 00281 port = NULL; 00282 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 00283 while (curNode) { 00284 if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv4")) 00285 ipv4 = (char *) xmlNodeGetContent(curNode); 00286 if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv6")) 00287 ipv6 = (char *) xmlNodeGetContent(curNode); 00288 if (xmlStrEqual(curNode->name, (const xmlChar *)"Port")) 00289 port = (char *) xmlNodeGetContent(curNode); 00290 curNode = curNode->next; 00291 } 00292 if (ipv4 || ipv6) { 00293 if (serverlist == NULL) { 00294 serverlist = new_server(ipv4, ipv6, port); /* not freed */ 00295 cfg->serverlist = serverlist; 00296 } 00297 else { 00298 serverlist->next = new_server(ipv4, ipv6, port); /* not freed */ 00299 serverlist = serverlist->next; 00300 } 00301 } 00302 00303 if (ipv4) free((void*) ipv4); 00304 if (ipv6) free((void*) ipv6); 00305 if (port) free((void*) port); 00306 } 00307 xmlXPathFreeObject(xpathObj); 00308 } 00309 00310 /* Extract the notify listen address */ 00311 xpathObj = xmlXPathEvalExpression(notify_expr, xpathCtx); 00312 if (xpathObj != NULL && xpathObj->nodesetval) { 00313 for (i=0; i < xpathObj->nodesetval->nodeNr; i++) { 00314 ipv4 = NULL; 00315 ipv6 = NULL; 00316 port = NULL; 00317 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 00318 while (curNode) { 00319 if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv4")) 00320 ipv4 = (char *) xmlNodeGetContent(curNode); 00321 if (xmlStrEqual(curNode->name, (const xmlChar *)"IPv6")) 00322 ipv6 = (char *) xmlNodeGetContent(curNode); 00323 if (xmlStrEqual(curNode->name, (const xmlChar *)"Port")) 00324 port = (char *) xmlNodeGetContent(curNode); 00325 curNode = curNode->next; 00326 } 00327 if (ipv4 || ipv6 || port) { 00328 if (!ipv4 && !ipv6) { 00329 if (notifylist == NULL) { 00330 notifylist = new_server(NULL, "", port); 00331 cfg->notifylist = notifylist; 00332 00333 notifylist->next = new_server("", NULL, port); 00334 notifylist = notifylist->next; 00335 } 00336 else { 00337 notifylist->next = new_server("", NULL, port); 00338 notifylist = notifylist->next; 00339 00340 notifylist->next = new_server(NULL, "", port); 00341 notifylist = notifylist->next; 00342 } 00343 } 00344 else if (notifylist == NULL) { 00345 notifylist = new_server(ipv4, ipv6, port); 00346 cfg->notifylist = notifylist; 00347 } 00348 else { 00349 notifylist->next = new_server(ipv4, ipv6, port); 00350 notifylist = notifylist->next; 00351 } 00352 } 00353 00354 if (ipv4) free((void*) ipv4); 00355 if (ipv6) free((void*) ipv6); 00356 if (port) free((void*) port); 00357 } 00358 xmlXPathFreeObject(xpathObj); 00359 } 00360 00361 /* Extract the tsig credentials */ 00362 xpathObj = xmlXPathEvalExpression(tsig_expr, xpathCtx); 00363 if (xpathObj != NULL && xpathObj->nodesetval) { 00364 for (i=0; i < xpathObj->nodesetval->nodeNr; i++) { 00365 tsig_name = NULL; 00366 tsig_algo = NULL; 00367 tsig_secret = NULL; 00368 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 00369 while (curNode) { 00370 if (xmlStrEqual(curNode->name, (const xmlChar *)"Name")) 00371 tsig_name = (char *) xmlNodeGetContent(curNode); 00372 if (xmlStrEqual(curNode->name, (const xmlChar *)"Algorithm")) 00373 tsig_algo = (char *) xmlNodeGetContent(curNode); 00374 if (xmlStrEqual(curNode->name, (const xmlChar *)"Secret")) 00375 tsig_secret = (char *) xmlNodeGetContent(curNode); 00376 curNode = curNode->next; 00377 } 00378 if (tsig_name && tsig_algo && tsig_secret) { 00379 use_tsig = 1; 00380 if (cfg->tsig_name) { 00381 free((void*) cfg->tsig_name); 00382 } 00383 if (cfg->tsig_algo) { 00384 free((void*) cfg->tsig_algo); 00385 } 00386 if (cfg->tsig_secret) { 00387 free((void*) cfg->tsig_secret); 00388 } 00389 cfg->tsig_name = strdup(tsig_name); 00390 cfg->tsig_algo = strdup(tsig_algo); 00391 cfg->tsig_secret = strdup(tsig_secret); 00392 } 00393 if (tsig_name) { 00394 free((void*) tsig_name); 00395 } 00396 if (tsig_algo) { 00397 free((void*) tsig_algo); 00398 } 00399 if (tsig_secret) { 00400 free((void*) tsig_secret); 00401 } 00402 } 00403 xmlXPathFreeObject(xpathObj); 00404 } 00405 xmlXPathFreeContext(xpathCtx); 00406 } 00407 00408 /* Read the next line */ 00409 ret = xmlTextReaderRead(reader); 00410 free((void*) tag_name); 00411 } 00412 xmlFreeTextReader(reader); 00413 xmlFreeDoc(doc); 00414 if (ret != 0) { 00415 ods_log_error("zone fetcher failed to parse config file %s", 00416 filename?filename:"(null)"); 00417 ods_log_info("zone fetcher exiting..."); 00418 exit(EXIT_FAILURE); 00419 } 00420 } else { 00421 ods_log_error("zone fetcher was unable to open config file %s", 00422 filename?filename:"(null)"); 00423 ods_log_info("zone fetcher exiting..."); 00424 exit(EXIT_FAILURE); 00425 } 00426 00427 cfg->use_tsig = use_tsig; 00428 return 0; 00429 } 00430 00431 static zfzonelist_type* 00432 read_zonelist(const char* filename) 00433 { 00434 zfzonelist_type* zonelist = NULL, *zonelist_start = NULL; 00435 char* tag_name, *zone_name, *input_file; 00436 int ret; 00437 00438 xmlTextReaderPtr reader = NULL; 00439 xmlDocPtr doc = NULL; 00440 xmlXPathContextPtr xpathCtx = NULL; 00441 xmlXPathObjectPtr xpathObj = NULL; 00442 xmlChar *name_expr = (unsigned char*) "name"; 00443 xmlChar *adapter_expr = (unsigned char*) "//Zone/Adapters/Input/File"; 00444 00445 if (filename == NULL) { 00446 ods_log_error("no zonelist provided for zone fetcher"); 00447 ods_log_info("zone fetcher exiting..."); 00448 exit(EXIT_FAILURE); 00449 } 00450 00451 /* In case zonelist is huge use the XmlTextReader API so that we don't hold the whole file in memory */ 00452 reader = xmlNewTextReaderFilename(filename); 00453 if (reader != NULL) { 00454 ret = xmlTextReaderRead(reader); 00455 while (ret == 1) { 00456 tag_name = (char*) xmlTextReaderLocalName(reader); 00457 /* Found <Zone> */ 00458 if (strncmp(tag_name, "Zone", 4) == 0 && 00459 strncmp(tag_name, "ZoneList", 8) != 0 && 00460 xmlTextReaderNodeType(reader) == 1) { 00461 /* Get the zone name (TODO what if this is null?) */ 00462 zone_name = (char*) xmlTextReaderGetAttribute(reader, name_expr); 00463 /* Make sure that we got something */ 00464 if (zone_name == NULL) { 00465 /* error */ 00466 ods_log_error("zone fetcher failed to extract zone " 00467 "name from %s", filename?filename:"(null)"); 00468 /* Don't return? try to parse the rest of the zones? */ 00469 ret = xmlTextReaderRead(reader); 00470 continue; 00471 } 00472 /* Expand this node and get the rest of the info with XPath */ 00473 xmlTextReaderExpand(reader); 00474 doc = xmlTextReaderCurrentDoc(reader); 00475 if (doc == NULL) { 00476 ods_log_error("zone fetcher could not read zone " 00477 "%s; skipping", zone_name); 00478 /* Don't return? try to parse the rest of the zones? */ 00479 ret = xmlTextReaderRead(reader); 00480 continue; 00481 } 00482 xpathCtx = xmlXPathNewContext(doc); 00483 if (xpathCtx == NULL) { 00484 ods_log_error("zone fetcher can not create XPath " 00485 "context for %s; skipping zone", zone_name); 00486 /* Don't return? try to parse the rest of the zones? */ 00487 ret = xmlTextReaderRead(reader); 00488 continue; 00489 } 00490 00491 /* Extract the Input File Adapter filename */ 00492 xpathObj = xmlXPathEvalExpression(adapter_expr, xpathCtx); 00493 if (xpathObj == NULL || !xpathObj->nodesetval) { 00494 ods_log_error("zone fetcher was unable to evaluate " 00495 "xpath expression: %s; skipping zone", adapter_expr); 00496 /* Don't return? try to parse the rest of the zones? */ 00497 ret = xmlTextReaderRead(reader); 00498 continue; 00499 } 00500 input_file = (char*) xmlXPathCastToString(xpathObj); 00501 xmlXPathFreeObject(xpathObj); 00502 00503 if (zonelist == NULL) { 00504 zonelist = new_zone(zone_name, input_file); /* not freed */ 00505 zonelist_start = zonelist; 00506 } 00507 else { 00508 zonelist->next = new_zone(zone_name, input_file); 00509 zonelist = zonelist->next; 00510 } 00511 free((void*) zone_name); 00512 free((void*) input_file); 00513 00514 xmlXPathFreeContext(xpathCtx); 00515 } 00516 00517 /* Read the next line */ 00518 ret = xmlTextReaderRead(reader); 00519 free((void*) tag_name); 00520 } 00521 xmlFreeTextReader(reader); 00522 xmlFreeDoc(doc); 00523 if (ret != 0) { 00524 ods_log_error("zone fetcher failed to parse zonelist %s", 00525 filename?filename:"(null)"); 00526 ods_log_info("zone fetcher exiting..."); 00527 exit(EXIT_FAILURE); 00528 } 00529 } else { 00530 ods_log_error("zone fetcher was unable to open zonelist %s", 00531 filename?filename:"(null)"); 00532 ods_log_info("zone fetcher exiting..."); 00533 exit(EXIT_FAILURE); 00534 } 00535 00536 return zonelist_start; 00537 } 00538 00540 static int 00541 writepid(char* pidfile, pid_t pid) 00542 { 00543 FILE * fd; 00544 char pidbuf[32]; 00545 size_t result = 0, size = 0; 00546 00547 snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) pid); 00548 if ((fd = fopen(pidfile, "w")) == NULL ) { 00549 ods_log_error("zone fetcher could not open pidfile %s for " 00550 "writing: %s", pidfile?pidfile:"(null)", strerror(errno)); 00551 return -1; 00552 } 00553 size = strlen(pidbuf); 00554 if (size == 0) 00555 result = 1; 00556 result = fwrite((const void*) pidbuf, 1, size, fd); 00557 if (result == 0) { 00558 ods_log_error("zone fetcher failed to write to pidfile: %s", 00559 strerror(errno)); 00560 } else if (result < size) { 00561 ods_log_error("zone fetcher had short write to pidfile " 00562 "(disk full?)"); 00563 result = 0; 00564 } else 00565 result = 1; 00566 if (!result) { 00567 ods_log_error("zone fetcher could not write pidfile %s: %s", 00568 pidfile?pidfile:"(null)", strerror(errno)); 00569 fclose(fd); 00570 return -1; 00571 } 00572 fclose(fd); 00573 return 0; 00574 } 00575 00577 static void 00578 sig_handler(int sig) 00579 { 00580 switch (sig) 00581 { 00582 case SIGTERM: 00583 sig_quit = 1; 00584 break; 00585 case SIGHUP: 00586 sig_reload = 1; 00587 break; 00588 default: 00589 break; 00590 } 00591 return; 00592 } 00593 00594 static int 00595 init_sockets(sockets_type* sockets, serverlist_type* list) 00596 { 00597 int ret = 0, r, ip6_support = 1, on = 0; 00598 size_t i; 00599 struct addrinfo hints[MAX_INTERFACES]; 00600 serverlist_type* walk = list; 00601 serverlist_type* new_list = NULL; 00602 const char* node = NULL; 00603 const char* port = NULL; 00604 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY) 00605 on = 1; 00606 #endif 00607 00608 for (i = 0; i < MAX_INTERFACES; i++) { 00609 memset(&hints[i], 0, sizeof(hints[i])); 00610 hints[i].ai_family = AF_UNSPEC; 00611 hints[i].ai_flags = AI_PASSIVE; 00612 sockets->udp[i].s = -1; 00613 sockets->tcp[i].s = -1; 00614 } 00615 00616 /* if no NotifyListen was provided, we create the default IPv4/IPv6 00617 * address info structures */ 00618 if (!walk) { 00619 #ifdef IPV6_V6ONLY 00620 hints[0].ai_family = AF_INET6; 00621 hints[1].ai_family = AF_INET; 00622 new_list = new_server(NULL, "", NULL); 00623 new_list->next = new_server("", NULL, NULL); 00624 #else /* !IPV6_V6ONLY */ 00625 hints[0].ai_family = AF_INET6; 00626 new_list = new_server(NULL, "", NULL); 00627 #endif /* IPV6_V6ONLY */ 00628 walk = new_list; 00629 } 00630 00631 i = 0; 00632 while (walk) { 00633 node = strlen(walk->ipaddr) > 0 ? walk->ipaddr : NULL; 00634 port = walk->port ? walk->port : DNS_PORT_STRING; 00635 if (node != NULL) 00636 hints[i].ai_flags |= AI_NUMERICHOST; 00637 else 00638 hints[i].ai_family = walk->family; 00639 /* UDP */ 00640 hints[i].ai_socktype = SOCK_DGRAM; 00641 /* getaddrinfo */ 00642 if ((r = getaddrinfo(node, port, &hints[i], 00643 &(sockets->udp[i].addr))) != 0) { 00644 if (hints[i].ai_family == AF_INET6 && errno == EAFNOSUPPORT) { 00645 ods_log_error("zone fetcher udp fallback to ipv4, no ipv6: " 00646 " not supported"); 00647 ip6_support = 0; 00648 continue; 00649 } 00650 ods_log_error("zone fetcher cannot parse address %s:%s: " 00651 "getaddrinfo (%i): %s %s", node?node:"(null)", 00652 port?port:"(null)", walk->family, 00653 gai_strerror(r), r==EAI_SYSTEM?strerror(errno):""); 00654 } 00655 00656 /* socket */ 00657 if ((sockets->udp[i].s = socket(sockets->udp[i].addr->ai_family, 00658 SOCK_DGRAM, 0)) == -1) { 00659 if (sockets->udp[i].addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) { 00660 ods_log_error("zone fetcher udp fallback to ipv4, no ipv6: " 00661 " not supported"); 00662 ip6_support = 0; 00663 } 00664 else { 00665 ods_log_error("zone fetcher can't create udp/4 socket for " 00666 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00667 strerror(errno)); 00668 ret = -1; 00669 break; 00670 } 00671 } 00672 00673 if (sockets->udp[i].addr->ai_family == AF_INET) { 00674 if (fcntl(sockets->udp[i].s, F_SETFL, 00675 O_NONBLOCK) == -1) { 00676 ods_log_error("zone fetcher cannot fcntl udp/4 socket for " 00677 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00678 strerror(errno)); 00679 } 00680 if (bind(sockets->udp[i].s, 00681 (struct sockaddr *) sockets->udp[i].addr->ai_addr, 00682 sockets->udp[i].addr->ai_addrlen) != 0) 00683 { 00684 ods_log_error("zone fetcher can't bind udp/4 socket for " 00685 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00686 strerror(errno)); 00687 ret = -1; 00688 break; 00689 } 00690 } 00691 else if (ip6_support) { 00692 #ifdef IPV6_V6ONLY 00693 #if defined(IPPROTO_IPV6) 00694 ods_log_verbose("zone fetcher setsockopt ipv6_v6only..."); 00695 if (setsockopt(sockets->udp[i].s, IPPROTO_IPV6, IPV6_V6ONLY, &on, 00696 sizeof(on)) < 0) 00697 { 00698 ods_log_error("zone fetcher setsockopt(..., IPV6_V6ONLY, " 00699 "...) failed for " 00700 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00701 strerror(errno)); 00702 ret = -1; 00703 break; 00704 } 00705 #endif 00706 #endif /* IPV6_V6ONLY */ 00707 /* 00708 if (setsockopt(sockets->udp[i].s, SOL_SOCKET, SO_REUSEADDR, &on, 00709 sizeof(on)) < 0) { 00710 ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) " 00711 "failed for " 00712 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00713 strerror(errno)); 00714 } 00715 */ 00716 if (fcntl(sockets->udp[i].s, F_SETFL, O_NONBLOCK) == -1) { 00717 ods_log_error("zone fetcher cannot fcntl udp/6 socket for " 00718 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00719 strerror(errno)); 00720 } 00721 if (bind(sockets->udp[i].s, 00722 (struct sockaddr *) sockets->udp[i].addr->ai_addr, 00723 sockets->udp[i].addr->ai_addrlen) != 0) { 00724 ods_log_error("zone fetcher can't bind udp/6 socket for " 00725 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00726 strerror(errno)); 00727 ret = -1; 00728 break; 00729 } 00730 } 00731 00732 /* TCP */ 00733 hints[i].ai_socktype = SOCK_STREAM; 00734 /* getaddrinfo */ 00735 if ((r = getaddrinfo(node, port, &hints[i], 00736 &(sockets->tcp[i].addr))) != 0) { 00737 if (hints[i].ai_family == AF_INET6 && errno == EAFNOSUPPORT) { 00738 ods_log_error("zone fetcher tcp fallback to ipv4, no ipv6: " 00739 " not supported"); 00740 ip6_support = 0; 00741 continue; 00742 } 00743 ods_log_error("zone fetcher cannot parse address %s:%s: " 00744 "getaddrinfo (%i): %s %s", node?node:"(null)", 00745 port?port:"(null)", walk->family, 00746 gai_strerror(r), r==EAI_SYSTEM?strerror(errno):""); 00747 } 00748 /* socket */ 00749 if ((sockets->tcp[i].s = socket(sockets->tcp[i].addr->ai_family, 00750 SOCK_STREAM, 0)) == -1) { 00751 if (sockets->tcp[i].addr->ai_family == AF_INET6 && 00752 errno == EAFNOSUPPORT) { 00753 ods_log_error("zone fetcher tcp fallback to ipv4, no ipv6: " 00754 " not supported"); 00755 ip6_support = 0; 00756 } 00757 else { 00758 ods_log_error("zone fetcher can't create tcp socket for " 00759 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00760 strerror(errno)); 00761 ret = -1; 00762 break; 00763 } 00764 } 00765 /* setsockopt */ 00766 if (sockets->tcp[i].addr->ai_family == AF_INET) { 00767 if (setsockopt(sockets->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on, 00768 sizeof(on)) < 0) { 00769 ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) " 00770 "failed for " 00771 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00772 strerror(errno)); 00773 } 00774 /* fcntl */ 00775 if (fcntl(sockets->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) { 00776 ods_log_error("zone fetcher cannot fcntl tcp/4 for " 00777 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00778 strerror(errno)); 00779 } 00780 /* bind */ 00781 if (bind(sockets->tcp[i].s, 00782 (struct sockaddr *) sockets->tcp[i].addr->ai_addr, 00783 sockets->tcp[i].addr->ai_addrlen) != 0) { 00784 ods_log_error("zone fetcher can't bind tcp/4 socket for " 00785 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00786 strerror(errno)); 00787 ret = -1; 00788 break; 00789 } 00790 /* listen */ 00791 if (listen(sockets->tcp[i].s, 5) == -1) { 00792 ods_log_error("zone fetcher can't listen to tcp/4 socket for " 00793 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00794 strerror(errno)); 00795 ret = -1; 00796 break; 00797 } 00798 } else if (ip6_support) { 00799 /* setsockopt */ 00800 if (sockets->tcp[i].addr->ai_family == AF_INET6 && ip6_support) { 00801 #ifdef IPV6_V6ONLY 00802 #if defined(IPPROTO_IPV6) 00803 if (setsockopt(sockets->tcp[i].s, IPPROTO_IPV6, IPV6_V6ONLY, &on, 00804 sizeof(on)) < 0) 00805 { 00806 ods_log_error("zone fetcher setsockopt(..., IPV6_V6ONLY, " 00807 "...) failed for " 00808 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00809 strerror(errno)); 00810 ret = -1; 00811 break; 00812 } 00813 #endif 00814 #endif /* IPV6_V6ONLY */ 00815 } 00816 if (setsockopt(sockets->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on, 00817 sizeof(on)) < 0) { 00818 ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) " 00819 "failed for " 00820 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00821 strerror(errno)); 00822 } 00823 /* fcntl */ 00824 if (fcntl(sockets->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) { 00825 ods_log_error("zone fetcher cannot fcntl tcp/6 for " 00826 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00827 strerror(errno)); 00828 } 00829 /* bind */ 00830 if (bind(sockets->tcp[i].s, 00831 (struct sockaddr *) sockets->tcp[i].addr->ai_addr, 00832 sockets->tcp[i].addr->ai_addrlen) != 0) { 00833 ods_log_error("zone fetcher can't bind tcp/6 socket for " 00834 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00835 strerror(errno)); 00836 ret = -1; 00837 break; 00838 } 00839 /* listen */ 00840 if (listen(sockets->tcp[i].s, 5) == -1) { 00841 ods_log_error("zone fetcher can't listen to tcp/6 socket for " 00842 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00843 strerror(errno)); 00844 ret = -1; 00845 break; 00846 } 00847 } 00848 00849 walk = walk->next; 00850 i++; 00851 } 00852 00853 if (new_list) { 00854 free_serverlist(new_list); 00855 } 00856 00857 return ret; 00858 } 00859 00860 static void 00861 free_sockets(sockets_type* sockets) 00862 { 00863 size_t i = 0; 00864 00865 for (i=0; i < MAX_INTERFACES; i++) { 00866 if (sockets->udp[i].s != -1) { 00867 close(sockets->udp[i].s); 00868 freeaddrinfo((void*)sockets->udp[i].addr); 00869 } 00870 if (sockets->tcp[i].s != -1) { 00871 close(sockets->tcp[i].s); 00872 freeaddrinfo((void*)sockets->tcp[i].addr); 00873 } 00874 } 00875 } 00876 00877 static int 00878 odd_xfer(zfzonelist_type* zone, uint32_t serial, config_type* config, int kick_signer) 00879 { 00880 ldns_status status = LDNS_STATUS_OK; 00881 ldns_rr* axfr_rr = NULL, *soa_rr = NULL; 00882 uint32_t new_serial = 0; 00883 ldns_pkt* qpkt = NULL, *apkt; 00884 FILE* fd = NULL; 00885 char lock_ext[32]; 00886 char axfr_file[MAXPATHLEN]; 00887 char dest_file[MAXPATHLEN]; 00888 char lock_file[MAXPATHLEN]; 00889 char engine_sign_cmd[MAXPATHLEN + 1024]; 00890 int soa_seen = 0; 00891 ldns_resolver* xfrd = NULL; 00892 00893 /* soa serial query */ 00894 if (!zone || !zone->dname) { 00895 ods_log_error("zone fetcher failed to provide a zone for AXFR "); 00896 return -1; 00897 } 00898 /* Coverity comment: 00899 Event deref_ptr: Directly dereferenced pointer "zone" 00900 */ 00901 qpkt = ldns_pkt_query_new(ldns_rdf_clone(zone->dname), 00902 LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); 00903 if (!qpkt) { 00904 ods_log_error("zone fetcher failed to create SOA query. " 00905 "Aborting AXFR"); 00906 return -1; 00907 } 00908 00909 /* Initialise LDNS resolver for AXFR */ 00910 xfrd = init_xfrd(config); 00911 00912 if (!xfrd) { 00913 ods_log_error("zone fetcher failed to initialise AXFR structure"); 00914 return -1; 00915 } 00916 00917 status = ldns_resolver_send_pkt(&apkt, xfrd, qpkt); 00918 ldns_pkt_free(qpkt); 00919 00920 if (status != LDNS_STATUS_OK) { 00921 ods_log_error("zone fetcher failed to send SOA query: %s", 00922 ldns_get_errorstr_by_id(status)); 00923 ldns_resolver_deep_free(xfrd); 00924 return -1; 00925 } 00926 if (ldns_pkt_ancount(apkt) == 1) { 00927 soa_rr = ldns_rr_list_rr(ldns_pkt_answer(apkt), 0); 00928 if (soa_rr && ldns_rr_get_type(soa_rr) == LDNS_RR_TYPE_SOA) { 00929 new_serial = ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2)); 00930 } 00931 ldns_pkt_free(apkt); 00932 } else { 00933 ods_log_error("zone fetcher saw SOA response with ANCOUNT != 1, " 00934 "Aborting AXFR"); 00935 /* retry? */ 00936 ldns_pkt_free(apkt); 00937 ldns_resolver_deep_free(xfrd); 00938 return -1; 00939 } 00940 00941 if (DNS_SERIAL_GT(new_serial, serial)) { 00942 status = ldns_axfr_start(xfrd, zone->dname, LDNS_RR_CLASS_IN); 00943 if (status != LDNS_STATUS_OK) { 00944 ods_log_error("zone fetcher failed to start axfr: %s", 00945 ldns_get_errorstr_by_id(status)); 00946 ldns_resolver_deep_free(xfrd); 00947 return -1; 00948 } 00949 00950 /* Coverity comment: 00951 Event check_after_deref: Pointer "zone" dereferenced before NULL check 00952 */ 00953 if (zone && zone->input_file) { 00954 snprintf(lock_ext, sizeof(lock_ext), "axfr.%lu", 00955 (unsigned long) getpid()); 00956 00957 snprintf(axfr_file, sizeof(axfr_file), "%s.%s", zone->input_file, lock_ext); 00958 fd = fopen(axfr_file, "w"); 00959 if (!fd) { 00960 ods_log_error("zone fetcher cannot store AXFR to file %s", axfr_file); 00961 ldns_resolver_deep_free(xfrd); 00962 return -1; 00963 } 00964 } 00965 assert(fd); 00966 00967 axfr_rr = ldns_axfr_next(xfrd); 00968 if (!axfr_rr) { 00969 ods_log_error("zone fetcher AXFR for %s failed", 00970 zone->name?zone->name:"(null)"); 00971 fclose(fd); 00972 unlink(axfr_file); 00973 ldns_resolver_deep_free(xfrd); 00974 return -1; 00975 } 00976 else { 00977 while (axfr_rr) { 00978 if (ldns_rr_get_type(axfr_rr) == LDNS_RR_TYPE_SOA) { 00979 if (!soa_seen) { 00980 soa_seen = 1; 00981 ldns_rr_print(fd, axfr_rr); 00982 } 00983 } else { 00984 ldns_rr_print(fd, axfr_rr); 00985 } 00986 ldns_rr_free(axfr_rr); 00987 axfr_rr = ldns_axfr_next(xfrd); 00988 } 00989 00990 /* RoRi: 00991 * We MUST now check if the AXFR was successful by verifying that 00992 * LDNS has seen the SOA record twice. Not doing this can result 00993 * in a half-transferred zone if the AXFR is interrupted. 00994 */ 00995 if (!ldns_axfr_complete(xfrd)) { 00996 /* The AXFR was not successful, we've received only a partial zone */ 00997 ods_log_error("zone fetcher AXFR for %s failed, received only a partial zone", zone->name); 00998 fclose(fd); 00999 unlink(axfr_file); 01000 ldns_resolver_deep_free(xfrd); 01001 return -1; 01002 } 01003 01004 ods_log_info("zone fetcher transferred zone %s serial %u " 01005 "successfully", zone->name?zone->name:"(null)", new_serial); 01006 01007 /* Close file before moving it */ 01008 fclose(fd); 01009 01010 /* moving and kicking */ 01011 snprintf(lock_file, sizeof(lock_file), "%s.lock", 01012 zone->input_file?zone->input_file:"(null)"); 01013 01014 lock_axfr: 01015 if (access(lock_file, F_OK) == 0) { 01016 ods_log_deeebug("zone fetcher axfr file %s is locked, " 01017 "waiting...", dest_file); 01018 sleep(1); 01019 goto lock_axfr; 01020 } else { 01021 fd = fopen(lock_file, "w"); 01022 if (!fd) { 01023 ods_log_error("zone fetcher cannot lock AXFR file %s", 01024 lock_file); 01025 ldns_resolver_deep_free(xfrd); 01026 return -1; 01027 } 01028 } 01029 assert(fd); /* locked */ 01030 01031 snprintf(dest_file, sizeof(dest_file), "%s.axfr", 01032 zone->input_file?zone->input_file:"(null)"); 01033 if(rename(axfr_file, dest_file) == 0) { 01034 fclose(fd); 01035 (void) unlink(lock_file); /* unlocked */ 01036 01037 if (kick_signer) { 01038 snprintf(engine_sign_cmd, sizeof(engine_sign_cmd), 01039 "%s sign %s > /dev/null 2>&1", 01040 ODS_SE_CLI, zone->name?zone->name:"--all"); 01041 if (system(engine_sign_cmd) != 0) { 01042 ods_log_error("zone fetcher could not kick " 01043 "the signer engine to sign zone %s", 01044 zone->name?zone->name:"--all"); 01045 } 01046 } 01047 } else { 01048 fclose(fd); 01049 (void) unlink(lock_file); /* unlocked */ 01050 01051 ods_log_error("zone fetcher could not move AXFR to %s", 01052 dest_file); 01053 } 01054 ldns_resolver_deep_free(xfrd); 01055 return 0; 01056 } 01057 } else { 01058 ods_log_info("zone fetcher zone %s is already up to date, " 01059 "serial is %u", zone->name?zone->name:"(null)", serial); 01060 } 01061 01062 ldns_resolver_deep_free(xfrd); 01063 return 0; 01064 } 01065 01066 static void 01067 send_udp(uint8_t* buf, size_t len, void* data) 01068 { 01069 struct handle_udp_userdata *userdata = (struct handle_udp_userdata*)data; 01070 /* udp send reply */ 01071 ssize_t nb; 01072 nb = sendto(userdata->udp_sock, buf, len, 0, 01073 (struct sockaddr*)&userdata->addr_him, userdata->hislen); 01074 if (nb == -1) 01075 ods_log_error("zone fetcher sendto() failed: %s", strerror(errno)); 01076 else if ((size_t)nb != len) 01077 ods_log_error("zone fetcher sendto(): only sent %d of %d octets.", 01078 (int)nb, (int)len); 01079 } 01080 01081 static void 01082 write_n_bytes(int sock, uint8_t* buf, size_t sz) 01083 { 01084 size_t count = 0; 01085 while(count < sz) { 01086 ssize_t nb = send(sock, buf+count, sz-count, 0); 01087 if(nb < 0) { 01088 ods_log_error("zone fetcher send() failed: %s", 01089 strerror(errno)); 01090 return; 01091 } 01092 count += nb; 01093 } 01094 } 01095 01096 static void 01097 send_tcp(uint8_t* buf, size_t len, void* data) 01098 { 01099 struct handle_tcp_userdata *userdata = (struct handle_tcp_userdata*)data; 01100 uint16_t tcplen; 01101 /* tcp send reply */ 01102 tcplen = htons(len); 01103 write_n_bytes(userdata->s, (uint8_t*)&tcplen, sizeof(tcplen)); 01104 write_n_bytes(userdata->s, buf, len); 01105 } 01106 01107 static void 01108 handle_query(uint8_t* inbuf, ssize_t inlen, 01109 void (*sendfunc)(uint8_t*, size_t, void*), 01110 void* userdata, config_type* config) 01111 { 01112 zfzonelist_type* zonelist = NULL; 01113 ldns_status status = LDNS_STATUS_OK; 01114 ldns_pkt *query_pkt = NULL; 01115 ldns_rr *query_rr = NULL; 01116 uint32_t serial = 0; 01117 char* owner_name = NULL; 01118 uint8_t *outbuf = NULL; 01119 size_t answer_size = 0; 01120 FILE* fd; 01121 01122 /* packet parsing */ 01123 status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen); 01124 if (status != LDNS_STATUS_OK) { 01125 ods_log_error("zone fetcher got bad packet: %s", 01126 ldns_get_errorstr_by_id(status)); 01127 return; 01128 } 01129 query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); 01130 01131 if (ldns_pkt_get_opcode(query_pkt) != LDNS_PACKET_NOTIFY || 01132 ldns_pkt_get_rcode(query_pkt) != LDNS_RCODE_NOERROR || 01133 ldns_pkt_qr(query_pkt) || 01134 !ldns_pkt_aa(query_pkt) || 01135 ldns_pkt_tc(query_pkt) || 01136 ldns_pkt_rd(query_pkt) || 01137 ldns_pkt_ra(query_pkt) || 01138 ldns_pkt_cd(query_pkt) || 01139 ldns_pkt_ad(query_pkt) || 01140 ldns_pkt_qdcount(query_pkt) != 1 || 01141 ldns_pkt_nscount(query_pkt) != 0 || 01142 ldns_pkt_arcount(query_pkt) != 0 || 01143 ldns_rr_get_type(query_rr) != LDNS_RR_TYPE_SOA || 01144 ldns_rr_get_class(query_rr) != LDNS_RR_CLASS_IN) 01145 { 01146 ods_log_info("zone fetcher drop bad notify"); 01147 return; 01148 } 01149 01150 /* NOTIFY OK */ 01151 if (config) { 01152 zonelist = config->zonelist; 01153 } 01154 ldns_pkt_set_qr(query_pkt, 1); 01155 status = ldns_pkt2wire(&outbuf, query_pkt, &answer_size); 01156 if (status != LDNS_STATUS_OK) { 01157 ods_log_error("zone fetcher error creating notify response: %s", 01158 ldns_get_errorstr_by_id(status)); 01159 } 01160 sendfunc(outbuf, answer_size, userdata); 01161 LDNS_FREE(outbuf); 01162 01163 /* send AXFR request */ 01164 while (zonelist) { 01165 if (ldns_dname_compare(ldns_rr_owner(query_rr), zonelist->dname) == 0) 01166 { 01167 ods_log_info("zone fetcher received NOTIFY for zone %s", 01168 zonelist->name?zonelist->name:"(null)"); 01169 /* get latest serial */ 01170 fd = fopen(zonelist->input_file, "r"); 01171 if (!fd) { 01172 serial = 0; 01173 } else { 01174 serial = lookup_serial(fd); 01175 fclose(fd); 01176 } 01177 if (odd_xfer(zonelist, serial, config, 1) != 0) { 01178 ods_log_error("AXFR for zone %s failed", 01179 zonelist->name?zonelist->name:"(null)"); 01180 } 01181 ldns_pkt_free(query_pkt); 01182 return; 01183 } 01184 /* next */ 01185 zonelist = zonelist->next; 01186 } 01187 owner_name = ldns_rdf2str(ldns_rr_owner(query_rr)); 01188 ods_log_warning("zone fetcher notify received for unknown zone: %s", 01189 owner_name?owner_name:"(null)"); 01190 free((void*)owner_name); 01191 ldns_pkt_free(query_pkt); 01192 } 01193 01194 static void 01195 read_n_bytes(int sock, uint8_t* buf, size_t sz) 01196 { 01197 size_t count = 0; 01198 while(count < sz) { 01199 ssize_t nb = recv(sock, buf+count, sz-count, 0); 01200 if(nb < 0) { 01201 ods_log_error("zone fetcher recv() failed: %s", 01202 strerror(errno)); 01203 return; 01204 } 01205 count += nb; 01206 } 01207 } 01208 01209 static char* 01210 addr2ip(struct sockaddr_storage addr, char* remote, size_t len) 01211 { 01212 if (addr.ss_family == AF_INET6) { 01213 if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, 01214 remote, len)) { 01215 return NULL; 01216 } 01217 } else { 01218 if (!inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr, 01219 remote, len)) 01220 return NULL; 01221 } 01222 01223 return remote; 01224 } 01225 01226 static int 01227 acl_matches(struct sockaddr_storage* addr, config_type* config) 01228 { 01229 serverlist_type* serverlist = NULL; 01230 01231 if (config && config->serverlist) { 01232 serverlist = config->serverlist; 01233 while (serverlist) { 01234 if (serverlist->family == AF_INET6) { 01235 struct sockaddr_in6* addr6 = (struct sockaddr_in6*)addr; 01236 if (serverlist->family == addr->ss_family && 01237 memcmp(&addr6->sin6_addr, &serverlist->addr.addr6, 01238 sizeof(struct in6_addr)) == 0) 01239 { 01240 return 1; 01241 } 01242 } 01243 else { 01244 struct sockaddr_in* addr4 = (struct sockaddr_in*)addr; 01245 if (serverlist->family == addr4->sin_family && 01246 memcmp(&addr4->sin_addr, &serverlist->addr.addr, 01247 sizeof(struct in_addr)) == 0) 01248 { 01249 return 1; 01250 } 01251 } 01252 01253 serverlist = serverlist->next; 01254 } 01255 } 01256 return 0; 01257 } 01258 01259 static void 01260 handle_udp(int udp_sock, config_type* config) 01261 { 01262 ssize_t nb; 01263 uint8_t inbuf[INBUF_SIZE]; 01264 struct handle_udp_userdata userdata; 01265 char* remote; 01266 01267 userdata.udp_sock = udp_sock; 01268 userdata.hislen = (socklen_t) sizeof(userdata.addr_him); 01269 nb = recvfrom(udp_sock, inbuf, INBUF_SIZE, 0, 01270 (struct sockaddr*) &userdata.addr_him, &userdata.hislen); 01271 if (nb < 1) { 01272 ods_log_error("zone fetcher recvfrom() failed: %s", 01273 strerror(errno)); 01274 return; 01275 } 01276 01277 /* acl */ 01278 if (!acl_matches(&userdata.addr_him, config)) { 01279 remote = (char*) malloc(sizeof(char)*userdata.hislen); 01280 ods_log_warning("zone fetcher refused message from " 01281 "unauthoritative source: %s", 01282 addr2ip(userdata.addr_him, remote, userdata.hislen)); 01283 free((void*)remote); 01284 return; 01285 } 01286 handle_query(inbuf, nb, send_udp, &userdata, config); 01287 } 01288 01289 static void 01290 handle_tcp(int tcp_sock, config_type* config) 01291 { 01292 int s; 01293 struct sockaddr_storage addr_him; 01294 socklen_t hislen; 01295 uint8_t inbuf[INBUF_SIZE]; 01296 uint16_t tcplen; 01297 struct handle_tcp_userdata userdata; 01298 char* remote; 01299 01300 /* accept */ 01301 hislen = (socklen_t)sizeof(addr_him); 01302 if((s = accept(tcp_sock, (struct sockaddr*)&addr_him, &hislen)) < 0) { 01303 ods_log_error("zone fetcher accept() failed: %s", strerror(errno)); 01304 return; 01305 } 01306 userdata.s = s; 01307 01308 /* tcp recv */ 01309 read_n_bytes(s, (uint8_t*)&tcplen, sizeof(tcplen)); 01310 tcplen = ntohs(tcplen); 01311 if(tcplen >= INBUF_SIZE) { 01312 ods_log_error("zone fetcher query %d bytes too large, " 01313 "buffer %d bytes.", tcplen, INBUF_SIZE); 01314 close(s); 01315 return; 01316 } 01317 read_n_bytes(s, inbuf, tcplen); 01318 01319 /* acl */ 01320 if (!acl_matches(&addr_him, config)) { 01321 remote = (char*) malloc(sizeof(char)*hislen); 01322 ods_log_warning("zone fetcher refused message from " 01323 "unauthoritative source: %s", 01324 addr2ip(addr_him, remote, hislen)); 01325 free((void*)remote); 01326 close(s); 01327 return; 01328 } 01329 handle_query(inbuf, (ssize_t) tcplen, send_tcp, &userdata, config); 01330 close(s); 01331 } 01332 01333 01338 static void 01339 reload_zonelist(config_type *config) { 01340 zfzonelist_type *new_zonelist, **thisp; 01341 zfzonelist_type *added_zonelist = NULL, *kept_zonelist = NULL; 01342 int added_count = 0, changed_count = 0, kept_count = 0; 01343 /* Fail softly if the zonelist cannot be accessed for reloading */ 01344 if (!config->zonelist_file) { 01345 ods_log_error("zone fetcher is unable to access the zonelist"); 01346 return; 01347 } else { 01348 ods_log_verbose("zone fetcher will reload the zonelist"); 01349 } 01350 /* Read the zonelist file and construct a new linked list of zonelist entries */ 01351 new_zonelist = read_zonelist (config->zonelist_file); 01352 /* Iterate over the new zonelist file and compare it to previously configured zonelist entries */ 01353 while (new_zonelist) { 01354 zfzonelist_type *next_zonelist = new_zonelist->next; 01355 zfzonelist_type *this = config->zonelist; 01356 int found = 0; 01357 while (this && !found) { 01358 found = !strcmp (this->name, new_zonelist->name); 01359 if (!found) { 01360 this = this->next; 01361 } 01362 } 01363 01364 /* If the zone name is found in the old zonelist, it is either a full match or a replacement */ 01365 if (found) { 01366 if (strcmp (new_zonelist->input_file, this->input_file)) { 01367 /* the zonelist entry has changed -- treat as a replacement/new zonelist entry */ 01368 changed_count++; 01369 new_zonelist->next = added_zonelist; 01370 added_zonelist = new_zonelist; 01371 } else { 01372 /* the zonelist entry is already configured -- treat as a kept zonelist entry */ 01373 kept_count++; 01374 new_zonelist->next = kept_zonelist; 01375 kept_zonelist = new_zonelist; 01376 } 01377 } else { 01378 /* new_zonelist introduces a new zonelist entry */ 01379 added_count++; 01380 new_zonelist->next = added_zonelist; 01381 added_zonelist = new_zonelist; 01382 } 01383 new_zonelist = next_zonelist; 01384 } 01385 01386 /* Replace the configured zonelist with the added_zonelist and kept_zonelist */ 01387 free_zonelist (config->zonelist); 01388 config->zonelist = kept_zonelist; 01389 thisp = &config->zonelist; 01390 while (*thisp) { 01391 thisp = &(*thisp)->next; 01392 } 01393 *thisp = added_zonelist; 01394 01395 /* Perform an initial AXFR for the newly added zones (assume no present inputfile) */ 01396 new_zonelist = added_zonelist; 01397 while (new_zonelist) { 01398 /* send the request -- assume no file is present so SOA is 0 */ 01399 if (odd_xfer (new_zonelist, 0, config, 1) != 0) { 01400 ods_log_error("AXFR for new zone %s failed", new_zonelist->name); 01401 } 01402 /* next */ 01403 new_zonelist = new_zonelist->next; 01404 } 01405 ods_log_verbose("Reloaded zonelist -- kept %d, changed %d and added %d zones", 01406 kept_count, changed_count, added_count); 01407 return; 01408 } 01409 01410 01411 static void 01412 xfrd_ns(sockets_type* sockets, config_type* cfg) 01413 { 01414 fd_set rset, wset, eset; 01415 struct timeval timeout; 01416 int count, maxfd = 0; 01417 size_t i; 01418 01419 /* service */ 01420 count = 0; 01421 timeout.tv_sec = 0; 01422 timeout.tv_usec = 0; 01423 while (!sig_quit) { 01424 if (sig_reload) { 01425 reload_zonelist(cfg); 01426 sig_reload = 0; 01427 } 01428 FD_ZERO(&rset); 01429 FD_ZERO(&wset); 01430 FD_ZERO(&eset); 01431 for (i=0; i < MAX_INTERFACES; i++) { 01432 if (sockets->udp[i].s != -1) 01433 FD_SET(sockets->udp[i].s, &rset); 01434 if (sockets->tcp[i].s != -1) 01435 FD_SET(sockets->tcp[i].s, &rset); 01436 if (sockets->udp[i].s > maxfd) maxfd = sockets->udp[i].s; 01437 if (sockets->tcp[i].s > maxfd) maxfd = sockets->tcp[i].s; 01438 } 01439 01440 if (select(maxfd+1, &rset, &wset, &eset, NULL) < 0) { 01441 if (errno == EINTR) 01442 continue; 01443 ods_log_error("zone fetcher select(): %s", strerror(errno)); 01444 } 01445 01446 for (i=0; i < MAX_INTERFACES; i++) { 01447 if (sockets->udp[i].s != -1 && FD_ISSET(sockets->udp[i].s, &rset)) 01448 handle_udp(sockets->udp[i].s, cfg); 01449 if (sockets->tcp[i].s != -1 && FD_ISSET(sockets->tcp[i].s, &rset)) 01450 handle_tcp(sockets->tcp[i].s, cfg); 01451 } 01452 } 01453 } 01454 01455 static void 01456 list_settings(FILE* out, config_type* config, const char* filename) 01457 { 01458 zfzonelist_type* zones = NULL; 01459 serverlist_type* servers = NULL; 01460 01461 if (config) { 01462 fprintf(out, "configuration settings:\n"); 01463 fprintf(out, "filename: %s\n", filename?filename:"(null)"); 01464 fprintf(out, "pidfile: %s\n", 01465 config->pidfile?config->pidfile:"(null)"); 01466 fprintf(out, "tsig: %s\n", config->use_tsig?"yes":"no"); 01467 if (config->use_tsig) { 01468 fprintf(out, "tsig name: %s\n", 01469 config->tsig_name?config->tsig_name:"(null)"); 01470 fprintf(out, "tsig algorithm: %s\n", 01471 config->tsig_algo?config->tsig_algo:"(null)"); 01472 fprintf(out, "tsig secret: ?\n"); 01473 } 01474 fprintf(out, "zones: %s\n", config->zonelist?"":"none"); 01475 zones = config->zonelist; 01476 while (zones) { 01477 fprintf(out, "\t%s\n", zones->name?zones->name:"(null)"); 01478 zones = zones->next; 01479 } 01480 fprintf(out, "master servers: %s\n", config->serverlist?"":"none"); 01481 servers = config->serverlist; 01482 while (servers) { 01483 fprintf(out, "\t%s\n", servers->ipaddr?servers->ipaddr:"(null)"); 01484 servers = servers->next; 01485 } 01486 fprintf(out, "interfaces: %s\n", config->notifylist?"":"none"); 01487 servers = config->notifylist; 01488 while (servers) { 01489 fprintf(out, "\t%s %s:%s\n", 01490 servers->family==AF_INET6?"ipv6":"ipv4", 01491 servers->ipaddr?servers->ipaddr:"(null)", 01492 servers->port?servers->port:"(null)"); 01493 servers = servers->next; 01494 } 01495 fprintf(out, "list zone fetcher settings done.\n"); 01496 } 01497 else fprintf(out, "no config\n"); 01498 } 01499 01500 int 01501 tools_zone_fetcher(const char* config_file, const char* zonelist_file, 01502 const char* group, const char* user, const char* chroot, const char* log_file, 01503 int use_syslog, int verbosity) 01504 { 01505 zfzonelist_type *zonelist = NULL; 01506 config_type* config = NULL; 01507 uint32_t serial = 0; 01508 FILE* fd; 01509 sockets_type sockets; 01510 int c, info = 0; 01511 int error = 0; 01512 struct sigaction action; 01513 uid_t uid = -1; 01514 gid_t gid = -1; 01515 01516 ods_log_init(log_file, use_syslog, verbosity); 01517 01518 /* read transfer configuration */ 01519 config = new_config(); 01520 config->pidfile = strdup(ODS_ZF_PIDFILE); /* not freed */ 01521 if (!config->pidfile) { 01522 ods_log_alert("zone fetcher error: no pidfile given"); 01523 free_config(config); 01524 exit(EXIT_FAILURE); 01525 } 01526 01527 c = read_axfr_config(config_file, config); 01528 config->zonelist = read_zonelist(zonelist_file); 01529 config->zonelist_file = strdup(zonelist_file); 01530 01531 if (info) { 01532 list_settings(stdout, config, config_file); 01533 } 01534 01535 if (config->serverlist == NULL) { 01536 ods_log_alert("zone fetcher error: no master servers configured " 01537 "with <RequestTransfer>"); 01538 free_config(config); 01539 exit(EXIT_FAILURE); 01540 } 01541 01542 /* setup signal handing */ 01543 action.sa_handler = sig_handler; 01544 sigfillset(&action.sa_mask); 01545 action.sa_flags = 0; 01546 sigaction(SIGHUP, &action, NULL); 01547 sigaction(SIGTERM, &action, NULL); 01548 01549 /* write pidfile */ 01550 if (writepid(config->pidfile, getpid()) != 0) { 01551 ods_log_error("write pidfile %s failed", config->pidfile); 01552 ods_log_info("zone fetcher exiting..."); 01553 exit(EXIT_FAILURE); 01554 } 01555 01556 ods_log_info("zone fetcher started"); 01557 01558 /* foreach zone, do a single axfr request */ 01559 zonelist = config->zonelist; 01560 while (zonelist != NULL) { 01561 /* get latest serial */ 01562 fd = fopen(zonelist->input_file, "r"); 01563 if (!fd) { 01564 serial = 0; 01565 } else { 01566 serial = lookup_serial(fd); 01567 fclose(fd); 01568 } 01569 /* send the request */ 01570 if (odd_xfer(zonelist, serial, config, 1) != 0) { 01571 ods_log_error("AXFR for zone %s failed", 01572 zonelist->name?zonelist->name:"(null)"); 01573 } 01574 /* next */ 01575 zonelist = zonelist->next; 01576 } 01577 01578 /* listen to NOTIFY messages */ 01579 c = init_sockets(&sockets, config->notifylist); 01580 if (c == -1) { 01581 ods_log_error("zone fetcher failed to initialize sockets"); 01582 if (unlink(config->pidfile) == -1) { 01583 ods_log_error("unlink pidfile %s failed: %s", 01584 config->pidfile?config->pidfile:"(null)", 01585 strerror(errno)); 01586 } 01587 ods_log_info("zone fetcher exiting..."); 01588 exit(EXIT_FAILURE); 01589 } 01590 01591 /* drop privileges */ 01592 error = privdrop(user, group, chroot, &uid, &gid); 01593 privclose(user, group); 01594 if (error != 0) { 01595 ods_log_error("zone fetcher failed to drop privileges"); 01596 if (unlink(config->pidfile) == -1) { 01597 ods_log_error("unlink pidfile %s failed: %s", 01598 config->pidfile?config->pidfile:"(null)", 01599 strerror(errno)); 01600 } 01601 free_sockets(&sockets); 01602 ods_log_info("zone fetcher exiting..."); 01603 exit(EXIT_FAILURE); 01604 } 01605 01606 xfrd_ns(&sockets, config); 01607 01608 if (unlink(config->pidfile) == -1) { 01609 ods_log_warning("unlink pidfile %s failed: %s", 01610 config->pidfile?config->pidfile:"(null)", 01611 strerror(errno)); 01612 } 01613 free_sockets(&sockets); 01614 01615 /* done */ 01616 ods_log_debug("zone fetcher done"); 01617 free_config(config); 01618 ods_log_close(); 01619 return 0; 01620 }