|
|
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.