Annotation of 43BSDReno/usr.sbin/named/ns_maint.c, revision 1.1.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.