📄 named-xfer.c
字号:
syslog(LOG_ERR, "malloc(%u) failed", 2 * PACKETSZ); error++; break; } bufsize = 2 * PACKETSZ; } bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = port; sin.sin_addr = zp->z_addr[cnt]; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); error++; break; } dprintf(2, (ddt, "connecting to server #%d [%s].%d\n", cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port))); if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { (void) my_close(s); error++; dprintf(2, (ddt, "connect failed: %s\n", strerror(errno))); continue; } tryagain: if ((n = res_mkquery(QUERY, zp->z_origin, Class, T_SOA, (char *)NULL, 0, NULL, (char *)buf, bufsize)) < 0) { if (!quiet) syslog(LOG_ERR, "zone %s: res_mkquery T_SOA failed", zp->z_origin); (void) my_close(s);#ifdef POSIX_SIGNALS (void) sigaction(SIGALRM, &osv, (struct sigaction *)0);#else (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);#endif return XFER_FAIL; } /* * Send length & message for SOA query */ if (writemsg(s, buf, n) < 0) { (void) my_close(s); error++; dprintf(2, (ddt, "writemsg failed\n")); continue; } /* * Get out your butterfly net and catch the SOA */ cp = buf; l = sizeof(u_int16_t); read_interrupted = 0; while (l > 0) { dprintf(11, (ddt, "Before setitimer\n")); (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); dprintf(11, (ddt, "Before recv(l = %d)\n",n)); errno = 0; if ((n = recv(s, (char *)cp, l, 0)) > 0) { cp += n; l -= n; } else { dprintf(11, (ddt, "bad recv->%d, errno= %d, read_interrupt=%d\n", n, errno, read_interrupted)); if (n == -1 && errno == EINTR && !read_interrupted) continue; error++; break; } } (void) setitimer(ITIMER_REAL, &zeroival, (struct itimerval *)NULL); if (error) { (void) my_close(s); continue; } if ((len = htons(*(u_int16_t *)buf)) == 0) { (void) my_close(s); continue; } if (len > bufsize) { if ((buf = (u_char *)realloc(buf, len)) == NULL) { syslog(LOG_ERR, "malloc(%u) failed for SOA from server [%s], zone %s\n", len, inet_ntoa(sin.sin_addr), zp->z_origin); (void) my_close(s); continue; } bufsize = len; } l = len; cp = buf; while (l > 0) { (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); errno = 0; if ((n = recv(s, (char *)cp, l, 0)) > 0) { cp += n; l -= n; } else { if (errno == EINTR && !read_interrupted) continue; error++; dprintf(11, (ddt, "recv failed: n= %d, errno = %d\n", n, errno)); break; } } (void) setitimer(ITIMER_REAL, &zeroival, (struct itimerval *)NULL); if (error) { (void) my_close(s); continue; }#ifdef DEBUG if (debug >= 3) { (void)fprintf(ddt,"len = %d\n", len); fp_query((char *)buf, ddt); }#endif hp = (HEADER *) buf; ancount = ntohs(hp->ancount); aucount = ntohs(hp->nscount); /* * close socket if: * 1) rcode != NOERROR * 2) not an authority response * 3) both the number of answers and authority count < 1) */ if (hp->rcode != NOERROR || !(hp->aa) || (ancount < 1 && aucount < 1)) {#ifndef GEN_AXFR if (Class == C_IN) { dprintf(1, (ddt,"SOA failed, trying C_HS\n")); Class = C_HS; goto tryagain; }#endif if (!quiet) syslog(LOG_ERR, "%s from [%s], zone %s: rcode %d, aa %d, ancount %d, aucount %d\n", "bad response to SOA query", inet_ntoa(sin.sin_addr), zp->z_origin, hp->rcode, hp->aa, ancount, aucount); dprintf(1, (ddt, "%s from [%s], zone %s: rcode %d, aa %d, ancount %d, aucount %d\n", "bad response to SOA query", inet_ntoa(sin.sin_addr), zp->z_origin, hp->rcode, hp->aa, ancount, aucount)); (void) my_close(s); error++; continue; } zp_start = *zp; if (len < sizeof(HEADER) + QFIXEDSZ) { badsoa: if (!quiet) syslog(LOG_ERR, "malformed SOA from [%s], zone %s: too short\n", inet_ntoa(sin.sin_addr), zp->z_origin); dprintf(1, (ddt, "malformed SOA from [%s]: too short\n", inet_ntoa(sin.sin_addr))); (void) my_close(s); error++; continue; } tmp = buf + sizeof(HEADER); eom = buf + len; if ((n = dn_skipname(tmp, eom)) == -1) goto badsoa; tmp += n + QFIXEDSZ; if ((n = dn_skipname(tmp, eom)) == -1) goto badsoa; tmp += n; if (soa_zinfo(&zp_start, tmp, eom) == -1) goto badsoa; /* compare using sequence space arithmetic */ if (SEQ_GT(zp_start.z_serial, serial_no) || serial_no == 0) { dprintf(1, (ddt, "need update, serial %d\n", zp_start.z_serial)); hp = (HEADER *) buf; soacnt = 0; nscnt = 0; for (;;) { if ((soacnt == 0) || (zp->z_type == Z_STUB)) { int type;#ifdef STUBS if (zp->z_type == Z_STUB) { if (!soacnt) type = T_SOA; else if (!nscnt) type = T_NS; else type = T_SOA; } else#endif type = T_AXFR; if ((n = res_mkquery(QUERY, zp->z_origin, Class, type, (char *)NULL, 0, NULL, (char *)buf, bufsize )) < 0) { if (!quiet) {#ifdef STUBS if (zp->z_type == Z_STUB) syslog(LOG_ERR, (type == T_SOA) ? "zone %s: res_mkquery T_SOA failed" : "zone %s: res_mkquery T_NS failed", zp->z_origin); else#endif syslog(LOG_ERR, "zone %s: res_mkquery T_AXFR failed", zp->z_origin); } (void) my_close(s);#ifdef POSIX_SIGNALS sigaction(SIGALRM, &osv, (struct sigaction *)0);#else sigvec(SIGALRM, &osv, (struct sigvec *)0);#endif return XFER_FAIL; } /* * Send length & msg for zone transfer */ if (writemsg(s, buf, n) < 0) { (void) my_close(s); error++; dprintf(2, (ddt, "writemsg failed\n" )); break; } } /* * Receive length & response */ cp = buf; l = sizeof(u_int16_t); /* allow extra time for fork on first read */ if (soacnt == 0) ival.it_value.tv_sec = 300; while (l > 0) { (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *) NULL ); errno = 0; n = recv(s, (char *)cp, l, 0); if (n > 0) { cp += n; l -= n; } else { if (errno == EINTR && !read_interrupted) continue; error++; dprintf(2, (ddt, "recv failed: n= %d, errno = %d\n", n, errno)); break; } } if (soacnt == 0) ival.it_value.tv_sec = XFER_TIMER; (void) setitimer(ITIMER_REAL, &zeroival, (struct itimerval *)NULL); if (error) break; if ((len = htons(*(u_int16_t *)buf)) == 0) break; l = len; cp = buf; eom = buf + len; while (l > 0) { (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *) NULL ); errno = 0; n = recv(s, (char *)cp, l, 0); if (n > 0) { cp += n; l -= n; } else { if (errno == EINTR && !read_interrupted) continue; error++; dprintf(2, (ddt, "recv failed\n")); break; } } (void) setitimer(ITIMER_REAL, &zeroival, (struct itimerval *)NULL); if (error) break;#ifdef DEBUG if (debug >= 3) { (void)fprintf(ddt,"len = %d\n", len); fp_query((char *)buf, ddt); } if (fp) fp_query((char *)buf, fp);#endif if (len < sizeof(HEADER)) { badrec: error++; if (!quiet) syslog(LOG_ERR, "record too short from [%s], zone %s\n", inet_ntoa(sin.sin_addr), zp->z_source); dprintf(1, (ddt, "record too short from [%s]\n", inet_ntoa(sin.sin_addr))); break; } cp = buf + sizeof(HEADER); if (hp->qdcount) { if ((n = dn_skipname(cp, eom)) == -1 || n + QFIXEDSZ >= eom - cp) goto badrec; cp += n + QFIXEDSZ; } nmp = cp; if ((n = dn_skipname(cp, eom)) == -1) goto badrec; tmp = cp + n;#ifdef STUBS if (zp->z_type == Z_STUB) { ancount = ntohs(hp->ancount); for (cnt = 0 ; cnt < ancount ; cnt++) { n = print_output(buf, bufsize, cp); cp += n; } if (hp->nscount) { /* we should not get here */ ancount = ntohs(hp->nscount); for (cnt = 0 ; cnt < ancount ; cnt++) { n = print_output(buf, bufsize, cp); cp += n; } } ancount = ntohs(hp->arcount); for (cnt = 0 ; cnt < ancount ; cnt ++) { n = print_output(buf, bufsize, cp); cp += n; } if (cp != eom) { dprintf(1, (ddt, "getzone: print_update failed (%d, %d)\n", cp - buf, n)); error++; break; } } else {#endif /*STUBS*/ n = print_output(buf, bufsize, cp); if (cp + n != eom) { dprintf(1, (ddt, "getzone: print_update failed (%d, %d)\n", cp - buf, n)); error++; break; }#ifdef STUBS }#endif GETSHORT(n, tmp); if (n == T_SOA) { if (soacnt == 0) { soacnt++; if (dn_expand(buf, buf + 512, nmp, name, sizeof(name)) == -1) goto badsoa; if (eom - tmp <= 2 * sizeof(u_int16_t) + sizeof(u_int32_t)) { goto badsoa; } tmp += 2 * sizeof(u_int16_t) + sizeof(u_int32_t); if ((n = dn_skipname(tmp, eom)) == -1) goto badsoa; tmp += n; if ((n = dn_skipname(tmp, eom)) == -1) goto badsoa; tmp += n; if (eom - tmp <= sizeof(u_int32_t)) goto badsoa; GETLONG(serial, tmp); dprintf(3, (ddt, "first SOA for %s, serial %d\n", name, serial)); continue; } if (dn_expand(buf, buf + 512, nmp, name2, sizeof(name2)) == -1) goto badsoa; if (strcasecmp((char *)name, (char *)name2) != 0) { dprintf(2, (ddt, "extraneous SOA for %s\n", name2)); continue; } tmp -= sizeof(u_int16_t); if (soa_zinfo(&zp_finish, tmp, eom) == -1) goto badsoa; dprintf(2, (ddt, "SOA, serial %d\n", zp_finish.z_serial)); if (serial != zp_finish.z_serial) { soacnt = 0; got_soa = 0; minimum_ttl = 0; strcpy(prev_origin, zp->z_origin); prev_dname[0] = DEF_DNAME; dprintf(1, (ddt, "serial changed, restart\n" )); /* * Flush buffer, truncate file * and seek to beginning to restart. */ fflush(dbfp); if (ftruncate(fileno(dbfp), 0) != 0) { if (!quiet) syslog(LOG_ERR, "ftruncate %s: %m\n", tmpname); return(XFER_FAIL); } fseek(dbfp, 0L, 0); } else break;#ifdef STUBS } else if (zp->z_type == Z_STUB && n == T_NS) { nscnt++; } else if (zp->z_type == Z_STUB) { break;#endif } } (void) my_close(s); if (error == 0) {#ifdef POSIX_SIGNALS (void) sigaction(SIGALRM, &osv, (struct sigaction *)0);#else (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);#endif return XFER_SUCCESS; } dprintf(2, (ddt, "error receiving zone transfer\n")); } else if (zp_start.z_serial == serial_no) { (void) my_close(s); dprintf(1, (ddt, "zone up-to-date, serial %u\n", zp_start.z_serial)); return XFER_UPTODATE; } else { (void) my_close(s); if (!quiet) syslog(LOG_ERR, "serial from [%s], zone %s: %u lower than current: %u\n", inet_ntoa(sin.sin_addr), zp->z_origin, zp_start.z_serial, serial_no); dprintf(1, (ddt,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -