|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)db_load.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: /*
11: * Load data base from ascii backupfile. Format similar to RFC 883.
12: */
13:
14: #include <sys/types.h>
15: #include <sys/time.h>
16: #include <netinet/in.h>
17: #include <stdio.h>
18: #include <syslog.h>
19: #include <ctype.h>
20: #include <netdb.h>
21: #include <arpa/nameser.h>
22: #include "ns.h"
23: #include "db.h"
24:
25: extern char *index();
26:
27: /*
28: * Map class and type names to number
29: */
30: struct map {
31: char token[8];
32: int val;
33: };
34:
35: struct map m_class[] = {
36: "in", C_IN,
37: "any", C_ANY,
38: };
39: #define NCLASS (sizeof(m_class)/sizeof(struct map))
40:
41: struct map m_type[] = {
42: "a", T_A,
43: "ns", T_NS,
44: "cname", T_CNAME,
45: "soa", T_SOA,
46: "mb", T_MB,
47: "mg", T_MG,
48: "mr", T_MR,
49: "null", T_NULL,
50: "wks", T_WKS,
51: "ptr", T_PTR,
52: "hinfo", T_HINFO,
53: "minfo", T_MINFO,
54: "mx", T_MX,
55: "uinfo", T_UINFO,
56: "uid", T_UID,
57: "gid", T_GID,
58: "any", T_ANY,
59: };
60: #define NTYPE (sizeof(m_type)/sizeof(struct map))
61:
62: /*
63: * Parser token values
64: */
65: #define CURRENT 1
66: #define DOT 2
67: #define AT 3
68: #define DNAME 4
69: #define INCLUDE 5
70: #define ORIGIN 6
71:
72: int lineno = 1; /* current line number */
73:
74: /*
75: * Load the database from 'filename'. Origin is appended to all domain
76: * names in the file.
77: */
78: db_load(filename, in_origin, zone)
79: char *filename, *in_origin;
80: int zone;
81: {
82: register char *cp;
83: register struct map *mp;
84: char domain[MAXDNAME];
85: char origin[MAXDNAME];
86: char buf[BUFSIZ];
87: char data[MAXDATA];
88: char *op;
89: int class, type, ttl;
90: struct databuf *dp;
91: FILE *fp;
92: int slineno, i;
93: long n;
94:
95: #ifdef DEBUG
96: if (debug)
97: fprintf(ddt,"db_load(%s, %s, %d)\n", filename, in_origin, zone);
98: #endif
99:
100: (void) strcpy(origin, in_origin);
101: if ((fp = fopen(filename, "r")) == NULL) {
102: syslog(LOG_ERR, "%s: %m", filename);
103: return (NODBFILE);
104: }
105: lineno = 1;
106: domain[0] = '\0';
107: class = C_IN;
108: while ((n = gettoken(fp)) != EOF) {
109: switch ((int)n) {
110: case INCLUDE:
111: if (!getword(buf, sizeof(buf), fp)) /* file name */
112: break;
113: slineno = lineno;
114: (void) db_load(buf, origin, zone);
115: lineno = slineno;
116: continue;
117:
118: case ORIGIN:
119: (void) strcpy(buf, origin);
120: if (!getword(origin, sizeof(origin), fp))
121: break;
122: makename(origin, buf);
123: continue;
124:
125: case DNAME:
126: if (!getword(domain, sizeof(domain), fp))
127: break;
128: n = strlen(domain) - 1;
129: if (domain[n] == '.')
130: domain[n] = '\0';
131: else if (*origin) {
132: (void) strcat(domain, ".");
133: (void) strcat(domain, origin);
134: }
135: goto gotdomain;
136:
137: case AT:
138: (void) strcpy(domain, origin);
139: goto gotdomain;
140:
141: case DOT:
142: domain[0] = '\0';
143: /* fall thru ... */
144: case CURRENT:
145: gotdomain:
146: if (!getword(buf, sizeof(buf), fp))
147: break;
148: cp = buf;
149: if (isdigit(*cp)) {
150: n = 0;
151: do
152: n = n * 10 + (*cp++ - '0');
153: while (isdigit(*cp));
154: if (zone == 0) {
155: if (gettimeofday(&tt,
156: (struct timezone *)0) < 0)
157: syslog(LOG_ERR,
158: "gettimeofday failed: %m");
159: n += (long) tt.tv_sec;
160: }
161: ttl = n;
162: if (!getword(buf, sizeof(buf), fp))
163: break;
164: } else
165: ttl = 0;
166: for (mp = m_class; mp < m_class+NCLASS; mp++)
167: if (!cistrcmp(buf, mp->token)) {
168: class = mp->val;
169: (void) getword(buf, sizeof(buf), fp);
170: break;
171: }
172: for (mp = m_type; mp < m_type+NTYPE; mp++)
173: if (!cistrcmp(buf, mp->token)) {
174: type = mp->val;
175: goto fndtype;
176: }
177: #ifdef DEBUG
178: if (debug)
179: fprintf(ddt,"Unknown type: %s.\n", buf);
180: #endif
181: break;
182: fndtype:
183: if (!getword(buf, sizeof(buf), fp))
184: break;
185: #ifdef DEBUG
186: if (debug >= 3)
187: fprintf(ddt,"d='%s',c=%d,t=%d, ttl=%d, data='%s'\n",
188: domain, class, type, ttl, buf);
189: #endif
190: /*
191: * Convert the ascii data 'buf' to the proper format
192: * based on the type and pack into 'data'.
193: */
194: switch (type) {
195: case T_A:
196: n = ntohl((u_long)inet_addr((char *)buf));
197: putlong((u_long)n, data);
198: n = sizeof(u_long);
199: break;
200:
201: case T_HINFO:
202: n = strlen(buf);
203: if (n > 255) {
204: syslog(LOG_WARNING, "CPU too large (%d)",n);
205: n = 255;
206: }
207: data[0] = n;
208: bcopy(buf, (char *)data + 1, (int)n);
209: n++;
210: if (!getword(buf, sizeof(buf), fp))
211: break;
212: i = strlen(buf);
213: if (i > 255) {
214: syslog(LOG_WARNING, "OS too large (%d)", i);
215: i = 255;
216: }
217: data[n] = i;
218: bcopy(buf, data + n + 1, i);
219: n += i + 1;
220: break;
221:
222: case T_SOA:
223: case T_MINFO:
224: (void) strcpy(data, buf);
225: makename(data, origin);
226: cp = data + strlen(data) + 1;
227: if (!getword(cp, sizeof(data) - (cp - data),fp))
228: break;
229: makename(cp, origin);
230: cp += strlen(cp) + 1;
231: if (type == T_MINFO) {
232: n = cp - data;
233: break;
234: }
235: if (getnonblank(fp) != '(')
236: goto err;
237: putlong((u_long)(zones[zone].z_serial =
238: getnum(fp)), cp);
239: cp += sizeof(u_long);
240: putlong((u_long)(zones[zone].z_refresh =
241: getnum(fp)), cp);
242: cp += sizeof(u_long);
243: putlong((u_long)(zones[zone].z_retry =
244: getnum(fp)), cp);
245: cp += sizeof(u_long);
246: putlong ((u_long)(zones[zone].z_expire =
247: getnum(fp)), cp);
248: cp += sizeof(u_long);
249: putlong ((u_long)(zones[zone].z_minimum =
250: getnum(fp)), cp);
251: cp += sizeof(u_long);
252: n = cp - data;
253: if (getnonblank(fp) != ')')
254: goto err;
255: endline(fp);
256: break;
257:
258: case T_UID:
259: case T_GID:
260: n = 0;
261: cp = buf;
262: while (isdigit(*cp))
263: n = n * 10 + (*cp++ - '0');
264: if (cp == buf)
265: goto err;
266: putlong((u_long)n, data);
267: n = sizeof(long);
268: break;
269:
270: case T_WKS:
271: /* Address */
272: n = ntohl((u_long)inet_addr((char *)buf));
273: putlong((u_long)n, data);
274: data[sizeof(u_long)] = getprotocol(fp);
275: /* Protocol */
276: n = sizeof(u_long) + sizeof(char);
277: /* Services */
278: n = getservices((int)n, data, fp);
279: break;
280:
281: case T_NS:
282: case T_CNAME:
283: case T_MB:
284: case T_MG:
285: case T_MR:
286: case T_PTR:
287: (void) strcpy(data, buf);
288: makename(data, origin);
289: n = strlen(data) + 1;
290: break;
291:
292: case T_UINFO:
293: cp = index(buf, '&');
294: bzero(data, sizeof(data));
295: if ( cp != NULL) {
296: (void) strncpy(data, buf, cp - buf);
297: op = index(domain, '.');
298: if ( op != NULL)
299: (void) strncat(data,
300: domain,op-domain);
301: else
302: (void) strcat(data, domain);
303: (void) strcat(data, ++cp);
304: } else
305: (void) strcpy(data, buf);
306: n = strlen(data) + 1;
307: break;
308: case T_MX:
309: n = 0;
310: cp = buf;
311: while (isdigit(*cp))
312: n = n * 10 + (*cp++ - '0');
313: /* catch bad values */
314: if ((cp == buf) || (n & ~0xffff))
315: goto err;
316:
317: putshort((u_short)n, data);
318: cp = data + sizeof(u_short);
319:
320: if (!getword(buf, sizeof(buf), fp))
321: break;
322: (void) strcpy(cp,buf);
323: makename(cp, origin);
324: /* get pointer to place in data */
325: cp += strlen(cp) +1;
326:
327: /* now save length */
328: n = (cp - data);
329: break;
330:
331: default:
332: goto err;
333: }
334: dp = savedata(class, type, (u_long)ttl, data, (int)n);
335: dp->d_zone = zone;
336: if ((n = db_update(domain, dp, dp, DB_NODATA)) < 0) {
337: #ifdef DEBUG
338: if (debug && (n != DATAEXISTS))
339: fprintf(ddt,"update failed\n");
340: #endif
341: }
342: continue;
343: }
344: err:
345: syslog(LOG_ERR, "%s: line %d: database format error (%s)",
346: filename, lineno, buf);
347: (void) fclose(fp);
348: return (-1);
349: }
350: (void) fclose(fp);
351: return (OK);
352: }
353:
354: int gettoken(fp)
355: register FILE *fp;
356: {
357: register int c;
358: char op[32];
359:
360: for (;;) {
361: c = getc(fp);
362: top:
363: switch (c) {
364: case EOF:
365: return (EOF);
366:
367: case '$':
368: if (!getword(op, sizeof(op), fp))
369: return (EOF);
370: if (!cistrcmp("include", op))
371: return (INCLUDE);
372: if (!cistrcmp("origin", op))
373: return (ORIGIN);
374: printf("Unknown $ option: %s\n", op);
375: /* fall through... */
376:
377: case ';':
378: while ((c = getc(fp)) != EOF && c != '\n')
379: ;
380: goto top;
381:
382: case ' ':
383: case '\t':
384: return (CURRENT);
385:
386: case '.':
387: return (DOT);
388:
389: case '@':
390: return (AT);
391:
392: case '\n':
393: lineno++;
394: continue;
395:
396: default:
397: (void) ungetc(c, fp);
398: return (DNAME);
399: }
400: }
401: }
402:
403: /*
404: * Get next word, skipping blanks & comments.
405: */
406: getword(buf, size, fp)
407: char *buf;
408: int size;
409: FILE *fp;
410: {
411: register char *cp;
412: register int c;
413:
414: for (cp = buf; (c = getc(fp)) != EOF; ) {
415: if (isspace(c)) {
416: if (c == '\n')
417: lineno++;
418: if (cp != buf)
419: break;
420: continue;
421: }
422: if (c == ';') {
423: while ((c = getc(fp)) != EOF && c != '\n')
424: ;
425: if (c == '\n')
426: lineno++;
427: if (cp != buf)
428: break;
429: continue;
430: }
431: if (c == '"') {
432: while ((c = getc(fp)) != EOF && c != '"' && c != '\n') {
433: if (c == '\\') {
434: if ((c = getc(fp)) == EOF)
435: c = '\\';
436: if (c == '\n')
437: lineno++;
438: }
439: if (cp >= buf+size-1)
440: break;
441: *cp++ = c;
442: }
443: if (c == '\n') {
444: lineno++;
445: break;
446: }
447: continue;
448: }
449: if (c == '\\') {
450: if ((c = getc(fp)) == EOF)
451: c = '\\';
452: if (c == '\n')
453: lineno++;
454: }
455: if (cp >= buf+size-1)
456: break;
457: *cp++ = c;
458: }
459: *cp = '\0';
460: return (cp != buf);
461: }
462:
463: getw_b_nl(buf, size, fp)
464: char *buf;
465: int size;
466: FILE *fp;
467: {
468: register char *cp;
469: register int c;
470:
471: for (cp = buf; (c = getc(fp)) != EOF; ) {
472: if (isspace(c)) {
473: if (c == '\n') {
474: *cp = '\0';
475: return (0);
476: }
477: if (cp != buf)
478: break;
479: continue;
480: }
481: if (c == ';') {
482: while ((c = getc(fp)) != EOF && c != '\n')
483: ;
484: if (c == '\n')
485: lineno++;
486: if (cp != buf)
487: break;
488: continue;
489: }
490: if (cp >= buf+size-1)
491: break;
492: *cp++ = c;
493: }
494: *cp = '\0';
495: return (cp != buf);
496: }
497:
498: getnum(fp)
499: FILE *fp;
500: {
501: register int c, n;
502: int seendigit = 0;
503: int seendecimal = 0;
504:
505: for (n = 0; (c = getc(fp)) != EOF; ) {
506: if (isspace(c)) {
507: if (c == '\n')
508: lineno++;
509: if (seendigit)
510: break;
511: continue;
512: }
513: if (c == ';') {
514: while ((c = getc(fp)) != EOF && c != '\n')
515: ;
516: if (c == '\n')
517: lineno++;
518: if (seendigit)
519: break;
520: continue;
521: }
522: if (!isdigit(c)) {
523: if (c != '.') {
524: syslog(LOG_ERR, "line %d: expected a number",
525: lineno);
526: exit(1);
527: }
528: if (!seendigit)
529: n = 1;
530: if (seendecimal) {
531: syslog(LOG_ERR, "line %d: expected a number",
532: lineno);
533: exit(1);
534: } else {
535: n = n * 1000 ;
536: seendigit = 1;
537: seendecimal = 1;
538: }
539: continue;
540: }
541: n = n * 10 + (c - '0');
542: seendigit = 1;
543: }
544: return (n);
545: }
546:
547: getnonblank(fp)
548: FILE *fp;
549: {
550: register int c;
551:
552: while ( (c = getc(fp)) != EOF ) {
553: if (isspace(c)) {
554: if (c == '\n')
555: lineno++;
556: continue;
557: }
558: if (c == ';') {
559: while ((c = getc(fp)) != EOF && c != '\n')
560: ;
561: if (c == '\n')
562: lineno++;
563: continue;
564: }
565: return(c);
566: }
567: syslog(LOG_ERR, "line %d: unexpected EOF", lineno);
568: return (EOF);
569: }
570:
571: /*
572: * Take name and fix it according to following rules:
573: * "." means root.
574: * "@" means current origin.
575: * "name." means no changes.
576: * "name" means append origin.
577: */
578: makename(name, origin)
579: char *name, *origin;
580: {
581: int n;
582:
583: if (origin[0] == '.')
584: origin++;
585: n = strlen(name);
586: if (n == 1) {
587: if (name[0] == '.') {
588: name[0] = '\0';
589: return;
590: }
591: if (name[0] == '@') {
592: (void) strcpy(name, origin);
593: return;
594: }
595: }
596: if (n > 0) {
597: if (name[n - 1] == '.')
598: name[n - 1] = '\0';
599: else if (origin[0] != '\0') {
600: name[n] = '.';
601: (void) strcpy(name + n + 1, origin);
602: }
603: }
604: }
605:
606: endline(fp)
607: register FILE *fp;
608: {
609: register int c;
610: while (c = getc(fp))
611: if ((c == EOF) || (c == '\n')) {
612: (void) ungetc(c,fp);
613: break;
614: }
615: }
616:
617: #define MAXPORT 256
618: #define MAXLEN 24
619:
620: getprotocol(fp)
621: FILE *fp;
622: {
623: int k;
624: char b[MAXLEN];
625: struct protoent *proto;
626:
627: (void) getword(b, sizeof(b), fp);
628:
629: proto = getprotobyname(b);
630: if(proto == NULL) {
631: k = 0;
632: (void) sscanf(b,"%d",&k);
633: }
634: else
635: k = proto->p_proto;
636: return(k);
637: }
638:
639: int getservices(n, data, fp)
640: int n;
641: char *data;
642: FILE *fp;
643: {
644: int j, ch;
645: u_short k;
646: int maxl;
647: int bracket, eol;
648: char b[MAXLEN];
649: char bm[MAXPORT/8];
650: struct servent *service;
651:
652: for (j = 0; j < MAXPORT/8; j++)
653: bm[j] = 0;
654: maxl = 0;
655: bracket = eol = 0;
656: while (1) {
657: if (!getw_b_nl(b, sizeof(b), fp) && (!bracket)) {
658: if (strlen(b) == 0)
659: break;
660: eol++;
661: }
662: if ( b[0] == '(') {
663: bracket++;
664: continue;
665: }
666: if ( b[0] == ')') {
667: bracket = 0;
668: while ((ch = getc(fp)) != EOF && ch != '\n')
669: ;
670: break;
671: }
672: service = getservbyname(b, (char *)NULL);
673: if (service == NULL) {
674: k=0;
675: (void) sscanf(b,"%d",&k);
676: if (k == 0)
677: continue;
678: }
679: else
680: k = ntohs((u_short)service->s_port);
681: if ((k < MAXPORT) && (k)) {
682: bm[k/8] |= (0x80>>(k%8));
683: if (k > maxl)
684: maxl=k;
685: }
686: else
687: syslog(LOG_WARNING,"port no.(%d) too big\n",k);
688: if(eol)
689: break;
690: }
691: maxl = maxl/8+1;
692: bcopy(bm, data+n, maxl);
693: return(maxl+n);
694: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.