OpenDNSSEC-signer 1.2.1

/build/buildd-opendnssec_1.2.1.dfsg-1-ia64-j6OroR/opendnssec-1.2.1.dfsg/signer/src/tools/zone_fetcher.c

Go to the documentation of this file.
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 }