Annotation of 43BSDTahoe/etc/named/db_update.c, revision 1.1.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.