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