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