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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1986, 1990 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[] = "@(#)db_update.c        4.26 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include <sys/types.h>
        !            25: #include <sys/socket.h>
        !            26: #include <sys/time.h>
        !            27: #include <netinet/in.h>
        !            28: #include <stdio.h>
        !            29: #include <syslog.h>
        !            30: #include <arpa/nameser.h>
        !            31: #include "ns.h"
        !            32: #include "db.h"
        !            33: 
        !            34: extern struct timeval  tt;
        !            35: extern FILE *ddt;
        !            36: extern struct sockaddr_in from_addr;   /* Source addr of last packet */
        !            37: extern int needs_prime_cache;
        !            38: 
        !            39: int    max_cache_ttl = (7*24*60*60);   /* ONE_WEEK maximum ttl */
        !            40: int    min_cache_ttl = (5*60);         /* 5 minute minimum ttl */
        !            41: 
        !            42: /*
        !            43:  * Update data base. Flags control the action.
        !            44:  * Inverse query tables modified.
        !            45:  */
        !            46: db_update(name, odp, newdp, flags, htp)
        !            47:        char name[];
        !            48:        struct databuf *odp, *newdp;
        !            49:        int flags;
        !            50:        struct hashbuf *htp;
        !            51: {
        !            52:        register struct namebuf *np;
        !            53:        register struct databuf *dp, *pdp;
        !            54:        char *fname;
        !            55:         int foundRR = 0;
        !            56: 
        !            57: #ifdef DEBUG
        !            58:        if (debug >= 3)
        !            59:                fprintf(ddt,"db_update(%s, 0x%x, 0x%x, 0%o, 0x%x)%s\n",
        !            60:                    name, odp, newdp, flags, htp,
        !            61:                    (odp && (odp->d_flags&DB_F_HINT)) ? " hint":"" );
        !            62: #endif
        !            63:        np = nlookup(name, &htp, &fname, newdp != NULL);
        !            64:        if (np == NULL || fname != name)
        !            65:                return (NONAME);
        !            66: 
        !            67:         /* Reflect certain updates in hint cache also... */
        !            68:        /* Don't stick data we are authoritative for in hints. */
        !            69:         if (!(flags & DB_NOHINTS) && (odp != NULL) &&
        !            70:            (odp->d_zone <= 0) && !(odp->d_flags & DB_F_HINT) &&
        !            71:             ((name[0] == '\0' && odp->d_type == T_NS) ||
        !            72:             (odp->d_type == T_A)))
        !            73:         {
        !            74:                register struct databuf *dp;
        !            75: #ifdef DEBUG
        !            76:                if (debug >= 3)
        !            77:                        fprintf(ddt,"db_update: hint '%s' %d\n",
        !            78:                                name, odp->d_ttl);
        !            79: #endif
        !            80:                dp = savedata(odp->d_class, odp->d_type, odp->d_ttl,
        !            81:                        odp->d_data, odp->d_size);
        !            82:                dp->d_zone = DB_Z_CACHE;
        !            83:                dp->d_flags = DB_F_HINT;
        !            84:                if (db_update(name, dp,dp, (flags|DB_NOHINTS), fcachetab) != OK) {
        !            85: #ifdef DEBUG           
        !            86:                        if (debug > 2)
        !            87:                                fprintf(ddt, "db_update: hint %x freed\n", dp);
        !            88: #endif
        !            89:                        (void) free((char *)dp);
        !            90:                }
        !            91:         }
        !            92: 
        !            93:        if (odp != NULL) {
        !            94:                pdp = NULL;
        !            95:                for (dp = np->n_data; dp != NULL; ) {
        !            96:                        if (!match(dp, odp->d_class, odp->d_type)) {
        !            97:                                if ((dp->d_type == T_CNAME ||
        !            98:                                    odp->d_type == T_CNAME) &&
        !            99:                                    odp->d_mark == dp->d_mark &&
        !           100:                                    zones[odp->d_zone].z_type != Z_CACHE) {
        !           101:                                        syslog(LOG_ERR,
        !           102:                                "%s has CNAME and other data (illegal)\n",
        !           103:                                            name);
        !           104: #ifdef DEBUG
        !           105:                                        if (debug)
        !           106:                                            fprintf(ddt,
        !           107:                                "db_update: %s: CNAME and more (%d, %d)\n",
        !           108:                                                name, odp->d_type, dp->d_type);
        !           109: #endif
        !           110:                                }
        !           111:                                goto skip;
        !           112:                        }
        !           113: #ifdef DEBUG
        !           114:                        if (debug >= 5)
        !           115:                                fprintf(ddt,"db_update: flags = %#x, sizes = %d, %d (%d)\n",
        !           116:                                    flags, odp->d_size, dp->d_size,
        !           117:                                    db_cmp(dp, odp));
        !           118: #endif
        !           119:                        if (flags & DB_NOTAUTH && dp->d_zone) {
        !           120: #ifdef DEBUG
        !           121:                                if (debug)
        !           122:                                        fprintf(ddt,
        !           123:                                        "%s attempted update to auth zone %d '%s'\n",
        !           124:                                    inet_ntoa(from_addr.sin_addr),
        !           125:                                    dp->d_zone, zones[dp->d_zone].z_origin);
        !           126: #endif
        !           127:                                return (AUTH);
        !           128:                        }
        !           129:                        if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {
        !           130:                                /* refresh ttl if cache entry */
        !           131:                                if (dp->d_zone == 0) {
        !           132:                                        if (odp->d_zone != 0) { /* XXX */
        !           133:                                                /* changing cache->auth */
        !           134:                                                dp->d_zone = odp->d_zone;
        !           135:                                                dp->d_ttl = odp->d_ttl;
        !           136:                                                if (debug > 3)
        !           137:                                                        fprintf(ddt,
        !           138:                                "db_update: cache entry now in auth zone\n");
        !           139:                                                return (DATAEXISTS);
        !           140:                                        }
        !           141:                                        fixttl(odp);
        !           142:                                        if (odp->d_ttl > dp->d_ttl)
        !           143:                                                dp->d_ttl = odp->d_ttl;
        !           144: #ifdef DEBUG
        !           145:                                        if (debug >= 3)
        !           146:                                        fprintf(ddt,"db_update: new ttl %d, +%d\n",
        !           147:                                                dp->d_ttl, dp->d_ttl - tt.tv_sec);
        !           148: #endif
        !           149:                                }
        !           150:                                return (DATAEXISTS);
        !           151:                        }
        !           152:                        /*
        !           153:                         * If the old databuf has some data, check that the
        !           154:                         * data matches that in the new databuf (so UPDATED
        !           155:                         * will delete only the matching RR)
        !           156:                         */
        !           157:                        if (odp->d_size > 0) {
        !           158:                                if (db_cmp(dp, odp))
        !           159:                                        goto skip;
        !           160:                        }
        !           161:                        foundRR = 1;
        !           162:                        if (flags & DB_DELETE)
        !           163:                                dp = rm_datum(dp, np, pdp);
        !           164:                        else {
        !           165: skip:                          pdp = dp;
        !           166:                                dp = dp->d_next;
        !           167:                        }
        !           168:                }
        !           169:                 if (!foundRR) {
        !           170:                        if (flags & DB_DELETE)
        !           171:                                return(NODATA);
        !           172:                        if (flags & DB_MEXIST)
        !           173:                                return(NODATA);
        !           174:                }
        !           175:        }
        !           176:        if (newdp == NULL)
        !           177:                return (OK);
        !           178:        fixttl(newdp);
        !           179: #ifdef DEBUG
        !           180:         if (debug >= 3)
        !           181:                fprintf(ddt,"db_update: adding%s %x\n",
        !           182:                        (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp);
        !           183: #endif
        !           184:        if (!(newdp->d_flags & DB_F_HINT))
        !           185:                addinv(np, newdp);      /* modify inverse query tables */
        !           186: 
        !           187:        /* Add to end of list, generally preserving order */
        !           188:        newdp->d_next = NULL;
        !           189:        if ((dp = np->n_data) == NULL)  {
        !           190:                np->n_data = newdp;
        !           191:                return (OK);
        !           192:        }
        !           193:        /* XXX: need to check for duplicate WKS records and flag error */
        !           194:        while (dp->d_next != NULL) {
        !           195:                if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
        !           196:                        return (DATAEXISTS);
        !           197:                dp = dp->d_next;
        !           198:        }
        !           199:        if ((flags & DB_NODATA) && !db_cmp(dp, newdp))
        !           200:                return (DATAEXISTS);
        !           201:        dp->d_next = newdp;
        !           202:        return (OK);
        !           203: }
        !           204: 
        !           205: fixttl(dp)
        !           206: register struct databuf *dp;
        !           207: {
        !           208:        if (dp->d_zone == 0 && !(dp->d_flags & DB_F_HINT)) {
        !           209:                if (dp->d_ttl <= tt.tv_sec)
        !           210:                        return;
        !           211:                else if (dp->d_ttl < tt.tv_sec+min_cache_ttl)
        !           212:                        dp->d_ttl = tt.tv_sec+min_cache_ttl;
        !           213:                else if (dp->d_ttl > tt.tv_sec+max_cache_ttl)
        !           214:                        dp->d_ttl = tt.tv_sec+max_cache_ttl;
        !           215:        }
        !           216:        return;
        !           217: }
        !           218: 
        !           219: struct invbuf *invtab[INVHASHSZ];      /* Inverse query hash table */
        !           220: 
        !           221: /*
        !           222:  * Add data 'dp' to inverse query tables for name 'np'.
        !           223:  */
        !           224: addinv(np, dp)
        !           225:        struct namebuf *np;
        !           226:        struct databuf *dp;
        !           227: {
        !           228:        register struct invbuf *ip;
        !           229:        register int hval, i;
        !           230: 
        !           231:        switch (dp->d_type) {
        !           232:        case T_A:
        !           233:        case T_UID:
        !           234:        case T_GID:
        !           235:                break;
        !           236: 
        !           237:        default:
        !           238:                return;
        !           239:        }
        !           240: 
        !           241:        hval = dhash(dp->d_data, dp->d_size);
        !           242:        for (ip = invtab[hval]; ip != NULL; ip = ip->i_next)
        !           243:                for (i = 0; i < INVBLKSZ; i++)
        !           244:                        if (ip->i_dname[i] == NULL) {
        !           245:                                ip->i_dname[i] = np;
        !           246:                                return;
        !           247:                        }
        !           248:        ip = saveinv();
        !           249:        ip->i_next = invtab[hval];
        !           250:        invtab[hval] = ip;
        !           251:        ip->i_dname[0] = np;
        !           252: }
        !           253: 
        !           254: /*
        !           255:  * Remove data 'odp' from inverse query table.
        !           256:  */
        !           257: rminv(odp)
        !           258:        struct databuf *odp;
        !           259: {
        !           260:        register struct invbuf *ip;
        !           261:        register struct databuf *dp;
        !           262:        struct namebuf *np;
        !           263:        register int i;
        !           264: 
        !           265:        for (ip = invtab[dhash(odp->d_data, odp->d_size)]; ip != NULL;
        !           266:            ip = ip->i_next) {
        !           267:                for (i = 0; i < INVBLKSZ; i++) {
        !           268:                        if ((np = ip->i_dname[i]) == NULL)
        !           269:                                break;
        !           270:                        for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
        !           271:                                if (!match(dp, odp->d_class, odp->d_type))
        !           272:                                        continue;
        !           273:                                if (db_cmp(dp, odp))
        !           274:                                        continue;
        !           275:                                while (i < INVBLKSZ-1) {
        !           276:                                        ip->i_dname[i] = ip->i_dname[i+1];
        !           277:                                        i++;
        !           278:                                }
        !           279:                                ip->i_dname[i] = NULL;
        !           280:                                return;
        !           281:                        }
        !           282:                }
        !           283:        }
        !           284: }
        !           285: 
        !           286: /*
        !           287:  * Compute hash value from data.
        !           288:  */
        !           289: dhash(dp, dlen)
        !           290:        char *dp;
        !           291:        int dlen;
        !           292: {
        !           293:        register char *cp;
        !           294:        register unsigned hval;
        !           295:        register int n;
        !           296: 
        !           297:        n = dlen;
        !           298:        if (n > 8)
        !           299:                n = 8;
        !           300:        hval = 0;
        !           301:        for (cp = dp; --n >= 0; ) {
        !           302:                hval <<= 1;
        !           303:                hval += *cp++;
        !           304:        }
        !           305:        return (hval % INVHASHSZ);
        !           306: }
        !           307: 
        !           308: /*
        !           309:  * Compare type, class and data from databufs for equivalence.
        !           310:  * Must be case insensitive for some domain names.
        !           311:  * Return 0 if equivalent, nonzero otherwise.
        !           312:  */
        !           313: db_cmp(dp1, dp2)
        !           314:        register struct databuf *dp1, *dp2;
        !           315: 
        !           316: {
        !           317:        register char *cp1, *cp2;
        !           318:        int len;
        !           319: 
        !           320:        if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class)
        !           321:                return(1);
        !           322:        if (dp1->d_size != dp2->d_size)
        !           323:                return(1);
        !           324:        if (dp1->d_mark != dp2->d_mark)
        !           325:                return(1);              /* old and new RR's are distinct */
        !           326:        switch (dp1->d_type) {
        !           327: 
        !           328:        case T_A:
        !           329:        case T_UID:
        !           330:        case T_GID:
        !           331:        case T_WKS:
        !           332:        case T_NULL:
        !           333: #ifdef ALLOW_T_UNSPEC
        !           334:         case T_UNSPEC:
        !           335: #endif ALLOW_T_UNSPEC
        !           336:                return(bcmp(dp1->d_data, dp2->d_data, dp1->d_size));
        !           337: 
        !           338:        case T_NS:
        !           339:        case T_CNAME:
        !           340:        case T_PTR:
        !           341:        case T_MB:
        !           342:        case T_MG:
        !           343:        case T_MR:
        !           344:        case T_UINFO:
        !           345:                return(strcasecmp(dp1->d_data, dp2->d_data));
        !           346: 
        !           347:        case T_HINFO:
        !           348:                cp1 = dp1->d_data;
        !           349:                cp2 = dp2->d_data;
        !           350:                len = *cp1;
        !           351:                if (strncasecmp(++cp1, ++cp2, len))
        !           352:                        return(1);
        !           353:                cp1 += len;
        !           354:                cp2 += len;
        !           355:                len = *cp1;
        !           356:                return(strncasecmp(++cp1, ++cp2, len));
        !           357: 
        !           358:        case T_SOA:
        !           359:        case T_MINFO:
        !           360:                if (strcasecmp(dp1->d_data, dp2->d_data))
        !           361:                        return(1);
        !           362:                cp1 = dp1->d_data + strlen(dp1->d_data) + 1;
        !           363:                cp2 = dp2->d_data + strlen(dp2->d_data) + 1;
        !           364:                if (dp1->d_type != T_SOA)
        !           365:                        return(strcasecmp(cp1, cp2));
        !           366:                if (strcasecmp(cp1, cp2))
        !           367:                        return(1);
        !           368:                cp1 += strlen(cp1) + 1;
        !           369:                cp2 += strlen(cp2) + 1;
        !           370:                return(bcmp(cp1, cp2, sizeof(u_long) * 5));
        !           371:        
        !           372:        case T_MX:
        !           373:                cp1 = dp1->d_data;
        !           374:                cp2 = dp2->d_data;
        !           375:                if (*cp1++ != *cp2++ || *cp1++ != *cp2++)       /* cmp prio */
        !           376:                        return(1);
        !           377:                return(strcasecmp(cp1, cp2));
        !           378: 
        !           379:        case T_TXT:
        !           380:                if (dp1->d_size != dp2->d_size)
        !           381:                        return(1);
        !           382:                return(bcmp(dp1->d_data, dp2->d_data, dp1->d_size));
        !           383: 
        !           384:        default:
        !           385:                return (1);
        !           386:        }
        !           387: }

unix.superglobalmegacorp.com

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