dighost.c
来自「非常好的dns解析软件」· C语言 代码 · 共 2,368 行 · 第 1/5 页
C
2,368 行
} dns_name_format(lookup->name, store, sizeof(store)); trying(store, lookup); INSIST(dns_name_isabsolute(lookup->name)); isc_random_get(&id); lookup->sendmsg->id = (unsigned short)id & 0xFFFF; lookup->sendmsg->opcode = dns_opcode_query; lookup->msgcounter = 0; /* * If this is a trace request, completely disallow recursion, since * it's meaningless for traces. */ if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root)) lookup->recurse = ISC_FALSE; if (lookup->recurse && lookup->rdtype != dns_rdatatype_axfr && lookup->rdtype != dns_rdatatype_ixfr) { debug("recursive query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; } /* XXX aaflag */ if (lookup->aaonly) { debug("AA query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA; } if (lookup->adflag) { debug("AD query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD; } if (lookup->cdflag) { debug("CD query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD; } dns_message_addname(lookup->sendmsg, lookup->name, DNS_SECTION_QUESTION); if (lookup->trace && lookup->trace_root) { lookup->qrdtype = lookup->rdtype; lookup->rdtype = dns_rdatatype_ns; } if ((lookup->rdtype == dns_rdatatype_axfr) || (lookup->rdtype == dns_rdatatype_ixfr)) { lookup->doing_xfr = ISC_TRUE; /* * Force TCP mode if we're doing an xfr. * XXX UDP ixfr's would be useful */ lookup->tcp_mode = ISC_TRUE; } add_question(lookup->sendmsg, lookup->name, lookup->rdclass, lookup->rdtype); /* add_soa */ if (lookup->rdtype == dns_rdatatype_ixfr) insert_soa(lookup); /* XXX Insist this? */ lookup->tsigctx = NULL; lookup->querysig = NULL; if (key != NULL) { debug("initializing keys"); result = dns_message_settsigkey(lookup->sendmsg, key); check_result(result, "dns_message_settsigkey"); } lookup->sendspace = isc_mempool_get(commctx); if (lookup->sendspace == NULL) fatal("memory allocation failure"); result = dns_compress_init(&cctx, -1, mctx); check_result(result, "dns_compress_init"); debug("starting to render the message"); isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE); result = dns_message_renderbegin(lookup->sendmsg, &cctx, &lookup->renderbuf); check_result(result, "dns_message_renderbegin"); if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) { if (lookup->udpsize == 0) lookup->udpsize = 4096; if (lookup->edns < 0) lookup->edns = 0; add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, lookup->dnssec); } result = dns_message_rendersection(lookup->sendmsg, DNS_SECTION_QUESTION, 0); check_result(result, "dns_message_rendersection"); result = dns_message_rendersection(lookup->sendmsg, DNS_SECTION_AUTHORITY, 0); check_result(result, "dns_message_rendersection"); result = dns_message_renderend(lookup->sendmsg); check_result(result, "dns_message_renderend"); debug("done rendering"); dns_compress_invalidate(&cctx); /* * Force TCP mode if the request is larger than 512 bytes. */ if (isc_buffer_usedlength(&lookup->renderbuf) > 512) lookup->tcp_mode = ISC_TRUE; lookup->pending = ISC_FALSE; for (serv = ISC_LIST_HEAD(lookup->my_server_list); serv != NULL; serv = ISC_LIST_NEXT(serv, link)) { query = isc_mem_allocate(mctx, sizeof(dig_query_t)); if (query == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); debug("create query %p linked to lookup %p", query, lookup); query->lookup = lookup; query->waiting_connect = ISC_FALSE; query->waiting_senddone = ISC_FALSE; query->pending_free = ISC_FALSE; query->recv_made = ISC_FALSE; query->first_pass = ISC_TRUE; query->first_soa_rcvd = ISC_FALSE; query->second_rr_rcvd = ISC_FALSE; query->first_repeat_rcvd = ISC_FALSE; query->warn_id = ISC_TRUE; query->first_rr_serial = 0; query->second_rr_serial = 0; query->servname = serv->servername; query->userarg = serv->userarg; query->rr_count = 0; query->msg_count = 0; query->byte_count = 0; ISC_LINK_INIT(query, link); ISC_LIST_INIT(query->recvlist); ISC_LIST_INIT(query->lengthlist); query->sock = NULL; query->recvspace = isc_mempool_get(commctx); if (query->recvspace == NULL) fatal("memory allocation failure"); isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE); isc_buffer_init(&query->lengthbuf, query->lengthspace, 2); isc_buffer_init(&query->slbuf, query->slspace, 2); query->sendbuf = lookup->renderbuf; ISC_LINK_INIT(query, link); ISC_LIST_ENQUEUE(lookup->q, query, link); } /* XXX qrflag, print_query, etc... */ if (!ISC_LIST_EMPTY(lookup->q) && qr) { extrabytes = 0; printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg, ISC_TRUE); }}/*% * Event handler for send completion. Track send counter, and clear out * the query if the send was canceled. */static voidsend_done(isc_task_t *_task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; isc_buffer_t *b = NULL; dig_query_t *query, *next; dig_lookup_t *l; REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); UNUSED(_task); LOCK_LOOKUP; debug("send_done()"); sendcount--; debug("sendcount=%d", sendcount); INSIST(sendcount >= 0); for (b = ISC_LIST_HEAD(sevent->bufferlist); b != NULL; b = ISC_LIST_HEAD(sevent->bufferlist)) ISC_LIST_DEQUEUE(sevent->bufferlist, b, link); query = event->ev_arg; query->waiting_senddone = ISC_FALSE; l = query->lookup; 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); } isc_event_free(&event); if (query->pending_free) isc_mem_free(mctx, query); check_if_done(); UNLOCK_LOOKUP;}/*% * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding * IO sockets. The cancel handlers should take care of cleaning up the * query and lookup structures */static voidcancel_lookup(dig_lookup_t *lookup) { dig_query_t *query, *next; debug("cancel_lookup()"); query = ISC_LIST_HEAD(lookup->q); while (query != NULL) { next = ISC_LIST_NEXT(query, link); if (query->sock != NULL) { isc_socket_cancel(query->sock, global_task, ISC_SOCKCANCEL_ALL); check_if_done(); } else { clear_query(query); } query = next; } if (lookup->timer != NULL) isc_timer_detach(&lookup->timer); lookup->pending = ISC_FALSE; lookup->retries = 0;}static voidbringup_timer(dig_query_t *query, unsigned int default_timeout) { dig_lookup_t *l; unsigned int local_timeout; isc_result_t result; debug("bringup_timer()"); /* * If the timer already exists, that means we're calling this * a second time (for a retry). Don't need to recreate it, * just reset it. */ l = query->lookup; if (ISC_LIST_NEXT(query, link) != NULL) local_timeout = SERVER_TIMEOUT; else { if (timeout == 0) local_timeout = default_timeout; else local_timeout = timeout; } 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; 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_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link); debug("sending a request"); TIME_NOW(&query->time_sent); INSIST(query->sock != NULL); query->waiting_senddone = ISC_TRUE; result = isc_socket_sendtov(query->sock, &query->sendlist, global_task, send_done, query, &query->sockaddr, NULL); check_result(result, "isc_socket_sendtov"); sendcount++;}/*% * 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; 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--; 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 *que
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?