1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that this notice is preserved and that due credit is given
   7:  * to the University of California at Berkeley. The name of the University
   8:  * may not be used to endorse or promote products derived from this
   9:  * software without specific prior written permission. This software
  10:  * is provided ``as is'' without express or implied warranty.
  11:  */
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)ns_maint.c	4.23 (Berkeley) 2/28/88";
  15: #endif /* not lint */
  16: 
  17: #include <sys/param.h>
  18: #include <sys/socket.h>
  19: #include <sys/time.h>
  20: #if defined(SYSV)
  21: #include <unistd.h>
  22: #endif SYSV
  23: #include <netinet/in.h>
  24: #include <stdio.h>
  25: #include <syslog.h>
  26: #include <signal.h>
  27: #include <errno.h>
  28: #include <arpa/nameser.h>
  29: #include "ns.h"
  30: #include "db.h"
  31: 
  32: extern int errno;
  33: extern u_long maint_interval;
  34: 
  35: 
  36: /*
  37:  * Invoked at regular intervals by signal interrupt; refresh all secondary
  38:  * zones from primary name server and remove old cache entries.  Also,
  39:  * ifdef'd ALLOW_UPDATES, dump database if it has changed since last
  40:  * dump/bootup.
  41:  */
  42: ns_maint()
  43: {
  44:     register struct zoneinfo *zp;
  45:     struct itimerval ival;
  46:     time_t next_refresh = 0;
  47:     int zonenum;
  48: 
  49: #ifdef DEBUG
  50:     if (debug)
  51:         fprintf(ddt,"ns_maint()\n");
  52: #endif
  53: 
  54:     for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) {
  55:         switch(zp->z_type) {
  56: #ifdef ALLOW_UPDATES
  57:         case Z_PRIMARY:
  58: #endif ALLOW_UPDATES
  59:         case Z_SECONDARY:
  60:         case Z_CACHE:
  61:             break;
  62: 
  63:         default:
  64:             continue;
  65:         }
  66:         gettime(&tt);
  67: #ifdef DEBUG
  68:         if (debug >= 2)
  69:             printzoneinfo(zonenum);
  70: #endif
  71:         if (tt.tv_sec >= zp->z_time && zp->z_refresh > 0) {
  72:             if (zp->z_type == Z_CACHE)
  73:                 doachkpt();
  74:             if (zp->z_type == Z_SECONDARY)
  75:                 zoneref(zp);
  76: #ifdef ALLOW_UPDATES
  77:             /*
  78: 			 * Checkpoint the zone if it has changed
  79: 			 * since we last checkpointed
  80: 			 */
  81:             if (zp->z_type == Z_PRIMARY && zp->hasChanged)
  82:                 zonedump(zp);
  83: #endif ALLOW_UPDATES
  84:             zp->z_time = tt.tv_sec + zp->z_refresh;
  85:         }
  86: 
  87:         /*
  88: 		 * Find when the next refresh needs to be and set
  89: 		 * interrupt time accordingly.
  90: 		 */
  91:         if (next_refresh == 0 ||
  92:             (zp->z_time != 0 && next_refresh > zp->z_time))
  93:             next_refresh = zp->z_time;
  94:     }
  95: 
  96:         /*
  97: 	 *  Schedule the next call to this function.
  98: 	 *  Don't visit any sooner than maint_interval.
  99: 	 */
 100:     bzero((char *)&ival, sizeof (ival));
 101:     ival.it_value.tv_sec = next_refresh - tt.tv_sec;
 102:     if (ival.it_value.tv_sec < maint_interval)
 103:         ival.it_value.tv_sec = maint_interval;
 104:     (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
 105: #ifdef DEBUG
 106:     if (debug)
 107:         fprintf(ddt,"exit ns_maint() Next interrupt in %ld sec\n",
 108:             ival.it_value.tv_sec);
 109: #endif
 110: }
 111: 
 112: zoneref(zp)
 113:     struct zoneinfo *zp;
 114: {
 115:     HEADER *hp;
 116:     u_short len;
 117:     u_long serial;
 118:     int s, n, l, tries;
 119:     int cnt, soacnt, error = 0;
 120:     int zone = zp - zones;
 121:     u_char *cp, *nmp, *eom;
 122:     u_char *tmp;
 123:     u_char buf[PACKETSZ];
 124:     char name[MAXDNAME], name2[MAXDNAME];
 125:     struct sockaddr_in sin;
 126:     struct zoneinfo zp_start, zp_finish;
 127:     struct itimerval ival;
 128:     struct itimerval zeroival;
 129:     extern struct sockaddr_in nsaddr;
 130:     extern int errno;
 131:     extern int read_interrupted;
 132:     extern int read_alarm();
 133:     struct sigvec sv, osv;
 134: 
 135: #ifdef DEBUG
 136:     if (debug)
 137:         fprintf(ddt,"zoneref() %s\n", zp->z_origin);
 138: #endif
 139:     bzero((char *)&zeroival, sizeof(zeroival));
 140:     ival = zeroival;
 141:     ival.it_value.tv_sec = 30;
 142:     sv.sv_handler = read_alarm;
 143:     sv.sv_onstack = 0;
 144:     sv.sv_mask = ~0;
 145:     (void) sigvec(SIGALRM, &sv, &osv);
 146: 
 147:     for( cnt = 0; cnt < zp->z_addrcnt; cnt++) {
 148:         error = 0;
 149:         bzero((char *)&sin, sizeof(sin));
 150:         sin.sin_family = AF_INET;
 151:         sin.sin_port = nsaddr.sin_port;
 152:         sin.sin_addr = zp->z_addr[cnt];
 153:         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 154:             syslog(LOG_ERR, "zoneref: socket: %m");
 155:             error++;
 156:             break;
 157:         }
 158: #ifdef DEBUG
 159:         if (debug >= 2) {
 160:             fprintf(ddt,"connecting to server #%d %s, %d\n",
 161:                cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
 162:         }
 163: #endif
 164:         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
 165:             (void) close(s);
 166:             error++;
 167: #ifdef DEBUG
 168:             if (debug >= 2)
 169:                 fprintf(ddt,"connect failed, errno %d\n", errno);
 170: #endif
 171:             continue;
 172:         }
 173:         if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
 174:             T_SOA, (char *)NULL, 0, NULL, buf, sizeof(buf))) < 0) {
 175:                 syslog(LOG_ERR, "zoneref: res_mkquery failed");
 176:             (void) close(s);
 177:             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
 178:                 return;
 179:         }
 180:         /*
 181: 	 	 * Send length & message for zone transfer
 182: 	 	 */
 183:         if (writemsg(s, buf, n) < 0) {
 184:             (void) close(s);
 185:             error++;
 186: #ifdef DEBUG
 187:             if (debug >= 2)
 188:                 fprintf(ddt,"writemsg failed\n");
 189: #endif
 190:             continue;
 191:         }
 192:         /*
 193: 		 * Get out your butterfly net and catch the SOA
 194: 		 */
 195:         cp = buf;
 196:         l = sizeof(u_short);
 197:         read_interrupted = 0;
 198:         while (l > 0) {
 199:             (void) setitimer(ITIMER_REAL, &ival,
 200:                 (struct itimerval *)NULL);
 201:             if ((n = recv(s, cp, l, 0)) > 0) {
 202:                 cp += n;
 203:                 l -= n;
 204:             } else {
 205:                 if (errno == EINTR && !read_interrupted)
 206:                     continue;
 207:                 error++;
 208:                 break;
 209:             }
 210:         }
 211:         (void) setitimer(ITIMER_REAL, &zeroival,
 212:             (struct itimerval *)NULL);
 213:         if (error) {
 214:             (void) close(s);
 215:             continue;
 216:         }
 217:         if ((len = htons(*(u_short *)buf)) == 0) {
 218:             (void) close(s);
 219:             if (zp->z_sysloged == 0)
 220:                 syslog(LOG_ERR,
 221:                 "no SOA from server %s, zone %s (len 0)\n",
 222:                 inet_ntoa(sin.sin_addr), zp->z_origin);
 223:             continue;
 224:         }
 225:         l = len;
 226:         cp = buf;
 227:         while (l > 0) {
 228:             (void) setitimer(ITIMER_REAL, &ival,
 229:                 (struct itimerval *)NULL);
 230:             if ((n = recv(s, cp, l, 0)) > 0) {
 231:                 cp += n;
 232:                 l -= n;
 233:             } else {
 234:                 if (errno == EINTR && !read_interrupted)
 235:                     continue;
 236:                 error++;
 237:                 break;
 238:             }
 239:         }
 240:         (void) setitimer(ITIMER_REAL, &zeroival,
 241:             (struct itimerval *)NULL);
 242:         if (error) {
 243:             (void) close(s);
 244:             continue;
 245:         }
 246: #ifdef DEBUG
 247:         if (debug >= 3) {
 248:             fprintf(ddt,"len = %d\n", len);
 249:             fp_query(buf, ddt);
 250:         }
 251: #endif DEBUG
 252:         zp_start = *zp;
 253:         tmp = buf + sizeof(HEADER);
 254:         eom = buf + len;
 255:         /* NEED TO CHECK MESSAGE LENGTH, ANCOUNT, AA */
 256:         tmp += dn_skipname(tmp, eom) + QFIXEDSZ;
 257:         tmp += dn_skipname(tmp, eom);
 258:         soa_zinfo(&zp_start, tmp, eom);
 259:         if (zp->z_serial >= zp_start.z_serial && zp->z_auth)  {
 260: #ifdef DEBUG
 261:             if (debug)
 262:                 fprintf(ddt,"zoneref: up to date (%ld >= %ld)\n",
 263:                     zp->z_serial, zp_start.z_serial);
 264: #endif DEBUG
 265:             zp->z_lastupdate = tt.tv_sec;
 266:             zp->z_refresh = zp_start.z_refresh;
 267:             (void) close(s);
 268:             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
 269:             if (zp->z_source) {
 270: #if defined(SYSV)
 271:                 struct utimbuf t;
 272: 
 273:                 t.actime = t.modtime = tt.tv_sec;
 274:                 (void) utime(zp->z_source, &t);
 275: #else
 276:                 struct timeval t[2];
 277: 
 278:                 t[0] = tt;
 279:                 t[1] = tt;
 280:                 (void) utimes(zp->z_source, t);
 281: #endif /* SYSV */
 282:             }
 283:             return;
 284:         }
 285: #ifdef DEBUG
 286:         if (debug)
 287:             fprintf(ddt,"zoneref: need xfer (%ld < %ld)\n",
 288:                 zp->z_serial, zp_start.z_serial);
 289: #endif DEBUG
 290:         hp = (HEADER *) buf;
 291:         soacnt = 0;
 292:         /* mark all existing RR's for zone as "old" */
 293:         mark_zone (hashtab, zone, 1);
 294:         for (tries = 0; ; tries++) {
 295:             if (soacnt == 0) {
 296:                 /* delete unmarked (new) RR's for zone */
 297:                 if (tries)
 298:                     clean_zone (hashtab, zone, 0);
 299:                 if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
 300:                   T_AXFR, (char *)NULL, 0, NULL,
 301:                   buf, sizeof(buf))) < 0) {
 302:                 syslog(LOG_ERR, "zoneref: res_mkquery failed");
 303:                 (void) close(s);
 304:                 (void) sigvec(SIGALRM, &osv,
 305:                     (struct sigvec *)0);
 306:                 return;
 307:                 }
 308:                 /*
 309: 	 	 	     * Send length & message for zone transfer
 310: 	 	 	     */
 311:                 if (writemsg(s, buf, n) < 0) {
 312:                     (void) close(s);
 313:                     error++;
 314: #ifdef DEBUG
 315:                     if (debug >= 2)
 316:                         fprintf(ddt,"writemsg failed\n");
 317: #endif
 318:                     break;
 319:                 }
 320:             }
 321:             /*
 322: 			 * Receive length & response
 323: 			 */
 324:             cp = buf;
 325:             l = sizeof(u_short);
 326:             while (l > 0) {
 327:                 (void) setitimer(ITIMER_REAL, &ival,
 328:                     (struct itimerval *)NULL);
 329:                 if ((n = recv(s, cp, l, 0)) > 0) {
 330:                     cp += n;
 331:                     l -= n;
 332:                 } else {
 333:                     if (errno == EINTR && !read_interrupted)
 334:                         continue;
 335:                     error++;
 336:                     break;
 337:                 }
 338:             }
 339:             (void) setitimer(ITIMER_REAL, &zeroival,
 340:                 (struct itimerval *)NULL);
 341:             if (error)
 342:                 break;
 343:             if ((len = htons(*(u_short *)buf)) == 0)
 344:                 break;
 345:             l = len;
 346:             cp = buf;
 347:             eom = buf + len;
 348:             while (l > 0) {
 349:                 (void) setitimer(ITIMER_REAL, &ival,
 350:                     (struct itimerval *)NULL);
 351:                 if ((n = recv(s, cp, l, 0)) > 0) {
 352:                     cp += n;
 353:                     l -= n;
 354:                 } else {
 355:                     if (errno == EINTR && !read_interrupted)
 356:                         continue;
 357:                     error++;
 358:                     break;
 359:                 }
 360:             }
 361:             (void) setitimer(ITIMER_REAL, &zeroival,
 362:                 (struct itimerval *)NULL);
 363:             if (error)
 364:                 break;
 365: #ifdef DEBUG
 366:             if (debug >= 3) {
 367:                 fprintf(ddt,"len = %d\n", len);
 368:                 fp_query(buf, ddt);
 369:             }
 370: #endif
 371:             cp = buf + sizeof(HEADER);
 372:             if (hp->qdcount)
 373:                 cp += dn_skipname(cp, eom) + QFIXEDSZ;
 374:             nmp = cp;
 375:             tmp = cp + dn_skipname(cp, eom);
 376:             n = doupdate(buf, sizeof(buf), cp, zone,
 377:                     (struct databuf **)0, DB_NODATA);
 378:             if (cp + n != eom) {
 379: #ifdef DEBUG
 380:                if (debug)
 381:                          fprintf(ddt,"zoneref: doupdate failed (%d, %d)\n",
 382:                     cp - buf, n);
 383: #endif
 384:                 error++;
 385:                 break;
 386:             }
 387:             GETSHORT(n, tmp);
 388:             if (n == T_SOA) {
 389:                 if (soacnt == 0) {
 390:                     soacnt++;
 391:                     dn_expand(buf, buf + 512, nmp, name,
 392:                         sizeof(name));
 393:                     tmp += 2 * sizeof(u_short)
 394:                         + sizeof(u_long);
 395:                     tmp += dn_skipname(tmp, eom);
 396:                     tmp += dn_skipname(tmp, eom);
 397:                     GETLONG(serial, tmp);
 398: #ifdef DEBUG
 399:                     if (debug)
 400:                         fprintf(ddt,
 401:                             "first SOA for %s, serial %ld\n",
 402:                             name, serial);
 403: #endif DEBUG
 404:                     continue;
 405:                 }
 406:                 dn_expand(buf, buf + 512, nmp, name2,
 407:                     sizeof(name2));
 408:                 if (strcasecmp(name, name2) !=0) {
 409: #ifdef DEBUG
 410:                     if (debug)
 411:                         fprintf(ddt,
 412:                           "extraneous SOA for %s\n",
 413:                           name2);
 414: #endif DEBUG
 415:                     continue;
 416:                 }
 417:                 tmp -= sizeof(u_short);
 418:                 soa_zinfo(&zp_finish, tmp, eom);
 419: #ifdef DEBUG
 420:                 if (debug)
 421:                     fprintf(ddt,
 422:                       "SOA, serial %ld\n", zp_finish.z_serial);
 423: #endif DEBUG
 424:                 if (serial != zp_finish.z_serial) {
 425:                      soacnt = 0;
 426: #ifdef DEBUG
 427:                     if (debug)
 428:                         fprintf(ddt,
 429:                         "serial changed, restart\n");
 430: #endif DEBUG
 431:                 } else
 432:                     break;
 433:             }
 434:         }
 435:         (void) close(s);
 436:         if ( error == 0) {
 437:             zp->z_refresh = zp_finish.z_refresh;
 438:             zp->z_retry   = zp_finish.z_retry;
 439:             zp->z_expire  = zp_finish.z_expire;
 440:             zp->z_minimum = zp_finish.z_minimum;
 441:             zp->z_serial  = zp_finish.z_serial;
 442:             zp->z_lastupdate = tt.tv_sec;
 443:             zp->z_sysloged = 0;
 444:             zp->z_auth = 1;
 445:             /* delete previously marked RR's here, then dump */
 446:             clean_zone (hashtab, zone, 1);
 447:             zonedump(zp);
 448:             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
 449:             return;
 450:         }
 451:         /* error: delete unmarked RR's here; remove old marks */
 452:         clean_zone (hashtab, zone, 0);
 453:         mark_zone (hashtab, zone, 0);
 454: #ifdef DEBUG
 455:         if (debug >= 2)
 456:             fprintf(ddt,"error receiving zone transfer\n");
 457: #endif
 458:     }
 459:     (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
 460:     /*
 461: 	 *     Freedom at last!!
 462: 	 *
 463: 	 *  The land where all repressed slaves dream of.
 464: 	 *
 465: 	 *  Can't find a master to talk to.
 466: 	 *  syslog it and hope we can find a master during next maintenance.
 467: 	 */
 468:     if (error && (!zp->z_sysloged)) {
 469:         syslog(LOG_WARNING,
 470:         "zoneref: Masters for secondary zone %s unreachable",
 471:         zp->z_origin);
 472:         zp->z_sysloged++;
 473:     }
 474:     zp->z_refresh = zp->z_retry;
 475:     if (tt.tv_sec - zp->z_lastupdate > zp->z_expire)
 476:         zp->z_auth = 0;
 477: }
 478: 
 479: #ifdef unused
 480: /*
 481:  * Recursively delete all domains (except for root SOA records),
 482:  * starting from head of list pointed to by np.
 483:  */
 484: static DelDom(fnp, isroot)
 485:     struct namebuf *fnp;
 486:     int isroot;
 487: {
 488:     register struct databuf *dp, *pdp = NULL;
 489:     register struct namebuf *np = fnp;
 490:     struct namebuf **npp, **nppend;
 491: 
 492: #ifdef DEBUG
 493:     if (debug >= 3)
 494:         fprintf(ddt, "DelDom('%s', %d)\n", fnp->n_dname, isroot);
 495: #endif DEBUG
 496: 
 497:     /* first do data records */
 498:     for (dp = np->n_data; dp != NULL; ) {
 499:         /* skip the root SOA record (marks end of data) */
 500:         if (isroot && dp->d_type == T_SOA) {
 501:             pdp = dp;
 502:             dp = dp->d_next;
 503:             continue;
 504:                 }
 505:         dp = rm_datum(dp, np, pdp);
 506:     }
 507: 
 508:     /* next do subdomains */
 509:         if (np->n_hash == NULL)
 510:                 return;
 511:     npp = np->n_hash->h_tab;
 512:     nppend = npp + np->n_hash->h_size;
 513:     while (npp < nppend) {
 514:         for (np = *npp++; np != NULL; np = np->n_next) {
 515:             DelDom(np, 0);
 516:         }
 517:     }
 518: }
 519: #endif unused
 520: 
 521: #ifdef DEBUG
 522: printzoneinfo(zonenum)
 523: int zonenum;
 524: {
 525:     struct timeval  tt;
 526:     struct zoneinfo *zp = &zones[zonenum];
 527:     char *ZoneType;
 528: 
 529:     if (!debug)
 530:         return; /* Else fprintf to ddt will bomb */
 531:     fprintf(ddt, "printzoneinfo(%d):\n", zonenum);
 532: 
 533:     gettime(&tt);
 534:     switch (zp->z_type) {
 535:         case Z_PRIMARY: ZoneType = "Primary"; break;
 536:         case Z_SECONDARY: ZoneType = "Secondary"; break;
 537:         case Z_CACHE: ZoneType = "Cache"; break;
 538:         default: ZoneType = "Unknown";
 539:     }
 540:     if (zp->z_origin[0] == '\0')
 541:         fprintf(ddt,"origin ='.'");
 542:     else
 543:         fprintf(ddt,"origin ='%s'", zp->z_origin);
 544:     fprintf(ddt,", type = %s", ZoneType);
 545:     fprintf(ddt,", source = %s\n", zp->z_source);
 546:     fprintf(ddt,"z_refresh = %ld", zp->z_refresh);
 547:     fprintf(ddt,", retry = %ld", zp->z_retry);
 548:     fprintf(ddt,", expire = %ld", zp->z_expire);
 549:     fprintf(ddt,", minimum = %ld", zp->z_minimum);
 550:     fprintf(ddt,", serial = %ld\n", zp->z_serial);
 551:     fprintf(ddt,"z_time = %ld", zp->z_time);
 552:     fprintf(ddt,", now time : %ld sec", tt.tv_sec);
 553:     fprintf(ddt,", time left: %ld sec\n", zp->z_time - tt.tv_sec);
 554: }
 555: #endif DEBUG
 556: 
 557: /*
 558:  * New code added by Rich Wales (UCLA), October 1986:
 559:  *
 560:  * The following routines manipulate the d_mark field.  When a zone
 561:  * is being refreshed, the old RR's are marked.  This allows old RR's to
 562:  * be cleaned up after the new copy of the zone has been completely read
 563:  * -- or new RR's to be cleaned up if an error prevents transfer of a
 564:  * new zone copy.
 565:  *
 566:  */
 567: 
 568: /*
 569:  *     Set the "d_mark" field to on each RR in the zone "zone".
 570:  *     Initially called with "htp" equal to "hashtab", this routine
 571:  *     calls itself recursively in order to traverse all subdomains.
 572:  */
 573: mark_zone (htp, zone, flag)
 574:     struct hashbuf *htp;
 575:     register int zone;
 576:     register int flag;
 577: {
 578:     register struct databuf *dp;
 579:     register struct namebuf *np;
 580:     register struct namebuf **npp, **nppend;
 581: 
 582:     nppend = htp->h_tab + htp->h_size;
 583:     for (npp = htp->h_tab; npp < nppend; npp++) {
 584:         for (np = *npp; np != NULL; np = np->n_next) {
 585:         for (dp = np->n_data; dp != NULL; dp = dp->d_next)
 586:         if (dp->d_zone == zone)
 587:             dp->d_mark = flag;
 588:         if (np->n_hash != NULL) /* mark subdomains */
 589:         mark_zone (np->n_hash, zone, flag);
 590:         }
 591:     }
 592: }
 593: 
 594: /*
 595:  * clean_zone (htp, zone, flag) --
 596:  *     Delete all RR's in the zone "zone" whose "d_mark" values are
 597:  *     equal to "flag".  Originally called with "htp" equal to
 598:  *     "hashtab", this routine calls itself recursively in order to
 599:  *     traverse all subdomains.
 600:  */
 601: clean_zone (htp, zone, flag)
 602:     register struct hashbuf *htp;
 603:     register int zone;
 604:     register int flag;
 605: {
 606:     register struct databuf *dp, *pdp;
 607:     register struct namebuf *np;
 608:     struct namebuf **npp, **nppend;
 609: 
 610:     nppend = htp->h_tab + htp->h_size;
 611:     for (npp = htp->h_tab; npp < nppend; npp++) {
 612:         for (np = *npp; np != NULL; np = np->n_next) {
 613:             for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
 614:         if (dp->d_zone == zone && dp->d_mark == flag)
 615:             dp = rm_datum(dp, np, pdp);
 616:                 else {
 617:                     pdp = dp;
 618:             dp = dp->d_next;
 619:                 }
 620:             }
 621:         /* Call recursively to clean up subdomains. */
 622:         if (np->n_hash != NULL)
 623:         clean_zone (np->n_hash, zone, flag);
 624:     }
 625:     }
 626: }

Defined functions

DelDom defined in line 484; used 1 times
clean_zone defined in line 601; used 4 times
mark_zone defined in line 573; used 3 times
ns_maint defined in line 42; used 1 times
printzoneinfo defined in line 522; used 2 times
zoneref defined in line 112; used 1 times
  • in line 75

Defined variables

sccsid defined in line 14; never used
Last modified: 1988-09-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5498
Valid CSS Valid XHTML 1.0 Strict