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

unix.superglobalmegacorp.com

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