Annotation of 43BSDTahoe/etc/named/db_dump.c, revision 1.1

1.1     ! root        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 the above copyright notice and this paragraph are
        !             7:  * duplicated in all such forms and that any documentation,
        !             8:  * advertising materials, and other materials related to such
        !             9:  * distribution and use acknowledge that the software was developed
        !            10:  * by the University of California, Berkeley.  The name of the
        !            11:  * University may not be used to endorse or promote products derived
        !            12:  * from this software without specific prior written permission.
        !            13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            16:  */
        !            17: 
        !            18: #ifndef lint
        !            19: static char sccsid[] = "@(#)db_dump.c  4.21 (Berkeley) 6/18/88";
        !            20: #endif /* not lint */
        !            21: 
        !            22: #include <sys/param.h>
        !            23: #include <sys/time.h>
        !            24: #include <sys/stat.h>
        !            25: #include <netinet/in.h>
        !            26: #include <netdb.h>
        !            27: #include <stdio.h>
        !            28: #include <syslog.h>
        !            29: #include <arpa/nameser.h>
        !            30: #include "ns.h"
        !            31: #include "db.h"
        !            32: 
        !            33: extern char *p_type(), *p_class();
        !            34: 
        !            35: #ifdef DUMPFILE
        !            36: char   *dumpfile = DUMPFILE;
        !            37: #else
        !            38: char   *dumpfile = "/usr/tmp/named_dump.db";
        !            39: #endif
        !            40: 
        !            41: extern char *cache_file;
        !            42: 
        !            43: /*
        !            44:  * Dump current cache in a format similar to RFC 883.
        !            45:  *
        !            46:  * We try to be careful and determine whether the operation succeeded
        !            47:  * so that the new cache file can be installed.
        !            48:  */
        !            49: 
        !            50: #define DB_ROOT_TIMBUF 3600
        !            51: 
        !            52: doachkpt()
        !            53: {
        !            54:     extern int errno;
        !            55:     FILE *fp;
        !            56:     char tmpcheckfile[256];
        !            57: 
        !            58:     /* nowhere to checkpoint cache... */
        !            59:     if (cache_file == NULL) {
        !            60: #ifdef DEBUG
        !            61:         if (debug >= 3)
        !            62:             fprintf(ddt,"doachkpt(to where?)\n");
        !            63: #endif
        !            64:         return;
        !            65:     }
        !            66: 
        !            67: #ifdef DEBUG
        !            68:     if (debug >= 3)
        !            69:         fprintf(ddt,"doachkpt()\n");
        !            70: #endif
        !            71: 
        !            72:     (void) sprintf(tmpcheckfile, "%s.chk", cache_file);
        !            73:     if ((fp = fopen(tmpcheckfile, "w")) == NULL) {
        !            74: #ifdef DEBUG
        !            75:         if (debug >= 3)
        !            76:             fprintf(ddt,"doachkpt(can't open %s for write)\n", tmpcheckfile);
        !            77: #endif
        !            78:         return;
        !            79:     }
        !            80: 
        !            81:     (void) gettime(&tt);
        !            82:     fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
        !            83:     fflush(fp);
        !            84:     if (ferror(fp)) {
        !            85: #ifdef DEBUG
        !            86:         if (debug >= 3)
        !            87:             fprintf(ddt,"doachkpt(write to checkpoint file failed)\n");
        !            88: #endif
        !            89:         return;
        !            90:     }
        !            91: 
        !            92:     if (fcachetab != NULL) {
        !            93:        int n;
        !            94:        if ((n = scan_root(hashtab)) < MINROOTS) {
        !            95:            syslog(LOG_ERR, "%d root hints... (too low)", n);
        !            96:            fprintf(fp, "; ---- Root hint cache dump ----\n");
        !            97:            (void) db_dump(fcachetab, fp, DB_Z_CACHE, "");
        !            98:        }
        !            99:     }
        !           100: 
        !           101:     if (hashtab != NULL) {
        !           102:         fprintf(fp, "; ---- Cache dump ----\n");
        !           103:         if (db_dump(hashtab, fp, DB_Z_CACHE, "") == NODBFILE) {
        !           104: #ifdef DEBUG
        !           105:             if (debug >= 3)
        !           106:                 fprintf(ddt,"doachkpt(checkpoint failed)\n");
        !           107: #endif
        !           108:             (void) fclose(fp);
        !           109:             return;
        !           110:         }
        !           111:     }
        !           112: 
        !           113:     (void) fsync(fileno(fp));
        !           114:     if (fclose(fp) == EOF) {
        !           115: #ifdef DEBUG
        !           116:         if (debug >= 3)
        !           117:             fprintf(ddt,"doachkpt(close failed)\n");
        !           118: #endif
        !           119:         return;
        !           120:     }
        !           121: 
        !           122:     if (rename(tmpcheckfile, cache_file)) {
        !           123: #ifdef DEBUG
        !           124:         if (debug >= 3)
        !           125:             fprintf(ddt,"doachkpt(install %s to %s failed, %d)\n",
        !           126:                     tmpcheckfile,cache_file, errno);
        !           127: #endif
        !           128:     }
        !           129: }
        !           130: 
        !           131: /*
        !           132:  * What we do is scan the root hint cache to make sure there are at least
        !           133:  * MINROOTS root pointers with non-0 TTL's so that the checkpoint will not
        !           134:  * lose the root.  Failing this, all pointers are written out w/ TTL ~0
        !           135:  * (root pointers timed out and prime_cache() not done or failed).
        !           136:  */
        !           137: #define TIMBUF 300
        !           138: 
        !           139: int
        !           140: scan_root(htp)
        !           141:        struct hashbuf *htp;
        !           142: {
        !           143:        register struct databuf *dp;
        !           144:        register struct namebuf *np;
        !           145:        struct timeval soon;
        !           146:        int roots = 0;
        !           147: 
        !           148: #ifdef DEBUG
        !           149:        if (debug)
        !           150:                fprintf(ddt,"scan_root(0x%x)\n", htp);
        !           151: #endif
        !           152: 
        !           153:        /* metric by which we determine whether a root NS pointer is still */
        !           154:        /* valid (will be written out if we do a dump).  we also add some */
        !           155:        /* time buffer for safety... */
        !           156:        (void) gettime(&soon);
        !           157:        soon.tv_sec += TIMBUF;
        !           158: 
        !           159:        for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
        !           160:                if (np->n_dname[0] == '\0') {
        !           161:                        dp = np->n_data;
        !           162:                        while (dp != NULL) {
        !           163:                                if (dp->d_type == T_NS &&
        !           164:                                    dp->d_ttl > soon.tv_sec) {
        !           165:                                        roots++;
        !           166:                                        if (roots >= MINROOTS)
        !           167:                                                return (roots);
        !           168:                                }
        !           169:                                dp = dp->d_next;
        !           170:                        }
        !           171:                }
        !           172:        }
        !           173:        return (roots);
        !           174: }
        !           175: 
        !           176: #ifdef notdef
        !           177: mark_cache(htp, ttl)
        !           178:     struct hashbuf *htp;
        !           179:     int ttl;
        !           180: {
        !           181:     register struct databuf *dp;
        !           182:     register struct namebuf *np;
        !           183:     struct namebuf **npp, **nppend;
        !           184:     struct timeval soon;
        !           185: 
        !           186: #ifdef DEBUG
        !           187:     if (debug)
        !           188:         fprintf(ddt,"mark_cache()\n");
        !           189: #endif
        !           190: 
        !           191:     (void) gettime(&soon);
        !           192:     soon.tv_sec += TIMBUF;
        !           193: 
        !           194:     npp = htp->h_tab;
        !           195:     nppend = npp + htp->h_size;
        !           196:     while (npp < nppend) {
        !           197:         for (np = *npp++; np != NULL; np = np->n_next) {
        !           198:             if (np->n_data == NULL)
        !           199:                 continue;
        !           200:             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
        !           201:                 if (dp->d_ttl < soon.tv_sec)
        !           202:                     dp->d_ttl = ttl;
        !           203:             }
        !           204:         }
        !           205:     }
        !           206: 
        !           207:     npp = htp->h_tab;
        !           208:     nppend = npp + htp->h_size;
        !           209:     while (npp < nppend) {
        !           210:         for (np = *npp++; np != NULL; np = np->n_next) {
        !           211:             if (np->n_hash == NULL)
        !           212:                 continue;
        !           213:             mark_cache(np->n_hash, ttl);
        !           214:         }
        !           215:     }
        !           216: }
        !           217: #endif notdef
        !           218: 
        !           219: /*
        !           220:  * Dump current data base in a format similar to RFC 883.
        !           221:  */
        !           222: 
        !           223: doadump()
        !           224: {
        !           225:        FILE    *fp;
        !           226: 
        !           227: #ifdef DEBUG
        !           228:        if (debug >= 3)
        !           229:                fprintf(ddt,"doadump()\n");
        !           230: #endif
        !           231: 
        !           232:        if ((fp = fopen(dumpfile, "w")) == NULL)
        !           233:                return;
        !           234:        gettime(&tt);
        !           235:        fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
        !           236:        fprintf(fp, "; --- Cache & Data ---\n");
        !           237:        if (hashtab != NULL)
        !           238:                (void) db_dump(hashtab, fp, DB_Z_ALL, "");
        !           239:        fprintf(fp, "; --- Hints ---\n");
        !           240:        if (fcachetab != NULL)
        !           241:                (void) db_dump(fcachetab, fp, DB_Z_ALL, "");
        !           242:        (void) fclose(fp);
        !           243: }
        !           244: 
        !           245: /* Create a disk database to back up zones 
        !           246:  */
        !           247: zonedump(zp)
        !           248:     register struct zoneinfo *zp;
        !           249: {
        !           250:        FILE    *fp;
        !           251:        char *fname;
        !           252:        struct hashbuf *htp;
        !           253:        char *op;
        !           254:        struct stat st;
        !           255: 
        !           256:        /* Only dump zone if there is a cache specified */
        !           257:        if (zp->z_source && *(zp->z_source)) {
        !           258: #ifdef DEBUG
        !           259:            if (debug)
        !           260:                    fprintf(ddt, "zonedump(%s)\n", zp->z_source);
        !           261: #endif
        !           262: 
        !           263:            if ((fp = fopen(zp->z_source, "w")) == NULL)
        !           264:                    return;
        !           265:            if (op = index(zp->z_origin, '.'))
        !           266:                op++;
        !           267:            gettime(&tt);
        !           268:            htp = hashtab;
        !           269:            if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) {
        !           270:                    db_dump(htp, fp, zp-zones, (op == NULL ? "" : op));
        !           271: #ifdef ALLOW_UPDATES
        !           272:                    zp->hasChanged = 0;         /* Checkpointed */
        !           273: #endif ALLOW_UPDATES
        !           274:            }
        !           275:            (void) fclose(fp);
        !           276:            if (stat(zp->z_source, &st) == 0)
        !           277:                    zp->z_ftime = st.st_mtime;
        !           278:        }
        !           279: #ifdef DEBUG
        !           280:            else if (debug)
        !           281:                fprintf(ddt, "zonedump: no zone to dump\n");
        !           282: #endif
        !           283: }
        !           284: 
        !           285: int
        !           286: db_dump(htp, fp, zone, origin)
        !           287:        int zone;
        !           288:        struct hashbuf *htp;
        !           289:        FILE *fp;
        !           290:        char *origin;
        !           291: {
        !           292:        register struct databuf *dp;
        !           293:        register struct namebuf *np;
        !           294:        struct namebuf **npp, **nppend;
        !           295:        char dname[MAXDNAME];
        !           296:        u_long n;
        !           297:        u_long addr;
        !           298:        u_short i;
        !           299:        int j;
        !           300:        register u_char *cp;
        !           301:        char *proto;
        !           302:        extern char *inet_ntoa(), *p_protocal(), *p_service();
        !           303:        int found_data, tab, printed_origin = 0;
        !           304: 
        !           305:        npp = htp->h_tab;
        !           306:        nppend = npp + htp->h_size;
        !           307:        while (npp < nppend) {
        !           308:            for (np = *npp++; np != NULL; np = np->n_next) {
        !           309:                if (np->n_data == NULL)
        !           310:                        continue;
        !           311:                /* Blecch - can't tell if there is data here for the
        !           312:                 * right zone, so can't print name yet
        !           313:                 */
        !           314:                found_data = 0;
        !           315:                /* we want a snapshot in time... */
        !           316:                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
        !           317:                        /* Is the data for this zone? */
        !           318:                        if (zone != DB_Z_ALL && dp->d_zone != zone)
        !           319:                            continue;
        !           320:                        if (dp->d_zone == DB_Z_CACHE &&
        !           321:                            dp->d_ttl <= tt.tv_sec &&
        !           322:                            (dp->d_flags & DB_F_HINT) == 0)
        !           323:                                continue;
        !           324:                        if (!printed_origin) {
        !           325:                            fprintf(fp, "$ORIGIN %s.\n", origin);
        !           326:                            printed_origin++;
        !           327:                        }
        !           328:                        tab = 0;
        !           329:                        if (!found_data) {
        !           330:                            if (np->n_dname[0] == 0) {
        !           331:                                if (origin[0] == 0)
        !           332:                                    fprintf(fp, ".\t");
        !           333:                                else
        !           334:                                    fprintf(fp, ".%s.\t", origin); /* ??? */
        !           335:                            } else
        !           336:                                fprintf(fp, "%s\t", np->n_dname);
        !           337:                            if (strlen(np->n_dname) < 8)
        !           338:                                tab = 1;
        !           339:                            found_data++;
        !           340:                        } else {
        !           341:                            (void) putc('\t', fp);
        !           342:                            tab = 1;
        !           343:                        }
        !           344:                        if (dp->d_zone == DB_Z_CACHE) {
        !           345:                            if (dp->d_flags & DB_F_HINT &&
        !           346:                                (long)(dp->d_ttl - tt.tv_sec) < DB_ROOT_TIMBUF)
        !           347:                                    fprintf(fp, "%d\t", DB_ROOT_TIMBUF);
        !           348:                            else
        !           349:                                    fprintf(fp, "%d\t",
        !           350:                                        (int)(dp->d_ttl - tt.tv_sec));
        !           351:                        } else if (dp->d_ttl != 0 &&
        !           352:                            dp->d_ttl != zones[dp->d_zone].z_minimum)
        !           353:                                fprintf(fp, "%d\t", (int)dp->d_ttl);
        !           354:                        else if (tab)
        !           355:                            (void) putc('\t', fp);
        !           356:                        fprintf(fp, "%s\t%s\t", p_class(dp->d_class),
        !           357:                                p_type(dp->d_type));
        !           358:                        cp = (u_char *)dp->d_data;
        !           359:                        /*
        !           360:                         * Print type specific data
        !           361:                         */
        !           362:                        switch (dp->d_type) {
        !           363:                        case T_A:
        !           364:                                switch (dp->d_class) {
        !           365:                                case C_IN:
        !           366:                                        GETLONG(n, cp);
        !           367:                                        n = htonl(n);
        !           368:                                        fprintf(fp, "%s",
        !           369:                                           inet_ntoa(*(struct in_addr *)&n));
        !           370:                                        break;
        !           371:                                }
        !           372:                                if (dp->d_nstime)
        !           373:                                        fprintf(fp, "\t; %d", dp->d_nstime);
        !           374:                                fprintf(fp, "\n");
        !           375:                                break;
        !           376:                        case T_CNAME:
        !           377:                        case T_MB:
        !           378:                        case T_MG:
        !           379:                        case T_MR:
        !           380:                        case T_PTR:
        !           381:                                if (cp[0] == '\0')
        !           382:                                        fprintf(fp, ".\n");
        !           383:                                else
        !           384:                                        fprintf(fp, "%s.\n", cp);
        !           385:                                break;
        !           386: 
        !           387:                        case T_NS:
        !           388:                                cp = (u_char *)dp->d_data;
        !           389:                                if (cp[0] == '\0')
        !           390:                                        fprintf(fp, ".\t");
        !           391:                                else
        !           392:                                        fprintf(fp, "%s.", cp);
        !           393:                                if (dp->d_nstime)
        !           394:                                        fprintf(fp, "\t; %d???", dp->d_nstime);
        !           395:                                fprintf(fp, "\n");
        !           396:                                break;
        !           397: 
        !           398:                        case T_HINFO:
        !           399:                                if (n = *cp++) {
        !           400:                                        fprintf(fp, "\"%.*s\"", (int)n, cp);
        !           401:                                        cp += n;
        !           402:                                } else
        !           403:                                        fprintf(fp, "\"\"");
        !           404:                                if (n = *cp++)
        !           405:                                        fprintf(fp, " \"%.*s\"", (int)n, cp);
        !           406:                                else
        !           407:                                        fprintf(fp, "\"\"");
        !           408:                                (void) putc('\n', fp);
        !           409:                                break;
        !           410: 
        !           411:                        case T_SOA:
        !           412:                                fprintf(fp, "%s.", cp);
        !           413:                                cp += strlen(cp) + 1;
        !           414:                                fprintf(fp, " %s. (\n", cp);
        !           415:                                cp += strlen(cp) + 1;
        !           416:                                GETLONG(n, cp);
        !           417:                                fprintf(fp, "\t\t%lu", n);
        !           418:                                GETLONG(n, cp);
        !           419:                                fprintf(fp, " %lu", n);
        !           420:                                GETLONG(n, cp);
        !           421:                                fprintf(fp, " %lu", n);
        !           422:                                GETLONG(n, cp);
        !           423:                                fprintf(fp, " %lu", n);
        !           424:                                GETLONG(n, cp);
        !           425:                                fprintf(fp, " %lu )\n", n);
        !           426:                                break;
        !           427: 
        !           428:                        case T_MX:
        !           429:                                GETSHORT(n, cp);
        !           430:                                fprintf(fp,"%lu", n);
        !           431:                                fprintf(fp," %s.\n", cp);
        !           432:                                break;
        !           433: 
        !           434: 
        !           435:                        case T_UINFO:
        !           436:                                fprintf(fp, "\"%s\"\n", cp);
        !           437:                                break;
        !           438: 
        !           439:                        case T_UID:
        !           440:                        case T_GID:
        !           441:                                if (dp->d_size == sizeof(u_long)) {
        !           442:                                        GETLONG(n, cp);
        !           443:                                        fprintf(fp, "%lu\n", n);
        !           444:                                }
        !           445:                                break;
        !           446: 
        !           447:                        case T_WKS:
        !           448:                                GETLONG(addr, cp);      
        !           449:                                addr = htonl(addr);     
        !           450:                                fprintf(fp,"%s ",
        !           451:                                    inet_ntoa(*(struct in_addr *)&addr));
        !           452:                                proto = p_protocal(*cp); /* protocal */
        !           453:                                cp += sizeof(char); 
        !           454:                                fprintf(fp, "%s ", proto);
        !           455:                                i = 0;
        !           456:                                while(cp < (u_char *)dp->d_data + dp->d_size) {
        !           457:                                        j = *cp++;
        !           458:                                        do {
        !           459:                                                if(j & 0200)
        !           460:                                                        fprintf(fp," %s",
        !           461:                                                           p_service(i, proto));
        !           462:                                                j <<= 1;
        !           463:                                        } while(++i & 07);
        !           464:                                } 
        !           465:                                fprintf(fp,"\n");
        !           466:                                break;
        !           467: 
        !           468:                        case T_MINFO:
        !           469:                                fprintf(fp, "%s.", cp);
        !           470:                                cp += strlen(cp) + 1;
        !           471:                                fprintf(fp, " %s.\n", cp);
        !           472:                                break;
        !           473: #ifdef ALLOW_T_UNSPEC
        !           474:                        case T_UNSPEC:
        !           475:                                /* Dump binary data out in an ASCII-encoded
        !           476:                                   format */
        !           477:                                {
        !           478:                                        /* Allocate more than enough space:
        !           479:                                         *  actually need 5/4 size + 20 or so
        !           480:                                         */
        !           481:                                        int TmpSize = 2 * dp->d_size + 30;
        !           482:                                        char *TmpBuf = (char *) malloc(TmpSize);
        !           483:                                        if (TmpBuf == NULL) {
        !           484: #ifdef DEBUG
        !           485:                                            if (debug)
        !           486:                                                fprintf(ddt, "Dump T_UNSPEC: malloc returned NULL\n");
        !           487: #endif DEBUG
        !           488:                                                syslog(LOG_ERR, "Dump T_UNSPEC: malloc: %m");
        !           489:                                        }
        !           490:                                        if (btoa(cp, dp->d_size, TmpBuf,
        !           491:                                                 TmpSize) == CONV_OVERFLOW) {
        !           492: #ifdef DEBUG
        !           493:                                                if (debug)
        !           494:                                                    fprintf(ddt, "Dump T_UNSPEC: Output buffer overflow\n");
        !           495: #endif DEBUG
        !           496:                                                    syslog(LOG_ERR, "Dump T_UNSPEC: Output buffer overflow\n");
        !           497:                                        } else
        !           498:                                                fprintf(fp, "%s\n", TmpBuf);
        !           499:                                }
        !           500:                                break;
        !           501: #endif ALLOW_T_UNSPEC
        !           502:                        default:
        !           503:                                fprintf(fp, "???\n");
        !           504:                        }
        !           505:                }
        !           506:            }
        !           507:        }
        !           508:         if (ferror(fp))
        !           509:             return(NODBFILE);
        !           510: 
        !           511:        npp = htp->h_tab;
        !           512:        nppend = npp + htp->h_size;
        !           513:        while (npp < nppend) {
        !           514:            for (np = *npp++; np != NULL; np = np->n_next) {
        !           515:                if (np->n_hash == NULL)
        !           516:                        continue;
        !           517:                getname(np, dname, sizeof(dname));
        !           518:                if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE)
        !           519:                    return(NODBFILE);
        !           520:            }
        !           521:        }
        !           522:        return(OK);
        !           523: }
        !           524: 
        !           525: /*  These next two routines will be moveing to res_debug.c */
        !           526: /* They are currently here for ease of distributing the WKS record fix */
        !           527: char *
        !           528: p_protocal(num)
        !           529: int num;
        !           530: {
        !           531:        static  char number[8];
        !           532:        struct protoent *pp;
        !           533:        extern struct protoent *cgetprotobynumber();
        !           534: 
        !           535:        pp = cgetprotobynumber(num);
        !           536:        if(pp == 0)  {
        !           537:                (void) sprintf(number, "%d", num);
        !           538:                return(number);
        !           539:        }
        !           540:        return(pp->p_name);
        !           541: }
        !           542: 
        !           543: char *
        !           544: p_service(port, proto)
        !           545: u_short port;
        !           546: char *proto;
        !           547: {
        !           548:        static  char number[8];
        !           549:        struct servent *ss;
        !           550:        extern struct servent *cgetservbyport();
        !           551: 
        !           552:        ss = cgetservbyport(htons(port), proto);
        !           553:        if(ss == 0)  {
        !           554:                (void) sprintf(number, "%d", port);
        !           555:                return(number);
        !           556:        }
        !           557:        return(ss->s_name);
        !           558: }
        !           559: 
        !           560: #ifdef ALLOW_T_UNSPEC
        !           561: /*
        !           562:  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
        !           563:  * Computes the number of bytes, and three kinds of simple checksums.
        !           564:  * Incoming bytes are collected into 32-bit words, then printed in base 85:
        !           565:  *     exp(85,5) > exp(2,32)
        !           566:  * The ASCII characters used are between '!' and 'u';
        !           567:  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
        !           568:  *
        !           569:  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
        !           570:  * the atob/btoa programs, released with the compress program, in mod.sources.
        !           571:  * Modified by Mike Schwartz 8/19/86 for use in BIND.
        !           572:  */
        !           573: 
        !           574: /* Make sure global variable names are unique */
        !           575: #define Ceor T_UNSPEC_Ceor
        !           576: #define Csum T_UNSPEC_Csum
        !           577: #define Crot T_UNSPEC_Crot
        !           578: #define word T_UNSPEC_word
        !           579: #define bcount T_UNSPEC_bcount
        !           580: 
        !           581: static long int Ceor, Csum, Crot, word, bcount;
        !           582: 
        !           583: #define EN(c)  ((int) ((c) + '!'))
        !           584: #define DE(c) ((c) - '!')
        !           585: #define AddToBuf(bufp, c) **bufp = c; (*bufp)++;
        !           586: #define streq(s0, s1)  strcmp(s0, s1) == 0
        !           587: #define times85(x)     ((((((x<<2)+x)<<2)+x)<<2)+x)
        !           588: 
        !           589: 
        !           590: /* Decode ASCII-encoded byte c into binary representation and 
        !           591:  * place into *bufp, advancing bufp 
        !           592:  */
        !           593: static int
        !           594: byte_atob(c, bufp)
        !           595:        register c;
        !           596:        char **bufp;
        !           597: {
        !           598:        if (c == 'z') {
        !           599:                if (bcount != 0)
        !           600:                        return(CONV_BADFMT);
        !           601:                else {
        !           602:                        putbyte(0, bufp);
        !           603:                        putbyte(0, bufp);
        !           604:                        putbyte(0, bufp);
        !           605:                        putbyte(0, bufp);
        !           606:                }
        !           607:        } else if ((c >= '!') && (c < ('!' + 85))) {
        !           608:                if (bcount == 0) {
        !           609:                        word = DE(c);
        !           610:                        ++bcount;
        !           611:                } else if (bcount < 4) {
        !           612:                        word = times85(word);
        !           613:                        word += DE(c);
        !           614:                        ++bcount;
        !           615:                } else {
        !           616:                        word = times85(word) + DE(c);
        !           617:                        putbyte((int)((word >> 24) & 255), bufp);
        !           618:                        putbyte((int)((word >> 16) & 255), bufp);
        !           619:                        putbyte((int)((word >> 8) & 255), bufp);
        !           620:                        putbyte((int)(word & 255), bufp);
        !           621:                        word = 0;
        !           622:                        bcount = 0;
        !           623:                }
        !           624:        } else
        !           625:                return(CONV_BADFMT);
        !           626:        return(CONV_SUCCESS);
        !           627: }
        !           628: 
        !           629: /* Compute checksum info and place c into *bufp, advancing bufp */
        !           630: static
        !           631: putbyte(c, bufp)
        !           632:        register c;
        !           633:        char **bufp;
        !           634: {
        !           635:        Ceor ^= c;
        !           636:        Csum += c;
        !           637:        Csum += 1;
        !           638:        if ((Crot & 0x80000000)) {
        !           639:                Crot <<= 1;
        !           640:                Crot += 1;
        !           641:        } else {
        !           642:                Crot <<= 1;
        !           643:        }
        !           644:        Crot += c;
        !           645:        AddToBuf(bufp, c);
        !           646: }
        !           647: 
        !           648: /* Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
        !           649:    it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
        !           650:    outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
        !           651:    in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
        !           652:    boundary, there will be no problem...it will be padded with 0 bytes, and
        !           653:    numbytes will indicate the correct number of bytes.  The main point is
        !           654:    that since the buffer is filled in 4 bytes at a time, even if there is
        !           655:    not a full 4 bytes of data at the end, there has to be room to 0-pad the
        !           656:    data, so the buffer must be of size divisible by 4).  Place the number of
        !           657:    output bytes in numbytes, and return a failure/success status  */
        !           658: int
        !           659: atob(inbuf, inbuflen, outbuf, outbuflen, numbytes)
        !           660:        char *inbuf;
        !           661:        int inbuflen;
        !           662:        char *outbuf;
        !           663:        int outbuflen;
        !           664:        int *numbytes;
        !           665: {
        !           666:        int inc, nb;
        !           667:        long int oeor, osum, orot;
        !           668:        char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen];
        !           669: 
        !           670:        if ( (outbuflen % 4) != 0)
        !           671:                return(CONV_BADBUFLEN);
        !           672:        Ceor = Csum = Crot = word = bcount = 0;
        !           673:        for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) {
        !           674:                if (outp > endoutp)
        !           675:                        return(CONV_OVERFLOW);
        !           676:                if (*inp == 'x') {
        !           677:                        inp +=2;
        !           678:                        break;
        !           679:                } else {
        !           680:                        if (byte_atob(*inp, &outp) == CONV_BADFMT)
        !           681:                                return(CONV_BADFMT);
        !           682:                }
        !           683:        }
        !           684: 
        !           685:        /* Get byte count and checksum information from end of buffer */
        !           686:        if(sscanf(inp, "%ld %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
        !           687:                return(CONV_BADFMT);
        !           688:        if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
        !           689:                return(CONV_BADCKSUM);
        !           690:        return(CONV_SUCCESS);
        !           691: }
        !           692: 
        !           693: /* Encode binary byte c into ASCII representation and place into *bufp,
        !           694:    advancing bufp */
        !           695: static
        !           696: byte_btoa(c, bufp)
        !           697:        register c;
        !           698:        char **bufp;
        !           699: {
        !           700:        Ceor ^= c;
        !           701:        Csum += c;
        !           702:        Csum += 1;
        !           703:        if ((Crot & 0x80000000)) {
        !           704:                Crot <<= 1;
        !           705:                Crot += 1;
        !           706:        } else {
        !           707:                Crot <<= 1;
        !           708:        }
        !           709:        Crot += c;
        !           710: 
        !           711:        word <<= 8;
        !           712:        word |= c;
        !           713:        if (bcount == 3) {
        !           714:                if (word == 0) {
        !           715:                        AddToBuf(bufp, 'z');
        !           716:                } else {
        !           717:                    register int tmp = 0;
        !           718:                    register long int tmpword = word;
        !           719:                        
        !           720:                    if (tmpword < 0) {  
        !           721:                           /* Because some don't support unsigned long */
        !           722:                        tmp = 32;
        !           723:                        tmpword -= (long)(85 * 85 * 85 * 85 * 32);
        !           724:                    }
        !           725:                    if (tmpword < 0) {
        !           726:                        tmp = 64;
        !           727:                        tmpword -= (long)(85 * 85 * 85 * 85 * 32);
        !           728:                    }
        !           729:                    AddToBuf(bufp,
        !           730:                         EN((tmpword / (long)(85 * 85 * 85 * 85)) + tmp));
        !           731:                    tmpword %= (long)(85 * 85 * 85 * 85);
        !           732:                    AddToBuf(bufp, EN(tmpword / (85 * 85 * 85)));
        !           733:                    tmpword %= (85 * 85 * 85);
        !           734:                    AddToBuf(bufp, EN(tmpword / (85 * 85)));
        !           735:                    tmpword %= (85 * 85);
        !           736:                    AddToBuf(bufp, EN(tmpword / 85));
        !           737:                    tmpword %= 85;
        !           738:                    AddToBuf(bufp, EN(tmpword));
        !           739:                }
        !           740:                bcount = 0;
        !           741:        } else {
        !           742:                bcount += 1;
        !           743:        }
        !           744: }
        !           745: 
        !           746: 
        !           747: /*
        !           748:  * Encode the binary data from inbuf, of length inbuflen, into a
        !           749:  * null-terminated ASCII representation in outbuf, not to exceed outbuflen
        !           750:  * bytes. Return success/failure status
        !           751:  */
        !           752: int
        !           753: btoa(inbuf, inbuflen, outbuf, outbuflen)
        !           754:        char *inbuf;
        !           755:        int inbuflen;
        !           756:        char *outbuf;
        !           757:        int outbuflen;
        !           758: {
        !           759:        long int inc, nb;
        !           760:        long int oeor, osum, orot;
        !           761:        char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen -1];
        !           762: 
        !           763:        Ceor = Csum = Crot = word = bcount = 0;
        !           764:        for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) {
        !           765:                byte_btoa((unsigned char) (*inp), &outp);
        !           766:                if (outp >= endoutp)
        !           767:                        return(CONV_OVERFLOW);
        !           768:        }
        !           769:        while (bcount != 0) {
        !           770:                byte_btoa(0, &outp);
        !           771:                if (outp >= endoutp)
        !           772:                        return(CONV_OVERFLOW);
        !           773:        }
        !           774:        /* Put byte count and checksum information at end of buffer, delimited
        !           775:           by 'x' */
        !           776:        (void) sprintf(outp, "x %ld %lx %lx %lx", inbuflen, Ceor, Csum, Crot);
        !           777:        if (&outp[strlen(outp) - 1] >= endoutp)
        !           778:                return(CONV_OVERFLOW);
        !           779:        else
        !           780:                return(CONV_SUCCESS);
        !           781: }
        !           782: #endif ALLOW_T_UNSPEC

unix.superglobalmegacorp.com

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