diff options
Diffstat (limited to 'usr.sbin/named/db_dump.c')
-rw-r--r-- | usr.sbin/named/db_dump.c | 919 |
1 files changed, 0 insertions, 919 deletions
diff --git a/usr.sbin/named/db_dump.c b/usr.sbin/named/db_dump.c deleted file mode 100644 index e38719d..0000000 --- a/usr.sbin/named/db_dump.c +++ /dev/null @@ -1,919 +0,0 @@ -#if !defined(lint) && !defined(SABER) -static char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91"; -static char rcsid[] = "$Id: db_dump.c,v 1.5 1996/01/07 05:48:21 peter Exp $"; -#endif /* not lint */ - -/* - * ++Copyright++ 1986, 1988, 1990 - * - - * Copyright (c) 1986, 1988, 1990 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - - * --Copyright-- - */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <netinet/in.h> -#ifdef ISO -#include <netiso/iso.h> -#endif -#include <arpa/nameser.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <stdio.h> -#include <syslog.h> -#include <resolv.h> -#include <errno.h> - -#include "named.h" - -static int scan_root __P((struct hashbuf *)); -static const char *MkCredStr __P((int)); - -#ifdef ALLOW_T_UNSPEC -static void putbyte __P((int, char **)); -#endif - -/* - * Dump current cache in a format similar to RFC 883. - * - * We try to be careful and determine whether the operation succeeded - * so that the new cache file can be installed. - */ - -void -doachkpt() -{ - FILE *fp; - char tmpcheckfile[256]; - - /* nowhere to checkpoint cache... */ - if (cache_file == NULL) { - dprintf(3, (ddt, "skipping doachkpt (cache_file == NULL)\n")); - return; - } - - dprintf(3, (ddt, "doachkpt()\n")); - - (void) sprintf(tmpcheckfile, "%s.chk", cache_file); - if ((fp = fopen(tmpcheckfile, "w")) == NULL) { - dprintf(3, (ddt, - "doachkpt(can't open %s for write)\n", tmpcheckfile)); - return; - } - - (void) gettime(&tt); - fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec)); - fflush(fp); - if (ferror(fp)) { - dprintf(3, (ddt, "doachkpt(write to checkpoint file failed)\n")); - return; - } - - if (fcachetab != NULL) { - int n = scan_root(hashtab); - - if (n < MINROOTS) { - syslog(LOG_NOTICE, "%d root hints... (too low)", n); - fprintf(fp, "; ---- Root hint cache dump ----\n"); - (void) db_dump(fcachetab, fp, DB_Z_CACHE, ""); - } - } - - if (hashtab != NULL) { - fprintf(fp, "; ---- Cache dump ----\n"); - if (db_dump(hashtab, fp, DB_Z_CACHE, "") == NODBFILE) { - dprintf(3, (ddt, "doachkpt(checkpoint failed)\n")); - (void) my_fclose(fp); - return; - } - } - - if (my_fclose(fp) == EOF) { - return; - } - - if (rename(tmpcheckfile, cache_file)) { - dprintf(3, (ddt, "doachkpt(install %s to %s failed, %d)\n", - tmpcheckfile, cache_file, errno)); - } -} - -/* - * What we do is scan the root hint cache to make sure there are at least - * MINROOTS root pointers with non-0 TTL's so that the checkpoint will not - * lose the root. Failing this, all pointers are written out w/ TTL ~0 - * (root pointers timed out and prime_cache() not done or failed). - */ - -static int -scan_root(htp) - struct hashbuf *htp; -{ - register struct databuf *dp; - register struct namebuf *np; - struct timeval soon; - int roots = 0; - - dprintf(1, (ddt, "scan_root(0x%lx)\n", (u_long)htp)); - - /* metric by which we determine whether a root NS pointer is still */ - /* valid (will be written out if we do a dump). we also add some */ - /* time buffer for safety... */ - (void) gettime(&soon); - soon.tv_sec += TIMBUF; - - for (np = htp->h_tab[0]; np != NULL; np = np->n_next) { - if (np->n_dname[0] == '\0') { - dp = np->n_data; - while (dp != NULL) { - if (dp->d_type == T_NS && - dp->d_ttl > soon.tv_sec) { - roots++; - if (roots >= MINROOTS) - return (roots); - } - dp = dp->d_next; - } - } - } - return (roots); -} - -#ifdef notdef -mark_cache(htp, ttl) - struct hashbuf *htp; - int ttl; -{ - register struct databuf *dp; - register struct namebuf *np; - struct namebuf **npp, **nppend; - struct timeval soon; - - dprintf(1, (ddt, "mark_cache()\n")); - - (void) gettime(&soon); - soon.tv_sec += TIMBUF; - - npp = htp->h_tab; - nppend = npp + htp->h_size; - while (npp < nppend) { - for (np = *npp++; np != NULL; np = np->n_next) { - if (np->n_data == NULL) - continue; - for (dp = np->n_data; dp != NULL; dp = dp->d_next) { - if (dp->d_ttl < soon.tv_sec) - dp->d_ttl = ttl; - } - } - } - - npp = htp->h_tab; - nppend = npp + htp->h_size; - while (npp < nppend) { - for (np = *npp++; np != NULL; np = np->n_next) { - if (np->n_hash == NULL) - continue; - mark_cache(np->n_hash, ttl); - } - } -} -#endif /* notdef */ - -/* - * Dump current data base in a format similar to RFC 883. - */ - -void -doadump() -{ - FILE *fp; - - dprintf(3, (ddt, "doadump()\n")); - syslog(LOG_NOTICE, "dumping nameserver data\n"); - - if ((fp = fopen(dumpfile, "w")) == NULL) - return; - gettime(&tt); - fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec)); - if (zones && nzones) - zt_dump(fp); - fputs( -"; Note: Cr=(auth,answer,addtnl,cache) tag only shown for non-auth RR's\n", - fp); - fputs( -"; Note: NT=milliseconds for any A RR which we've used as a nameserver\n", - fp); - fprintf(fp, "; --- Cache & Data ---\n"); - if (hashtab != NULL) - (void) db_dump(hashtab, fp, DB_Z_ALL, ""); - fprintf(fp, "; --- Hints ---\n"); - if (fcachetab != NULL) - (void) db_dump(fcachetab, fp, DB_Z_ALL, ""); - (void) my_fclose(fp); - syslog(LOG_NOTICE, "finished dumping nameserver data\n"); -} - -#ifdef ALLOW_UPDATES -/* Create a disk database to back up zones - */ -void -zonedump(zp) - register struct zoneinfo *zp; -{ - FILE *fp; - char *fname; - struct hashbuf *htp; - char *op; - struct stat st; - - /* Only dump zone if there is a cache specified */ - if (zp->z_source && *(zp->z_source)) { - dprintf(1, (ddt, "zonedump(%s)\n", zp->z_source)); - - if ((fp = fopen(zp->z_source, "w")) == NULL) - return; - if (op = strchr(zp->z_origin, '.')) - op++; - gettime(&tt); - htp = hashtab; - if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) { - db_dump(htp, fp, zp-zones, (op == NULL ? "" : op)); - zp->z_flags &= ~Z_CHANGED; /* Checkpointed */ - } - (void) my_fclose(fp); - if (stat(zp->z_source, &st) == 0) - zp->z_ftime = st.st_mtime; - } else { - dprintf(1, (ddt, "zonedump: no zone to dump\n")); - } -} -#endif - -int -zt_dump(fp) - FILE *fp; -{ - register struct zoneinfo *zp; - - fprintf(fp, ";; ++zone table++\n"); - for (zp = &zones[1]; zp < &zones[nzones]; zp++) { - char *pre, buf[64]; - u_int cnt; - - if (!zp->z_origin) - continue; - - fprintf(fp, "; %s (type %d, class %d, source %s)\n", - zp->z_origin - ? (*zp->z_origin ? zp->z_origin : ".") - : "Nil", - zp->z_type, zp->z_class, - zp->z_source ? zp->z_source : "Nil"); - fprintf(fp, ";\ttime=%ld, lastupdate=%ld, serial=%u,\n", - zp->z_time, zp->z_lastupdate, zp->z_serial); - fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n", - zp->z_refresh, zp->z_retry, - zp->z_expire, zp->z_minimum); - fprintf(fp, ";\tftime=%ld, xaddr=[%s], state=%04x, pid=%d\n", - zp->z_ftime, inet_ntoa(zp->z_xaddr), - zp->z_flags, (int)zp->z_xferpid); - sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt); - pre = buf; - for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { - fprintf(fp, "%s[%s]", pre, inet_ntoa(zp->z_addr[cnt])); - pre = ", "; - } - if (zp->z_addrcnt) - fputc('\n', fp); -#ifdef BIND_NOTIFY - if (zp->z_notifylist) { - register struct notify *ap; - - for (ap = zp->z_notifylist; ap; ap = ap->next) - fprintf(fp, ";\tNotify [%s] %s", - inet_ntoa(ap->addr), - ctime(&ap->last)); - } -#endif - } - fprintf(fp, ";; --zone table--\n"); - return (0); -} - -int -db_dump(htp, fp, zone, origin) - struct hashbuf *htp; - FILE *fp; - int zone; - char *origin; -{ - register struct databuf *dp = NULL; - register struct namebuf *np; - struct namebuf **npp, **nppend; - char dname[MAXDNAME]; - u_int32_t n; - u_int32_t addr; - int j, i; -#ifdef ISO - struct iso_addr isoa; -#endif - register u_char *cp; - u_char *end; - char *proto, *sep; - int found_data = 0, tab, printed_origin = 0; - - npp = htp->h_tab; - nppend = npp + htp->h_size; - while (npp < nppend) { - for (np = *npp++; np != NULL; np = np->n_next) { - if (np->n_data == NULL) - continue; - /* Blecch - can't tell if there is data here for the - * right zone, so can't print name yet - */ - found_data = 0; - /* we want a snapshot in time... */ - for (dp = np->n_data; dp != NULL; dp = dp->d_next) { - /* Is the data for this zone? */ - if (zone != DB_Z_ALL && dp->d_zone != zone) - continue; - if (dp->d_zone == DB_Z_CACHE && - dp->d_ttl <= tt.tv_sec && - (dp->d_flags & DB_F_HINT) == 0) - continue; - if (!printed_origin) { - fprintf(fp, "$ORIGIN %s.\n", origin); - printed_origin++; - } - tab = 0; -#ifdef NCACHE - if (dp->d_rcode == NXDOMAIN || - dp->d_rcode == NOERROR_NODATA) { - fputc(';', fp); - } else if (found_data == 0 || found_data == 1) { - found_data = 2; - } -#endif /*NCACHE*/ - if (found_data == 0 || found_data == 2) { - if (np->n_dname[0] == 0) { - if (origin[0] == 0) - fprintf(fp, ".\t"); - else - fprintf(fp, ".%s.\t", origin); /* ??? */ - } else - fprintf(fp, "%s\t", np->n_dname); - if (strlen(np->n_dname) < (size_t)8) - tab = 1; - found_data++; - } else { - (void) putc('\t', fp); - tab = 1; - } - if (dp->d_zone == DB_Z_CACHE) { - if (dp->d_flags & DB_F_HINT - && (int32_t)(dp->d_ttl - tt.tv_sec) - < DB_ROOT_TIMBUF) - fprintf(fp, "%d\t", DB_ROOT_TIMBUF); - else - fprintf(fp, "%d\t", - (int)(dp->d_ttl - tt.tv_sec)); - } else if (dp->d_ttl != 0 && - dp->d_ttl != zones[dp->d_zone].z_minimum) - fprintf(fp, "%d\t", (int)dp->d_ttl); - else if (tab) - (void) putc('\t', fp); - fprintf(fp, "%s\t%s\t", - p_class(dp->d_class), - p_type(dp->d_type)); - cp = (u_char *)dp->d_data; - sep = "\t;"; -#ifdef NCACHE -#ifdef RETURNSOA - if (dp->d_rcode == NOERROR_NODATA) { - fprintf(fp, "NODATA%s-$", sep); - goto eoln; - } -#else - if (dp->d_rcode == NXDOMAIN || - dp->d_rcode == NOERROR_NODATA) { - fprintf(fp, "%s%s-$", - (dp->d_rcode == NXDOMAIN) - ?"NXDOMAIN" :"NODATA", - sep); - goto eoln; - } -#endif -#endif - /* - * Print type specific data - */ - switch (dp->d_type) { - case T_A: - switch (dp->d_class) { - case C_IN: - case C_HS: - GETLONG(n, cp); - n = htonl(n); - fputs(inet_ntoa(*(struct in_addr *)&n), - fp); - break; - } - if (dp->d_nstime) { - fprintf(fp, "%sNT=%d", - sep, dp->d_nstime); - sep = " "; - } - break; - case T_CNAME: - case T_MB: - case T_MG: - case T_MR: - case T_PTR: - fprintf(fp, "%s.", cp); - break; - - case T_NS: - cp = (u_char *)dp->d_data; - if (cp[0] == '\0') - fprintf(fp, ".\t"); - else - fprintf(fp, "%s.", cp); - break; - - case T_HINFO: - case T_ISDN: - if ((n = *cp++) != '\0') { - fprintf(fp, "\"%.*s\"", (int)n, cp); - cp += n; - } else - fprintf(fp, "\"\""); - if ((n = *cp++) != '\0') - fprintf(fp, " \"%.*s\"", (int)n, cp); - else - fprintf(fp, " \"\""); - break; - - case T_SOA: - fprintf(fp, "%s.", cp); - cp += strlen((char *)cp) + 1; - fprintf(fp, " %s. (\n", cp); -#if defined(RETURNSOA) && defined(NCACHE) - if (dp->d_rcode == NXDOMAIN) - fputs(";", fp); -#endif - cp += strlen((char *)cp) + 1; - GETLONG(n, cp); - fprintf(fp, "\t\t%lu", (u_long)n); - GETLONG(n, cp); - fprintf(fp, " %lu", (u_long)n); - GETLONG(n, cp); - fprintf(fp, " %lu", (u_long)n); - GETLONG(n, cp); - fprintf(fp, " %lu", (u_long)n); - GETLONG(n, cp); - fprintf(fp, " %lu )", (u_long)n); -#if defined(RETURNSOA) && defined(NCACHE) - if (dp->d_rcode == NXDOMAIN) { - fprintf(fp,";%s.;NXDOMAIN%s-$",cp,sep); - } -#endif - break; - - case T_MX: - case T_AFSDB: - case T_RT: - GETSHORT(n, cp); - fprintf(fp, "%lu", (u_long)n); - fprintf(fp, " %s.", cp); - break; - - case T_PX: - GETSHORT(n, cp); - fprintf(fp, "%lu", (u_long)n); - fprintf(fp, " %s.", cp); - cp += strlen((char *)cp) + 1; - fprintf(fp, " %s.", cp); - break; - - case T_TXT: - case T_X25: - end = (u_char *)dp->d_data + dp->d_size; - (void) putc('"', fp); - while (cp < end) { - if ((n = *cp++) != '\0') { - for (j = n ; j > 0 && cp < end ; j--) - if (*cp == '\n') { - (void) putc('\\', fp); - (void) putc(*cp++, fp); - } else - (void) putc(*cp++, fp); - } - } - (void) fputs("\"", fp); - break; - -#ifdef ISO - case T_NSAP: - isoa.isoa_len = dp->d_size; - if (isoa.isoa_len > sizeof(isoa.isoa_genaddr)) - isoa.isoa_len = sizeof(isoa.isoa_genaddr); - bcopy(dp->d_data, isoa.isoa_genaddr, - isoa.isoa_len); - (void) fputs(iso_ntoa(&isoa), fp); - break; -#endif -#ifdef LOC_RR - case T_LOC: - (void) fputs(loc_ntoa(dp->d_data, NULL), fp); - break; -#endif /* LOC_RR */ - case T_UINFO: - fprintf(fp, "\"%s\"", cp); - break; - - case T_UID: - case T_GID: - if (dp->d_size == INT32SZ) { - GETLONG(n, cp); - } else { - n = -2; /* XXX - hack */ - } - fprintf(fp, "%u", n); - break; - - case T_WKS: - GETLONG(addr, cp); - addr = htonl(addr); - fputs(inet_ntoa(*(struct in_addr *)&addr), fp); - proto = protocolname(*cp); - cp += sizeof(char); - fprintf(fp, "%s ", proto); - i = 0; - while(cp < (u_char *)dp->d_data + dp->d_size) { - j = *cp++; - do { - if (j & 0200) - fprintf(fp, " %s", - servicename(i, proto)); - j <<= 1; - } while (++i & 07); - } - break; - - case T_MINFO: - case T_RP: - fprintf(fp, "%s.", cp); - cp += strlen((char *)cp) + 1; - fprintf(fp, " %s.", cp); - break; -#ifdef ALLOW_T_UNSPEC - case T_UNSPEC: - /* Dump binary data out in an ASCII-encoded - format */ - { - /* Allocate more than enough space: - * actually need 5/4 size + 20 or so - */ - int TmpSize = 2 * dp->d_size + 30; - char *TmpBuf = (char *) malloc(TmpSize); - if (TmpBuf == NULL) { - TmpBuf = "BAD_MALLOC"; - } - if (btoa(cp, dp->d_size, TmpBuf, TmpSize) - == CONV_OVERFLOW) { - TmpBuf = "OVERFLOW"; - } - fprintf(fp, "%s", TmpBuf); - } - break; -#endif /* ALLOW_T_UNSPEC */ - default: - fprintf(fp, "%s?d_type=%d?", - sep, dp->d_type); - sep = " "; - } - if (dp->d_cred < DB_C_ZONE) { - fprintf(fp, "%sCr=%s", - sep, MkCredStr(dp->d_cred)); - sep = " "; - } else { - fprintf(fp, "%sCl=%d", - sep, dp->d_clev); - sep = " "; - } -eoln: -#ifdef STATS - if (dp->d_ns) { - fprintf(fp, "%s[%s]", - sep, inet_ntoa(dp->d_ns->addr)); - sep = " "; - } -#endif - putc('\n', fp); - } - } - } - if (ferror(fp)) - return(NODBFILE); - - npp = htp->h_tab; - nppend = npp + htp->h_size; - while (npp < nppend) { - for (np = *npp++; np != NULL; np = np->n_next) { - if (np->n_hash == NULL) - continue; - getname(np, dname, sizeof(dname)); - if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE) - return(NODBFILE); - } - } - return(OK); -} - -static const char * -MkCredStr(cred) - int cred; -{ - static char badness[20]; - - switch (cred) { - case DB_C_ZONE: return "zone"; - case DB_C_AUTH: return "auth"; - case DB_C_ANSWER: return "answer"; - case DB_C_ADDITIONAL: return "addtnl"; - case DB_C_CACHE: return "cache"; - default: break; - } - sprintf(badness, "?%d?", cred); - return (badness); -} - -#ifdef ALLOW_T_UNSPEC -/* - * Subroutines to convert between 8 bit binary bytes and printable ASCII. - * Computes the number of bytes, and three kinds of simple checksums. - * Incoming bytes are collected into 32-bit words, then printed in base 85: - * exp(85,5) > exp(2,32) - * The ASCII characters used are between '!' and 'u'; - * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data. - * - * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for - * the atob/btoa programs, released with the compress program, in mod.sources. - * Modified by Mike Schwartz 8/19/86 for use in BIND. - */ - -/* Make sure global variable names are unique */ -#define Ceor T_UNSPEC_Ceor -#define Csum T_UNSPEC_Csum -#define Crot T_UNSPEC_Crot -#define word T_UNSPEC_word -#define bcount T_UNSPEC_bcount - -static int32_t Ceor, Csum, Crot, word, bcount; - -#define EN(c) ((int) ((c) + '!')) -#define DE(c) ((c) - '!') -#define AddToBuf(bufp, c) **bufp = c; (*bufp)++; -#define times85(x) ((((((x<<2)+x)<<2)+x)<<2)+x) - -/* Decode ASCII-encoded byte c into binary representation and - * place into *bufp, advancing bufp - */ -static int -byte_atob(c, bufp) - register c; - char **bufp; -{ - if (c == 'z') { - if (bcount != 0) - return(CONV_BADFMT); - else { - putbyte(0, bufp); - putbyte(0, bufp); - putbyte(0, bufp); - putbyte(0, bufp); - } - } else if ((c >= '!') && (c < ('!' + 85))) { - if (bcount == 0) { - word = DE(c); - ++bcount; - } else if (bcount < 4) { - word = times85(word); - word += DE(c); - ++bcount; - } else { - word = times85(word) + DE(c); - putbyte((int)((word >> 24) & 255), bufp); - putbyte((int)((word >> 16) & 255), bufp); - putbyte((int)((word >> 8) & 255), bufp); - putbyte((int)(word & 255), bufp); - word = 0; - bcount = 0; - } - } else - return(CONV_BADFMT); - return(CONV_SUCCESS); -} - -/* Compute checksum info and place c into *bufp, advancing bufp */ -static void -putbyte(c, bufp) - register c; - char **bufp; -{ - Ceor ^= c; - Csum += c; - Csum += 1; - if ((Crot & 0x80000000)) { - Crot <<= 1; - Crot += 1; - } else { - Crot <<= 1; - } - Crot += c; - AddToBuf(bufp, c); -} - -/* Read the ASCII-encoded data from inbuf, of length inbuflen, and convert - it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes; - outbuflen must be divisible by 4. (Note: this is because outbuf is filled - in 4 bytes at a time. If the actual data doesn't end on an even 4-byte - boundary, there will be no problem...it will be padded with 0 bytes, and - numbytes will indicate the correct number of bytes. The main point is - that since the buffer is filled in 4 bytes at a time, even if there is - not a full 4 bytes of data at the end, there has to be room to 0-pad the - data, so the buffer must be of size divisible by 4). Place the number of - output bytes in numbytes, and return a failure/success status */ -int -atob(inbuf, inbuflen, outbuf, outbuflen, numbytes) - char *inbuf; - int inbuflen; - char *outbuf; - int outbuflen; - int *numbytes; -{ - int inc, nb; - int32_t oeor, osum, orot; - char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen]; - - if ( (outbuflen % 4) != 0) - return(CONV_BADBUFLEN); - Ceor = Csum = Crot = word = bcount = 0; - for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) { - if (outp > endoutp) - return(CONV_OVERFLOW); - if (*inp == 'x') { - inp +=2; - break; - } else { - if (byte_atob(*inp, &outp) == CONV_BADFMT) - return(CONV_BADFMT); - } - } - - /* Get byte count and checksum information from end of buffer */ - if(sscanf(inp, "%ld %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4) - return(CONV_BADFMT); - if ((oeor != Ceor) || (osum != Csum) || (orot != Crot)) - return(CONV_BADCKSUM); - return(CONV_SUCCESS); -} - -/* Encode binary byte c into ASCII representation and place into *bufp, - advancing bufp */ -static void -byte_btoa(c, bufp) - register c; - char **bufp; -{ - Ceor ^= c; - Csum += c; - Csum += 1; - if ((Crot & 0x80000000)) { - Crot <<= 1; - Crot += 1; - } else { - Crot <<= 1; - } - Crot += c; - - word <<= 8; - word |= c; - if (bcount == 3) { - if (word == 0) { - AddToBuf(bufp, 'z'); - } else { - register int tmp = 0; - register int32_t tmpword = word; - - if (tmpword < 0) { - /* Because some don't support unsigned long */ - tmp = 32; - tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32); - } - if (tmpword < 0) { - tmp = 64; - tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32); - } - AddToBuf(bufp, - EN((tmpword / (int32_t)(85 * 85 * 85 * 85)) + tmp)); - tmpword %= (int32_t)(85 * 85 * 85 * 85); - AddToBuf(bufp, EN(tmpword / (85 * 85 * 85))); - tmpword %= (85 * 85 * 85); - AddToBuf(bufp, EN(tmpword / (85 * 85))); - tmpword %= (85 * 85); - AddToBuf(bufp, EN(tmpword / 85)); - tmpword %= 85; - AddToBuf(bufp, EN(tmpword)); - } - bcount = 0; - } else { - bcount += 1; - } -} - - -/* - * Encode the binary data from inbuf, of length inbuflen, into a - * null-terminated ASCII representation in outbuf, not to exceed outbuflen - * bytes. Return success/failure status - */ -static int -btoa(inbuf, inbuflen, outbuf, outbuflen) - char *inbuf; - int inbuflen; - char *outbuf; - int outbuflen; -{ - int32_t inc, nb; - int32_t oeor, osum, orot; - char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen -1]; - - Ceor = Csum = Crot = word = bcount = 0; - for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) { - byte_btoa((unsigned char) (*inp), &outp); - if (outp >= endoutp) - return(CONV_OVERFLOW); - } - while (bcount != 0) { - byte_btoa(0, &outp); - if (outp >= endoutp) - return(CONV_OVERFLOW); - } - /* Put byte count and checksum information at end of buffer, delimited - by 'x' */ - (void) sprintf(outp, "x %ld %lx %lx %lx", inbuflen, Ceor, Csum, Crot); - if (&outp[strlen(outp) - 1] >= endoutp) - return(CONV_OVERFLOW); - else - return(CONV_SUCCESS); -} -#endif /* ALLOW_T_UNSPEC */ |