📄 dighost.c
字号:
} debug("have local timeout of %d", local_timeout); isc_interval_set(&l->interval, local_timeout, 0); if (l->timer != NULL) isc_timer_detach(&l->timer); result = isc_timer_create(timermgr, isc_timertype_once, NULL, &l->interval, global_task, connect_timeout, l, &l->timer); check_result(result, "isc_timer_create");} static voidconnect_done(isc_task_t *task, isc_event_t *event);/* * Unlike send_udp, this can't be called multiple times with the same * query. When we retry TCP, we requeue the whole lookup, which should * start anew. */static voidsend_tcp_connect(dig_query_t *query) { isc_result_t result; dig_query_t *next; dig_lookup_t *l; debug("send_tcp_connect(%p)", query); l = query->lookup; query->waiting_connect = ISC_TRUE; query->lookup->current_query = query; get_address(query->servname, port, &query->sockaddr); if (specified_source && (isc_sockaddr_pf(&query->sockaddr) != isc_sockaddr_pf(&bind_address))) { printf(";; Skipping server %s, incompatible " "address family\n", query->servname); query->waiting_connect = ISC_FALSE; next = ISC_LIST_NEXT(query, link); l = query->lookup; clear_query(query); if (next == NULL) { printf(";; No acceptable nameservers\n"); check_next_lookup(l); return; } send_tcp_connect(next); return; } INSIST(query->sock == NULL); result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr), isc_sockettype_tcp, &query->sock); check_result(result, "isc_socket_create"); sockcount++; debug("sockcount=%d", sockcount); if (specified_source) result = isc_socket_bind(query->sock, &bind_address); else { if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4) isc_sockaddr_any(&bind_any); else isc_sockaddr_any6(&bind_any); result = isc_socket_bind(query->sock, &bind_any); } check_result(result, "isc_socket_bind"); bringup_timer(query, TCP_TIMEOUT); result = isc_socket_connect(query->sock, &query->sockaddr, global_task, connect_done, query); check_result(result, "isc_socket_connect"); /* * If we're at the endgame of a nameserver search, we need to * immediately bring up all the queries. Do it here. */ if (l->ns_search_only && !l->trace_root) { debug("sending next, since searching"); next = ISC_LIST_NEXT(query, link); if (next != NULL) send_tcp_connect(next); }}/* * Send a UDP packet to the remote nameserver, possible starting the * recv action as well. Also make sure that the timer is running and * is properly reset. */static voidsend_udp(dig_query_t *query) { dig_lookup_t *l = NULL; dig_query_t *next; isc_result_t result; debug("send_udp(%p)", query); l = query->lookup; bringup_timer(query, UDP_TIMEOUT); l->current_query = query; debug("working on lookup %p, query %p", query->lookup, query); if (!query->recv_made) { /* XXX Check the sense of this, need assertion? */ query->waiting_connect = ISC_FALSE; get_address(query->servname, port, &query->sockaddr); result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr), isc_sockettype_udp, &query->sock); check_result(result, "isc_socket_create"); sockcount++; debug("sockcount=%d", sockcount); if (specified_source) { result = isc_socket_bind(query->sock, &bind_address); } else { isc_sockaddr_anyofpf(&bind_any, isc_sockaddr_pf(&query->sockaddr)); result = isc_socket_bind(query->sock, &bind_any); } check_result(result, "isc_socket_bind"); query->recv_made = ISC_TRUE; ISC_LINK_INIT(&query->recvbuf, link); ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); debug("recving with lookup=%p, query=%p, sock=%p", query->lookup, query, query->sock); result = isc_socket_recvv(query->sock, &query->recvlist, 1, global_task, recv_done, query); check_result(result, "isc_socket_recvv"); recvcount++; debug("recvcount=%d", recvcount); } ISC_LIST_INIT(query->sendlist); ISC_LINK_INIT(&l->sendbuf, link); ISC_LIST_ENQUEUE(query->sendlist, &l->sendbuf, link); debug("sending a request"); TIME_NOW(&query->time_sent); INSIST(query->sock != NULL); result = isc_socket_sendtov(query->sock, &query->sendlist, global_task, send_done, query, &query->sockaddr, NULL); check_result(result, "isc_socket_sendtov"); sendcount++; /* * If we're at the endgame of a nameserver search, we need to * immediately bring up all the queries. Do it here. */ if (l->ns_search_only && !l->trace_root) { debug("sending next, since searching"); next = ISC_LIST_NEXT(query, link); if (next != NULL) send_udp(next); }}/* * IO timeout handler, used for both connect and recv timeouts. If * retries are still allowed, either resend the UDP packet or queue a * new TCP lookup. Otherwise, cancel the lookup. */static voidconnect_timeout(isc_task_t *task, isc_event_t *event) { dig_lookup_t *l = NULL, *n; dig_query_t *query = NULL, *cq; UNUSED(task); REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE); debug("connect_timeout()"); LOCK_LOOKUP; l = event->ev_arg; query = l->current_query; isc_event_free(&event); INSIST(!free_now); if ((query != NULL) && (query->lookup->current_query != NULL) && (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) { debug("trying next server..."); cq = query->lookup->current_query; if (!l->tcp_mode) send_udp(ISC_LIST_NEXT(cq, link)); else send_tcp_connect(ISC_LIST_NEXT(cq, link)); UNLOCK_LOOKUP; return; } if (l->retries > 1) { if (!l->tcp_mode) { l->retries--; debug("resending UDP request to first server"); send_udp(ISC_LIST_HEAD(l->q)); } else { debug("making new TCP request, %d tries left", l->retries); l->retries--; n = requeue_lookup(l, ISC_TRUE); cancel_lookup(l); check_next_lookup(l); } } else { fputs(l->cmdline, stdout); printf(";; connection timed out; no servers could be " "reached\n"); cancel_lookup(l); check_next_lookup(l); if (exitcode < 9) exitcode = 9; } UNLOCK_LOOKUP;}/* * Event handler for the TCP recv which gets the length header of TCP * packets. Start the next recv of length bytes. */static voidtcp_length_done(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent; isc_buffer_t *b = NULL; isc_result_t result; dig_query_t *query = NULL; dig_lookup_t *l; isc_uint16_t length; REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); INSIST(!free_now); UNUSED(task); debug("tcp_length_done()"); LOCK_LOOKUP; sevent = (isc_socketevent_t *)event; query = event->ev_arg; recvcount--; INSIST(recvcount >= 0); if (sevent->result == ISC_R_CANCELED) { isc_event_free(&event); l = query->lookup; clear_query(query); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (sevent->result != ISC_R_SUCCESS) { char sockstr[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); printf(";; communications error to %s: %s\n", sockstr, isc_result_totext(sevent->result)); l = query->lookup; isc_socket_detach(&query->sock); sockcount--; debug("sockcount=%d", sockcount); INSIST(sockcount >= 0); isc_event_free(&event); clear_query(query); check_next_lookup(l); UNLOCK_LOOKUP; return; } b = ISC_LIST_HEAD(sevent->bufferlist); ISC_LIST_DEQUEUE(sevent->bufferlist, &query->lengthbuf, link); length = isc_buffer_getuint16(b); if (length == 0) { isc_event_free(&event); launch_next_query(query, ISC_FALSE); UNLOCK_LOOKUP; return; } /* * Even though the buffer was already init'ed, we need * to redo it now, to force the length we want. */ isc_buffer_invalidate(&query->recvbuf); isc_buffer_init(&query->recvbuf, query->recvspace, length); ENSURE(ISC_LIST_EMPTY(query->recvlist)); ISC_LINK_INIT(&query->recvbuf, link); ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); debug("recving with lookup=%p, query=%p", query->lookup, query); result = isc_socket_recvv(query->sock, &query->recvlist, length, task, recv_done, query); check_result(result, "isc_socket_recvv"); recvcount++; debug("resubmitted recv request with length %d, recvcount=%d", length, recvcount); isc_event_free(&event); UNLOCK_LOOKUP;}/* * For transfers that involve multiple recvs (XFR's in particular), * launch the next recv. */static voidlaunch_next_query(dig_query_t *query, isc_boolean_t include_question) { isc_result_t result; dig_lookup_t *l; INSIST(!free_now); debug("launch_next_query()"); if (!query->lookup->pending) { debug("ignoring launch_next_query because !pending"); isc_socket_detach(&query->sock); sockcount--; debug("sockcount=%d", sockcount); INSIST(sockcount >= 0); query->waiting_connect = ISC_FALSE; l = query->lookup; clear_query(query); check_next_lookup(l); return; } isc_buffer_clear(&query->slbuf); isc_buffer_clear(&query->lengthbuf); isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->lookup->sendbuf.used); ISC_LIST_INIT(query->sendlist); ISC_LINK_INIT(&query->slbuf, link); ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link); if (include_question) { ISC_LINK_INIT(&query->lookup->sendbuf, link); ISC_LIST_ENQUEUE(query->sendlist, &query->lookup->sendbuf, link); } ISC_LINK_INIT(&query->lengthbuf, link); ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link); result = isc_socket_recvv(query->sock, &query->lengthlist, 0, global_task, tcp_length_done, query); check_result(result, "isc_socket_recvv"); recvcount++; debug("recvcount=%d", recvcount); if (!query->first_soa_rcvd) { debug("sending a request in launch_next_query"); TIME_NOW(&query->time_sent); result = isc_socket_sendv(query->sock, &query->sendlist, global_task, send_done, query); check_result(result, "isc_socket_sendv"); sendcount++; debug("sendcount=%d", sendcount); } query->waiting_connect = ISC_FALSE;#if 0 check_next_lookup(query->lookup);#endif return;}/* * Event handler for TCP connect complete. Make sure the connection was * successful, then pass into launch_next_query to actually send the * question. */static voidconnect_done(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = NULL; dig_query_t *query = NULL, *next; dig_lookup_t *l; UNUSED(task); REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); INSIST(!free_now); debug("connect_done()"); LOCK_LOOKUP; sevent = (isc_socketevent_t *)event; query = sevent->ev_arg; INSIST(query->waiting_connect); query->waiting_connect = ISC_FALSE; if (sevent->result == ISC_R_CANCELED) { debug("in cancel handler"); isc_socket_detach(&query->sock); sockcount--; INSIST(sockcount >= 0); debug("sockcount=%d", sockcount); query->waiting_connect = ISC_FALSE; isc_event_free(&event); l = query->lookup; clear_query(query); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (sevent->result != ISC_R_SUCCESS) { char sockstr[ISC_SOCKADDR_FORMATSIZE]; debug("unsuccessful connection: %s", isc_result_totext(sevent->result)); isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); if (sevent->result != ISC_R_CANCELED) printf(";; Connection to %s(%s) for %s failed: " "%s.\n", sockstr, query->servname, query->lookup->textname, isc_result_totext(sevent->result)); isc_socket_detach(&query->sock); sockcount--; INSIST(sockcount >= 0); /* XXX Clean up exitcodes */ if (exitcode < 9) exitcode = 9; debug("sockcount=%d", sockcount); query->waiting_connect = ISC_FALSE; isc_event_free(&event); l = query->lookup; if (l->current_query != NULL) next = ISC_LIST_NEXT(l->current_query, link); else next = NULL; clear_query(query); if (next != NULL) { bringup_timer(next, TCP_TIMEOUT); send_tcp_connect(next); } else { check_next_lookup(l); } UNLOCK_LOOKUP; return; } launch_next_query(query, ISC_TRUE); isc_event_free(&event); UNLOCK_LOOKUP;}/* * Check if the ongoing XFR needs more data before it's complete, using * the semantics of IXFR and AXFR protocols. Much of the complexity of * this routine comes from determining when an IXFR is complete. * ISC_FALSE means more data is on the way, and the recv has been issued. */static isc_boolean_tcheck_for_more_data(dig_query_t *query, dns_message_t *msg, isc_socketevent_t *sevent){ dns_rdataset_t *rdataset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; isc_uint32_t serial; isc_result_t result; debug("check_for_more_data()"); /* * By the time we're in this routine, we know we're doing * either an AXFR or IXFR. If there's no second_rr_type, * then we don't yet know which kind of answer we got back * from the server. Here, we're going to walk through the * rr's in th
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -