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