Annotation of 43BSDReno/usr.sbin/named/ns_maint.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1986, 1988 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_maint.c 4.37 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include <sys/param.h>
        !            25: #include <sys/socket.h>
        !            26: #include <sys/time.h>
        !            27: #if defined(SYSV)
        !            28: #include <unistd.h>
        !            29: #endif SYSV
        !            30: #include <netinet/in.h>
        !            31: #include <stdio.h>
        !            32: #include <syslog.h>
        !            33: #include <signal.h>
        !            34: #include <errno.h>
        !            35: #include <arpa/nameser.h>
        !            36: #include <sys/wait.h>
        !            37: #include "ns.h"
        !            38: #include "db.h"
        !            39: #include "pathnames.h"
        !            40: 
        !            41: extern int errno;
        !            42: extern int maint_interval;
        !            43: extern int needzoneload;
        !            44: extern u_short ns_port;
        !            45: extern char *ctime();
        !            46: 
        !            47: int xfers_running;            /* number of xfers running */
        !            48: int xfers_deferred;           /* number of needed xfers not run yet */
        !            49: static int alarm_pending;
        !            50: 
        !            51: 
        !            52: /*
        !            53:  * Invoked at regular intervals by signal interrupt; refresh all secondary
        !            54:  * zones from primary name server and remove old cache entries.  Also,
        !            55:  * ifdef'd ALLOW_UPDATES, dump database if it has changed since last
        !            56:  * dump/bootup.
        !            57:  */
        !            58: ns_maint()
        !            59: {
        !            60:        register struct zoneinfo *zp;
        !            61:        struct itimerval ival;
        !            62:        time_t next_refresh = 0;
        !            63:        int zonenum;
        !            64: 
        !            65:        gettime(&tt);
        !            66: 
        !            67: #ifdef DEBUG
        !            68:        if (debug)
        !            69:                fprintf(ddt,"\nns_maint(); now %s", ctime(&tt.tv_sec));
        !            70: #endif
        !            71: 
        !            72:        xfers_deferred = 0;
        !            73:        alarm_pending = 0;
        !            74:        for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) {
        !            75: #ifdef DEBUG
        !            76:                if (debug >= 2)
        !            77:                        printzoneinfo(zonenum);
        !            78: #endif
        !            79:                if (tt.tv_sec >= zp->z_time && zp->z_refresh > 0) {
        !            80:                        /*
        !            81:                         * Set default time for next action first,
        !            82:                         * so that it can be changed later if necessary.
        !            83:                         */
        !            84:                        zp->z_time = tt.tv_sec + zp->z_refresh;
        !            85: 
        !            86:                        switch (zp->z_type) {
        !            87: 
        !            88:                        case Z_CACHE:
        !            89:                                doachkpt();
        !            90:                                break;
        !            91: 
        !            92:                        case Z_SECONDARY:
        !            93:                                if ((zp->z_state & Z_NEED_RELOAD) == 0) {
        !            94:                                    if (zp->z_state & Z_XFER_RUNNING)
        !            95:                                        abortxfer(zp);
        !            96:                                    else if (xfers_running < MAX_XFERS_RUNNING)
        !            97:                                        startxfer(zp);
        !            98:                                    else {
        !            99:                                        zp->z_state |= Z_NEED_XFER;
        !           100:                                        ++xfers_deferred;
        !           101: #ifdef DEBUG
        !           102:                                        if (debug > 1)
        !           103:                                            fprintf(ddt,
        !           104:                                                "xfer deferred for %s\n",
        !           105:                                                zp->z_origin);
        !           106: #endif
        !           107:                                    }
        !           108:                                }
        !           109:                                break;
        !           110: #ifdef ALLOW_UPDATES
        !           111:                        case Z_PRIMARY:
        !           112:                                /*
        !           113:                                 * Checkpoint the zone if it has changed
        !           114:                                 * since we last checkpointed
        !           115:                                 */
        !           116:                                if (zp->hasChanged)
        !           117:                                        zonedump(zp);
        !           118:                                break;
        !           119: #endif ALLOW_UPDATES
        !           120:                        }
        !           121:                        gettime(&tt);
        !           122:                }
        !           123:        }
        !           124:        sched_maint();
        !           125: #ifdef DEBUG
        !           126:        if (debug)
        !           127:                fprintf(ddt,"exit ns_maint()\n");
        !           128: #endif
        !           129: }
        !           130: 
        !           131: /*
        !           132:  * Find when the next refresh needs to be and set
        !           133:  * interrupt time accordingly.
        !           134:  */
        !           135: sched_maint()
        !           136: {
        !           137:        register struct zoneinfo *zp;
        !           138:        struct itimerval ival;
        !           139:        time_t next_refresh = 0;
        !           140:        static time_t next_alarm;
        !           141: 
        !           142:        for (zp = zones; zp < &zones[nzones]; zp++)
        !           143:                if (zp->z_time != 0 &&
        !           144:                    (next_refresh == 0 || next_refresh > zp->z_time))
        !           145:                        next_refresh = zp->z_time;
        !           146:         /*
        !           147:         *  Schedule the next call to ns_maint.
        !           148:         *  Don't visit any sooner than maint_interval.
        !           149:         */
        !           150:        bzero((char *)&ival, sizeof (ival));
        !           151:        if (next_refresh != 0) {
        !           152:                if (next_refresh == next_alarm && alarm_pending) {
        !           153: #ifdef DEBUG
        !           154:                        if (debug)
        !           155:                            fprintf(ddt,"sched_maint: no schedule change\n");
        !           156: #endif
        !           157:                        return;
        !           158:                }
        !           159:                ival.it_value.tv_sec = next_refresh - tt.tv_sec;
        !           160:                if (ival.it_value.tv_sec < maint_interval)
        !           161:                        ival.it_value.tv_sec = maint_interval;
        !           162:                next_alarm = next_refresh;
        !           163:                alarm_pending = 1;
        !           164:        }
        !           165:        (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
        !           166: #ifdef DEBUG
        !           167:        if (debug)
        !           168:                fprintf(ddt,"sched_maint: Next interrupt in %d sec\n",
        !           169:                        ival.it_value.tv_sec);
        !           170: #endif
        !           171: }
        !           172: 
        !           173: /*
        !           174:  * Start an asynchronous zone transfer for a zone.
        !           175:  * Depends on current time being in tt.
        !           176:  * The caller must call sched_maint after startxfer.
        !           177:  */
        !           178: startxfer(zp)
        !           179:        struct zoneinfo *zp;
        !           180: {
        !           181:        static char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
        !           182:        int cnt, argc = 0, argc_ns = 0, pid, omask;
        !           183:        char debug_str[10];
        !           184:        char serial_str[10];
        !           185:        char port_str[10];
        !           186: 
        !           187: #ifdef DEBUG
        !           188:        if (debug)
        !           189:                fprintf(ddt,"startxfer() %s\n", zp->z_origin);
        !           190: #endif
        !           191: 
        !           192:        argv[argc++] = "named-xfer";
        !           193:        argv[argc++] = "-z";
        !           194:        argv[argc++] = zp->z_origin;
        !           195:        argv[argc++] = "-f";
        !           196:        argv[argc++] = zp->z_source;
        !           197:        argv[argc++] = "-s";
        !           198:        sprintf(serial_str, "%d", zp->z_serial);
        !           199:        argv[argc++] = serial_str;
        !           200:        if (zp->z_state & Z_SYSLOGGED)
        !           201:                argv[argc++] = "-q";
        !           202:        argv[argc++] = "-P";
        !           203:        sprintf(port_str, "%d", ns_port);
        !           204:        argv[argc++] = port_str;
        !           205: #ifdef DEBUG
        !           206:        if (debug) {
        !           207:                argv[argc++] = "-d";
        !           208:                sprintf(debug_str, "%d", debug);
        !           209:                argv[argc++] = debug_str;
        !           210:                argv[argc++] = "-l";
        !           211:                argv[argc++] = "/usr/tmp/xfer.ddt";
        !           212:                if (debug > 5) {
        !           213:                        argv[argc++] = "-t";
        !           214:                        argv[argc++] = "/usr/tmp/xfer.trace";
        !           215:                }
        !           216:        }
        !           217: #endif
        !           218:        
        !           219:        /*
        !           220:         * Copy the server ip addresses into argv, after converting
        !           221:         * to ascii and saving the static inet_ntoa result
        !           222:         */
        !           223:        for (cnt = 0; cnt < zp->z_addrcnt; cnt++)
        !           224:                argv[argc++] = strcpy(argv_ns[argc_ns++],
        !           225:                    inet_ntoa(zp->z_addr[cnt]));
        !           226: 
        !           227:        argv[argc] = 0;
        !           228: 
        !           229: #ifdef DEBUG
        !           230: #ifdef ECHOARGS
        !           231:        if (debug) {
        !           232:                int i;
        !           233:                for (i = 0; i < argc; i++) 
        !           234:                        fprintf(ddt, "Arg %d=%s\n", i, argv[i]);
        !           235:         }
        !           236: #endif /* ECHOARGS */
        !           237: #endif /* DEBUG */
        !           238: 
        !           239: #ifdef SYSV
        !           240: #define vfork fork
        !           241: #else
        !           242:        gettime(&tt);
        !           243:        omask = sigblock(sigmask(SIGCHLD));
        !           244: #endif
        !           245:        if ((pid = vfork()) == -1) {
        !           246: #ifdef DEBUG
        !           247:                if (debug)
        !           248:                        fprintf(ddt, "xfer [v]fork: %d\n", errno);
        !           249: #endif
        !           250:                syslog(LOG_ERR, "xfer [v]fork: %m");
        !           251: #ifndef SYSV
        !           252:                (void) sigsetmask(omask);
        !           253: #endif
        !           254:                zp->z_time = tt.tv_sec + 10;
        !           255:                return;
        !           256:        }
        !           257: 
        !           258:        if (pid) {
        !           259: #ifdef DEBUG
        !           260:                if (debug)
        !           261:                        fprintf(ddt, "started xfer child %d\n", pid);
        !           262: #endif
        !           263:                zp->z_state &= ~Z_NEED_XFER;
        !           264:                zp->z_state |= Z_XFER_RUNNING;
        !           265:                zp->z_xferpid = pid;
        !           266:                xfers_running++;
        !           267:                zp->z_time = tt.tv_sec + MAX_XFER_TIME;
        !           268: #ifndef SYSV
        !           269:                (void) sigsetmask(omask);
        !           270: #endif
        !           271:        } else {
        !           272:                execve(_PATH_XFER, argv, NULL);
        !           273:                syslog(LOG_ERR, "can't exec %s: %m", _PATH_XFER);
        !           274:                _exit(XFER_FAIL);       /* avoid duplicate buffer flushes */
        !           275:        }
        !           276: }
        !           277: 
        !           278: #ifdef DEBUG
        !           279: printzoneinfo(zonenum)
        !           280: int zonenum;
        !           281: {
        !           282:        struct timeval  tt;
        !           283:        struct zoneinfo *zp = &zones[zonenum];
        !           284:        char *ZoneType;
        !           285: 
        !           286:        if (!debug)
        !           287:                return; /* Else fprintf to ddt will bomb */
        !           288:        fprintf(ddt, "printzoneinfo(%d):\n", zonenum);
        !           289: 
        !           290:        gettime(&tt);
        !           291:        switch (zp->z_type) {
        !           292:                case Z_PRIMARY: ZoneType = "Primary"; break;
        !           293:                case Z_SECONDARY: ZoneType = "Secondary"; break;
        !           294:                case Z_CACHE: ZoneType = "Cache"; break;
        !           295:                default: ZoneType = "Unknown";
        !           296:        }
        !           297:        if (zp->z_origin[0] == '\0')
        !           298:                fprintf(ddt,"origin ='.'");
        !           299:        else
        !           300:                fprintf(ddt,"origin ='%s'", zp->z_origin);
        !           301:        fprintf(ddt,", type = %s", ZoneType);
        !           302:        fprintf(ddt,", source = %s\n", zp->z_source);
        !           303:        fprintf(ddt,"z_refresh = %ld", zp->z_refresh);
        !           304:        fprintf(ddt,", retry = %ld", zp->z_retry);
        !           305:        fprintf(ddt,", expire = %ld", zp->z_expire);
        !           306:        fprintf(ddt,", minimum = %ld", zp->z_minimum);
        !           307:        fprintf(ddt,", serial = %ld\n", zp->z_serial);
        !           308:        fprintf(ddt,"z_time = %d", zp->z_time);
        !           309:        if (zp->z_time) {
        !           310:                fprintf(ddt,", now time : %d sec", tt.tv_sec);
        !           311:                fprintf(ddt,", time left: %d sec", zp->z_time - tt.tv_sec);
        !           312:        }
        !           313:        fprintf(ddt,"; state %x\n", zp->z_state);
        !           314: }
        !           315: #endif DEBUG
        !           316: 
        !           317: /*
        !           318:  * remove_zone (htp, zone) --
        !           319:  *     Delete all RR's in the zone "zone" under specified hash table.
        !           320:  */
        !           321: remove_zone(htp, zone)
        !           322:        register struct hashbuf *htp;
        !           323:        register int zone;
        !           324: {
        !           325:        register struct databuf *dp, *pdp;
        !           326:        register struct namebuf *np;
        !           327:        struct namebuf **npp, **nppend;
        !           328: 
        !           329:        nppend = htp->h_tab + htp->h_size;
        !           330:        for (npp = htp->h_tab; npp < nppend; npp++)
        !           331:            for (np = *npp; np != NULL; np = np->n_next) {
        !           332:                for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
        !           333:                        if (dp->d_zone == zone)
        !           334:                                dp = rm_datum(dp, np, pdp);
        !           335:                        else {
        !           336:                                pdp = dp;
        !           337:                                dp = dp->d_next;
        !           338:                        }
        !           339:                }
        !           340:                /* Call recursively to remove subdomains. */
        !           341:                if (np->n_hash)
        !           342:                        remove_zone(np->n_hash, zone);
        !           343:            }
        !           344: }
        !           345:    
        !           346: /*
        !           347:  * Abort an xfer that has taken too long.
        !           348:  */
        !           349: abortxfer(zp)
        !           350:        register struct zoneinfo *zp;
        !           351: {
        !           352: 
        !           353:        kill(zp->z_xferpid, SIGKILL); /* don't trust it at all */
        !           354: #ifdef DEBUG
        !           355:        if (debug)
        !           356:          fprintf(ddt, "Killed child %d (zone %s) due to timeout\n",
        !           357:             zp->z_xferpid, zp->z_origin);
        !           358: #endif /* DEBUG */
        !           359:        zp->z_time = tt.tv_sec + zp->z_retry;
        !           360: }
        !           361: 
        !           362: #ifdef SYSV
        !           363: union wait {
        !           364:        unsigned short  w_termsig:7;    /* termination signal */
        !           365:        unsigned short  w_coredump:1;   /* core dump indicator */
        !           366:        unsigned short  w_retcode:8;    /* exit code if w_termsig==0 */
        !           367: };
        !           368: #endif
        !           369: 
        !           370: /*
        !           371:  * SIGCHLD signal handler: process exit of xfer's.
        !           372:  * (Note: also called when outgoing transfer completes.)
        !           373:  */
        !           374: VOID
        !           375: endxfer()
        !           376: {
        !           377:        register struct zoneinfo *zp;   
        !           378:        int pid, xfers = 0;
        !           379:        union wait status;
        !           380: 
        !           381:        gettime(&tt);
        !           382: #if defined(SYSV)
        !           383:        { int stat;
        !           384:        pid = wait(&stat);
        !           385:        status.w_termsig = stat & 0x7f;
        !           386:        status.w_retcode = stat >> 8;
        !           387:        }
        !           388: #else /* SYSV */
        !           389:        while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
        !           390: #endif /* SYSV */
        !           391:                for (zp = zones; zp < &zones[nzones]; zp++)
        !           392:                    if (zp->z_xferpid == pid) {
        !           393:                        xfers++;
        !           394:                        xfers_running--;
        !           395:                        zp->z_xferpid = 0;
        !           396:                        zp->z_state &= ~Z_XFER_RUNNING;
        !           397: #ifdef DEBUG
        !           398:                        if (debug) 
        !           399:                            fprintf(ddt,
        !           400:                "\nendxfer: child %d zone %s returned status=%d termsig=%d\n", 
        !           401:                                pid, zp->z_origin, status.w_retcode,
        !           402:                                status.w_termsig);
        !           403: #endif
        !           404:                        if (status.w_termsig != 0) {
        !           405:                                if (status.w_termsig != SIGKILL) {
        !           406:                                        syslog(LOG_ERR,
        !           407:                                           "named-xfer exited with signal %d\n",
        !           408:                                           status.w_termsig);
        !           409: #ifdef DEBUG
        !           410:                                        if (debug)
        !           411:                                            fprintf(ddt,
        !           412:                                         "\tchild termination with signal %d\n",
        !           413:                                                status.w_termsig);
        !           414: #endif
        !           415:                                }
        !           416:                                zp->z_time = tt.tv_sec + zp->z_retry;
        !           417:                        } else switch (status.w_retcode) {
        !           418:                                case XFER_UPTODATE:
        !           419:                                        zp->z_state &= ~Z_SYSLOGGED;
        !           420:                                        zp->z_lastupdate = tt.tv_sec;
        !           421:                                        zp->z_time = tt.tv_sec + zp->z_refresh;
        !           422:                                        /*
        !           423:                                         * Restore z_auth in case expired,
        !           424:                                         * but only if there were no errors
        !           425:                                         * in the zone file.
        !           426:                                         */
        !           427:                                        if ((zp->z_state & Z_DB_BAD) == 0)
        !           428:                                                zp->z_auth = 1;
        !           429:                                        if (zp->z_source) {
        !           430: #if defined(SYSV)
        !           431:                                                struct utimbuf t;
        !           432: 
        !           433:                                                t.actime = tt.tv_sec;
        !           434:                                                t.modtime = tt.tv_sec;
        !           435:                                                (void) utime(zp->z_source, &t);
        !           436: #else
        !           437:                                                struct timeval t[2];
        !           438: 
        !           439:                                                t[0] = tt;
        !           440:                                                t[1] = tt;
        !           441:                                                (void) utimes(zp->z_source, t);
        !           442: #endif /* SYSV */
        !           443:                                        }
        !           444:                                        break;
        !           445: 
        !           446:                                case XFER_SUCCESS:
        !           447:                                        zp->z_state |= Z_NEED_RELOAD;
        !           448:                                        zp->z_state &= ~Z_SYSLOGGED;
        !           449:                                        needzoneload++;
        !           450:                                        break;
        !           451: 
        !           452:                                case XFER_TIMEOUT:
        !           453: #ifdef DEBUG
        !           454:                                        if (debug) fprintf(ddt,
        !           455:                    "zoneref: Masters for secondary zone %s unreachable\n",
        !           456:                                            zp->z_origin);
        !           457: #endif
        !           458:                                        if ((zp->z_state & Z_SYSLOGGED) == 0) {
        !           459:                                                zp->z_state |= Z_SYSLOGGED;
        !           460:                                                syslog(LOG_WARNING,
        !           461:                      "zoneref: Masters for secondary zone %s unreachable",
        !           462:                                                    zp->z_origin);
        !           463:                                        }
        !           464:                                        zp->z_time = tt.tv_sec + zp->z_retry;
        !           465:                                        break;
        !           466: 
        !           467:                                default:
        !           468:                                        if ((zp->z_state & Z_SYSLOGGED) == 0) {
        !           469:                                                zp->z_state |= Z_SYSLOGGED;
        !           470:                                                syslog(LOG_ERR,
        !           471:                                                    "named-xfer exit code %d",
        !           472:                                                    status.w_retcode);
        !           473:                                        }
        !           474:                                        /* FALLTHROUGH */
        !           475:                                case XFER_FAIL:
        !           476:                                        zp->z_state |= Z_SYSLOGGED;
        !           477:                                        zp->z_time = tt.tv_sec + zp->z_retry;
        !           478:                                        break;
        !           479:                        }
        !           480:                        break;
        !           481:                }
        !           482: #ifndef SYSV
        !           483:        }
        !           484: #endif /* SYSV */
        !           485:        if (xfers) {
        !           486:                for (zp = zones;
        !           487:                    xfers_deferred != 0 && xfers_running < MAX_XFERS_RUNNING &&
        !           488:                    zp < &zones[nzones]; zp++)
        !           489:                        if (zp->z_state & Z_NEED_XFER) {
        !           490:                                xfers_deferred--;
        !           491:                                startxfer(zp);
        !           492:                        }
        !           493:                sched_maint();
        !           494:        }
        !           495: #if defined(SYSV)
        !           496:        (void)signal(SIGCLD, endxfer);
        !           497: #endif
        !           498: }
        !           499: 
        !           500: /*
        !           501:  * Reload zones whose transfers have completed.
        !           502:  */
        !           503: loadxfer()
        !           504: {
        !           505:        register struct zoneinfo *zp;   
        !           506: 
        !           507:        gettime(&tt);
        !           508:        for (zp = zones; zp < &zones[nzones]; zp++)
        !           509:            if (zp->z_state & Z_NEED_RELOAD) {
        !           510: #ifdef DEBUG
        !           511:                if (debug)
        !           512:                        fprintf(ddt, "loadxfer() '%s'\n",
        !           513:                        zp->z_origin[0] ? zp->z_origin : ".");
        !           514: #endif
        !           515:                zp->z_state &= ~Z_NEED_RELOAD;
        !           516:                zp->z_auth = 0;
        !           517:                remove_zone(hashtab, zp - zones);
        !           518:                if (db_load(zp->z_source, zp->z_origin, zp, 0) == 0)
        !           519:                        zp->z_auth = 1;
        !           520:                if (zp->z_state & Z_TMP_FILE)
        !           521:                        (void) unlink(zp->z_source);
        !           522:            }
        !           523:        sched_maint();
        !           524: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.