📄 ares_process.c
字号:
{ assert( query != 0 ); assert( channel->queries != 0 ); if (query->server == whichserver) { query->skip_server[whichserver] = 1;#if 0 // !cj! - this seem to corrput memory when it is called next_server(channel, query, now);#endif } }}static void next_server(ares_channel channel, struct query *query, time_t now){ /* Advance to the next server or try. */ query->server++; for (; query->itry < channel->tries; query->itry++) { for (; query->server < channel->nservers; query->server++) { if (!query->skip_server[query->server]) { ares__send_query(channel, query, now); return; } } query->server = 0; /* Only one try if we're using TCP. */ if (query->using_tcp) break; } end_query(channel, query, query->error_status, NULL, 0);}/* * Same as next_server, but only attempt the next one if it's in a different network * (subnet, designated by the NIC's physical address). We don't loop around to the * beginning of the servers list since server responded with reply-code of 3 * 'No such name' * returns: * 1 - query sent * 0 - nothing happened */static int next_server_new_network(ares_channel channel, struct query *query, time_t now){ if (query->itry >= channel->tries) return 0; query->server++; for (; query->server < channel->nservers; query->server++) { int i = 0; struct server_state* nextToTry = &channel->servers[query->server]; if (query->skip_server[query->server]) continue; if (nextToTry->physical_addr_len == 0) continue; // only try the next DNS server, nextToTry, if it hasn't been tried UP TO THIS POINT: query->server. for (i = 0; i < query->server; i++) { if ( (channel->servers[i].physical_addr_len == nextToTry->physical_addr_len) && (memcmp(nextToTry->physical_addr, channel->servers[i].physical_addr, nextToTry->physical_addr_len) == 0)) { // we've tried this network already, try next one (query->server++). break; } } if (i == query->server) { ares__send_query(channel, query, now); return 1; } } return 0;}void ares__send_query(ares_channel channel, struct query *query, time_t now){ struct send_request *sendreq; struct server_state *server; server = &channel->servers[query->server]; if (query->using_tcp) { /* Make sure the TCP socket for this server is set up and queue * a send request. */ if (server->tcp_socket == -1) { if (open_tcp_socket(channel, server) == -1) { query->skip_server[query->server] = 1; next_server(channel, query, now); return; } } sendreq = malloc(sizeof(struct send_request)); if (!sendreq) end_query(channel, query, ARES_ENOMEM, NULL, 0); sendreq->data = query->tcpbuf; sendreq->len = query->tcplen; sendreq->next = NULL; if (server->qtail) server->qtail->next = sendreq; else server->qhead = sendreq; server->qtail = sendreq; query->timeout = 0; } else { if (server->udp_socket == -1) { if (open_udp_socket(channel, server) == -1) { query->skip_server[query->server] = 1; next_server(channel, query, now); return; } } if (send(server->udp_socket, query->qbuf, query->qlen, 0) == -1) { query->skip_server[query->server] = 1; next_server(channel, query, now); return; } query->timeout = now + ((query->itry == 0) ? channel->timeout : channel->timeout << query->itry / channel->nservers); }}static int open_tcp_socket(ares_channel channel, struct server_state *server){ int s; struct sockaddr_in sin;#ifdef USE_IPV6 struct sockaddr_in6 sin6;#endif /* Acquire a socket. */#ifdef USE_IPV6 assert(server->family == AF_INET || server->family == AF_INET6); s = socket(server->family, SOCK_STREAM, 0);#else s = socket(AF_INET, SOCK_STREAM, 0);#endif if (s == -1) return -1; /* Set the socket non-blocking. */#ifdef WIN32 { unsigned long noBlock = 1; int errNoBlock = ioctlsocket( s, FIONBIO , &noBlock ); if ( errNoBlock != 0 ) { return -1; } }#else { int flags; if (fcntl(s, F_GETFL, &flags) == -1) { ares__kill_socket(s); return -1; } flags |= O_NONBLOCK; // Fixed evil but here - used to be &= if (fcntl(s, F_SETFL, flags) == -1) { ares__kill_socket(s); return -1; }}#endif#ifdef WIN32#define PORTABLE_INPROGRESS_ERR WSAEWOULDBLOCK#else#define PORTABLE_INPROGRESS_ERR EINPROGRESS#endif /* Connect to the server. */#ifdef USE_IPV6 if (server->family == AF_INET6) { memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_addr = server->addr6; sin6.sin6_port = channel->tcp_port; sin6.sin6_flowinfo = 0; sin6.sin6_scope_id = 0; // do i need to explicitly set the length? if (connect(s, (const struct sockaddr *) &sin6 , sizeof(sin6)) == -1 && getErrno() != PORTABLE_INPROGRESS_ERR) { ares__kill_socket(s); return -1; } } else // IPv4 DNS server { memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = server->addr; sin.sin_port = channel->tcp_port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1 && getErrno() != PORTABLE_INPROGRESS_ERR) { ares__kill_socket(s); return -1; } }#else memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = server->addr; sin.sin_port = channel->tcp_port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1 && getErrno() != PORTABLE_INPROGRESS_ERR) { ares__kill_socket(s); return -1; }#endif server->tcp_socket = s; return 0;}static int open_udp_socket(ares_channel channel, struct server_state *server){ int s;#ifdef USE_IPV6 // added by Rohan 7-Sept-2004 // should really replace sockaddr_in6 with sockaddr_storage struct sockaddr_in6 sin6; struct sockaddr_in sin; /* Acquire a socket. */ assert(server->family == AF_INET || server->family == AF_INET6); s = socket(server->family, SOCK_DGRAM, 0);#ifdef WIN32 { unsigned long errNoBlock = 1; errNoBlock = ioctlsocket( s, FIONBIO , &errNoBlock ); if ( errNoBlock != 0 ) { return -1; } }#endif if (s == -1) return -1; /* Connect to the server. */ if (server->family == AF_INET6) { memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_addr = server->addr6; sin6.sin6_port = channel->udp_port; sin6.sin6_flowinfo = 0; sin6.sin6_scope_id = 0; // do i need to explicitly set the length? if (connect(s, (const struct sockaddr *) &sin6, sizeof(sin6)) == -1) { ares__kill_socket(s); return -1; } } else // IPv4 DNS server { memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = server->addr; sin.sin_port = channel->udp_port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { ares__kill_socket(s); return -1; } }#else struct sockaddr_in sin; /* Acquire a socket. */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) return -1; /* Connect to the server. */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = server->addr; sin.sin_port = channel->udp_port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { ares__kill_socket(s); return -1; }#endif if(channel->socket_function) { channel->socket_function(s, 1, __FILE__, __LINE__); } server->udp_socket = s; return 0;}static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen){ struct { const unsigned char *p; int qdcount; char *name; int namelen; int type; int dnsclass; } q, a; int i, j; if (qlen < HFIXEDSZ || alen < HFIXEDSZ) return 0; /* Extract qdcount from the request and reply buffers and compare them. */ q.qdcount = DNS_HEADER_QDCOUNT(qbuf); a.qdcount = DNS_HEADER_QDCOUNT(abuf); if (q.qdcount != a.qdcount) return 0; /* For each question in qbuf, find it in abuf. */ q.p = qbuf + HFIXEDSZ; for (i = 0; i < q.qdcount; i++) { /* Decode the question in the query. */ if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen) != ARES_SUCCESS) return 0; q.p += q.namelen; if (q.p + QFIXEDSZ > qbuf + qlen) { free(q.name); return 0; } q.type = DNS_QUESTION_TYPE(q.p); q.dnsclass = DNS_QUESTION_CLASS(q.p); q.p += QFIXEDSZ; /* Search for this question in the answer. */ a.p = abuf + HFIXEDSZ; for (j = 0; j < a.qdcount; j++) { /* Decode the question in the answer. */ if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) != ARES_SUCCESS) { free(q.name); return 0; } a.p += a.namelen; if (a.p + QFIXEDSZ > abuf + alen) { free(q.name); free(a.name); return 0; } a.type = DNS_QUESTION_TYPE(a.p); a.dnsclass = DNS_QUESTION_CLASS(a.p); a.p += QFIXEDSZ; /* Compare the decoded questions. */ if (strcasecmp(q.name, a.name) == 0 && q.type == a.type && q.dnsclass == a.dnsclass) { free(a.name); break; } free(a.name); } free(q.name); if (j == a.qdcount) return 0; } return 1;}static void end_query(ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen){ struct query **q; int i; query->callback(query->arg, status, abuf, alen); for (q = &channel->queries; *q; q = &(*q)->next) { if (*q == query) break; } *q = query->next; free(query->tcpbuf); free(query->skip_server); free(query); /* Simple cleanup policy: if no queries are remaining, close all * network sockets unless STAYOPEN is set. */ if (!channel->queries && !(channel->flags & ARES_FLAG_STAYOPEN)) { for (i = 0; i < channel->nservers; i++) ares__close_sockets(&channel->servers[i]); }}void ares__kill_socket(int s){#ifdef WIN32 closesocket(s);#else close(s);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -