|
|
1.1 root 1: /*-
2: * Copyright (c) 1988, 1990 The 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: * The original version of xfer by Kevin Dunlap.
20: * Completed and integrated with named by David Waitzman
21: * ([email protected]) 3/14/88.
22: * Modified by M. Karels and O. Kure 10-88.
23: */
24:
25: #ifndef lint
26: char copyright[] =
27: "@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\
28: All rights reserved.\n";
29: #endif /* not lint */
30:
31: #ifndef lint
32: static char sccsid[] = "@(#)named-xfer.c 4.15 (Berkeley) 7/24/90";
33: #endif /* not lint */
34:
35: #include <sys/types.h>
36: #include <sys/file.h>
37: #include <sys/stat.h>
38: #include <sys/socket.h>
39: #include <sys/uio.h>
40: #include <sys/signal.h>
41:
42: #include <netinet/in.h>
43: #include <net/if.h>
44: #include <netdb.h>
45: #include <arpa/inet.h>
46: #include <arpa/nameser.h>
47:
48: #include <errno.h>
49: #include <resolv.h>
50: #include <string.h>
51: #include <stdio.h>
52: #include <syslog.h>
53:
54: #define XFER /* modifies the ns.h include file */
55: #include "ns.h"
56: #include "pathnames.h"
57:
58: char *savestr();
59:
60: /* max length of data in RR data field */
61: #define MAXDATA 2048 /* from db.h */
62:
63: int debug = 0;
64: int quiet = 0;
65: int read_interrupted = 0;
66: struct zoneinfo zones; /* zone information */
67: struct timeval tt;
68:
69: static char *ddtfile = _PATH_TMPXFER;
70: static char *tmpname;
71: FILE *fp = 0, *ddt, *dbfp;
72: char *domain; /* domain being xfered */
73: int domain_len; /* strlen(domain) */
74:
75: main(argc, argv)
76: int argc;
77: char *argv[];
78: {
79: register struct zoneinfo *zp;
80: register struct hostent *hp;
81: char *dbfile = NULL, *tracefile = NULL, *tm = NULL;
82: int dbfd, ddtd, result, c;
83: u_long serial_no = 0;
84: extern char *optarg;
85: extern int optind, getopt();
86: u_short port = htons(NAMESERVER_PORT);
87:
88: (void) umask(022);
89: #ifdef LOG_DAEMON
90: openlog("named-xfer", LOG_PID|LOG_CONS, LOG_DAEMON);
91: #else
92: openlog("named-xfer", LOG_PID);
93: #endif
94: while ((c = getopt(argc, argv, "d:l:s:t:z:f:p:P:q")) != EOF)
95: switch (c) {
96: case 'd':
97: debug = atoi(optarg);
98: break;
99: case 'l':
100: ddtfile = (char *)malloc(strlen(optarg) +
101: sizeof(".XXXXXX") + 1);
102: (void) strcpy(ddtfile, optarg);
103: (void) strcat(ddtfile, ".XXXXXX");
104: break;
105: case 's':
106: serial_no = (u_long) atol(optarg);
107: break;
108: case 't':
109: tracefile = optarg;
110: break;
111: case 'z': /* zone == domain */
112: domain = optarg;
113: domain_len = strlen(domain);
114: break;
115: case 'f':
116: dbfile = optarg;
117: tmpname = (char *)malloc((unsigned)strlen(optarg) +
118: sizeof(".XXXXXX") + 1);
119: (void) strcpy(tmpname, optarg);
120: break;
121: case 'p':
122: port = htons((u_short)atoi(optarg));
123: break;
124: case 'P':
125: port = (u_short)atoi(optarg);
126: break;
127: case 'q':
128: quiet++;
129: break;
130: case '?':
131: default:
132: usage();
133: /* NOTREACHED */
134: }
135:
136: if (!domain || !dbfile || optind >= argc) {
137: usage();
138: /* NOTREACHED */
139: }
140: if (tracefile && (fp = fopen(tracefile, "w")) == NULL)
141: perror(tracefile);
142: (void) strcat(tmpname, ".XXXXXX");
143: /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */
144: if ((dbfd = mkstemp(tmpname)) == -1) {
145: perror(tmpname);
146: if (!quiet)
147: syslog(LOG_ERR, "can't make tmpfile (%s): %m\n",
148: tmpname);
149: exit(XFER_FAIL);
150: }
151: if (fchmod(dbfd, 0644) == -1) {
152: perror(tmpname);
153: if (!quiet)
154: syslog(LOG_ERR, "can't fchmod tmpfile (%s): %m\n",
155: tmpname);
156: exit(XFER_FAIL);
157: }
158: if ((dbfp = fdopen(dbfd, "r+")) == NULL) {
159: perror(tmpname);
160: if (!quiet)
161: syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname);
162: exit(XFER_FAIL);
163: }
164: #ifdef DEBUG
165: if (debug) {
166: /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */
167: if ((ddtd = mkstemp(ddtfile)) == -1) {
168: perror(ddtfile);
169: debug = 0;
170: } else if (fchmod(ddtd, 0644) == -1) {
171: perror(ddtfile);
172: debug = 0;
173: } else if ((ddt = fdopen(ddtd, "w")) == NULL) {
174: perror(ddtfile);
175: debug = 0;
176: } else {
177: #if defined(SYSV)
178: setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
179: #else
180: setlinebuf(ddt);
181: #endif
182: }
183: }
184: #endif
185: /*
186: * Ignore many types of signals that named (assumed to be our parent)
187: * considers important- if not, the user controlling named with
188: * signals usually kills us.
189: */
190: (void) signal(SIGHUP, SIG_IGN);
191: (void) signal(SIGSYS, SIG_IGN);
192: if (debug == 0) {
193: (void) signal(SIGINT, SIG_IGN);
194: (void) signal(SIGQUIT, SIG_IGN);
195: }
196: (void) signal(SIGIOT, SIG_IGN);
197:
198: #if defined(SIGUSR1) && defined(SIGUSR2)
199: (void) signal(SIGUSR1, SIG_IGN);
200: (void) signal(SIGUSR2, SIG_IGN);
201: #else SIGUSR1&&SIGUSR2
202: (void) signal(SIGEMT, SIG_IGN);
203: (void) signal(SIGFPE, SIG_IGN);
204: #endif SIGUSR1&&SIGUSR2
205:
206: #ifdef DEBUG
207: if (debug) (void)fprintf(ddt, "domain `%s' file `%s' ser no %lu \n",
208: domain, dbfile,serial_no);
209: #endif
210: buildservicelist();
211: buildprotolist();
212:
213: /* init zone data */
214:
215: zp = &zones;
216: zp->z_type = Z_SECONDARY;
217: zp->z_origin = domain;
218: zp->z_source = dbfile;
219: zp->z_addrcnt = 0;
220: #ifdef DEBUG
221: if (debug) {
222: (void)fprintf(ddt,"zone found (%d): ", zp->z_type);
223: if (zp->z_origin[0] == '\0')
224: (void)fprintf(ddt,"'.'");
225: else
226: (void)fprintf(ddt,"'%s'", zp->z_origin);
227: (void)fprintf(ddt,", source = %s\n", zp->z_source);
228: }
229: #endif
230: for (; optind != argc; optind++,zp->z_addrcnt++) {
231: tm = argv[optind];
232: zp->z_addr[zp->z_addrcnt].s_addr = inet_addr(tm);
233:
234: if (zp->z_addr[zp->z_addrcnt].s_addr == (unsigned)-1) {
235: hp = gethostbyname(tm);
236: if (hp == NULL) {
237: syslog(LOG_ERR, "uninterpretable server %s\n",
238: tm);
239: continue;
240: }
241: bcopy(hp->h_addr,
242: (char *)&zp->z_addr[zp->z_addrcnt].s_addr,
243: sizeof(zp->z_addr[zp->z_addrcnt].s_addr));
244: #ifdef DEBUG
245: if (debug)
246: (void)fprintf(ddt,", %s",tm);
247: #endif
248: }
249: if (zp->z_addrcnt >= NSMAX) {
250: zp->z_addrcnt = NSMAX;
251: #ifdef DEBUG
252: if (debug)
253: (void)fprintf(ddt, "\nns.h NSMAX reached\n");
254: #endif
255: break;
256: }
257: }
258: #ifdef DEBUG
259: if (debug) (void)fprintf(ddt," (addrcnt) = %d\n", zp->z_addrcnt);
260: #endif
261:
262: _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
263: result = getzone(zp, serial_no, port);
264: (void) fclose(dbfp);
265: switch (result) {
266:
267: case XFER_SUCCESS: /* ok exit */
268: if (rename(tmpname, dbfile) == -1) {
269: perror("rename");
270: if (!quiet)
271: syslog(LOG_ERR, "rename %s to %s: %m",
272: tmpname, dbfile);
273: exit(XFER_FAIL);
274: }
275: exit(XFER_SUCCESS);
276:
277: case XFER_UPTODATE: /* the zone was already uptodate */
278: (void) unlink(tmpname);
279: exit(XFER_UPTODATE);
280:
281: case XFER_TIMEOUT:
282: #ifdef DEBUG
283: if (!debug)
284: #endif
285: (void) unlink(tmpname);
286: exit(XFER_TIMEOUT); /* servers not reachable exit */
287:
288: case XFER_FAIL:
289: default:
290: #ifdef DEBUG
291: if (!debug)
292: #endif
293: (void) unlink(tmpname);
294: exit(XFER_FAIL); /* yuck exit */
295: }
296: }
297:
298: usage()
299: {
300: (void)fprintf(stderr,
301: "Usage: xfer\n\
302: \t-z zone_to_transfer\n\
303: \t-f db_file\n\
304: \t-s serial_no\n\
305: \t[-d debug_level]\n\
306: \t[-l debug_log_file (default %s)]\n\
307: \t[-t trace_file]\n\
308: \t[-p port]\n\
309: \tservers...\n", ddtfile);
310: exit(XFER_FAIL);
311: }
312:
313: int minimum_ttl = 0, got_soa = 0;
314: char prev_origin[MAXDNAME];
315: char prev_dname[MAXDNAME];
316:
317: getzone(zp, serial_no, port)
318: struct zoneinfo *zp;
319: u_long serial_no;
320: u_short port;
321: {
322: HEADER *hp;
323: u_short len;
324: u_long serial;
325: int s, n, l, cnt, soacnt, error = 0;
326: u_char *cp, *nmp, *eom, *tmp ;
327: u_char *buf = NULL;
328: int bufsize;
329: u_char name[MAXDNAME], name2[MAXDNAME];
330: struct sockaddr_in sin;
331: struct zoneinfo zp_start, zp_finish;
332: struct itimerval ival, zeroival;
333: extern VOID read_alarm();
334: struct sigvec sv, osv;
335: int ancount, aucount;
336: #ifdef DEBUG
337: if (debug)
338: (void)fprintf(ddt,"getzone() %s\n", zp->z_origin);
339: #endif
340: bzero((char *)&zeroival, sizeof(zeroival));
341: ival = zeroival;
342: ival.it_value.tv_sec = 120;
343: sv.sv_handler = read_alarm;
344: sv.sv_onstack = 0;
345: sv.sv_mask = ~0;
346: (void) sigvec(SIGALRM, &sv, &osv);
347:
348: strcpy(prev_origin, zp->z_origin);
349:
350: for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
351: error = 0;
352: if (buf == NULL) {
353: if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) {
354: syslog(LOG_ERR, "malloc(%u) failed",
355: 2 * PACKETSZ);
356: error++;
357: break;
358: }
359: bufsize = 2 * PACKETSZ;
360: }
361: bzero((char *)&sin, sizeof(sin));
362: sin.sin_family = AF_INET;
363: sin.sin_port = port;
364: sin.sin_addr = zp->z_addr[cnt];
365: if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
366: syslog(LOG_ERR, "socket: %m");
367: error++;
368: break;
369: }
370: #ifdef DEBUG
371: if (debug >= 2) {
372: (void)fprintf(ddt,"connecting to server #%d %s, %d\n",
373: cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
374: }
375: #endif
376: if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
377: (void) close(s);
378: error++;
379: #ifdef DEBUG
380: if (debug >= 2)
381: (void)fprintf(ddt, "connect failed, %s\n",
382: strerror(errno));
383: #endif
384: continue;
385: }
386: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
387: T_SOA, (char *)NULL, 0, NULL, buf, bufsize)) < 0) {
388: if (!quiet)
389: syslog(LOG_ERR, "zone %s: res_mkquery T_SOA failed",
390: zp->z_origin);
391: (void) close(s);
392: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
393: return XFER_FAIL;
394: }
395: /*
396: * Send length & message for zone transfer
397: */
398: if (writemsg(s, buf, n) < 0) {
399: (void) close(s);
400: error++;
401: #ifdef DEBUG
402: if (debug >= 2)
403: (void)fprintf(ddt,"writemsg failed\n");
404: #endif
405: continue;
406: }
407: /*
408: * Get out your butterfly net and catch the SOA
409: */
410: cp = buf;
411: l = sizeof(u_short);
412: read_interrupted = 0;
413: while (l > 0) {
414: #ifdef DEBUG
415: if (debug > 10) (void)fprintf(ddt,"Before setitimer\n");
416: #endif
417: (void) setitimer(ITIMER_REAL, &ival,
418: (struct itimerval *)NULL);
419: #ifdef DEBUG
420: if (debug > 10) (void)fprintf(ddt,"Before recv(l = %d)\n",n);
421: #endif
422: errno = 0;
423: if ((n = recv(s, (char *)cp, l, 0)) > 0) {
424: cp += n;
425: l -= n;
426: } else {
427: #ifdef DEBUG
428: if (debug > 10)
429: (void)fprintf(ddt,
430: "bad recv->%d, errno= %d, read_interrupt=%d\n", n, errno, read_interrupted);
431: #endif
432: if (n == -1 && errno == EINTR
433: && !read_interrupted)
434: continue;
435: error++;
436: break;
437: }
438: }
439:
440: (void) setitimer(ITIMER_REAL, &zeroival,
441: (struct itimerval *)NULL);
442: if (error) {
443: (void) close(s);
444: continue;
445: }
446: if ((len = htons(*(u_short *)buf)) == 0) {
447: (void) close(s);
448: continue;
449: }
450: if (len > bufsize) {
451: if ((buf = (u_char *)realloc(buf, len)) == NULL) {
452: syslog(LOG_ERR,
453: "malloc(%u) failed for SOA from server %s, zone %s\n",
454: len, inet_ntoa(sin.sin_addr), zp->z_origin);
455: (void) close(s);
456: continue;
457: }
458: bufsize = len;
459: }
460: l = len;
461: cp = buf;
462: while (l > 0) {
463: (void) setitimer(ITIMER_REAL, &ival,
464: (struct itimerval *)NULL);
465: errno = 0;
466: if ((n = recv(s, (char *)cp, l, 0)) > 0) {
467: cp += n;
468: l -= n;
469: } else {
470: if (errno == EINTR && !read_interrupted)
471: continue;
472: error++;
473: #ifdef DEBUG
474: if (debug > 10)
475: (void)fprintf(ddt,
476: "recv failed: n= %d, errno = %d\n",
477: n, errno);
478: #endif
479: break;
480: }
481: }
482: (void) setitimer(ITIMER_REAL, &zeroival,
483: (struct itimerval *)NULL);
484: if (error) {
485: (void) close(s);
486: continue;
487: }
488: #ifdef DEBUG
489: if (debug >= 3) {
490: (void)fprintf(ddt,"len = %d\n", len);
491: fp_query(buf, ddt);
492: }
493: #endif DEBUG
494: hp = (HEADER *) buf;
495: ancount = ntohs(hp->ancount);
496: aucount = ntohs(hp->nscount);
497:
498: /*
499: * close socket if:
500: * 1) rcode != NOERROR
501: * 2) not an authority response
502: * 3) both the number of answers and authority count < 1)
503: */
504: if (hp->rcode != NOERROR || !(hp->aa) ||
505: (ancount < 1 && aucount < 1)) {
506: if (!quiet)
507: syslog(LOG_ERR,
508: "%s from %s, zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
509: "bad response to SOA query",
510: inet_ntoa(sin.sin_addr), zp->z_origin,
511: hp->rcode, hp->aa, ancount, aucount);
512: #ifdef DEBUG
513: if (debug)
514: fprintf(ddt,
515: "%s from %s, zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
516: "bad response to SOA query",
517: inet_ntoa(sin.sin_addr), zp->z_origin,
518: hp->rcode, hp->aa, ancount, aucount);
519: #endif DEBUG
520: (void) close(s);
521: error++;
522: continue;
523: }
524: zp_start = *zp;
525: if (len < sizeof(HEADER) + QFIXEDSZ) {
526: badsoa:
527: if (!quiet)
528: syslog(LOG_ERR,
529: "malformed SOA from %s, zone %s: too short\n",
530: inet_ntoa(sin.sin_addr), zp->z_origin);
531: #ifdef DEBUG
532: if (debug)
533: fprintf(ddt,
534: "malformed SOA from %s: too short\n",
535: inet_ntoa(sin.sin_addr));
536: #endif DEBUG
537: (void) close(s);
538: error++;
539: continue;
540: }
541: tmp = buf + sizeof(HEADER);
542: eom = buf + len;
543: if ((n = dn_skipname(tmp, eom)) == -1)
544: goto badsoa;
545: tmp += n + QFIXEDSZ;
546: if ((n = dn_skipname(tmp, eom)) == -1)
547: goto badsoa;
548: tmp += n;
549: if (soa_zinfo(&zp_start, tmp, eom) == -1)
550: goto badsoa;
551: if (zp_start.z_serial > serial_no || serial_no == 0) {
552: #ifdef DEBUG
553: if (debug)
554: (void)fprintf(ddt, "need update, serial %d\n",
555: zp_start.z_serial);
556: #endif DEBUG
557: hp = (HEADER *) buf;
558: soacnt = 0;
559: for (;;) {
560: if (soacnt == 0) {
561: if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
562: T_AXFR, (char *)NULL, 0, NULL,
563: buf, bufsize)) < 0) {
564: if (!quiet)
565: syslog(LOG_ERR,
566: "zone %s: res_mkquery T_AXFR failed",
567: zp->z_origin);
568: (void) close(s);
569: (void) sigvec(SIGALRM, &osv,
570: (struct sigvec *)0);
571: return XFER_FAIL;
572: }
573: /*
574: * Send length & message for zone transfer
575: */
576: if (writemsg(s, buf, n) < 0) {
577: (void) close(s);
578: error++;
579: #ifdef DEBUG
580: if (debug >= 2)
581: (void)fprintf(ddt,"writemsg failed\n");
582: #endif
583: break;
584: }
585: }
586: /*
587: * Receive length & response
588: */
589: cp = buf;
590: l = sizeof(u_short);
591: /* allow extra time for the fork on first read */
592: if (soacnt == 0)
593: ival.it_value.tv_sec = 300;
594: while (l > 0) {
595: (void) setitimer(ITIMER_REAL, &ival,
596: (struct itimerval *)NULL);
597: errno = 0;
598: if ((n = recv(s, (char *)cp, l, 0)) > 0) {
599: cp += n;
600: l -= n;
601: } else {
602: if (errno == EINTR && !read_interrupted)
603: continue;
604: error++;
605: #ifdef DEBUG
606: if (debug >= 2)
607: (void)fprintf(ddt,
608: "recv failed: n= %d, errno = %d\n",
609: n, errno);
610: #endif
611: break;
612: }
613: }
614: if (soacnt == 0)
615: ival.it_value.tv_sec = 120;
616: (void) setitimer(ITIMER_REAL, &zeroival,
617: (struct itimerval *)NULL);
618: if (error)
619: break;
620: if ((len = htons(*(u_short *)buf)) == 0)
621: break;
622: l = len;
623: cp = buf;
624: eom = buf + len;
625: while (l > 0) {
626: (void) setitimer(ITIMER_REAL, &ival,
627: (struct itimerval *)NULL);
628: errno = 0;
629: if ((n = recv(s, (char *)cp, l, 0)) > 0) {
630: cp += n;
631: l -= n;
632: } else {
633: if (errno == EINTR && !read_interrupted)
634: continue;
635: error++;
636: #ifdef DEBUG
637: if (debug >= 2)
638: (void)fprintf(ddt,"recv failed\n");
639: #endif
640: break;
641: }
642: }
643: (void) setitimer(ITIMER_REAL, &zeroival,
644: (struct itimerval *)NULL);
645: if (error)
646: break;
647: #ifdef DEBUG
648: if (debug >= 3) {
649: (void)fprintf(ddt,"len = %d\n", len);
650: fp_query(buf, ddt);
651: }
652: if (fp) fp_query(buf,fp);
653: #endif
654: if (len < sizeof(HEADER)) {
655: badrec:
656: error++;
657: if (!quiet)
658: syslog(LOG_ERR,
659: "record too short from %s, zone %s\n",
660: inet_ntoa(sin.sin_addr),
661: zp->z_source);
662: #ifdef DEBUG
663: if (debug)
664: fprintf(ddt,
665: "record too short from %s\n",
666: inet_ntoa(sin.sin_addr));
667: #endif DEBUG
668: break;
669: }
670: cp = buf + sizeof(HEADER);
671: if (hp->qdcount) {
672: if ((n = dn_skipname(cp, eom)) == -1 ||
673: n + QFIXEDSZ >= eom - cp)
674: goto badrec;
675: cp += n + QFIXEDSZ;
676: }
677: nmp = cp;
678: if ((n = dn_skipname(cp, eom)) == -1)
679: goto badrec;
680: tmp = cp + n;
681:
682: n = print_output(buf, bufsize, cp);
683: if (cp + n != eom) {
684: #ifdef DEBUG
685: if (debug)
686: (void)fprintf(ddt,
687: "getzone: print_update failed (%d, %d)\n",
688: cp - buf, n);
689: #endif
690: error++;
691: break;
692: }
693: GETSHORT(n, tmp);
694: if (n == T_SOA) {
695: if (soacnt == 0) {
696: soacnt++;
697: if (dn_expand(buf, buf + 512, nmp,
698: name, sizeof(name)) == -1)
699: goto badsoa;
700: if (eom - tmp <= 2 * sizeof(u_short) +
701: sizeof(u_long))
702: goto badsoa;
703: tmp += 2 * sizeof(u_short)
704: + sizeof(u_long);
705: if ((n = dn_skipname(tmp, eom)) == -1)
706: goto badsoa;
707: tmp += n;
708: if ((n = dn_skipname(tmp, eom)) == -1)
709: goto badsoa;
710: tmp += n;
711: if (eom - tmp <= sizeof(u_long))
712: goto badsoa;
713: GETLONG(serial, tmp);
714: #ifdef DEBUG
715: if (debug > 2)
716: (void)fprintf(ddt,
717: "first SOA for %s, serial %d\n",
718: name, serial);
719: #endif DEBUG
720: continue;
721: }
722: if (dn_expand(buf, buf + 512, nmp, name2,
723: sizeof(name2)) == -1)
724: goto badsoa;
725: if (strcasecmp((char *)name, (char *)name2) != 0) {
726: #ifdef DEBUG
727: if (debug > 1)
728: (void)fprintf(ddt,
729: "extraneous SOA for %s\n",
730: name2);
731: #endif DEBUG
732: continue;
733: }
734: tmp -= sizeof(u_short);
735: if (soa_zinfo(&zp_finish, tmp, eom) == -1)
736: goto badsoa;
737: #ifdef DEBUG
738: if (debug > 1)
739: (void)fprintf(ddt,
740: "SOA, serial %d\n", zp_finish.z_serial);
741: #endif DEBUG
742: if (serial != zp_finish.z_serial) {
743: soacnt = 0;
744: got_soa = 0;
745: minimum_ttl = 0;
746: strcpy(prev_origin, zp->z_origin);
747: prev_dname[0] = 0;
748: #ifdef DEBUG
749: if (debug)
750: (void)fprintf(ddt,
751: "serial changed, restart\n");
752: #endif DEBUG
753: /*
754: * Flush buffer, truncate file
755: * and seek to beginning to restart.
756: */
757: fflush(dbfp);
758: if (ftruncate(fileno(dbfp), 0) != 0) {
759: if (!quiet)
760: syslog(LOG_ERR,
761: "ftruncate %s: %m\n",
762: tmpname);
763: return(XFER_FAIL);
764: }
765: fseek(dbfp, 0L, 0);
766: } else
767: break;
768: }
769: }
770: (void) close(s);
771: if (error == 0) {
772: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
773: return XFER_SUCCESS;
774: }
775: #ifdef DEBUG
776: if (debug >= 2)
777: (void)fprintf(ddt,"error receiving zone transfer\n");
778: #endif
779: } else {
780: (void) close(s);
781: #ifdef DEBUG
782: if (debug)
783: (void)fprintf(ddt,
784: "zone up-to-date, serial %d\n", zp_start.z_serial);
785: #endif DEBUG
786: return XFER_UPTODATE;
787: }
788: }
789: (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
790: if (error)
791: return XFER_TIMEOUT;
792: return XFER_FAIL;
793: }
794:
795: /*
796: * Set flag saying to read was interrupted
797: * used for a read timer
798: */
799: VOID
800: read_alarm()
801: {
802: extern int read_interrupted;
803: read_interrupted = 1;
804: }
805:
806: writemsg(rfd, msg, msglen)
807: int rfd;
808: u_char *msg;
809: int msglen;
810: {
811: struct iovec iov[2];
812: u_short len = htons((u_short)msglen);
813:
814: iov[0].iov_base = (caddr_t)&len;
815: iov[0].iov_len = sizeof(len);
816: iov[1].iov_base = (caddr_t)msg;
817: iov[1].iov_len = msglen;
818: if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
819: #ifdef DEBUG
820: if (debug)
821: (void)fprintf(ddt,"write failed %d\n", errno);
822: #endif
823: return (-1);
824: }
825: return (0);
826: }
827:
828:
829: soa_zinfo(zp, cp, eom)
830: register struct zoneinfo *zp;
831: register u_char *cp;
832: u_char *eom;
833: {
834: register int n;
835:
836: if (eom - cp < 3 * sizeof(u_short) + sizeof(u_long))
837: return (-1);
838: cp += 3 * sizeof(u_short) + sizeof(u_long);
839: if ((n = dn_skipname(cp, eom)) == -1)
840: return (-1);
841: cp += n;
842: if ((n = dn_skipname(cp, eom)) == -1)
843: return (-1);
844: cp += n;
845: if (eom - cp < 5 * sizeof(u_long))
846: return (-1);
847: GETLONG(zp->z_serial, cp);
848: GETLONG(zp->z_refresh, cp);
849: gettime(&tt);
850: zp->z_time = tt.tv_sec + zp->z_refresh;
851: GETLONG(zp->z_retry, cp);
852: GETLONG(zp->z_expire, cp);
853: GETLONG(zp->z_minimum, cp);
854: return (0);
855: }
856:
857: gettime(ttp)
858: struct timeval *ttp;
859: {
860: if (gettimeofday(ttp, (struct timezone *)0) < 0)
861: syslog(LOG_ERR, "gettimeofday failed: %m");
862: }
863:
864: /*
865: * Parse the message, determine if it should be printed, and if so, print it
866: * in .db file form.
867: * Does minimal error checking on the message content.
868: */
869: print_output(msg, msglen, rrp)
870: u_char *msg;
871: int msglen;
872: u_char *rrp;
873: {
874: register u_char *cp;
875: register HEADER *hp = (HEADER *) msg;
876: u_long addr, ttl;
877: int i, j, tab, result, class, type, dlen, n1;
878: long n;
879: u_char *cp1, data[BUFSIZ];
880: u_char *temp_ptr; /* used to get ttl for RR */
881: char *cdata, *origin, *proto, dname[MAXDNAME];
882: extern char *inet_ntoa(), *protocolname(), *servicename();
883:
884: cp = rrp;
885: if ((n = dn_expand(msg, msg + msglen, cp, (u_char *) dname,
886: sizeof(dname))) < 0) {
887: hp->rcode = FORMERR;
888: return (-1);
889: }
890: cp += n;
891: GETSHORT(type, cp);
892: GETSHORT(class, cp);
893: GETLONG(ttl, cp);
894: GETSHORT(dlen, cp);
895:
896: origin = index(dname, '.');
897: if (origin == NULL)
898: origin = "";
899: else
900: origin++; /* move past the '.' */
901: #ifdef DEBUG
902: if (debug > 2)
903: (void) fprintf(ddt, "print_output: dname %s type %d class %d ttl %d\n",
904: dname, type, class, ttl);
905: #endif
906: /*
907: * Convert the resource record data into the internal database format.
908: */
909: switch (type) {
910: case T_A:
911: case T_WKS:
912: case T_HINFO:
913: case T_UINFO:
914: case T_TXT:
915: case T_UID:
916: case T_GID:
917: cp1 = cp;
918: n = dlen;
919: cp += n;
920: break;
921:
922: case T_CNAME:
923: case T_MB:
924: case T_MG:
925: case T_MR:
926: case T_NS:
927: case T_PTR:
928: if ((n = dn_expand(msg, msg + msglen, cp, data,
929: sizeof(data))) < 0) {
930: hp->rcode = FORMERR;
931: return (-1);
932: }
933: cp += n;
934: cp1 = data;
935: n = strlen((char *) data) + 1;
936: break;
937:
938: case T_MINFO:
939: case T_SOA:
940: if ((n = dn_expand(msg, msg + msglen, cp, data,
941: sizeof(data))) < 0) {
942: hp->rcode = FORMERR;
943: return (-1);
944: }
945: cp += n;
946: cp1 = data + (n = strlen((char *) data) + 1);
947: n1 = sizeof(data) - n;
948: if (type == T_SOA)
949: n1 -= 5 * sizeof(u_long);
950: if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) {
951: hp->rcode = FORMERR;
952: return (-1);
953: }
954: cp += n;
955: cp1 += strlen((char *) cp1) + 1;
956: if (type == T_SOA) {
957: temp_ptr = cp + 4 * sizeof(u_long);
958: GETLONG(minimum_ttl, temp_ptr);
959: bcopy((char *) cp, (char *) cp1,
960: n = 5 * sizeof(u_long));
961: cp += n;
962: cp1 += n;
963: }
964: n = cp1 - data;
965: cp1 = data;
966: break;
967:
968: case T_MX:
969: /* grab preference */
970: bcopy((char *) cp, (char *) data, sizeof(u_short));
971: cp1 = data + sizeof(u_short);
972: cp += sizeof(u_short);
973:
974: /* get name */
975: if ((n = dn_expand(msg, msg + msglen, cp, cp1,
976: sizeof(data) - sizeof(u_short))) < 0)
977: return (-1);
978: cp += n;
979:
980: /* compute end of data */
981: cp1 += strlen((char *) cp1) + 1;
982: /* compute size of data */
983: n = cp1 - data;
984: cp1 = data;
985: break;
986:
987: default:
988: #ifdef DEBUG
989: if (debug >= 3)
990: (void) fprintf(ddt, "unknown type %d\n", type);
991: #endif
992: return ((cp - rrp) + dlen);
993: }
994: if (n > MAXDATA) {
995: #ifdef DEBUG
996: if (debug)
997: (void) fprintf(ddt,
998: "update type %d: %d bytes is too much data\n",
999: type, n);
1000: #endif
1001: hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */
1002: return (-1);
1003: }
1004: cdata = (char *) cp1;
1005: result = cp - rrp;
1006:
1007: /*
1008: * Only print one SOA per db file
1009: */
1010: if (type == T_SOA) {
1011: if (got_soa)
1012: return result;
1013: else
1014: got_soa++;
1015: }
1016: /*
1017: * If the origin has changed, print the new origin
1018: */
1019: if (strcasecmp(prev_origin, origin)) {
1020: (void) strcpy(prev_origin, origin);
1021: (void) fprintf(dbfp, "$ORIGIN %s.\n", origin);
1022: }
1023: tab = 0;
1024:
1025: if (strcasecmp(prev_dname, dname)) {
1026: /*
1027: * set the prev_dname to be the current dname, then cut off all
1028: * characters of dname after (and including) the first '.'
1029: */
1030: char *cutp = index(dname, '.');
1031:
1032: (void) strcpy(prev_dname, dname);
1033: if (cutp)
1034: *cutp = NULL;
1035:
1036: if (dname[0] == 0) {
1037: if (origin[0] == 0)
1038: (void) fprintf(dbfp, ".\t");
1039: else
1040: (void) fprintf(dbfp, ".%s.\t", origin); /* ??? */
1041: } else
1042: (void) fprintf(dbfp, "%s\t", dname);
1043: if (strlen(dname) < 8)
1044: tab = 1;
1045: } else {
1046: (void) putc('\t', dbfp);
1047: tab = 1;
1048: }
1049:
1050: if (ttl != 0 && ttl != minimum_ttl)
1051: (void) fprintf(dbfp, "%d\t", (int) ttl);
1052: else if (tab)
1053: (void) putc('\t', dbfp);
1054:
1055: (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type));
1056: cp = (u_char *) cdata;
1057:
1058: /*
1059: * Print type specific data
1060: */
1061: switch (type) {
1062:
1063: case T_A:
1064: switch (class) {
1065: case C_IN:
1066: case C_HS:
1067: GETLONG(n, cp);
1068: n = htonl(n);
1069: (void) fprintf(dbfp, "%s",
1070: inet_ntoa(*(struct in_addr *) & n));
1071: break;
1072: }
1073: (void) fprintf(dbfp, "\n");
1074: break;
1075:
1076: case T_CNAME:
1077: case T_MB:
1078: case T_MG:
1079: case T_MR:
1080: case T_PTR:
1081: if (cp[0] == '\0')
1082: (void) fprintf(dbfp, ".\n");
1083: else
1084: (void) fprintf(dbfp, "%s.\n", cp);
1085: break;
1086:
1087: case T_NS:
1088: cp = (u_char *) cdata;
1089: if (cp[0] == '\0')
1090: (void) fprintf(dbfp, ".\t");
1091: else
1092: (void) fprintf(dbfp, "%s.", cp);
1093: (void) fprintf(dbfp, "\n");
1094: break;
1095:
1096: case T_HINFO:
1097: if (n = *cp++) {
1098: (void) fprintf(dbfp, "\"%.*s\"", (int) n, cp);
1099: cp += n;
1100: } else
1101: (void) fprintf(dbfp, "\"\"");
1102: if (n = *cp++)
1103: (void) fprintf(dbfp, " \"%.*s\"", (int) n, cp);
1104: else
1105: (void) fprintf(dbfp, "\"\"");
1106: (void) putc('\n', dbfp);
1107: break;
1108:
1109: case T_SOA:
1110: (void) fprintf(dbfp, "%s.", cp);
1111: cp += strlen((char *) cp) + 1;
1112: (void) fprintf(dbfp, " %s. (\n", cp);
1113: cp += strlen((char *) cp) + 1;
1114: GETLONG(n, cp);
1115: (void) fprintf(dbfp, "\t\t%lu", n);
1116: GETLONG(n, cp);
1117: (void) fprintf(dbfp, " %lu", n);
1118: GETLONG(n, cp);
1119: (void) fprintf(dbfp, " %lu", n);
1120: GETLONG(n, cp);
1121: (void) fprintf(dbfp, " %lu", n);
1122: GETLONG(n, cp);
1123: (void) fprintf(dbfp, " %lu )\n", n);
1124: break;
1125:
1126: case T_MX:
1127: GETSHORT(n, cp);
1128: (void) fprintf(dbfp, "%lu", n);
1129: (void) fprintf(dbfp, " %s.\n", cp);
1130: break;
1131:
1132: case T_TXT:
1133: cp1 = cp + n;
1134: (void) putc('"', dbfp);
1135: while (cp < cp1) {
1136: if (i = *cp++) {
1137: for (j = i ; j > 0 && cp < cp1 ; j--)
1138: if (*cp == '\n') {
1139: (void) putc('\\', dbfp);
1140: (void) putc(*cp++, dbfp);
1141: } else
1142: (void) putc(*cp++, dbfp);
1143: }
1144: }
1145: (void) fputs("\"\n", dbfp);
1146: break;
1147:
1148: case T_UINFO:
1149: (void) fprintf(dbfp, "\"%s\"\n", cp);
1150: break;
1151:
1152: case T_UID:
1153: case T_GID:
1154: if (n == sizeof(u_long)) {
1155: GETLONG(n, cp);
1156: (void) fprintf(dbfp, "%lu\n", n);
1157: }
1158: break;
1159:
1160: case T_WKS:
1161: GETLONG(addr, cp);
1162: addr = htonl(addr);
1163: (void) fprintf(dbfp, "%s ",
1164: inet_ntoa(*(struct in_addr *) & addr));
1165: proto = protocolname(*cp);
1166: cp += sizeof(char);
1167: (void) fprintf(dbfp, "%s ", proto);
1168: i = 0;
1169: while (cp < (u_char *) cdata + n) {
1170: j = *cp++;
1171: do {
1172: if (j & 0200)
1173: (void) fprintf(dbfp, " %s",
1174: servicename(i, proto));
1175: j <<= 1;
1176: } while (++i & 07);
1177: }
1178: (void) fprintf(dbfp, "\n");
1179: break;
1180:
1181: case T_MINFO:
1182: (void) fprintf(dbfp, "%s.", cp);
1183: cp += strlen((char *) cp) + 1;
1184: (void) fprintf(dbfp, " %s.\n", cp);
1185: break;
1186:
1187: default:
1188: (void) fprintf(dbfp, "???\n");
1189: }
1190: if (ferror(dbfp)) {
1191: syslog(LOG_ERR, "%s: %m", tmpname);
1192: exit(XFER_FAIL);
1193: }
1194: return result;
1195: }
1196:
1197: /*
1198: * Make a copy of a string and return a pointer to it.
1199: */
1200: char *
1201: savestr(str)
1202: char *str;
1203: {
1204: char *cp;
1205:
1206: cp = (char *)malloc((unsigned)strlen(str) + 1);
1207: if (cp == NULL) {
1208: syslog(LOG_ERR, "savestr: %m");
1209: exit(XFER_FAIL);
1210: }
1211: (void) strcpy(cp, str);
1212: return (cp);
1213: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.