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

Defined functions

addinv defined in line 208; used 1 times
db_cmp defined in line 299; used 6 times
dhash defined in line 273; used 3 times
fixttl defined in line 189; used 2 times
rminv defined in line 241; used 1 times

Defined variables

max_cache_ttl defined in line 33; used 4 times
min_cache_ttl defined in line 34; used 2 times
sccsid defined in line 14; never used
Last modified: 1988-09-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4011
Valid CSS Valid XHTML 1.0 Strict