home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / named / ns_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-24  |  17.4 KB  |  704 lines

  1. /*-
  2.  * Copyright (c) 1986, 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)ns_init.c    4.38 (Berkeley) 3/21/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/socket.h>
  40. #include <sys/time.h>
  41. #include <sys/stat.h>
  42. #include <netinet/in.h>
  43. #include <arpa/nameser.h>
  44. #include <syslog.h>
  45. #include <signal.h>
  46. #include <resolv.h>
  47. #include <stdio.h>
  48. #include <errno.h>
  49. #include <ctype.h>
  50. #include <string.h>
  51. #undef nsaddr
  52. #include "pathnames.h"
  53. #include "ns.h"
  54. #include "db.h"
  55.  
  56. struct    zoneinfo *zones;        /* zone information */
  57. int    nzones;                /* number of zones in use */
  58. int    forward_only = 0;        /* run only as a slave */
  59. char    *cache_file;
  60. char    *localdomain;            /* "default" for non-dotted names */
  61. int    maint_interval = 15*60;        /* minimum ns_maint() interval */
  62.  
  63. extern    int lineno;
  64.  
  65.  
  66. /*
  67.  * Read boot file for configuration info.
  68.  */
  69.  
  70. ns_init(bootfile)
  71.     char *bootfile;
  72. {
  73.     register struct zoneinfo *zp;
  74.     struct zoneinfo *find_zone();
  75.     char buf[BUFSIZ], obuf[BUFSIZ], *source;
  76.     extern char *calloc();
  77.     FILE *fp;
  78.     int type;
  79.     extern int needmaint;
  80.     struct stat f_time;
  81.     static int loads = 0;            /* number of times loaded */
  82.     static int tmpnum = 0;        /* unique number for tmp zone files */
  83. #ifdef ALLOW_UPDATES
  84.     char *cp, *flag;
  85. #endif
  86.  
  87. #ifdef DEBUG
  88.     if (debug)
  89.         fprintf(ddt,"\nns_init(%s)\n", bootfile);
  90. #endif
  91.     gettime(&tt);
  92.  
  93.     if ((fp = fopen(bootfile, "r")) == NULL) {
  94.         syslog(LOG_ERR, "%s: %m", bootfile);
  95.         exit(1);
  96.     }
  97.     lineno = 0;
  98.         if (loads == 0) {
  99.         if ((zones =
  100.             (struct zoneinfo *)calloc(64, sizeof(struct zoneinfo)))
  101.                         == NULL) {
  102.             syslog(LOG_ERR,
  103.             "Not enough memory to allocate initial zones array");
  104.             exit(1);
  105.         }
  106.         nzones = 1;        /* zone zero is cache data */
  107.         /* allocate cache hash table, formerly the root hash table. */
  108.         hashtab = savehash((struct hashbuf *)NULL);
  109.  
  110.         /* allocate root-hints/file-cache hash table */
  111.         fcachetab = savehash((struct hashbuf *)NULL);
  112.         /* init zone data */
  113.         zones[0].z_type = Z_CACHE;
  114.         } else {
  115.         /* Mark previous zones as not yet found in boot file. */
  116.         for (zp = &zones[1]; zp < &zones[nzones]; zp++)
  117.             zp->z_state &= ~Z_FOUND;
  118.         if (localdomain)
  119.             free(localdomain);
  120.         localdomain = NULL;
  121.         free_forwarders();
  122.         forward_only = 0;
  123.     }
  124.  
  125. #ifdef DEBUG
  126.         if (debug >= 3) {
  127.             fprintf(ddt,"\n content of zones before loading \n");
  128.             content_zone(nzones - 1);
  129.         }
  130. #endif
  131.     while (!feof(fp) && !ferror(fp)) {
  132.         if (!getword(buf, sizeof(buf), fp))
  133.             continue;
  134.         /* read named.boot keyword and process args */
  135.         if (strcasecmp(buf, "directory") == 0) {
  136.             (void) getword(buf, sizeof(buf), fp);
  137.             if (chdir(buf) < 0) {
  138.                 syslog(LOG_CRIT, "directory %s: %m\n",
  139.                     buf);
  140.                 exit(1);
  141.             }
  142.             continue;
  143.         } else if (strcasecmp(buf, "sortlist") == 0) {
  144.             get_sort_list(fp);
  145.             continue;
  146.         } else if (strcasecmp(buf, "forwarders") == 0) {
  147.             get_forwarders(fp);
  148.             continue;
  149.         } else if (strcasecmp(buf, "slave") == 0) {
  150.             forward_only++;
  151.             endline(fp);
  152.             continue;
  153.         } else if (strcasecmp(buf, "domain") == 0) {
  154.             if (getword(buf, sizeof(buf), fp))
  155.                 localdomain = savestr(buf);
  156.             endline(fp);
  157.             continue;
  158.         } else if (strcasecmp(buf, "cache") == 0)
  159.             type = Z_CACHE;
  160.         else if (strcasecmp(buf, "primary") == 0)
  161.             type = Z_PRIMARY;
  162.         else if (strcasecmp(buf, "secondary") == 0)
  163.             type = Z_SECONDARY;
  164.         else {
  165.             syslog(LOG_ERR, "%s: line %d: unknown field '%s'\n",
  166.                 bootfile, lineno, buf);
  167.             endline(fp);
  168.             continue;
  169.         }
  170.  
  171.         /*
  172.          * read zone origin
  173.          */
  174.         if (!getword(obuf, sizeof(obuf), fp)) {
  175.             syslog(LOG_ERR, "%s: line %d: missing origin\n",
  176.                 bootfile, lineno);
  177.             continue;
  178.         }
  179. #ifdef DEBUG
  180.         if (debug)
  181.             fprintf(ddt, "zone origin %s", obuf);
  182. #endif
  183.         if (obuf[0] == '.' && obuf[1] == '\0')
  184.             obuf[0] = '\0';
  185.         /*
  186.          * read source file or host address
  187.          */
  188.         if (!getword(buf, sizeof(buf), fp)) {
  189.             syslog(LOG_ERR,
  190.                 "%s: line %d: missing source or addr\n",
  191.                 bootfile, lineno);
  192.             continue;
  193.         }
  194.  
  195.         /* check for previous instance of this zone (reload) */
  196.         if ((zp = find_zone(obuf, type)) == 0) {
  197.             if (type == Z_CACHE) {
  198.                 zp = &zones[0];
  199.                 zp->z_origin = "";
  200.                 goto gotzone;
  201.             }
  202.             for (zp = &zones[1]; zp < &zones[nzones]; zp++)
  203.                 if (zp->z_type == 0)
  204.                     goto gotzone;
  205.             /*
  206.              * this code assume that nzones never decreases
  207.              */
  208.             if (nzones % 64  == 0) {
  209. #ifdef DEBUG
  210.                 if (debug > 1)
  211.                 fprintf(ddt, "Reallocating zones structure\n");
  212. #endif DEBUG
  213.                 /*
  214.                  * Realloc() not used since it might damage zones
  215.                  * if an error occurs
  216.                  */
  217.                 if ((zp = (struct zoneinfo *)
  218.                 malloc((64 + nzones) * sizeof(struct zoneinfo)))
  219.                         == NULL) {
  220.                     syslog(LOG_ERR, "no memory for more zones");
  221. #ifdef DEBUG
  222.                     if (debug)
  223.                     fprintf(ddt,
  224.                         "Out of memory for new zones\n");
  225. #endif DEBUG
  226.                     endline(fp);
  227.                     continue;
  228.                 }
  229.                 bcopy((char *)zones, (char *)zp,
  230.                         nzones * sizeof(struct zoneinfo));
  231.                 bzero((char *)&zp[nzones],
  232.                         64 * sizeof(struct zoneinfo));
  233.                 free(zones);
  234.                 zones = zp;
  235.             }
  236.             zp = &zones[nzones++];
  237.     gotzone:
  238.             zp->z_origin = savestr(obuf);
  239.             zp->z_type = type;
  240.         }
  241.         zp->z_addrcnt = 0;
  242.  
  243.         switch (type) {
  244.         case Z_CACHE:
  245.             source = savestr(buf);
  246. #ifdef DEBUG
  247.             if (debug)
  248.                 fprintf(ddt,", source = %s\n", source);
  249. #endif
  250.             zp->z_refresh = 0;    /* by default, no dumping */
  251.             if (getword(buf, sizeof(buf), fp)) {
  252. #ifdef notyet
  253.                 zp->z_refresh = atoi(buf);
  254.                 if (zp->z_refresh <= 0) {
  255.                     syslog(LOG_ERR,
  256.                 "%s: line %d: bad refresh time '%s', ignored\n",
  257.                         bootfile, lineno, buf);
  258.                     zp->z_refresh = 0;
  259.                 } else if (cache_file == NULL)
  260.                     cache_file = source;
  261. #else
  262.                 syslog(LOG_WARNING,
  263.                 "%s: line %d: cache refresh ignored\n",
  264.                     bootfile, lineno);
  265. #endif
  266.                 endline(fp);
  267.             }
  268.             /*
  269.              * If we've loaded this file, and the file has
  270.              * not been modified and contains no $include,
  271.              * then there's no need to reload.
  272.              */
  273.             if (zp->z_source && strcmp(source, zp->z_source) == 0 &&
  274.                 (zp->z_state & Z_INCLUDE) == 0 && 
  275.                 stat(zp->z_source, &f_time) == 0 &&
  276.                 zp->z_ftime == f_time.st_mtime) {
  277. #ifdef DEBUG
  278.                 if (debug)
  279.                     fprintf(ddt, "cache is up to date\n");
  280. #endif
  281.                 break; /* zone is already up to date */
  282.             }
  283.  
  284.             /* file has changed, or hasn't been loaded yet */
  285.             if (zp->z_source) {
  286.                 free(zp->z_source);
  287.                 remove_zone(fcachetab, 0);
  288.             }
  289.             zp->z_source = source;
  290. #ifdef DEBUG
  291.             if (debug)
  292.                 fprintf(ddt, "reloading zone\n");
  293. #endif
  294.             (void) db_load(zp->z_source, zp->z_origin, zp, 0);
  295.             break;
  296.  
  297.         case Z_PRIMARY:
  298.             source = savestr(buf);
  299. #ifdef ALLOW_UPDATES
  300.             if (getword(buf, sizeof(buf), fp)) {
  301.                 endline(fp);
  302.                 flag = buf;
  303.                 while (flag) {
  304.                     cp = index(flag, ',');
  305.                     if (cp)
  306.                     *cp++ = 0;
  307.                     if (strcasecmp(flag, "dynamic") == 0)
  308.                     zp->z_state |= Z_DYNAMIC;
  309.                     else if (strcasecmp(flag, "addonly") == 0)
  310.                     zp->z_state |= Z_DYNADDONLY;
  311.                     else {
  312.                     syslog(LOG_ERR,
  313.                            "%s: line %d: bad flag '%s'\n",
  314.                            bootfile, lineno, flag);
  315.                     }
  316.                     flag = cp;
  317.                 }
  318.             }
  319. #else ALLOW_UPDATES
  320.                     endline(fp);
  321. #endif
  322.  
  323. #ifdef DEBUG
  324.             if (debug)
  325.                 fprintf(ddt,", source = %s\n", source);
  326. #endif
  327.             /*
  328.              * If we've loaded this file, and the file has
  329.              * not been modified and contains no $include,
  330.              * then there's no need to reload.
  331.              */
  332.             if (zp->z_source && strcmp(source, zp->z_source) == 0 &&
  333.                 (zp->z_state & Z_INCLUDE) == 0 && 
  334.                 stat(zp->z_source, &f_time) == 0 &&
  335.                 zp->z_ftime == f_time.st_mtime) {
  336. #ifdef DEBUG
  337.                 if (debug)
  338.                     fprintf(ddt, "zone is up to date\n");
  339. #endif
  340.                 break; /* zone is already up to date */
  341.             }
  342.             if (zp->z_source) {
  343.                 free(zp->z_source);
  344.                 remove_zone(hashtab, zp - zones);
  345.             }
  346.                         zp->z_source = source;
  347.                         zp->z_auth = 0;
  348. #ifdef DEBUG
  349.             if (debug)
  350.                 fprintf(ddt, "reloading zone\n");
  351. #endif
  352.             if (db_load(zp->z_source, zp->z_origin, zp, 0) == 0)
  353.                 zp->z_auth = 1;
  354. #ifdef ALLOW_UPDATES
  355.             /* Guarantee calls to ns_maint() */
  356.             zp->z_refresh = maint_interval;
  357. #else ALLOW_UPDATES
  358.             zp->z_refresh = 0;    /* no maintenance needed */
  359.             zp->z_time = 0;
  360. #endif ALLOW_UPDATES
  361.             break;
  362.  
  363.         case Z_SECONDARY:
  364.             source = 0;
  365. #ifdef DEBUG
  366.             if (debug)
  367.                 fprintf(ddt,"\n\taddrs: ");
  368. #endif
  369.             do {
  370.                 zp->z_addr[zp->z_addrcnt].s_addr =
  371.                     inet_addr(buf);
  372.                 if (zp->z_addr[zp->z_addrcnt].s_addr ==
  373.                         (u_long)-1) {
  374.                     source = savestr(buf);
  375.                                     endline(fp);
  376.                     break;
  377.                 }
  378. #ifdef DEBUG
  379.                 if (debug)
  380.                     fprintf(ddt,"%s, ",buf);
  381. #endif
  382.                 if (++zp->z_addrcnt > NSMAX - 1) {
  383.                     zp->z_addrcnt = NSMAX - 1;
  384. #ifdef DEBUG
  385.                     if (debug)
  386.                         fprintf(ddt,
  387.                         "\nns.h NSMAX reached\n");
  388. #endif
  389.                 }
  390.             } while (getword(buf, sizeof(buf), fp));
  391. #ifdef DEBUG
  392.             if (debug)
  393.                 fprintf(ddt,"addrcnt = %d\n", zp->z_addrcnt);
  394. #endif
  395.             if (source == 0) {
  396.                 /*
  397.                  * We will always transfer this zone again
  398.                  * after a reload.
  399.                  */
  400.                 sprintf(buf, "/%s/NsTmp%d", _PATH_TMPDIR,
  401.                         tmpnum++);
  402.                 source = savestr(buf);
  403.                 zp->z_state |= Z_TMP_FILE;
  404.             } else
  405.                 zp->z_state &= ~Z_TMP_FILE;
  406.             /*
  407.              * If we had a backup file name, and it was changed,
  408.              * free old zone and start over.  If we don't have
  409.              * current zone contents, try again now in case
  410.              * we have a new server on the list.
  411.              */
  412.             if (zp->z_source && strcmp(source, zp->z_source)) {
  413. #ifdef DEBUG
  414.                 if (debug)
  415.                     fprintf(ddt,"backup file changed\n");
  416. #endif
  417.                 free(zp->z_source);
  418.                 zp->z_source = 0;
  419.                 zp->z_auth = 0;
  420.                 zp->z_serial = 0;    /* force xfer */
  421.                             remove_zone(hashtab, zp - zones);
  422.             }
  423.             if (zp->z_source)
  424.                 free(source);
  425.             else
  426.                 zp->z_source = source;
  427.             if (zp->z_auth == 0)
  428.                 zoneinit(zp);
  429.             break;
  430.  
  431.         }
  432.                 zp->z_state |= Z_FOUND;
  433. #ifdef DEBUG
  434.         if (debug)
  435.             fprintf(ddt,"zone[%d] type %d: '%s'",
  436.                     zp-zones, type,
  437.                 *(zp->z_origin) == '\0' ? "." : zp->z_origin);
  438. #endif
  439.         if (zp->z_refresh && zp->z_time == 0)
  440.             zp->z_time = zp->z_refresh + tt.tv_sec;
  441.         if (zp->z_time <= tt.tv_sec)
  442.             needmaint = 1;
  443. #ifdef DEBUG
  444.         if (debug)
  445.             fprintf(ddt, " z_time %d, z_refresh %d\n",
  446.                 zp->z_time, zp->z_refresh);
  447. #endif
  448.     }
  449.     (void) fclose(fp);
  450.         /* erase all old zones that were not found */
  451.         for (zp = &zones[1]; zp < &zones[nzones]; zp++)
  452.             if (zp->z_type && (zp->z_state & Z_FOUND) == 0) {
  453.         remove_zone(hashtab, zp - zones);
  454.         bzero((char *) zp, sizeof(*zp));
  455. #ifdef DEBUG
  456.         if(debug >=2)
  457.             fprintf(ddt,"\n zone no %d was removed \n", zp - zones);
  458. #endif
  459.         }
  460. #ifdef DEBUG
  461.         if(debug >= 2) {
  462.             fprintf(ddt,"\n content of zones after loading \n");
  463.             content_zone(nzones-1);
  464.         }
  465. #endif
  466.  
  467.     /*
  468.      * Schedule calls to ns_maint().
  469.      */
  470.     if (needmaint == 0)
  471.         sched_maint();
  472. #ifdef DEBUG
  473.     if (debug)
  474.         fprintf(ddt,"exit ns_init()%s\n", needmaint ?
  475.             ", need maintenance immediately" : "");
  476. #endif
  477.     loads++;
  478. }
  479.  
  480. zoneinit(zp)
  481.     register struct zoneinfo *zp;
  482. {
  483.     extern int needmaint;
  484.     struct stat sb;
  485.  
  486.     /*
  487.      * Try to load zone from backup file,
  488.      * if one was specified and it exists.
  489.      * If not, or if the data are out of date,
  490.      * we will refresh the zone from a primary
  491.      * immediately.
  492.      */
  493.     if (zp->z_source == NULL)
  494.         return;
  495.     if (stat(zp->z_source, &sb) == -1 ||
  496.         db_load(zp->z_source, zp->z_origin, zp, 0) != 0) {
  497.         /*
  498.          * Set zone to be refreshed immediately.
  499.          */
  500.         zp->z_refresh = INIT_REFRESH;
  501.         zp->z_retry = INIT_REFRESH;
  502.         zp->z_time = tt.tv_sec;
  503.         needmaint = 1;
  504.     } else
  505.         zp->z_auth = 1;
  506. }
  507.  
  508. #ifdef ALLOW_UPDATES
  509. /*
  510.  * Look for the authoritative zone with the longest matching RHS of dname
  511.  * and return its zone # or zero if not found.
  512.  */
  513. findzone(dname, class)
  514.     char *dname;
  515.     int class;
  516. {
  517.     char *dZoneName, *zoneName, *index();
  518.     int dZoneNameLen, zoneNameLen;
  519.     int maxMatchLen = 0;
  520.     int maxMatchZoneNum = 0;
  521.     int zoneNum;
  522.  
  523. #ifdef DEBUG
  524.     if (debug >= 4)
  525.         fprintf(ddt, "findzone(dname=%s, class=%d)\n", dname, class);
  526.     if (debug >= 5) {
  527.         fprintf(ddt, "zone dump:\n");
  528.         for (zoneNum = 1; zoneNum < nzones; zoneNum++)
  529.             printzoneinfo(zoneNum);
  530.     }
  531. #endif DEBUG
  532.  
  533.     dZoneName = index(dname, '.');
  534.     if (dZoneName == NULL)
  535.         dZoneName = "";    /* root */
  536.     else
  537.         dZoneName++;    /* There is a '.' in dname, so use remainder of
  538.                    string as the zone name */
  539.     dZoneNameLen = strlen(dZoneName);
  540.     for (zoneNum = 1; zoneNum < nzones; zoneNum++) {
  541.         zoneName = (zones[zoneNum]).z_origin;
  542.         zoneNameLen = strlen(zoneName);
  543.         /* The zone name may or may not end with a '.' */
  544.         if (zoneName[zoneNameLen - 1] == '.')
  545.             zoneNameLen--;
  546.         if (dZoneNameLen != zoneNameLen)
  547.             continue;
  548. #ifdef DEBUG
  549.         if (debug >= 5)
  550.             fprintf(ddt, "about to strncasecmp('%s', '%s', %d)\n",
  551.                     dZoneName, zoneName, dZoneNameLen);
  552. #endif
  553.         if (strncasecmp(dZoneName, zoneName, dZoneNameLen) == 0) {
  554. #ifdef DEBUG
  555.             if (debug >= 5)
  556.                 fprintf(ddt, "match\n");
  557. #endif
  558.             /*
  559.              * See if this is as long a match as any so far.
  560.              * Check if "<=" instead of just "<" so that if
  561.              * root domain (whose name length is 0) matches,
  562.              * we use it's zone number instead of just 0
  563.              */
  564.             if (maxMatchLen <= zoneNameLen) {
  565.                 maxMatchZoneNum = zoneNum;
  566.                 maxMatchLen = zoneNameLen;
  567.             }
  568.         }
  569. #ifdef DEBUG
  570.         else
  571.             if (debug >= 5)
  572.                 fprintf(ddt, "no match\n");
  573. #endif
  574.     }
  575. #ifdef DEBUG
  576.     if (debug >= 4)
  577.         fprintf(ddt, "findzone: returning %d\n", maxMatchZoneNum);
  578. #endif DEBUG
  579.     return (maxMatchZoneNum);
  580. }
  581. #endif ALLOW_UPDATES
  582.  
  583. soa_zinfo(zp, cp, eom)
  584.     register struct zoneinfo *zp;
  585.     register u_char *cp;
  586.     u_char *eom;
  587. {
  588.     cp += 3 * sizeof(u_short);
  589.     cp += sizeof(u_long);
  590.     cp += dn_skipname(cp, eom);
  591.     cp += dn_skipname(cp, eom);
  592.     GETLONG(zp->z_serial, cp);
  593.     GETLONG(zp->z_refresh, cp);
  594.     gettime(&tt);
  595.     zp->z_time = tt.tv_sec + zp->z_refresh;
  596.     GETLONG(zp->z_retry, cp);
  597.     GETLONG(zp->z_expire, cp);
  598.     GETLONG(zp->z_minimum, cp);
  599. }
  600.  
  601. get_forwarders(fp)
  602.     FILE *fp;
  603. {
  604.     char buf[BUFSIZ];
  605.     register struct fwdinfo *fip = NULL, *ftp = NULL;
  606.     extern struct sockaddr_in nsaddr;
  607.     extern struct fwdinfo *fwdtab;
  608.  
  609. #ifdef DEBUG
  610.     if (debug)
  611.         fprintf(ddt,"forwarders ");
  612. #endif
  613.  
  614.     /* on mulitple forwarder lines, move to end of the list */
  615.     if (fwdtab != NULL)
  616.         for (fip = fwdtab; fip->next != NULL; fip = fip->next)
  617.             ;
  618.  
  619.     while (getword(buf, sizeof(buf), fp)) {
  620.         if (strlen(buf) == 0)
  621.             break;
  622. #ifdef DEBUG
  623.         if (debug)
  624.             fprintf(ddt," %s",buf);
  625. #endif
  626.         if (ftp == NULL)
  627.             ftp = (struct fwdinfo *)malloc(sizeof(struct fwdinfo));
  628.         if (isdigit(buf[0]) &&
  629.             (ftp->fwdaddr.sin_addr.s_addr = inet_addr(buf)) !=
  630.             (u_long)-1) {
  631.             ftp->fwdaddr.sin_port = nsaddr.sin_port;
  632.             ftp->fwdaddr.sin_family = AF_INET;
  633.         } else {
  634.             syslog(LOG_ERR, "'%s' (ignored, NOT dotted quad)", buf);
  635. #ifdef DEBUG
  636.             if (debug)
  637.                 fprintf(ddt," (ignored, NOT dotted quad)");
  638. #endif
  639.             continue;    
  640.         }
  641.         ftp->next = NULL;
  642.         if (fwdtab == NULL)
  643.             fwdtab = ftp;    /* First time only */
  644.         else
  645.             fip->next = ftp;
  646.         fip = ftp;
  647.         ftp = NULL;
  648.     }
  649.     if (ftp)
  650.         free((char *)ftp);
  651.     
  652. #ifdef DEBUG
  653.     if (debug) 
  654.         fprintf(ddt,"\n");
  655.     if (debug > 2)
  656.         for (ftp = fwdtab; ftp != NULL; ftp = ftp->next)
  657.             fprintf(ddt,"ftp x%x %s next x%x\n", ftp,
  658.                 inet_ntoa(ftp->fwdaddr.sin_addr), ftp->next);
  659. #endif
  660. }
  661.  
  662. free_forwarders()
  663. {
  664.     extern struct fwdinfo *fwdtab;
  665.     register struct fwdinfo *ftp, *fnext;
  666.  
  667.     for (ftp = fwdtab; ftp != NULL; ftp = fnext) {
  668.         fnext = ftp->next;
  669.         free((char *)ftp);
  670.     }
  671.     fwdtab = NULL;
  672. }
  673.  
  674. struct zoneinfo *
  675. find_zone(name, type) 
  676.     char *name;
  677.     int type;
  678. {
  679.     register struct zoneinfo *zp;
  680.  
  681.         for (zp = &zones[1]; zp < &zones[nzones]; zp++)
  682.         if (zp->z_type == type && strcasecmp(name, zp->z_origin) == 0) {
  683. #ifdef DEBUG
  684.             if (debug > 1)
  685.                 fprintf(ddt, ", old zone (%d)", zp - zones);
  686. #endif
  687.             return (zp);
  688.         }
  689. #ifdef DEBUG
  690.     if(debug > 1)
  691.         fprintf(ddt, ", new zone");
  692. #endif
  693.     return ((struct zoneinfo *)NULL);
  694. }
  695.  
  696. /* prints out the content of zones */
  697. content_zone(end) 
  698.     int  end;
  699. {
  700.     int i;
  701.     for (i = 1; i <= end; i++)
  702.         printzoneinfo(i);
  703. }
  704.