|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.