00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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));
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
00242
00243 reader = xmlNewTextReaderFilename(filename);
00244 if (reader != NULL) {
00245 ret = xmlTextReaderRead(reader);
00246 while (ret == 1) {
00247 tag_name = (char*) xmlTextReaderLocalName(reader);
00248
00249 if (strncmp(tag_name, "ZoneFetch", 8) == 0 &&
00250 xmlTextReaderNodeType(reader) == 1) {
00251
00252
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
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);
00295 cfg->serverlist = serverlist;
00296 }
00297 else {
00298 serverlist->next = new_server(ipv4, ipv6, port);
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
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
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
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
00452 reader = xmlNewTextReaderFilename(filename);
00453 if (reader != NULL) {
00454 ret = xmlTextReaderRead(reader);
00455 while (ret == 1) {
00456 tag_name = (char*) xmlTextReaderLocalName(reader);
00457
00458 if (strncmp(tag_name, "Zone", 4) == 0 &&
00459 strncmp(tag_name, "ZoneList", 8) != 0 &&
00460 xmlTextReaderNodeType(reader) == 1) {
00461
00462 zone_name = (char*) xmlTextReaderGetAttribute(reader, name_expr);
00463
00464 if (zone_name == NULL) {
00465
00466 ods_log_error("zone fetcher failed to extract zone "
00467 "name from %s", filename?filename:"(null)");
00468
00469 ret = xmlTextReaderRead(reader);
00470 continue;
00471 }
00472
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
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
00487 ret = xmlTextReaderRead(reader);
00488 continue;
00489 }
00490
00491
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
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);
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
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
00617
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
00625 hints[0].ai_family = AF_INET6;
00626 new_list = new_server(NULL, "", NULL);
00627 #endif
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
00640 hints[i].ai_socktype = SOCK_DGRAM;
00641
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
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
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
00724 hints[i].ai_socktype = SOCK_STREAM;
00725
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
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
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
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
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
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
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
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
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
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
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
00885 if (!zone || !zone->dname) {
00886 ods_log_error("zone fetcher failed to provide a zone for AXFR ");
00887 return -1;
00888 }
00889
00890
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
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
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
00942
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
00982
00983
00984
00985
00986 if (!ldns_axfr_complete(xfrd)) {
00987
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
00999 fclose(fd);
01000
01001
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);
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);
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);
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
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
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
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
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
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
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
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
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
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
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
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
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
01345 new_zonelist = read_zonelist (config->zonelist_file);
01346
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
01359 if (found) {
01360 if (strcmp (new_zonelist->input_file, this->input_file)) {
01361
01362 changed_count++;
01363 new_zonelist->next = added_zonelist;
01364 added_zonelist = new_zonelist;
01365 } else {
01366
01367 kept_count++;
01368 new_zonelist->next = kept_zonelist;
01369 kept_zonelist = new_zonelist;
01370 }
01371 } else {
01372
01373 added_count++;
01374 new_zonelist->next = added_zonelist;
01375 added_zonelist = new_zonelist;
01376 }
01377 new_zonelist = next_zonelist;
01378 }
01379
01380
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
01390 new_zonelist = added_zonelist;
01391 while (new_zonelist) {
01392
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
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
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
01513 config = new_config();
01514 config->pidfile = strdup(ODS_ZF_PIDFILE);
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
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
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
01553 zonelist = config->zonelist;
01554 while (zonelist != NULL) {
01555
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
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
01569 zonelist = zonelist->next;
01570 }
01571
01572
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
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
01610 ods_log_debug("zone fetcher done");
01611 free_config(config);
01612 ods_log_close();
01613 return 0;
01614 }