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