📄 xfrin.c
字号:
xfr->state = XFRST_IXFR_DELSOA; } else { xfrin_log(xfr, ISC_LOG_DEBUG(3), "got nonincremental response"); CHECK(axfr_init(xfr)); xfr->state = XFRST_AXFR; } goto redo; case XFRST_IXFR_DELSOA: INSIST(rdata->type == dns_rdatatype_soa); CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata)); xfr->state = XFRST_IXFR_DEL; break; case XFRST_IXFR_DEL: if (rdata->type == dns_rdatatype_soa) { isc_uint32_t soa_serial = dns_soa_getserial(rdata); xfr->state = XFRST_IXFR_ADDSOA; xfr->ixfr.current_serial = soa_serial; goto redo; } CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata)); break; case XFRST_IXFR_ADDSOA: INSIST(rdata->type == dns_rdatatype_soa); CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); xfr->state = XFRST_IXFR_ADD; break; case XFRST_IXFR_ADD: if (rdata->type == dns_rdatatype_soa) { isc_uint32_t soa_serial = dns_soa_getserial(rdata); CHECK(ixfr_commit(xfr)); if (soa_serial == xfr->end_serial) { xfr->state = XFRST_END; break; } else if (soa_serial != xfr->ixfr.current_serial) { xfrin_log(xfr, ISC_LOG_ERROR, "IXFR out of sync: " "expected serial %u, got %u", xfr->ixfr.current_serial, soa_serial); FAIL(DNS_R_FORMERR); } else { xfr->state = XFRST_IXFR_DELSOA; goto redo; } } if (rdata->type == dns_rdatatype_ns && dns_name_iswildcard(name)) FAIL(DNS_R_INVALIDNS); CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); break; case XFRST_AXFR: /* * Old BINDs sent cross class A records for non IN classes. */ if (rdata->type == dns_rdatatype_a && rdata->rdclass != xfr->rdclass && xfr->rdclass != dns_rdataclass_in) break; CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); if (rdata->type == dns_rdatatype_soa) { CHECK(axfr_commit(xfr)); xfr->state = XFRST_END; break; } break; case XFRST_END: FAIL(DNS_R_EXTRADATA); default: INSIST(0); break; } result = ISC_R_SUCCESS; failure: return (result);}isc_result_tdns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype, isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey, isc_mem_t *mctx, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp){ isc_sockaddr_t sourceaddr; switch (isc_sockaddr_pf(masteraddr)) { case PF_INET: sourceaddr = *dns_zone_getxfrsource4(zone); break; case PF_INET6: sourceaddr = *dns_zone_getxfrsource6(zone); break; default: INSIST(0); } return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr, tsigkey, mctx, timermgr, socketmgr, task, done, xfrp));}isc_result_tdns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype, isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, isc_mem_t *mctx, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp){ dns_name_t *zonename = dns_zone_getorigin(zone); dns_xfrin_ctx_t *xfr; isc_result_t result; dns_db_t *db = NULL; REQUIRE(xfrp != NULL && *xfrp == NULL); (void)dns_zone_getdb(zone, &db); CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename, dns_zone_getclass(zone), xfrtype, masteraddr, sourceaddr, tsigkey, &xfr)); CHECK(xfrin_start(xfr)); xfr->done = done; xfr->refcount++; *xfrp = xfr; failure: if (db != NULL) dns_db_detach(&db); if (result != ISC_R_SUCCESS) xfrin_log1(ISC_LOG_ERROR, zonename, dns_zone_getclass(zone), masteraddr, "zone transfer setup failed"); return (result);}voiddns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) { if (! xfr->shuttingdown) xfrin_fail(xfr, ISC_R_CANCELED, "shut down");}voiddns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) { REQUIRE(target != NULL && *target == NULL); source->refcount++; *target = source;}voiddns_xfrin_detach(dns_xfrin_ctx_t **xfrp) { dns_xfrin_ctx_t *xfr = *xfrp; INSIST(xfr->refcount > 0); xfr->refcount--; maybe_free(xfr); *xfrp = NULL;}static voidxfrin_cancelio(dns_xfrin_ctx_t *xfr) { if (xfr->connects > 0) { isc_socket_cancel(xfr->socket, xfr->task, ISC_SOCKCANCEL_CONNECT); } else if (xfr->recvs > 0) { dns_tcpmsg_cancelread(&xfr->tcpmsg); } else if (xfr->sends > 0) { isc_socket_cancel(xfr->socket, xfr->task, ISC_SOCKCANCEL_SEND); }}static voidxfrin_reset(dns_xfrin_ctx_t *xfr) { REQUIRE(VALID_XFRIN(xfr)); xfrin_log(xfr, ISC_LOG_INFO, "resetting"); xfrin_cancelio(xfr); if (xfr->socket != NULL) isc_socket_detach(&xfr->socket); if (xfr->lasttsig != NULL) isc_buffer_free(&xfr->lasttsig); dns_diff_clear(&xfr->diff); xfr->difflen = 0; if (xfr->ixfr.journal != NULL) dns_journal_destroy(&xfr->ixfr.journal); if (xfr->axfr.add_private != NULL) { (void)dns_db_endload(xfr->db, &xfr->axfr.add_private); xfr->axfr.add_func = NULL; } if (xfr->tcpmsg_valid) { dns_tcpmsg_invalidate(&xfr->tcpmsg); xfr->tcpmsg_valid = ISC_FALSE; } if (xfr->ver != NULL) dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);}static voidxfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) { if (result != DNS_R_UPTODATE) { xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg, isc_result_totext(result)); if (xfr->is_ixfr) /* Pass special result code to force AXFR retry */ result = DNS_R_BADIXFR; } xfrin_cancelio(xfr); if (xfr->done != NULL) { (xfr->done)(xfr->zone, result); xfr->done = NULL; } xfr->shuttingdown = ISC_TRUE; maybe_free(xfr);}static isc_result_txfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, dns_name_t *zonename, dns_rdataclass_t rdclass, dns_rdatatype_t reqtype, isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, dns_xfrin_ctx_t **xfrp){ dns_xfrin_ctx_t *xfr = NULL; isc_result_t result; isc_uint32_t tmp; xfr = isc_mem_get(mctx, sizeof(*xfr)); if (xfr == NULL) return (ISC_R_NOMEMORY); xfr->mctx = mctx; xfr->refcount = 0; xfr->zone = NULL; dns_zone_iattach(zone, &xfr->zone); xfr->task = NULL; isc_task_attach(task, &xfr->task); xfr->timer = NULL; xfr->socketmgr = socketmgr; xfr->done = NULL; xfr->connects = 0; xfr->sends = 0; xfr->recvs = 0; xfr->shuttingdown = ISC_FALSE; dns_name_init(&xfr->name, NULL); xfr->rdclass = rdclass; isc_random_get(&tmp); xfr->checkid = ISC_TRUE; xfr->id = (isc_uint16_t)(tmp & 0xffff); xfr->reqtype = reqtype; /* sockaddr */ xfr->socket = NULL; /* qbuffer */ /* qbuffer_data */ /* tcpmsg */ xfr->tcpmsg_valid = ISC_FALSE; xfr->db = NULL; if (db != NULL) dns_db_attach(db, &xfr->db); xfr->ver = NULL; dns_diff_init(xfr->mctx, &xfr->diff); xfr->difflen = 0; xfr->state = XFRST_INITIALSOA; /* end_serial */ xfr->nmsg = 0; xfr->tsigkey = NULL; if (tsigkey != NULL) dns_tsigkey_attach(tsigkey, &xfr->tsigkey); xfr->lasttsig = NULL; xfr->tsigctx = NULL; xfr->sincetsig = 0; xfr->is_ixfr = ISC_FALSE; /* ixfr.request_serial */ /* ixfr.current_serial */ xfr->ixfr.journal = NULL; xfr->axfr.add_func = NULL; xfr->axfr.add_private = NULL; CHECK(dns_name_dup(zonename, mctx, &xfr->name)); CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, task, xfrin_timeout, xfr, &xfr->timer)); CHECK(dns_timer_setidle(xfr->timer, dns_zone_getmaxxfrin(xfr->zone), dns_zone_getidlein(xfr->zone), ISC_FALSE)); xfr->masteraddr = *masteraddr; INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr)); xfr->sourceaddr = *sourceaddr; isc_sockaddr_setport(&xfr->sourceaddr, 0); isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data, sizeof(xfr->qbuffer_data)); xfr->magic = XFRIN_MAGIC; *xfrp = xfr; return (ISC_R_SUCCESS); failure: xfrin_fail(xfr, result, "failed creating transfer context"); return (result);}static isc_result_txfrin_start(dns_xfrin_ctx_t *xfr) { isc_result_t result; CHECK(isc_socket_create(xfr->socketmgr, isc_sockaddr_pf(&xfr->sourceaddr), isc_sockettype_tcp, &xfr->socket)); CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr)); CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task, xfrin_connect_done, xfr)); xfr->connects++; return (ISC_R_SUCCESS); failure: xfrin_fail(xfr, result, "failed setting up socket"); return (result);}/* XXX the resolver could use this, too */static isc_result_trender(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) { dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; isc_result_t result; CHECK(dns_compress_init(&cctx, -1, mctx)); cleanup_cctx = ISC_TRUE; CHECK(dns_message_renderbegin(msg, &cctx, buf)); CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0)); CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0)); CHECK(dns_message_renderend(msg)); result = ISC_R_SUCCESS; failure: if (cleanup_cctx) dns_compress_invalidate(&cctx); return (result);}/* * A connection has been established. */static voidxfrin_connect_done(isc_task_t *task, isc_event_t *event) { isc_socket_connev_t *cev = (isc_socket_connev_t *) event; dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg; isc_result_t evresult = cev->result; isc_result_t result; char sourcetext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t sockaddr; REQUIRE(VALID_XFRIN(xfr)); UNUSED(task); INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT); isc_event_free(&event); xfr->connects--; if (xfr->shuttingdown) { maybe_free(xfr); return; } CHECK(evresult); result = isc_socket_getsockname(xfr->socket, &sockaddr); if (result == ISC_R_SUCCESS) { isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext)); } else strcpy(sourcetext, "<UNKNOWN>"); xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext); dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg); xfr->tcpmsg_valid = ISC_TRUE; CHECK(xfrin_send_request(xfr)); failure: if (result != ISC_R_SUCCESS) xfrin_fail(xfr, result, "failed to connect");}/* * Convert a tuple into a dns_name_t suitable for inserting * into the given dns_message_t. */static isc_result_ttuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target){ isc_result_t result; dns_rdata_t *rdata = NULL; dns_rdatalist_t *rdl = NULL; dns_rdataset_t *rds = NULL; dns_name_t *name = NULL; REQUIRE(target != NULL && *target == NULL); CHECK(dns_message_gettemprdata(msg, &rdata)); dns_rdata_init(rdata); dns_rdata_clone(&tuple->rdata, rdata); CHECK(dns_message_gettemprdatalist(msg, &rdl)); dns_rdatalist_init(rdl); rdl->type = tuple->rdata.type; rdl->rdclass = tuple->rdata.rdclass; rdl->ttl = tuple->ttl; ISC_LIST_APPEND(rdl->rdata, rdata, link); CHECK(dns_message_gettemprdataset(msg, &rds)); dns_rdataset_init(rds); CHECK(dns_rdatalist_tordataset(rdl, rds)); CHECK(dns_message_gettempname(msg, &name)); dns_name_init(name, NULL); dns_name_clone(&tuple->name, name); ISC_LIST_APPEND(name->list, rds, link); *target = name; return (ISC_R_SUCCESS); failure: if (rds != NULL) dns_rdataset_disassociate(rds); dns_message_puttemprdataset(msg, &rds); if (rdl != NULL) { ISC_LIST_UNLINK(rdl->rdata, rdata, link); dns_message_puttemprdatalist(msg, &rdl); } if (rdata != NULL) dns_message_puttemprdata(msg, &rdata); return (result);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -