home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / net / bind-contrib.tar.gz / bind-contrib.tar / contrib / multizdb / ns_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-25  |  22.5 KB  |  948 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)ns_init.c    4.38 (Berkeley) 3/21/91";
  3. static char rcsid[] = "$Id:";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986, 1990
  8.  * -
  9.  * Copyright (c) 1986, 1990
  10.  *    The Regents of the University of California.  All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *     This product includes software developed by the University of
  23.  *     California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  * -
  40.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  41.  * 
  42.  * Permission to use, copy, modify, and distribute this software for any
  43.  * purpose with or without fee is hereby granted, provided that the above
  44.  * copyright notice and this permission notice appear in all copies, and that
  45.  * the name of Digital Equipment Corporation not be used in advertising or
  46.  * publicity pertaining to distribution of the document or software without
  47.  * specific, written prior permission.
  48.  * 
  49.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  50.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  51.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  52.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  53.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  54.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  55.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56.  * SOFTWARE.
  57.  * -
  58.  * --Copyright--
  59.  */
  60.  
  61. #include <sys/param.h>
  62. #include <sys/socket.h>
  63. #include <sys/stat.h>
  64. #include <netinet/in.h>
  65. #include <arpa/nameser.h>
  66. #include <arpa/inet.h>
  67. #include <syslog.h>
  68. #include <signal.h>
  69. #include <resolv.h>
  70. #include <stdio.h>
  71. #include <errno.h>
  72. #include <ctype.h>
  73.  
  74. #include "named.h"
  75.  
  76. #undef nsaddr
  77.  
  78. static void        zoneinit __P((struct zoneinfo *)),
  79.             get_forwarders __P((FILE *)),
  80.             boot_read __P((char *)),
  81. #ifdef DEBUG
  82.             content_zone __P((int)),
  83. #endif
  84. #ifdef MULTIZDB
  85.             process_mzone_line __P((FILE *)),
  86. #endif
  87.             free_forwarders __P((void));
  88.  
  89. static struct zoneinfo    *find_zone __P((char *, int, int));
  90.  
  91. static char *multizone_file;  /* these don't nest */
  92.  
  93. /*
  94.  * Read boot file for configuration info.
  95.  */
  96. void
  97. ns_init(bootfile)
  98.     char *bootfile;
  99. {
  100.     register struct zoneinfo *zp;
  101.     static int loads = 0;            /* number of times loaded */
  102.  
  103.     dprintf(1, (ddt, "\nns_init(%s)\n", bootfile));
  104.     gettime(&tt);
  105.  
  106.         if (loads == 0) {
  107.         if ((zones =
  108.             (struct zoneinfo *)calloc(64, sizeof(struct zoneinfo)))
  109.                         == NULL) {
  110.             syslog(LOG_ERR,
  111.             "Not enough memory to allocate initial zones array");
  112.             exit(1);
  113.         }
  114.         nzones = 1;        /* zone zero is cache data */
  115.         /* allocate cache hash table, formerly the root hash table. */
  116.         hashtab = savehash((struct hashbuf *)NULL);
  117.  
  118.         /* allocate root-hints/file-cache hash table */
  119.         fcachetab = savehash((struct hashbuf *)NULL);
  120.         /* init zone data */
  121.         zones[0].z_type = Z_CACHE;
  122.         } else {
  123.         /* Mark previous zones as not yet found in boot file. */
  124.         for (zp = &zones[1]; zp < &zones[nzones]; zp++)
  125.             zp->z_flags &= ~Z_FOUND;
  126. #ifdef LOCALDOM
  127.         if (localdomain) {
  128.             free(localdomain);
  129.             localdomain = NULL;
  130.         }
  131. #endif
  132.         free_forwarders();
  133.         free_netlist(enettab);
  134. #ifdef XFRNETS
  135.         free_netlist(&xfrnets);
  136. #endif
  137. #ifdef BOGUSNS
  138.         free_netlist(&boglist);
  139. #endif
  140.         forward_only = 0;
  141.     }
  142.  
  143.     dprintf(3, (ddt, "\n content of zones before loading \n"));
  144. #ifdef DEBUG
  145.         if (debug >= 3) {
  146.             content_zone(nzones - 1);
  147.         }
  148. #endif
  149.     boot_read(bootfile);
  150.  
  151.         /* erase all old zones that were not found */
  152.         for (zp = &zones[1]; zp < &zones[nzones]; zp++) {
  153.             if (zp->z_type && (zp->z_flags & Z_FOUND) == 0) {
  154. #ifdef CLEANCACHE
  155.         remove_zone(hashtab, zp - zones, 1);
  156. #else
  157.         remove_zone(hashtab, zp - zones);
  158. #endif
  159. #ifdef SECURE_ZONES
  160.         free_netlist(&zp->secure_nets);
  161. #endif
  162.         syslog(LOG_NOTICE, "Zone \"%s\" was removed", zp->z_origin);
  163.         free(zp->z_origin);
  164.         free(zp->z_source);
  165.         bzero((char *) zp, sizeof(*zp));
  166.         }
  167.         }
  168.     dprintf(2, (ddt,"\n content of zones after loading\n"));
  169.  
  170. #ifdef DEBUG
  171.     if (debug >= 2) {
  172.             content_zone(nzones-1);
  173.         }
  174. #endif
  175.  
  176.     /*
  177.      * Schedule calls to ns_maint().
  178.      */
  179.     if (!needmaint)
  180.         sched_maint();
  181.     dprintf(1, (ddt, "exit ns_init()%s\n",
  182.             needmaint ? ", need maintenance immediately" : ""));
  183.     loads++;
  184. }
  185.  
  186. /*
  187.  * Read the actual boot file.
  188.  * Set up to recurse.
  189.  */
  190. static void
  191. boot_read(bootfile)
  192.     char *bootfile;
  193. {
  194.     char buf[BUFSIZ];
  195.     FILE *fp, *mzfp;
  196.     int slineno;            /* Saved global line number. */
  197.  
  198.     if ((fp = fopen(bootfile, "r")) == NULL) {
  199.         syslog(LOG_ERR, "%s: %m", bootfile);
  200.         exit(1);
  201.     }
  202.  
  203.     slineno = lineno;
  204.     lineno = 0;
  205.  
  206.     while (!feof(fp) && !ferror(fp)) {
  207.         if (!getword(buf, sizeof(buf), fp))
  208.             continue;
  209.         /* read named.boot keyword and process args */
  210.         if (strcasecmp(buf, "directory") == 0) {
  211.             (void) getword(buf, sizeof(buf), fp);
  212.             if (chdir(buf) < 0) {
  213.                 syslog(LOG_CRIT, "directory %s: %m\n",
  214.                     buf);
  215.                 exit(1);
  216.             }
  217.             continue;
  218.         } else if (strcasecmp(buf, "sortlist") == 0) {
  219.             get_netlist(fp, enettab, ALLOW_NETS, buf);
  220.             continue;
  221.         } else if (strcasecmp(buf, "max-fetch") == 0) {
  222.             max_xfers_running = getnum(fp, bootfile, 0);
  223.             continue;
  224.         } else if (strcasecmp(buf, "forwarders") == 0) {
  225.             get_forwarders(fp);
  226.             continue;
  227.         } else if (strcasecmp(buf, "slave") == 0) {
  228.             forward_only++;
  229.             endline(fp);
  230.             continue;
  231. #ifdef BOGUSNS
  232.         } else if (strcasecmp(buf, "bogusns") == 0) {
  233.             get_netlist(fp, &boglist, ALLOW_HOSTS, buf);
  234.             continue;
  235. #endif
  236. #ifdef XFRNETS
  237.         } else if ((strcasecmp(buf, "tcplist") == 0) ||
  238.                (strcasecmp(buf, "xfrnets") == 0)) {
  239.             get_netlist(fp, &xfrnets, ALLOW_NETS, buf);
  240.             continue;
  241. #endif
  242. #ifdef LOCALDOM
  243.         } else if (strcasecmp(buf, "domain") == 0) {
  244.             if (getword(buf, sizeof(buf), fp))
  245.                 localdomain = savestr(buf);
  246.             endline(fp);
  247.             continue;
  248. #endif
  249.         } else if (strcasecmp(buf, "include") == 0) {
  250.             if (getword(buf, sizeof(buf), fp))
  251.                 boot_read(buf);
  252.             endline(fp);
  253.             continue;
  254.         } else if (strncasecmp(buf, "cache", 5) == 0) {
  255.             process_zone_line(Z_CACHE, buf, fp, 0);
  256.         } else if (strncasecmp(buf, "primary", 7) == 0) {
  257.             process_zone_line(Z_PRIMARY, buf, fp, 0);
  258.         } else if (strncasecmp(buf, "secondary", 9) == 0) {
  259.             process_zone_line(Z_SECONDARY, buf, fp, 0);
  260. #ifdef STUBS
  261.         } else if (strncasecmp(buf, "stub", 4) == 0) {
  262.             process_zone_line(Z_STUB, buf, fp, 0);
  263. #endif
  264. #ifdef MULTIZDB
  265.         } else if (strncasecmp(buf, "multizone", 9) == 0) {
  266.             process_mzone_line(fp);
  267.             continue;
  268. #endif /* MULTIZDB */
  269.         } else {
  270.             syslog(LOG_ERR, "%s: line %d: unknown field '%s'\n",
  271.                 bootfile, lineno+1, buf);
  272.             endline(fp);
  273.             continue;
  274.         }
  275.     }
  276.     (void) my_fclose(fp);
  277.     lineno = slineno;
  278. }
  279.  
  280. static void
  281. zoneinit(zp)
  282.     register struct zoneinfo *zp;
  283. {
  284.     struct stat sb;
  285.  
  286.     /*
  287.      * Try to load zone from backup file,
  288.      * if one was specified and it exists.
  289.      * If not, or if the data are out of date,
  290.      * we will refresh the zone from a primary
  291.      * immediately.
  292.      */
  293.     if (!zp->z_source)
  294.         return;
  295.     if (stat(zp->z_source, &sb) == -1 ||
  296. #ifdef MULTIZDB
  297.         db_load(zp->z_source, zp->z_origin, zp, 0, 0) != 0) {
  298. #else
  299.         db_load(zp->z_source, zp->z_origin, zp, 0) != 0) {
  300. #endif
  301.         /*
  302.          * Set zone to be refreshed immediately.
  303.          */
  304.         zp->z_refresh = INIT_REFRESH;
  305.         zp->z_retry = INIT_REFRESH;
  306.         zp->z_time = tt.tv_sec;
  307.         needmaint = 1;
  308.     } else {
  309.         zp->z_flags |= Z_AUTH;
  310.     }
  311. }
  312.  
  313. #ifdef ALLOW_UPDATES
  314. /*
  315.  * Look for the authoritative zone with the longest matching RHS of dname
  316.  * and return its zone # or zero if not found.
  317.  */
  318. int
  319. findzone(dname, class)
  320.     char *dname;
  321.     int class;
  322. {
  323.     char *dZoneName, *zoneName;
  324.     int dZoneNameLen, zoneNameLen;
  325.     int maxMatchLen = 0;
  326.     int maxMatchZoneNum = 0;
  327.     int zoneNum;
  328.  
  329.     dprintf(4, (ddt, "findzone(dname=%s, class=%d)\n", dname, class));
  330. #ifdef DEBUG
  331.     if (debug >= 5) {
  332.         fprintf(ddt, "zone dump:\n");
  333.         for (zoneNum = 1; zoneNum < nzones; zoneNum++)
  334.             printzoneinfo(zoneNum);
  335.     }
  336. #endif
  337.  
  338.     dZoneName = strchr(dname, '.');
  339.     if (dZoneName == NULL)
  340.         dZoneName = "";    /* root */
  341.     else
  342.         dZoneName++;    /* There is a '.' in dname, so use remainder of
  343.                    string as the zone name */
  344.     dZoneNameLen = strlen(dZoneName);
  345.     for (zoneNum = 1; zoneNum < nzones; zoneNum++) {
  346.         zoneName = (zones[zoneNum]).z_origin;
  347.         zoneNameLen = strlen(zoneName);
  348.         /* The zone name may or may not end with a '.' */
  349.         if (zoneName[zoneNameLen - 1] == '.')
  350.             zoneNameLen--;
  351.         if (dZoneNameLen != zoneNameLen)
  352.             continue;
  353.         dprintf(5, (ddt, "about to strncasecmp('%s', '%s', %d)\n",
  354.                 dZoneName, zoneName, dZoneNameLen));
  355.         if (strncasecmp(dZoneName, zoneName, dZoneNameLen) == 0) {
  356.             dprintf(5, (ddt, "match\n"));
  357.             /*
  358.              * See if this is as long a match as any so far.
  359.              * Check if "<=" instead of just "<" so that if
  360.              * root domain (whose name length is 0) matches,
  361.              * we use it's zone number instead of just 0
  362.              */
  363.             if (maxMatchLen <= zoneNameLen) {
  364.                 maxMatchZoneNum = zoneNum;
  365.                 maxMatchLen = zoneNameLen;
  366.             }
  367.         } else {
  368.             dprintf(5, (ddt, "no match\n"));
  369.         }
  370.     }
  371.     dprintf(4, (ddt, "findzone: returning %d\n", maxMatchZoneNum));
  372.     return (maxMatchZoneNum);
  373. }
  374. #endif /* ALLOW_UPDATES */
  375.  
  376. static void
  377. get_forwarders(fp)
  378.     FILE *fp;
  379. {
  380.     char buf[BUFSIZ];
  381.     register struct fwdinfo *fip = NULL, *ftp = NULL;
  382.  
  383. #ifdef SLAVE_FORWARD
  384.     int forward_count = 0;
  385. #endif
  386.  
  387.     dprintf(1, (ddt, "forwarders "));
  388.  
  389.     /* on mulitple forwarder lines, move to end of the list */
  390. #ifdef SLAVE_FORWARD
  391.     if (fwdtab != NULL){
  392.         forward_count++;
  393.         for (fip = fwdtab; fip->next != NULL; fip = fip->next)
  394.             forward_count++;
  395.     }
  396. #else
  397.     if (fwdtab != NULL) {
  398.         for (fip = fwdtab; fip->next != NULL; fip = fip->next) {
  399.             ;
  400.         }
  401.     }
  402. #endif /* SLAVE_FORWARD */
  403.  
  404.     while (getword(buf, sizeof(buf), fp)) {
  405.         if (strlen(buf) == 0)
  406.             break;
  407.         dprintf(1, (ddt," %s",buf));
  408.         if (ftp == NULL)
  409.             ftp = (struct fwdinfo *)malloc(sizeof(struct fwdinfo));
  410.         if (inet_aton(buf, &ftp->fwdaddr.sin_addr)) {
  411.             ftp->fwdaddr.sin_port = ns_port;
  412.             ftp->fwdaddr.sin_family = AF_INET;
  413.         } else {
  414.             syslog(LOG_ERR, "'%s' (ignored, NOT dotted quad)",
  415.                    buf);
  416.             dprintf(1, (ddt, " (ignored, NOT dotted quad)"));
  417.             continue;    
  418.         }
  419. #ifdef FWD_LOOP
  420.         if (aIsUs(ftp->fwdaddr.sin_addr)) {
  421.             syslog(LOG_ERR,
  422.                    "Forwarder '%s' ignored, my address",
  423.                    buf);
  424.             dprintf(1, (ddt, " (ignored, my address)"));
  425.             continue;
  426.         }
  427. #endif /* FWD_LOOP */
  428.         ftp->next = NULL;
  429.         if (fwdtab == NULL)
  430.             fwdtab = ftp;    /* First time only */
  431.         else
  432.             fip->next = ftp;
  433.         fip = ftp;
  434.         ftp = NULL;
  435. #ifdef SLAVE_FORWARD
  436.         forward_count++;
  437. #endif /* SLAVE_FORWARD */
  438.     }
  439.     if (ftp)
  440.         free((char *)ftp);
  441.     
  442. #ifdef SLAVE_FORWARD
  443.     /*
  444.     ** Set the slave retry time to 60 seconds total divided
  445.     ** between each forwarder
  446.     */
  447.     if (forward_count != 0) {
  448.         slave_retry = (int) (60 / forward_count);
  449.         if(slave_retry <= 0)
  450.             slave_retry = 1;
  451.     }
  452. #endif
  453.  
  454.     dprintf(1, (ddt, "\n"));
  455. #ifdef DEBUG
  456.     if (debug > 2) {
  457.         for (ftp = fwdtab; ftp != NULL; ftp = ftp->next) {
  458.             fprintf(ddt,"ftp x%x [%s] next x%x\n",
  459.                 ftp,
  460.                 inet_ntoa(ftp->fwdaddr.sin_addr),
  461.                 ftp->next);
  462.         }
  463.     }
  464. #endif
  465. }
  466.  
  467. static void
  468. free_forwarders()
  469. {
  470.     register struct fwdinfo *ftp, *fnext;
  471.  
  472.     for (ftp = fwdtab; ftp != NULL; ftp = fnext) {
  473.         fnext = ftp->next;
  474.         free((char *)ftp);
  475.     }
  476.     fwdtab = NULL;
  477. }
  478.  
  479. static struct zoneinfo *
  480. find_zone(name, type, class) 
  481.     char *name;
  482.     int type, class;
  483. {
  484.     register struct zoneinfo *zp;
  485.  
  486.         for (zp = &zones[1]; zp < &zones[nzones]; zp++) {
  487.         if (zp->z_type == type && zp->z_class == class &&
  488.             strcasecmp(name, zp->z_origin) == 0) {
  489.             dprintf(2, (ddt, ", old zone (%d)", zp - zones));
  490.             return (zp);
  491.         }
  492.     }
  493.     dprintf(2, (ddt, ", new zone"));
  494.     return NULL;
  495. }
  496.  
  497. #ifdef DEBUG
  498. /* prints out the content of zones */
  499. static void
  500. content_zone(end) 
  501.     int end;
  502. {
  503.     int i;
  504.  
  505.     for (i = 1;  i <= end;  i++) {
  506.         printzoneinfo(i);
  507.     }
  508. }
  509. #endif
  510.  
  511. struct zoneinfo *
  512. zone_list_pointer(obuf, type, class)
  513. char *obuf;
  514. int type, class;
  515. {
  516.     struct zoneinfo *zp;
  517.     if (type == Z_CACHE)
  518.     {
  519.         return (&zones[0]);
  520.     }
  521.     zp = find_zone(obuf, type, class);
  522.     if (zp) return (zp);
  523.     /*
  524.     ** Fill a new zone slot, growing the zone slot list if necessary.
  525.     */
  526.     for (zp = &zones[1]; zp < &zones[nzones]; ++zp)
  527.     {
  528.         if (zp->z_type == Z_NIL)  return (zp);
  529.     }
  530.     /*
  531.     ** This code assumes that nzones never decreases.
  532.     */
  533.     if (nzones%64 == 0)
  534.     {
  535.         struct zoneinfo *nz;
  536.         dprintf(1, (ddt, "Reallocating zones structure\n"));
  537.         /*
  538.         ** realloc() not used since it might damage zones if an error occurs
  539.         */
  540.         nz = (struct zoneinfo *)malloc((64 + nzones) * sizeof(struct zoneinfo));
  541.         if (nz == 0)
  542.         {
  543.             syslog(LOG_ERR, "no memory for more zones\n");
  544.             dprintf(1, (ddt, "Out of memory for new zones\n"));
  545.             return (0);
  546.         }
  547.         bcopy((char *)zones, (char *)nz, nzones * sizeof(struct zoneinfo));
  548.         bzero((char *)&nz[nzones], 64 * sizeof(struct zoneinfo));
  549.         free(zones);
  550.         zones = nz;
  551.     }
  552.     zp = &zones[nzones++];
  553.     return (zp);
  554. }
  555.  
  556. static void
  557. zone_reload_bookkeeping(zp, source, mzfp)
  558. struct zoneinfo *zp;
  559. char *source;
  560. FILE *mzfp;
  561. {
  562. #ifdef STUBS
  563.     if (zp->z_type == Z_SECONDARY  ||  zp->z_type == Z_STUB)
  564. #else
  565.     if (zp->z_type == Z_SECONDARY)
  566. #endif
  567.     {
  568.         if (source)
  569.         {
  570.             if (zp->z_source)
  571.             {
  572.                 free(source);
  573.             }
  574.             else
  575.             {
  576.                 zp->z_source = source;
  577.             }
  578.         }
  579.         if (!(zp->z_flags & Z_AUTH))
  580.         {
  581.             zoneinit(zp);
  582.         }
  583. #ifdef FORCED_RELOAD
  584.         else
  585.         {
  586.             /*
  587.             ** Force secondary to try transfer right away after SIGHUP
  588.             */
  589.             if (reloading)
  590.             {
  591.                 zp->z_time = tt.tv_sec;
  592.                 needmaint = 1;
  593.             }
  594.         }
  595. #endif /* FORCED_RELOAD */
  596.     }
  597.     /*
  598.     ** Misc bookkeeping for all zones
  599.     */
  600.     zp->z_flags |= Z_FOUND;
  601. #ifdef MULTIZDB
  602.     if (mzfp)
  603.     {
  604.         if (zp->z_msource)
  605.         {
  606.             free(zp->z_msource);
  607.         }
  608.         zp->z_msource = savestr(multizone_file);
  609.     }
  610. #endif
  611.     dprintf(1, (ddt, "zone[%d] type %d: '%s'", zp-zones, zp->z_type, *(zp->z_origin) ? zp->z_origin : "."));
  612.     if (zp->z_refresh && zp->z_time == 0)
  613.     {
  614.         zp->z_time = zp->z_refresh + tt.tv_sec;
  615.     }
  616.     if (zp->z_time <= tt.tv_sec)
  617.     {
  618.         needmaint = 1;
  619.     }
  620.     dprintf(1, (ddt, " z_time %d, z_refresh %d\n", zp->z_time, zp->z_refresh));
  621. }
  622.  
  623. #ifdef MULTIZDB
  624. void
  625. process_mzone_line(fp)
  626. FILE *fp;
  627. {
  628.     int need_reread;
  629.     FILE *mzfp;
  630.     struct zoneinfo *zp, *przp;
  631.     struct stat mf_time;
  632.     char buf[BUFSIZ];
  633.     if (!getword(buf, sizeof(buf), fp))
  634.     {
  635.         syslog(LOG_ERR, "%s: line %d: missing multizone filename\n", bootfile, lineno+1);
  636.         endline(fp);
  637.         return;
  638.     }
  639.     endline(fp);
  640.     if (multizone_file) free(multizone_file);
  641.     multizone_file = savestr(buf);
  642.     dprintf(1, (ddt, "processing multizone file %s\n", multizone_file));
  643.     mzfp = fopen(multizone_file, "r");
  644.     if (mzfp == NULL)
  645.     {
  646.         syslog(LOG_ERR, "%s: line %d: can't open %s\n", bootfile, lineno+1, multizone_file);
  647.         return;
  648.     }
  649.     /*
  650.     ** Strategy to check the timestamp on zones from a multizone file is
  651.     ** to look in the list of zones for a primary that was loaded from
  652.     ** there since it's z_ftime will be that of the multizone file.  That
  653.     ** means that if there are no primary zones in a multizone file
  654.     ** (e.g., just a list of secondaries and/or stubs), we'll process it
  655.     ** anyhow.  Since the secondaries/stubs have backup files which get
  656.     ** checked as if they were named in the boot file, it's no big deal.
  657.     */
  658.     przp = 0;
  659.     for (zp = &zones[1]; zp < &zones[nzones]; ++zp)
  660.     {
  661.         if (zp->z_msource  &&  zp->z_type == Z_PRIMARY
  662.         &&  strcmp(multizone_file, zp->z_msource) == 0)
  663.         {
  664.             przp = zp;
  665.             break;
  666.         }
  667.     }
  668.     dprintf(2, (ddt, "using primary %s as multizone timestamp\n", przp?przp->z_origin:"--none--"));
  669.     need_reread = 1;
  670.     if (!przp
  671.     ||  fstat(mzfp, &mf_time) == -1
  672.     ||  przp->z_ftime != mf_time.st_mtime)
  673.     {
  674.         (void)db_load(0, 0, 0, 0, mzfp);
  675.     }
  676.     else
  677.     {
  678.         /*
  679.         ** Cycle through all zones with this as the multizone source file
  680.         ** and mark them as found.
  681.         */
  682.         for (zp = &zones[0]; zp < &zones[nzones]; ++zp)
  683.         {
  684.             if (zp->z_msource
  685.             &&  strcmp(multizone_file, zp->z_msource) == 0)
  686.             {
  687.                 zone_reload_bookkeeping(zp, 0, mzfp);
  688.             }
  689.         }
  690.     }
  691. }
  692. #endif /* MULTIZDB */
  693.  
  694. void
  695. process_zone_line(type, type_buf, fp, mzfp)
  696. int type;
  697. char *type_buf;
  698. FILE *fp;
  699. FILE *mzfp;
  700. {
  701.     static int tmpnum;
  702.     struct stat f_time;
  703.     int class, olen;
  704.     char *class_p, *source, obuf[BUFSIZ], buf[BUFSIZ];
  705.     struct zoneinfo *zp;
  706.     class = C_IN;
  707. #ifdef GEN_AXFR
  708.     if (class_p = strchr(type_buf, '/')) class = get_class(class_p+1);
  709. #endif
  710.     /*
  711.     ** Read zone origin
  712.     */
  713.     if (!getword(obuf, sizeof(obuf), fp))
  714.     {
  715.         syslog(LOG_ERR, "%s: line %d: missing origin\n", bootfile, lineno);
  716.         endline(fp);
  717.         return;
  718.     }
  719.     olen = strlen(obuf);
  720.     if ((obuf[olen-1] == '.') && (olen != 1))
  721.     {
  722.         syslog(LOG_ERR, "%s: line %d: zone \"%s\" has trailing dot\n", bootfile, lineno, obuf);
  723.     }
  724.     while ((--olen >= 0) && (obuf[olen] == '.'))
  725.     {
  726.         obuf[olen] = '\0';
  727.     }
  728.     dprintf(1, (ddt, "zone origin %s", obuf[0]?obuf:"."));
  729.     source = 0;
  730.     zp = zone_list_pointer(obuf, type, class);
  731.     if (zp == 0)
  732.     {
  733.         endline(fp);
  734.         return;
  735.     }
  736. #ifdef MULTIZDB
  737.     if (mzfp)
  738.     {
  739.         if (zp->z_msource)
  740.         {
  741.             free(zp->z_msource);
  742.         }
  743.         zp->z_msource = savestr(multizone_file);
  744.         if (type == Z_PRIMARY  ||  type == Z_CACHE)
  745.         {
  746.             /*
  747.             ** A source filename isn't used in $primary and $cache
  748.             ** directives in a multizone DB file, so fake one to simplify
  749.             ** the getword() stuff below.
  750.             */
  751.             ungetc('!', fp);
  752.         }
  753.     }
  754. #endif /* MULTIZDB */
  755.     zp->z_addrcnt = 0;
  756.     zp->z_type = type;
  757.     zp->z_class = class;
  758.     if (type == Z_CACHE)
  759.     {
  760.         zp->z_origin = "";
  761.     }
  762.     else
  763.     {
  764.         zp->z_origin = savestr(obuf);
  765.     }
  766.     while (getword(buf, sizeof(buf), fp))
  767.     {
  768.         if (
  769. #ifdef STUBS
  770.             (type == Z_SECONDARY  ||  type ==  Z_STUB)
  771. #else
  772.             (type == Z_SECONDARY)
  773. #endif
  774.         && inet_aton(buf, &zp->z_addr[zp->z_addrcnt]))
  775.         {
  776.             dprintf(1, (ddt, ", addr %s", buf));
  777.             if ((int)++zp->z_addrcnt > NSMAX - 1)
  778.             {
  779.                 zp->z_addrcnt = NSMAX - 1;
  780.                 dprintf(1, (ddt, "\nns_defs.h NSMAX reached\n"));
  781.             }
  782.         }
  783.         else
  784.         {
  785.             source = savestr(buf);
  786.             break;
  787.         }
  788.     }
  789.     switch (type)
  790.     {
  791.     case Z_PRIMARY:
  792.     case Z_CACHE:
  793. #ifdef MULTIZDB
  794.         if (!source  &&  !mzfp)
  795. #else
  796.         if (!source)
  797. #endif /* MULTIZDB */
  798.         {
  799.             syslog(LOG_ERR, "%s: line %d: zone %s missing source file\n", bootfile, lineno, obuf);
  800.             endline(fp);
  801.             return;
  802.         }
  803. #ifdef ALLOW_UPDATES
  804.         if (type == Z_PRIMARY  &&  getword(buf, sizeof(buf), fp))
  805.         {
  806.             char *flag, *cp;
  807.             flag = buf;
  808.             while (flag)
  809.             {
  810.                 cp = strchr(flag, ',');
  811.                 if (cp)  *cp++ = 0;
  812.                 if (strcasecmp(flag, "dynamic") == 0)
  813.                 {
  814.                     zp->z_flags |= Z_DYNAMIC;
  815.                 }
  816.                 else if (strcasecmp(flag, "addonly") == 0)
  817.                 {
  818.                     zp->z_flags |= Z_DYNADDONLY;
  819.                 }
  820.                 else
  821.                 {
  822.                     syslog(LOG_ERR, "%s: line %d: bad flag '%s'\n", bootfile, lineno, flag);
  823.                 }
  824.                 flag = cp;
  825.             }
  826.         }
  827. #endif /* ALLOW_UPDATES */
  828.         zp->z_refresh = 0;
  829.         if (type == Z_CACHE  &&  getword(buf, sizeof(buf), fp))
  830.         {
  831. #ifdef notyet
  832.             zp->z_refresh = atoi(buf);
  833.             if (zp->z_refresh <= 0)
  834.             {
  835.                 syslog(LOG_ERR, "%s: line %d: bad refresh time '%s', ignored\n", bootfile, lineno, buf);
  836.                 zp->z_refresh = 0;
  837.             }
  838.             else if (cache_file == 0)
  839.             {
  840.                 cache_file = source;
  841.             }
  842. #else
  843.             syslog(LOG_WARNING, "%s: line %d: cache refresh ignored\n", bootfile, lineno);
  844. #endif /* notyet */
  845.         }
  846.         break;
  847.     case Z_SECONDARY:
  848. #ifdef STUBS
  849.     case Z_STUB:    
  850. #endif        
  851.         if (zp->z_addrcnt <= 0)
  852.         {
  853.             syslog(LOG_ERR, "%s: line %d: zone %s missing host address\n", bootfile, lineno, obuf);
  854.             endline(fp);
  855.             return;
  856.         }
  857.         if (source)
  858.         {
  859.             zp->z_flags &= ~Z_TMP_FILE;
  860.         }
  861.         else
  862.         {
  863.             /*
  864.             ** We will always transfer this zone again after a reload.
  865.             */
  866.             zp->z_flags |= Z_TMP_FILE;
  867.             sprintf(buf, "/%s/NsTmp%d.%d", _PATH_TMPDIR, getpid(), tmpnum++);
  868.             source = savestr(buf);
  869.         }
  870.         break;
  871.     }
  872.     endline(fp);
  873.     dprintf(1, (ddt, ", source = %s\n", source));
  874.  
  875.     /*
  876.     ** Check source file timestamps, etc, to see if reload is necessary.
  877.     ** If we've loaded this file, and the file has not been modified and
  878.     ** contains no $include, then there's no need to reload.  (The
  879.     ** $include check is extraneous for secondary zones but does no
  880.     ** harm.)
  881.     */
  882.     if (!zp->z_source ||
  883.         strcmp(source, zp->z_source) || 
  884.         zp->z_flags & Z_INCLUDE ||
  885.         stat(zp->z_source, &f_time) == -1  ||
  886.         zp->z_ftime != f_time.st_mtime)
  887.     {
  888.         /*
  889.         ** Need reload or something.
  890.         */
  891.         dprintf(1, (ddt, "zone %s backup or source file out of date\n", zp->z_origin[0]?zp->z_origin:"."));
  892.         if (zp->z_source)
  893.         {
  894.             free(zp->z_source);
  895. #ifdef CLEANCACHE
  896.             remove_zone((type == Z_CACHE ? fcachetab : hashtab), zp - zones, 1);
  897. #else
  898.             remove_zone((type == Z_CACHE ? fcachetab : hashtab), zp - zones);
  899. #endif /* CLEANCACHE */
  900.             zp->z_flags &= ~Z_AUTH;
  901.         }
  902.         switch (type)
  903.         {
  904.         case Z_PRIMARY:
  905.             zp->z_source = source;
  906. #ifdef MULTIZDB
  907.             if (db_load(zp->z_source, zp->z_origin, zp, 0, mzfp) == 0)
  908. #else
  909.             if (db_load(zp->z_source, zp->z_origin, zp, 0) == 0)
  910. #endif
  911.             {
  912.                 zp->z_flags |= Z_AUTH;
  913.             }
  914. #ifdef ALLOW_UPDATES
  915.             /*
  916.              ** Guarantee calls to ns_maint()
  917.              */
  918.             zp->z_refresh = maint_interval;
  919. #else 
  920.             zp->z_refresh = 0;  /* no maintenance needed */
  921.             zp->z_time = 0;
  922. #endif /* ALLOW_UPDATES */
  923.             break;
  924.         case Z_CACHE:
  925.             zp->z_source = source;
  926. #ifdef MULTIZDB
  927.             (void)db_load(zp->z_source, zp->z_origin, zp, 0, mzfp);
  928. #else
  929.             (void)db_load(zp->z_source, zp->z_origin, zp, 0);
  930. #endif
  931.             break;
  932.         case Z_SECONDARY:
  933.         case Z_STUB:
  934.             zp->z_source = 0;
  935.             zp->z_flags &= ~Z_AUTH;
  936.             zp->z_serial = 0;
  937.             break;
  938.         }
  939.     }
  940.     else
  941.     {
  942.         if (cache_file != source) free(source);
  943.         dprintf(1, (ddt, "zone %s is up to date\n", zp->z_origin[0]?zp->z_origin:"."));
  944.     }
  945.     zone_reload_bookkeeping(zp, source, mzfp);
  946.     return;
  947. }
  948.