1: #ifndef lint 2: static char sccsid[] = "@(#)db_update.c 4.3 (Berkeley) 5/30/86"; 3: #endif 4: 5: /* 6: * Copyright (c) 1986 Regents of the University of California 7: * All Rights Reserved 8: */ 9: 10: #include <sys/types.h> 11: #include <sys/time.h> 12: #include <stdio.h> 13: #include <syslog.h> 14: #include <arpa/nameser.h> 15: #include "db.h" 16: 17: struct timeval tt; 18: extern FILE *ddt; 19: 20: /* 21: * Update data base. Flags control the action. 22: * Inverse query tables modified. 23: */ 24: db_update(name, odp, newdp, flags) 25: char name[]; 26: struct databuf *odp, *newdp; 27: int flags; 28: { 29: register struct namebuf *np; 30: register struct databuf *dp, *pdp; 31: struct hashbuf *htp = hashtab; 32: char *fname; 33: 34: #ifdef DEBUG 35: extern int debug; 36: 37: if (debug >= 3) 38: fprintf(ddt,"db_update( %s )\n",name); 39: #endif 40: np = nlookup(name, &htp, &fname, newdp != NULL); 41: if (np == NULL || fname != name) 42: return (NONAME); 43: if (odp != NULL) { 44: pdp = NULL; 45: for (dp = np->n_data; dp != NULL; pdp = dp, dp = dp->d_next) { 46: if (!match(dp, odp->d_class, odp->d_type)) 47: continue; 48: #ifdef DEBUG 49: if (debug >= 5) 50: fprintf(ddt,"f = %#x, size = %d, %d (%d)\n", 51: flags, odp->d_size, dp->d_size, 52: db_cmp(dp, odp)); 53: #endif 54: if ((flags & DB_NODATA) && 55: !db_cmp(dp, odp)) { 56: /* refresh ttl if cache entry */ 57: if (dp->d_zone == 0) { 58: if (dp->d_ttl < tt.tv_sec ) { 59: dp->d_ttl = odp->d_ttl; 60: return (OK); 61: } 62: if (dp->d_ttl < odp->d_ttl) 63: dp->d_ttl = odp->d_ttl; 64: } 65: return (DATAEXISTS); 66: } 67: if ((flags & DB_MEXIST) && db_cmp(dp, odp)) 68: return (NODATA); 69: if (flags & DB_DELETE) { 70: if (pdp == NULL) 71: np->n_data = dp->d_next; 72: else 73: pdp->d_next = dp->d_next; 74: rminv(dp); 75: (void) free((char *)dp); 76: } 77: } 78: } 79: if (newdp == NULL) 80: return (OK); 81: addinv(np, newdp); /* modify inverse query tables */ 82: 83: /* Add to end of list, generally preserving order */ 84: newdp->d_next = NULL; 85: if ((dp = np->n_data) == NULL) { 86: np->n_data = newdp; 87: return (OK); 88: } 89: while (dp->d_next != NULL) { 90: dp = dp->d_next; 91: /* NEEDS: check for duplicate WKS records and flag error */ 92: } 93: dp->d_next = newdp; 94: return (OK); 95: } 96: 97: struct invbuf *invtab[INVHASHSZ]; /* Inverse query hash table */ 98: 99: /* 100: * Add data 'dp' to inverse query tables for name 'np'. 101: */ 102: addinv(np, dp) 103: struct namebuf *np; 104: struct databuf *dp; 105: { 106: register struct invbuf *ip; 107: register int hval, i; 108: 109: switch (dp->d_type) { 110: case T_A: 111: case T_UID: 112: case T_GID: 113: break; 114: 115: default: 116: return; 117: } 118: 119: hval = dhash(dp->d_data, dp->d_size); 120: for (ip = invtab[hval]; ip != NULL; ip = ip->i_next) 121: for (i = 0; i < INVBLKSZ; i++) 122: if (ip->i_dname[i] == NULL) { 123: ip->i_dname[i] = np; 124: return; 125: } 126: ip = saveinv(); 127: ip->i_next = invtab[hval]; 128: invtab[hval] = ip; 129: ip->i_dname[0] = np; 130: } 131: 132: /* 133: * Remove data 'odp' from inverse query table. 134: */ 135: rminv(odp) 136: struct databuf *odp; 137: { 138: register struct invbuf *ip; 139: register struct databuf *dp; 140: struct namebuf *np; 141: register int i; 142: 143: for (ip = invtab[dhash(odp->d_data, odp->d_size)]; ip != NULL; 144: ip = ip->i_next) { 145: for (i = 0; i < INVBLKSZ; i++) { 146: if ((np = ip->i_dname[i]) == NULL) 147: break; 148: for (dp = np->n_data; dp != NULL; dp = dp->d_next) { 149: if (!match(dp, odp->d_class, odp->d_type)) 150: continue; 151: if (db_cmp(dp, odp)) 152: continue; 153: while (i < INVBLKSZ-1) { 154: ip->i_dname[i] = ip->i_dname[i+1]; 155: i++; 156: } 157: ip->i_dname[i] = NULL; 158: return; 159: } 160: } 161: } 162: } 163: 164: /* 165: * Compute hash value from data. 166: */ 167: dhash(dp, dlen) 168: char *dp; 169: int dlen; 170: { 171: register char *cp; 172: register unsigned hval; 173: register int n; 174: 175: n = dlen; 176: if (n > 8) 177: n = 8; 178: hval = 0; 179: for (cp = dp; --n >= 0; ) { 180: hval <<= 1; 181: hval += *cp++; 182: } 183: return (hval % INVHASHSZ); 184: } 185: 186: /* 187: * Compare data sections from databufs for equivalence. Must be case 188: * insensitive for some domain names. We assume that they are the 189: * same type when they are passed. Return 0 if equivalent, nonzero 190: * otherwise. 191: */ 192: 193: db_cmp(dp1, dp2) 194: register struct databuf *dp1, *dp2; 195: 196: { 197: register char *cp1, *cp2; 198: int len; 199: 200: if (dp1->d_size != dp2->d_size) 201: return(1); 202: switch (dp1->d_type) { 203: 204: case T_A: 205: case T_UID: 206: case T_GID: 207: case T_WKS: 208: case T_NULL: 209: return(bcmp(dp1->d_data, dp2->d_data, dp1->d_size)); 210: 211: case T_NS: 212: case T_CNAME: 213: case T_PTR: 214: case T_MB: 215: case T_MG: 216: case T_MR: 217: case T_UINFO: 218: return(cistrcmp(dp1->d_data, dp2->d_data)); 219: 220: case T_HINFO: 221: cp1 = dp1->d_data; 222: cp2 = dp2->d_data; 223: len = *cp1; 224: if (cistrncmp(++cp1, ++cp2, len)) 225: return(1); 226: cp1 += len; 227: cp2 += len; 228: len = *cp1; 229: return(cistrncmp(++cp1, ++cp2, len)); 230: 231: case T_SOA: 232: case T_MINFO: 233: if (cistrcmp(dp1->d_data, dp2->d_data)) 234: return(1); 235: cp1 = dp1->d_data + strlen(dp1->d_data) + 1; 236: cp2 = dp2->d_data + strlen(dp2->d_data) + 1; 237: if (dp1->d_type != T_SOA) 238: return(cistrcmp(cp1, cp2)); 239: if (cistrcmp(cp1, cp2)) 240: return(1); 241: cp1 += strlen(cp1) + 1; 242: cp2 += strlen(cp2) + 1; 243: return(bcmp(cp1, cp2, sizeof(u_long) * 5)); 244: 245: case T_MX: 246: cp1 = dp1->d_data; 247: cp2 = dp2->d_data; 248: if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ 249: return(1); 250: return(cistrcmp(cp1, cp2)); 251: 252: default: 253: return (1); 254: } 255: }