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