OpenDNSSEC-signer
1.3.8
|
00001 /* 00002 * $Id: zone_fetcher.c 5408 2011-08-16 08:15:16Z matthijs $ 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 if (fcntl(sockets->udp[i].s, F_SETFL, O_NONBLOCK) == -1) { 00708 ods_log_error("zone fetcher cannot fcntl udp/6 socket for " 00709 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00710 strerror(errno)); 00711 } 00712 if (bind(sockets->udp[i].s, 00713 (struct sockaddr *) sockets->udp[i].addr->ai_addr, 00714 sockets->udp[i].addr->ai_addrlen) != 0) { 00715 ods_log_error("zone fetcher can't bind udp/6 socket for " 00716 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00717 strerror(errno)); 00718 ret = -1; 00719 break; 00720 } 00721 } 00722 00723 /* TCP */ 00724 hints[i].ai_socktype = SOCK_STREAM; 00725 /* getaddrinfo */ 00726 if ((r = getaddrinfo(node, port, &hints[i], 00727 &(sockets->tcp[i].addr))) != 0) { 00728 if (hints[i].ai_family == AF_INET6 && errno == EAFNOSUPPORT) { 00729 ods_log_error("zone fetcher tcp fallback to ipv4, no ipv6: " 00730 " not supported"); 00731 ip6_support = 0; 00732 continue; 00733 } 00734 ods_log_error("zone fetcher cannot parse address %s:%s: " 00735 "getaddrinfo (%i): %s %s", node?node:"(null)", 00736 port?port:"(null)", walk->family, 00737 gai_strerror(r), r==EAI_SYSTEM?strerror(errno):""); 00738 } 00739 /* socket */ 00740 if ((sockets->tcp[i].s = socket(sockets->tcp[i].addr->ai_family, 00741 SOCK_STREAM, 0)) == -1) { 00742 if (sockets->tcp[i].addr->ai_family == AF_INET6 && 00743 errno == EAFNOSUPPORT) { 00744 ods_log_error("zone fetcher tcp fallback to ipv4, no ipv6: " 00745 " not supported"); 00746 ip6_support = 0; 00747 } 00748 else { 00749 ods_log_error("zone fetcher can't create tcp socket for " 00750 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00751 strerror(errno)); 00752 ret = -1; 00753 break; 00754 } 00755 } 00756 /* setsockopt */ 00757 if (sockets->tcp[i].addr->ai_family == AF_INET) { 00758 if (setsockopt(sockets->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on, 00759 sizeof(on)) < 0) { 00760 ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) " 00761 "failed for " 00762 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00763 strerror(errno)); 00764 } 00765 /* fcntl */ 00766 if (fcntl(sockets->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) { 00767 ods_log_error("zone fetcher cannot fcntl tcp/4 for " 00768 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00769 strerror(errno)); 00770 } 00771 /* bind */ 00772 if (bind(sockets->tcp[i].s, 00773 (struct sockaddr *) sockets->tcp[i].addr->ai_addr, 00774 sockets->tcp[i].addr->ai_addrlen) != 0) { 00775 ods_log_error("zone fetcher can't bind tcp/4 socket for " 00776 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00777 strerror(errno)); 00778 ret = -1; 00779 break; 00780 } 00781 /* listen */ 00782 if (listen(sockets->tcp[i].s, 5) == -1) { 00783 ods_log_error("zone fetcher can't listen to tcp/4 socket for " 00784 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00785 strerror(errno)); 00786 ret = -1; 00787 break; 00788 } 00789 } else if (ip6_support) { 00790 /* setsockopt */ 00791 if (sockets->tcp[i].addr->ai_family == AF_INET6 && ip6_support) { 00792 #ifdef IPV6_V6ONLY 00793 #if defined(IPPROTO_IPV6) 00794 if (setsockopt(sockets->tcp[i].s, IPPROTO_IPV6, IPV6_V6ONLY, &on, 00795 sizeof(on)) < 0) 00796 { 00797 ods_log_error("zone fetcher setsockopt(..., IPV6_V6ONLY, " 00798 "...) failed for " 00799 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00800 strerror(errno)); 00801 ret = -1; 00802 break; 00803 } 00804 #endif 00805 #endif /* IPV6_V6ONLY */ 00806 } 00807 if (setsockopt(sockets->tcp[i].s, SOL_SOCKET, SO_REUSEADDR, &on, 00808 sizeof(on)) < 0) { 00809 ods_log_error("zone fetcher setsockopt(..., SO_REUSEADDR, ...) " 00810 "failed for " 00811 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00812 strerror(errno)); 00813 } 00814 /* fcntl */ 00815 if (fcntl(sockets->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) { 00816 ods_log_error("zone fetcher cannot fcntl tcp/6 for " 00817 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00818 strerror(errno)); 00819 } 00820 /* bind */ 00821 if (bind(sockets->tcp[i].s, 00822 (struct sockaddr *) sockets->tcp[i].addr->ai_addr, 00823 sockets->tcp[i].addr->ai_addrlen) != 0) { 00824 ods_log_error("zone fetcher can't bind tcp/6 socket for " 00825 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00826 strerror(errno)); 00827 ret = -1; 00828 break; 00829 } 00830 /* listen */ 00831 if (listen(sockets->tcp[i].s, 5) == -1) { 00832 ods_log_error("zone fetcher can't listen to tcp/6 socket for " 00833 "%s:%s (%s)", node?node:"(null)", port?port:"(null)", 00834 strerror(errno)); 00835 ret = -1; 00836 break; 00837 } 00838 } 00839 00840 walk = walk->next; 00841 i++; 00842 } 00843 00844 if (new_list) { 00845 free_serverlist(new_list); 00846 } 00847 00848 return ret; 00849 } 00850 00851 static void 00852 free_sockets(sockets_type* sockets) 00853 { 00854 size_t i = 0; 00855 00856 for (i=0; i < MAX_INTERFACES; i++) { 00857 if (sockets->udp[i].s != -1) { 00858 close(sockets->udp[i].s); 00859 freeaddrinfo((void*)sockets->udp[i].addr); 00860 } 00861 if (sockets->tcp[i].s != -1) { 00862 close(sockets->tcp[i].s); 00863 freeaddrinfo((void*)sockets->tcp[i].addr); 00864 } 00865 } 00866 } 00867 00868 static int 00869 odd_xfer(zfzonelist_type* zone, uint32_t serial, config_type* config, int kick_signer) 00870 { 00871 ldns_status status = LDNS_STATUS_OK; 00872 ldns_rr* axfr_rr = NULL, *soa_rr = NULL; 00873 uint32_t new_serial = 0; 00874 ldns_pkt* qpkt = NULL, *apkt; 00875 FILE* fd = NULL; 00876 char lock_ext[32]; 00877 char axfr_file[MAXPATHLEN]; 00878 char dest_file[MAXPATHLEN]; 00879 char lock_file[MAXPATHLEN]; 00880 char engine_sign_cmd[MAXPATHLEN + 1024]; 00881 int soa_seen = 0; 00882 ldns_resolver* xfrd = NULL; 00883 00884 /* soa serial query */ 00885 if (!zone || !zone->dname) { 00886 ods_log_error("zone fetcher failed to provide a zone for AXFR "); 00887 return -1; 00888 } 00889 /* Coverity comment: 00890 Event deref_ptr: Directly dereferenced pointer "zone" 00891 */ 00892 qpkt = ldns_pkt_query_new(ldns_rdf_clone(zone->dname), 00893 LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); 00894 if (!qpkt) { 00895 ods_log_error("zone fetcher failed to create SOA query. " 00896 "Aborting AXFR"); 00897 return -1; 00898 } 00899 00900 /* Initialise LDNS resolver for AXFR */ 00901 xfrd = init_xfrd(config); 00902 00903 if (!xfrd) { 00904 ods_log_error("zone fetcher failed to initialise AXFR structure"); 00905 return -1; 00906 } 00907 00908 status = ldns_resolver_send_pkt(&apkt, xfrd, qpkt); 00909 ldns_pkt_free(qpkt); 00910 00911 if (status != LDNS_STATUS_OK) { 00912 ods_log_error("zone fetcher failed to send SOA query: %s", 00913 ldns_get_errorstr_by_id(status)); 00914 ldns_resolver_deep_free(xfrd); 00915 return -1; 00916 } 00917 if (ldns_pkt_ancount(apkt) == 1) { 00918 soa_rr = ldns_rr_list_rr(ldns_pkt_answer(apkt), 0); 00919 if (soa_rr && ldns_rr_get_type(soa_rr) == LDNS_RR_TYPE_SOA) { 00920 new_serial = ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2)); 00921 } 00922 ldns_pkt_free(apkt); 00923 } else { 00924 ods_log_error("zone fetcher saw SOA response with ANCOUNT != 1, " 00925 "Aborting AXFR"); 00926 /* retry? */ 00927 ldns_pkt_free(apkt); 00928 ldns_resolver_deep_free(xfrd); 00929 return -1; 00930 } 00931 00932 if (DNS_SERIAL_GT(new_serial, serial)) { 00933 status = ldns_axfr_start(xfrd, zone->dname, LDNS_RR_CLASS_IN); 00934 if (status != LDNS_STATUS_OK) { 00935 ods_log_error("zone fetcher failed to start axfr: %s", 00936 ldns_get_errorstr_by_id(status)); 00937 ldns_resolver_deep_free(xfrd); 00938 return -1; 00939 } 00940 00941 /* Coverity comment: 00942 Event check_after_deref: Pointer "zone" dereferenced before NULL check 00943 */ 00944 if (zone && zone->input_file) { 00945 snprintf(lock_ext, sizeof(lock_ext), "axfr.%lu", 00946 (unsigned long) getpid()); 00947 00948 snprintf(axfr_file, sizeof(axfr_file), "%s.%s", zone->input_file, lock_ext); 00949 fd = fopen(axfr_file, "w"); 00950 if (!fd) { 00951 ods_log_error("zone fetcher cannot store AXFR to file %s", axfr_file); 00952 ldns_resolver_deep_free(xfrd); 00953 return -1; 00954 } 00955 } 00956 assert(fd); 00957 00958 axfr_rr = ldns_axfr_next(xfrd); 00959 if (!axfr_rr) { 00960 ods_log_error("zone fetcher AXFR for %s failed", 00961 zone->name?zone->name:"(null)"); 00962 fclose(fd); 00963 unlink(axfr_file); 00964 ldns_resolver_deep_free(xfrd); 00965 return -1; 00966 } 00967 else { 00968 while (axfr_rr) { 00969 if (ldns_rr_get_type(axfr_rr) == LDNS_RR_TYPE_SOA) { 00970 if (!soa_seen) { 00971 soa_seen = 1; 00972 ldns_rr_print(fd, axfr_rr); 00973 } 00974 } else { 00975 ldns_rr_print(fd, axfr_rr); 00976 } 00977 ldns_rr_free(axfr_rr); 00978 axfr_rr = ldns_axfr_next(xfrd); 00979 } 00980 00981 /* RoRi: 00982 * We MUST now check if the AXFR was successful by verifying that 00983 * LDNS has seen the SOA record twice. Not doing this can result 00984 * in a half-transferred zone if the AXFR is interrupted. 00985 */ 00986 if (!ldns_axfr_complete(xfrd)) { 00987 /* The AXFR was not successful, we've received only a partial zone */ 00988 ods_log_error("zone fetcher AXFR for %s failed, received only a partial zone", zone->name); 00989 fclose(fd); 00990 unlink(axfr_file); 00991 ldns_resolver_deep_free(xfrd); 00992 return -1; 00993 } 00994 00995 ods_log_info("zone fetcher transferred zone %s serial %u " 00996 "successfully", zone->name?zone->name:"(null)", new_serial); 00997 00998 /* Close file before moving it */ 00999 fclose(fd); 01000 01001 /* moving and kicking */ 01002 snprintf(lock_file, sizeof(lock_file), "%s.lock", 01003 zone->input_file?zone->input_file:"(null)"); 01004 01005 lock_axfr: 01006 if (access(lock_file, F_OK) == 0) { 01007 ods_log_deeebug("zone fetcher axfr file %s is locked, " 01008 "waiting...", dest_file); 01009 sleep(1); 01010 goto lock_axfr; 01011 } else { 01012 fd = fopen(lock_file, "w"); 01013 if (!fd) { 01014 ods_log_error("zone fetcher cannot lock AXFR file %s", 01015 lock_file); 01016 ldns_resolver_deep_free(xfrd); 01017 return -1; 01018 } 01019 } 01020 assert(fd); /* locked */ 01021 01022 snprintf(dest_file, sizeof(dest_file), "%s.axfr", 01023 zone->input_file?zone->input_file:"(null)"); 01024 if(rename(axfr_file, dest_file) == 0) { 01025 fclose(fd); 01026 (void) unlink(lock_file); /* unlocked */ 01027 01028 if (kick_signer) { 01029 snprintf(engine_sign_cmd, sizeof(engine_sign_cmd), 01030 "%s sign %s > /dev/null 2>&1", 01031 ODS_SE_CLI, zone->name?zone->name:"--all"); 01032 if (system(engine_sign_cmd) != 0) { 01033 ods_log_error("zone fetcher could not kick " 01034 "the signer engine to sign zone %s", 01035 zone->name?zone->name:"--all"); 01036 } 01037 } 01038 } else { 01039 fclose(fd); 01040 (void) unlink(lock_file); /* unlocked */ 01041 01042 ods_log_error("zone fetcher could not move AXFR to %s", 01043 dest_file); 01044 } 01045 ldns_resolver_deep_free(xfrd); 01046 return 0; 01047 } 01048 } else { 01049 ods_log_info("zone fetcher zone %s is already up to date, " 01050 "serial is %u", zone->name?zone->name:"(null)", serial); 01051 } 01052 01053 ldns_resolver_deep_free(xfrd); 01054 return 0; 01055 } 01056 01057 static void 01058 send_udp(uint8_t* buf, size_t len, void* data) 01059 { 01060 struct handle_udp_userdata *userdata = (struct handle_udp_userdata*)data; 01061 /* udp send reply */ 01062 ssize_t nb; 01063 nb = sendto(userdata->udp_sock, buf, len, 0, 01064 (struct sockaddr*)&userdata->addr_him, userdata->hislen); 01065 if (nb == -1) 01066 ods_log_error("zone fetcher sendto() failed: %s", strerror(errno)); 01067 else if ((size_t)nb != len) 01068 ods_log_error("zone fetcher sendto(): only sent %d of %d octets.", 01069 (int)nb, (int)len); 01070 } 01071 01072 static void 01073 write_n_bytes(int sock, uint8_t* buf, size_t sz) 01074 { 01075 size_t count = 0; 01076 while(count < sz) { 01077 ssize_t nb = send(sock, buf+count, sz-count, 0); 01078 if(nb < 0) { 01079 ods_log_error("zone fetcher send() failed: %s", 01080 strerror(errno)); 01081 return; 01082 } 01083 count += nb; 01084 } 01085 } 01086 01087 static void 01088 send_tcp(uint8_t* buf, size_t len, void* data) 01089 { 01090 struct handle_tcp_userdata *userdata = (struct handle_tcp_userdata*)data; 01091 uint16_t tcplen; 01092 /* tcp send reply */ 01093 tcplen = htons(len); 01094 write_n_bytes(userdata->s, (uint8_t*)&tcplen, sizeof(tcplen)); 01095 write_n_bytes(userdata->s, buf, len); 01096 } 01097 01098 static void 01099 handle_query(uint8_t* inbuf, ssize_t inlen, 01100 void (*sendfunc)(uint8_t*, size_t, void*), 01101 void* userdata, config_type* config) 01102 { 01103 zfzonelist_type* zonelist = NULL; 01104 ldns_status status = LDNS_STATUS_OK; 01105 ldns_pkt *query_pkt = NULL; 01106 ldns_rr *query_rr = NULL; 01107 uint32_t serial = 0; 01108 char* owner_name = NULL; 01109 uint8_t *outbuf = NULL; 01110 size_t answer_size = 0; 01111 char dest_file[MAXPATHLEN]; 01112 FILE* fd; 01113 01114 /* packet parsing */ 01115 status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen); 01116 if (status != LDNS_STATUS_OK) { 01117 ods_log_error("zone fetcher got bad packet: %s", 01118 ldns_get_errorstr_by_id(status)); 01119 return; 01120 } 01121 query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); 01122 01123 if (ldns_pkt_get_opcode(query_pkt) != LDNS_PACKET_NOTIFY || 01124 ldns_pkt_get_rcode(query_pkt) != LDNS_RCODE_NOERROR || 01125 ldns_pkt_qr(query_pkt) || 01126 !ldns_pkt_aa(query_pkt) || 01127 ldns_pkt_tc(query_pkt) || 01128 ldns_pkt_rd(query_pkt) || 01129 ldns_pkt_ra(query_pkt) || 01130 ldns_pkt_cd(query_pkt) || 01131 ldns_pkt_ad(query_pkt) || 01132 ldns_pkt_qdcount(query_pkt) != 1 || 01133 ldns_pkt_nscount(query_pkt) != 0 || 01134 ldns_pkt_arcount(query_pkt) != 0 || 01135 ldns_rr_get_type(query_rr) != LDNS_RR_TYPE_SOA || 01136 ldns_rr_get_class(query_rr) != LDNS_RR_CLASS_IN) 01137 { 01138 ods_log_info("zone fetcher drop bad notify"); 01139 return; 01140 } 01141 01142 /* NOTIFY OK */ 01143 if (config) { 01144 zonelist = config->zonelist; 01145 } 01146 ldns_pkt_set_qr(query_pkt, 1); 01147 status = ldns_pkt2wire(&outbuf, query_pkt, &answer_size); 01148 if (status != LDNS_STATUS_OK) { 01149 ods_log_error("zone fetcher error creating notify response: %s", 01150 ldns_get_errorstr_by_id(status)); 01151 } 01152 sendfunc(outbuf, answer_size, userdata); 01153 LDNS_FREE(outbuf); 01154 01155 /* send AXFR request */ 01156 while (zonelist) { 01157 if (ldns_dname_compare(ldns_rr_owner(query_rr), zonelist->dname) == 0) 01158 { 01159 ods_log_info("zone fetcher received NOTIFY for zone %s", 01160 zonelist->name?zonelist->name:"(null)"); 01161 /* get latest serial */ 01162 snprintf(dest_file, sizeof(dest_file), "%s.axfr", 01163 zonelist->input_file?zonelist->input_file:"(null)"); 01164 fd = fopen(dest_file, "r"); 01165 if (!fd) { 01166 serial = 0; 01167 } else { 01168 serial = lookup_serial(fd); 01169 fclose(fd); 01170 } 01171 if (odd_xfer(zonelist, serial, config, 1) != 0) { 01172 ods_log_error("AXFR for zone %s failed", 01173 zonelist->name?zonelist->name:"(null)"); 01174 } 01175 ldns_pkt_free(query_pkt); 01176 return; 01177 } 01178 /* next */ 01179 zonelist = zonelist->next; 01180 } 01181 owner_name = ldns_rdf2str(ldns_rr_owner(query_rr)); 01182 ods_log_warning("zone fetcher notify received for unknown zone: %s", 01183 owner_name?owner_name:"(null)"); 01184 free((void*)owner_name); 01185 ldns_pkt_free(query_pkt); 01186 } 01187 01188 static void 01189 read_n_bytes(int sock, uint8_t* buf, size_t sz) 01190 { 01191 size_t count = 0; 01192 while(count < sz) { 01193 ssize_t nb = recv(sock, buf+count, sz-count, 0); 01194 if(nb < 0) { 01195 ods_log_error("zone fetcher recv() failed: %s", 01196 strerror(errno)); 01197 return; 01198 } 01199 count += nb; 01200 } 01201 } 01202 01203 static char* 01204 addr2ip(struct sockaddr_storage addr, char* remote, size_t len) 01205 { 01206 if (addr.ss_family == AF_INET6) { 01207 if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, 01208 remote, len)) { 01209 return NULL; 01210 } 01211 } else { 01212 if (!inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr, 01213 remote, len)) 01214 return NULL; 01215 } 01216 01217 return remote; 01218 } 01219 01220 static int 01221 acl_matches(struct sockaddr_storage* addr, config_type* config) 01222 { 01223 serverlist_type* serverlist = NULL; 01224 01225 if (config && config->serverlist) { 01226 serverlist = config->serverlist; 01227 while (serverlist) { 01228 if (serverlist->family == AF_INET6) { 01229 struct sockaddr_in6* addr6 = (struct sockaddr_in6*)addr; 01230 if (serverlist->family == addr->ss_family && 01231 memcmp(&addr6->sin6_addr, &serverlist->addr.addr6, 01232 sizeof(struct in6_addr)) == 0) 01233 { 01234 return 1; 01235 } 01236 } 01237 else { 01238 struct sockaddr_in* addr4 = (struct sockaddr_in*)addr; 01239 if (serverlist->family == addr4->sin_family && 01240 memcmp(&addr4->sin_addr, &serverlist->addr.addr, 01241 sizeof(struct in_addr)) == 0) 01242 { 01243 return 1; 01244 } 01245 } 01246 01247 serverlist = serverlist->next; 01248 } 01249 } 01250 return 0; 01251 } 01252 01253 static void 01254 handle_udp(int udp_sock, config_type* config) 01255 { 01256 ssize_t nb; 01257 uint8_t inbuf[INBUF_SIZE]; 01258 struct handle_udp_userdata userdata; 01259 char* remote; 01260 01261 userdata.udp_sock = udp_sock; 01262 userdata.hislen = (socklen_t) sizeof(userdata.addr_him); 01263 nb = recvfrom(udp_sock, inbuf, INBUF_SIZE, 0, 01264 (struct sockaddr*) &userdata.addr_him, &userdata.hislen); 01265 if (nb < 1) { 01266 ods_log_error("zone fetcher recvfrom() failed: %s", 01267 strerror(errno)); 01268 return; 01269 } 01270 01271 /* acl */ 01272 if (!acl_matches(&userdata.addr_him, config)) { 01273 remote = (char*) malloc(sizeof(char)*userdata.hislen); 01274 ods_log_warning("zone fetcher refused message from " 01275 "unauthoritative source: %s", 01276 addr2ip(userdata.addr_him, remote, userdata.hislen)); 01277 free((void*)remote); 01278 return; 01279 } 01280 handle_query(inbuf, nb, send_udp, &userdata, config); 01281 } 01282 01283 static void 01284 handle_tcp(int tcp_sock, config_type* config) 01285 { 01286 int s; 01287 struct sockaddr_storage addr_him; 01288 socklen_t hislen; 01289 uint8_t inbuf[INBUF_SIZE]; 01290 uint16_t tcplen; 01291 struct handle_tcp_userdata userdata; 01292 char* remote; 01293 01294 /* accept */ 01295 hislen = (socklen_t)sizeof(addr_him); 01296 if((s = accept(tcp_sock, (struct sockaddr*)&addr_him, &hislen)) < 0) { 01297 ods_log_error("zone fetcher accept() failed: %s", strerror(errno)); 01298 return; 01299 } 01300 userdata.s = s; 01301 01302 /* tcp recv */ 01303 read_n_bytes(s, (uint8_t*)&tcplen, sizeof(tcplen)); 01304 tcplen = ntohs(tcplen); 01305 if(tcplen >= INBUF_SIZE) { 01306 ods_log_error("zone fetcher query %d bytes too large, " 01307 "buffer %d bytes.", tcplen, INBUF_SIZE); 01308 close(s); 01309 return; 01310 } 01311 read_n_bytes(s, inbuf, tcplen); 01312 01313 /* acl */ 01314 if (!acl_matches(&addr_him, config)) { 01315 remote = (char*) malloc(sizeof(char)*hislen); 01316 ods_log_warning("zone fetcher refused message from " 01317 "unauthoritative source: %s", 01318 addr2ip(addr_him, remote, hislen)); 01319 free((void*)remote); 01320 close(s); 01321 return; 01322 } 01323 handle_query(inbuf, (ssize_t) tcplen, send_tcp, &userdata, config); 01324 close(s); 01325 } 01326 01327 01332 static void 01333 reload_zonelist(config_type *config) { 01334 zfzonelist_type *new_zonelist, **thisp; 01335 zfzonelist_type *added_zonelist = NULL, *kept_zonelist = NULL; 01336 int added_count = 0, changed_count = 0, kept_count = 0; 01337 /* Fail softly if the zonelist cannot be accessed for reloading */ 01338 if (!config->zonelist_file) { 01339 ods_log_error("zone fetcher is unable to access the zonelist"); 01340 return; 01341 } else { 01342 ods_log_verbose("zone fetcher will reload the zonelist"); 01343 } 01344 /* Read the zonelist file and construct a new linked list of zonelist entries */ 01345 new_zonelist = read_zonelist (config->zonelist_file); 01346 /* Iterate over the new zonelist file and compare it to previously configured zonelist entries */ 01347 while (new_zonelist) { 01348 zfzonelist_type *next_zonelist = new_zonelist->next; 01349 zfzonelist_type *this = config->zonelist; 01350 int found = 0; 01351 while (this && !found) { 01352 found = !strcmp (this->name, new_zonelist->name); 01353 if (!found) { 01354 this = this->next; 01355 } 01356 } 01357 01358 /* If the zone name is found in the old zonelist, it is either a full match or a replacement */ 01359 if (found) { 01360 if (strcmp (new_zonelist->input_file, this->input_file)) { 01361 /* the zonelist entry has changed -- treat as a replacement/new zonelist entry */ 01362 changed_count++; 01363 new_zonelist->next = added_zonelist; 01364 added_zonelist = new_zonelist; 01365 } else { 01366 /* the zonelist entry is already configured -- treat as a kept zonelist entry */ 01367 kept_count++; 01368 new_zonelist->next = kept_zonelist; 01369 kept_zonelist = new_zonelist; 01370 } 01371 } else { 01372 /* new_zonelist introduces a new zonelist entry */ 01373 added_count++; 01374 new_zonelist->next = added_zonelist; 01375 added_zonelist = new_zonelist; 01376 } 01377 new_zonelist = next_zonelist; 01378 } 01379 01380 /* Replace the configured zonelist with the added_zonelist and kept_zonelist */ 01381 free_zonelist (config->zonelist); 01382 config->zonelist = kept_zonelist; 01383 thisp = &config->zonelist; 01384 while (*thisp) { 01385 thisp = &(*thisp)->next; 01386 } 01387 *thisp = added_zonelist; 01388 01389 /* Perform an initial AXFR for the newly added zones (assume no present inputfile) */ 01390 new_zonelist = added_zonelist; 01391 while (new_zonelist) { 01392 /* send the request -- assume no file is present so SOA is 0 */ 01393 if (odd_xfer (new_zonelist, 0, config, 1) != 0) { 01394 ods_log_error("AXFR for new zone %s failed", new_zonelist->name); 01395 } 01396 /* next */ 01397 new_zonelist = new_zonelist->next; 01398 } 01399 ods_log_verbose("Reloaded zonelist -- kept %d, changed %d and added %d zones", 01400 kept_count, changed_count, added_count); 01401 return; 01402 } 01403 01404 01405 static void 01406 xfrd_ns(sockets_type* sockets, config_type* cfg) 01407 { 01408 fd_set rset, wset, eset; 01409 struct timeval timeout; 01410 int count, maxfd = 0; 01411 size_t i; 01412 01413 /* service */ 01414 count = 0; 01415 timeout.tv_sec = 0; 01416 timeout.tv_usec = 0; 01417 while (!sig_quit) { 01418 if (sig_reload) { 01419 reload_zonelist(cfg); 01420 sig_reload = 0; 01421 } 01422 FD_ZERO(&rset); 01423 FD_ZERO(&wset); 01424 FD_ZERO(&eset); 01425 for (i=0; i < MAX_INTERFACES; i++) { 01426 if (sockets->udp[i].s != -1) 01427 FD_SET(sockets->udp[i].s, &rset); 01428 if (sockets->tcp[i].s != -1) 01429 FD_SET(sockets->tcp[i].s, &rset); 01430 if (sockets->udp[i].s > maxfd) maxfd = sockets->udp[i].s; 01431 if (sockets->tcp[i].s > maxfd) maxfd = sockets->tcp[i].s; 01432 } 01433 01434 if (select(maxfd+1, &rset, &wset, &eset, NULL) < 0) { 01435 if (errno == EINTR) 01436 continue; 01437 ods_log_error("zone fetcher select(): %s", strerror(errno)); 01438 } 01439 01440 for (i=0; i < MAX_INTERFACES; i++) { 01441 if (sockets->udp[i].s != -1 && FD_ISSET(sockets->udp[i].s, &rset)) 01442 handle_udp(sockets->udp[i].s, cfg); 01443 if (sockets->tcp[i].s != -1 && FD_ISSET(sockets->tcp[i].s, &rset)) 01444 handle_tcp(sockets->tcp[i].s, cfg); 01445 } 01446 } 01447 } 01448 01449 static void 01450 list_settings(FILE* out, config_type* config, const char* filename) 01451 { 01452 zfzonelist_type* zones = NULL; 01453 serverlist_type* servers = NULL; 01454 01455 if (config) { 01456 fprintf(out, "configuration settings:\n"); 01457 fprintf(out, "filename: %s\n", filename?filename:"(null)"); 01458 fprintf(out, "pidfile: %s\n", 01459 config->pidfile?config->pidfile:"(null)"); 01460 fprintf(out, "tsig: %s\n", config->use_tsig?"yes":"no"); 01461 if (config->use_tsig) { 01462 fprintf(out, "tsig name: %s\n", 01463 config->tsig_name?config->tsig_name:"(null)"); 01464 fprintf(out, "tsig algorithm: %s\n", 01465 config->tsig_algo?config->tsig_algo:"(null)"); 01466 fprintf(out, "tsig secret: ?\n"); 01467 } 01468 fprintf(out, "zones: %s\n", config->zonelist?"":"none"); 01469 zones = config->zonelist; 01470 while (zones) { 01471 fprintf(out, "\t%s\n", zones->name?zones->name:"(null)"); 01472 zones = zones->next; 01473 } 01474 fprintf(out, "master servers: %s\n", config->serverlist?"":"none"); 01475 servers = config->serverlist; 01476 while (servers) { 01477 fprintf(out, "\t%s\n", servers->ipaddr?servers->ipaddr:"(null)"); 01478 servers = servers->next; 01479 } 01480 fprintf(out, "interfaces: %s\n", config->notifylist?"":"none"); 01481 servers = config->notifylist; 01482 while (servers) { 01483 fprintf(out, "\t%s %s:%s\n", 01484 servers->family==AF_INET6?"ipv6":"ipv4", 01485 servers->ipaddr?servers->ipaddr:"(null)", 01486 servers->port?servers->port:"(null)"); 01487 servers = servers->next; 01488 } 01489 fprintf(out, "list zone fetcher settings done.\n"); 01490 } 01491 else fprintf(out, "no config\n"); 01492 } 01493 01494 int 01495 tools_zone_fetcher(const char* config_file, const char* zonelist_file, 01496 const char* group, const char* user, const char* chroot, const char* log_file, 01497 int use_syslog, int verbosity) 01498 { 01499 zfzonelist_type *zonelist = NULL; 01500 config_type* config = NULL; 01501 uint32_t serial = 0; 01502 FILE* fd; 01503 sockets_type sockets; 01504 int c, info = 0; 01505 int error = 0; 01506 struct sigaction action; 01507 uid_t uid = -1; 01508 gid_t gid = -1; 01509 01510 ods_log_init(log_file, use_syslog, verbosity); 01511 01512 /* read transfer configuration */ 01513 config = new_config(); 01514 config->pidfile = strdup(ODS_ZF_PIDFILE); /* not freed */ 01515 if (!config->pidfile) { 01516 ods_log_alert("zone fetcher error: no pidfile given"); 01517 free_config(config); 01518 exit(EXIT_FAILURE); 01519 } 01520 01521 c = read_axfr_config(config_file, config); 01522 config->zonelist = read_zonelist(zonelist_file); 01523 config->zonelist_file = strdup(zonelist_file); 01524 01525 if (info) { 01526 list_settings(stdout, config, config_file); 01527 } 01528 01529 if (config->serverlist == NULL) { 01530 ods_log_alert("zone fetcher error: no master servers configured " 01531 "with <RequestTransfer>"); 01532 free_config(config); 01533 exit(EXIT_FAILURE); 01534 } 01535 01536 /* setup signal handing */ 01537 action.sa_handler = sig_handler; 01538 sigfillset(&action.sa_mask); 01539 action.sa_flags = 0; 01540 sigaction(SIGHUP, &action, NULL); 01541 sigaction(SIGTERM, &action, NULL); 01542 01543 /* write pidfile */ 01544 if (writepid(config->pidfile, getpid()) != 0) { 01545 ods_log_error("write pidfile %s failed", config->pidfile); 01546 ods_log_info("zone fetcher exiting..."); 01547 exit(EXIT_FAILURE); 01548 } 01549 01550 ods_log_info("zone fetcher started"); 01551 01552 /* foreach zone, do a single axfr request */ 01553 zonelist = config->zonelist; 01554 while (zonelist != NULL) { 01555 /* get latest serial */ 01556 fd = fopen(zonelist->input_file, "r"); 01557 if (!fd) { 01558 serial = 0; 01559 } else { 01560 serial = lookup_serial(fd); 01561 fclose(fd); 01562 } 01563 /* send the request */ 01564 if (odd_xfer(zonelist, serial, config, 1) != 0) { 01565 ods_log_error("AXFR for zone %s failed", 01566 zonelist->name?zonelist->name:"(null)"); 01567 } 01568 /* next */ 01569 zonelist = zonelist->next; 01570 } 01571 01572 /* listen to NOTIFY messages */ 01573 c = init_sockets(&sockets, config->notifylist); 01574 if (c == -1) { 01575 ods_log_error("zone fetcher failed to initialize sockets"); 01576 if (unlink(config->pidfile) == -1) { 01577 ods_log_error("unlink pidfile %s failed: %s", 01578 config->pidfile?config->pidfile:"(null)", 01579 strerror(errno)); 01580 } 01581 ods_log_info("zone fetcher exiting..."); 01582 exit(EXIT_FAILURE); 01583 } 01584 01585 /* drop privileges */ 01586 error = privdrop(user, group, chroot, &uid, &gid); 01587 privclose(user, group); 01588 if (error != 0) { 01589 ods_log_error("zone fetcher failed to drop privileges"); 01590 if (unlink(config->pidfile) == -1) { 01591 ods_log_error("unlink pidfile %s failed: %s", 01592 config->pidfile?config->pidfile:"(null)", 01593 strerror(errno)); 01594 } 01595 free_sockets(&sockets); 01596 ods_log_info("zone fetcher exiting..."); 01597 exit(EXIT_FAILURE); 01598 } 01599 01600 xfrd_ns(&sockets, config); 01601 01602 if (unlink(config->pidfile) == -1) { 01603 ods_log_warning("unlink pidfile %s failed: %s", 01604 config->pidfile?config->pidfile:"(null)", 01605 strerror(errno)); 01606 } 01607 free_sockets(&sockets); 01608 01609 /* done */ 01610 ods_log_debug("zone fetcher done"); 01611 free_config(config); 01612 ods_log_close(); 01613 return 0; 01614 }