#include "ares_private.h"
#include "ares_dns.h"
Include dependency graph for ares_process.c:
Go to the source code of this file.
Functions | |
void | write_tcp_data (ares_channel channel, fd_set *write_fds, time_t now) |
void | read_tcp_data (ares_channel channel, fd_set *read_fds, time_t now) |
void | read_udp_packets (ares_channel channel, fd_set *read_fds, time_t now) |
void | process_timeouts (ares_channel channel, time_t now) |
void | process_answer (ares_channel channel, unsigned char *abuf, int alen, int whichserver, int tcp, int now) |
void | handle_error (ares_channel channel, int whichserver, time_t now) |
void | next_server (ares_channel channel, struct query *query, time_t now) |
int | open_tcp_socket (ares_channel channel, struct server_state *server) |
int | open_udp_socket (ares_channel channel, struct server_state *server) |
int | same_questions (const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen) |
void | end_query (ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen) |
void | ares_process (ares_channel channel, fd_set *read_fds, fd_set *write_fds) |
void | ares__send_query (ares_channel channel, struct query *query, time_t now) |
|
Definition at line 375 of file ares_process.c. References ares_channel, ARES_ENOMEM, end_query(), malloc, next_server(), ares_channeldata::nservers, NULL, open_tcp_socket(), open_udp_socket(), query::qbuf, query::qlen, query::server, ares_channeldata::servers, query::skip_server, query::tcpbuf, query::tcplen, ares_channeldata::timeout, query::timeout, query::try, and query::using_tcp. Referenced by ares_send(), next_server(), and process_answer().
00376 { 00377 struct send_request *sendreq; 00378 struct server_state *server; 00379 00380 server = &channel->servers[query->server]; 00381 00382 if (query->using_tcp) 00383 { 00384 /* Make sure the TCP socket for this server is set up and queue 00385 * a send request. 00386 */ 00387 if (server->tcp_socket == -1) 00388 { 00389 if (open_tcp_socket(channel, server) == -1) 00390 { 00391 query->skip_server[query->server] = 1; 00392 next_server(channel, query, now); 00393 return; 00394 } 00395 } 00396 sendreq = malloc(sizeof(struct send_request)); 00397 if (!sendreq) 00398 end_query(channel, query, ARES_ENOMEM, NULL, 0); 00399 sendreq->data = query->tcpbuf; 00400 sendreq->len = query->tcplen; 00401 sendreq->next = NULL; 00402 if (server->qtail) 00403 server->qtail->next = sendreq; 00404 else 00405 server->qhead = sendreq; 00406 server->qtail = sendreq; 00407 query->timeout = 0; 00408 } 00409 else 00410 { 00411 if (server->udp_socket == -1) 00412 { 00413 if (open_udp_socket(channel, server) == -1) 00414 { 00415 query->skip_server[query->server] = 1; 00416 next_server(channel, query, now); 00417 return; 00418 } 00419 } 00420 if (send(server->udp_socket, (void *) query->qbuf, query->qlen, 0) == -1) 00421 { 00422 query->skip_server[query->server] = 1; 00423 next_server(channel, query, now); 00424 return; 00425 } 00426 query->timeout = now 00427 + ((query->try == 0) ? channel->timeout 00428 : channel->timeout << query->try / channel->nservers); 00429 } 00430 } |
Here is the call graph for this function:
|
Definition at line 46 of file ares_process.c. References ares_channel, process_timeouts(), read_tcp_data(), read_udp_packets(), time, and write_tcp_data(). Referenced by dns_client(), and gethostbynameaddr().
00047 { 00048 time_t now; 00049 00050 time(&now); 00051 write_tcp_data(channel, write_fds, now); 00052 read_tcp_data(channel, read_fds, now); 00053 read_udp_packets(channel, read_fds, now); 00054 process_timeouts(channel, now); 00055 } |
Here is the call graph for this function:
|
Definition at line 592 of file ares_process.c. References ares__close_sockets(), ares_channel, ARES_FLAG_STAYOPEN, query::arg, query::callback, ares_channeldata::flags, free, query::next, ares_channeldata::nservers, ares_channeldata::queries, ares_channeldata::servers, query::skip_server, status, and query::tcpbuf. Referenced by ares__send_query(), next_server(), and process_answer().
00594 { 00595 struct query **q; 00596 int i; 00597 00598 query->callback(query->arg, status, abuf, alen); 00599 for (q = &channel->queries; *q; q = &(*q)->next) 00600 { 00601 if (*q == query) 00602 break; 00603 } 00604 *q = query->next; 00605 free(query->tcpbuf); 00606 free(query->skip_server); 00607 free(query); 00608 00609 /* Simple cleanup policy: if no queries are remaining, close all 00610 * network sockets unless STAYOPEN is set. 00611 */ 00612 if (!channel->queries && !(channel->flags & ARES_FLAG_STAYOPEN)) 00613 { 00614 for (i = 0; i < channel->nservers; i++) 00615 ares__close_sockets(&channel->servers[i]); 00616 } 00617 } |
Here is the call graph for this function:
|
Definition at line 332 of file ares_process.c. References ares__close_sockets(), ares_channel, query::next, next_server(), ares_channeldata::queries, and ares_channeldata::servers. Referenced by read_tcp_data(), read_udp_packets(), and write_tcp_data().
00333 { 00334 struct query *query; 00335 00336 /* Reset communications with this server. */ 00337 ares__close_sockets(&channel->servers[whichserver]); 00338 00339 /* Tell all queries talking to this server to move on and not try 00340 * this server again. 00341 */ 00342 for (query = channel->queries; query; query = query->next) 00343 { 00344 if (query->server == whichserver) 00345 { 00346 query->skip_server[whichserver] = 1; 00347 next_server(channel, query, now); 00348 } 00349 } 00350 } |
Here is the call graph for this function:
|
Definition at line 352 of file ares_process.c. References ares__send_query(), ares_channel, end_query(), query::error_status, ares_channeldata::nservers, NULL, query::server, query::skip_server, ares_channeldata::tries, query::try, and query::using_tcp. Referenced by ares__send_query(), handle_error(), process_answer(), and process_timeouts().
00353 { 00354 /* Advance to the next server or try. */ 00355 query->server++; 00356 for (; query->try < channel->tries; query->try++) 00357 { 00358 for (; query->server < channel->nservers; query->server++) 00359 { 00360 if (!query->skip_server[query->server]) 00361 { 00362 ares__send_query(channel, query, now); 00363 return; 00364 } 00365 } 00366 query->server = 0; 00367 00368 /* Only one try if we're using TCP. */ 00369 if (query->using_tcp) 00370 break; 00371 } 00372 end_query(channel, query, query->error_status, NULL, 0); 00373 } |
Here is the call graph for this function:
|
Definition at line 432 of file ares_process.c. References server_state::addr, AF_INET, ares_channel, FIONBIO, lwip_ioctl(), O_NONBLOCK, sockaddr_in::sin_addr, sockaddr_in::sin_family, sockaddr_in::sin_port, SOCK_STREAM, ares_channeldata::tcp_port, server_state::tcp_socket, and u32_t. Referenced by ares__send_query().
00433 { 00434 int s; 00435 struct sockaddr_in sin; 00436 00437 /* Acquire a socket. */ 00438 s = socket(AF_INET, SOCK_STREAM, 0); 00439 if (s == -1) 00440 return -1; 00441 00442 /* Set the socket non-blocking. */ 00443 #ifdef __LWIP_SOCKETS_H__ 00444 { 00445 u32_t on = 1; 00446 if (lwip_ioctl(s, FIONBIO, &on)) 00447 { 00448 close(s); 00449 return -1; 00450 } 00451 } 00452 #else 00453 { 00454 int flags; 00455 00456 if (fcntl(s, F_GETFL, &flags) == -1) 00457 { 00458 close(s); 00459 return -1; 00460 } 00461 flags &= O_NONBLOCK; 00462 if (fcntl(s, F_SETFL, flags) == -1) 00463 { 00464 close(s); 00465 return -1; 00466 } 00467 } 00468 #endif 00469 00470 /* Connect to the server. */ 00471 memset(&sin, 0, sizeof(sin)); 00472 sin.sin_family = AF_INET; 00473 00474 sin.sin_addr = server->addr; 00475 00476 sin.sin_port = channel->tcp_port; 00477 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1 00478 && errno != EINPROGRESS) 00479 { 00480 close(s); 00481 return -1; 00482 } 00483 00484 server->tcp_socket = s; 00485 return 0; 00486 } |
Here is the call graph for this function:
|
Definition at line 488 of file ares_process.c. References server_state::addr, AF_INET, ares_channel, sockaddr_in::sin_addr, sockaddr_in::sin_family, sockaddr_in::sin_port, SOCK_DGRAM, ares_channeldata::udp_port, and server_state::udp_socket. Referenced by ares__send_query().
00489 { 00490 int s; 00491 struct sockaddr_in sin; 00492 00493 /* Acquire a socket. */ 00494 s = socket(AF_INET, SOCK_DGRAM, 0); 00495 if (s == -1) 00496 return -1; 00497 00498 /* Connect to the server. */ 00499 memset(&sin, 0, sizeof(sin)); 00500 sin.sin_family = AF_INET; 00501 sin.sin_addr = server->addr; 00502 sin.sin_port = channel->udp_port; 00503 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) 00504 { 00505 close(s); 00506 return -1; 00507 } 00508 00509 server->udp_socket = s; 00510 return 0; 00511 } |
|
Definition at line 264 of file ares_process.c. References ares__send_query(), ares_channel, ARES_FLAG_IGNTC, ARES_FLAG_NOCHECKRESP, ARES_SUCCESS, DNS_HEADER_QID, DNS_HEADER_RCODE, DNS_HEADER_TC, end_query(), ares_channeldata::flags, HFIXEDSZ, query::next, next_server(), NOTIMP, PACKETSZ, ares_channeldata::queries, REFUSED, same_questions(), and SERVFAIL. Referenced by read_tcp_data(), and read_udp_packets().
00266 { 00267 int id, tc, rcode; 00268 struct query *query; 00269 00270 /* If there's no room in the answer for a header, we can't do much 00271 * with it. */ 00272 if (alen < HFIXEDSZ) 00273 return; 00274 00275 /* Grab the query ID, truncate bit, and response code from the packet. */ 00276 id = DNS_HEADER_QID(abuf); 00277 tc = DNS_HEADER_TC(abuf); 00278 rcode = DNS_HEADER_RCODE(abuf); 00279 00280 /* Find the query corresponding to this packet. */ 00281 for (query = channel->queries; query; query = query->next) 00282 { 00283 if (query->qid == id) 00284 break; 00285 } 00286 if (!query) 00287 return; 00288 00289 /* If we got a truncated UDP packet and are not ignoring truncation, 00290 * don't accept the packet, and switch the query to TCP if we hadn't 00291 * done so already. 00292 */ 00293 if ((tc || alen > PACKETSZ) && !tcp && !(channel->flags & ARES_FLAG_IGNTC)) 00294 { 00295 if (!query->using_tcp) 00296 { 00297 query->using_tcp = 1; 00298 ares__send_query(channel, query, now); 00299 } 00300 return; 00301 } 00302 00303 /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we 00304 * are ignoring truncation. 00305 */ 00306 if (alen > PACKETSZ && !tcp) 00307 alen = PACKETSZ; 00308 00309 /* If we aren't passing through all error packets, discard packets 00310 * with SERVFAIL, NOTIMP, or REFUSED response codes. 00311 */ 00312 if (!(channel->flags & ARES_FLAG_NOCHECKRESP)) 00313 { 00314 if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED) 00315 { 00316 query->skip_server[whichserver] = 1; 00317 if (query->server == whichserver) 00318 next_server(channel, query, now); 00319 return; 00320 } 00321 if (!same_questions(query->qbuf, query->qlen, abuf, alen)) 00322 { 00323 if (query->server == whichserver) 00324 next_server(channel, query, now); 00325 return; 00326 } 00327 } 00328 00329 end_query(channel, query, ARES_SUCCESS, abuf, alen); 00330 } |
Here is the call graph for this function:
|
Definition at line 248 of file ares_process.c. References ares_channel, ARES_ETIMEOUT, fsdata_file::next, next, next_server(), and ares_channeldata::queries. Referenced by ares_process().
00249 { 00250 struct query *query, *next; 00251 00252 for (query = channel->queries; query; query = next) 00253 { 00254 next = query->next; 00255 if (query->timeout != 0 && now >= query->timeout) 00256 { 00257 query->error_status = ARES_ETIMEOUT; 00258 next_server(channel, query, now); 00259 } 00260 } 00261 } |
Here is the call graph for this function:
|
Definition at line 156 of file ares_process.c. References ares_channel, FD_ISSET, free, handle_error(), malloc, ares_channeldata::nservers, NULL, process_answer(), and ares_channeldata::servers. Referenced by ares_process().
00157 { 00158 struct server_state *server; 00159 int i, count; 00160 00161 for (i = 0; i < channel->nservers; i++) 00162 { 00163 /* Make sure the server has a socket and is selected in read_fds. */ 00164 server = &channel->servers[i]; 00165 if (server->tcp_socket == -1 || !FD_ISSET(server->tcp_socket, read_fds)) 00166 continue; 00167 00168 if (server->tcp_lenbuf_pos != 2) 00169 { 00170 /* We haven't yet read a length word, so read that (or 00171 * what's left to read of it). 00172 */ 00173 count = read(server->tcp_socket, 00174 server->tcp_lenbuf + server->tcp_lenbuf_pos, 00175 2 - server->tcp_lenbuf_pos); 00176 if (count <= 0) 00177 { 00178 handle_error(channel, i, now); 00179 continue; 00180 } 00181 00182 server->tcp_lenbuf_pos += count; 00183 if (server->tcp_lenbuf_pos == 2) 00184 { 00185 /* We finished reading the length word. Decode the 00186 * length and allocate a buffer for the data. 00187 */ 00188 server->tcp_length = server->tcp_lenbuf[0] << 8 00189 | server->tcp_lenbuf[1]; 00190 server->tcp_buffer = malloc(server->tcp_length); 00191 if (!server->tcp_buffer) 00192 handle_error(channel, i, now); 00193 server->tcp_buffer_pos = 0; 00194 } 00195 } 00196 else 00197 { 00198 /* Read data into the allocated buffer. */ 00199 count = read(server->tcp_socket, 00200 server->tcp_buffer + server->tcp_buffer_pos, 00201 server->tcp_length - server->tcp_buffer_pos); 00202 if (count <= 0) 00203 { 00204 handle_error(channel, i, now); 00205 continue; 00206 } 00207 00208 server->tcp_buffer_pos += count; 00209 if (server->tcp_buffer_pos == server->tcp_length) 00210 { 00211 /* We finished reading this answer; process it and 00212 * prepare to read another length word. 00213 */ 00214 process_answer(channel, server->tcp_buffer, server->tcp_length, 00215 i, 1, now); 00216 free(server->tcp_buffer); 00217 server->tcp_buffer = NULL; 00218 server->tcp_lenbuf_pos = 0; 00219 } 00220 } 00221 } 00222 } |
Here is the call graph for this function:
|
Definition at line 225 of file ares_process.c. References ares_channel, FD_ISSET, handle_error(), ares_channeldata::nservers, PACKETSZ, process_answer(), and ares_channeldata::servers. Referenced by ares_process().
00227 { 00228 struct server_state *server; 00229 int i, count; 00230 unsigned char buf[PACKETSZ + 1]; 00231 00232 for (i = 0; i < channel->nservers; i++) 00233 { 00234 /* Make sure the server has a socket and is selected in read_fds. */ 00235 server = &channel->servers[i]; 00236 if (server->udp_socket == -1 || !FD_ISSET(server->udp_socket, read_fds)) 00237 continue; 00238 00239 count = recv(server->udp_socket, buf, sizeof(buf), 0); 00240 if (count <= 0) 00241 handle_error(channel, i, now); 00242 00243 process_answer(channel, buf, count, i, 0, now); 00244 } 00245 } |
Here is the call graph for this function:
|
Definition at line 513 of file ares_process.c. References ares_expand_name(), ARES_SUCCESS, DNS_HEADER_QDCOUNT, DNS_QUESTION_CLASS, DNS_QUESTION_TYPE, free, HFIXEDSZ, name, QFIXEDSZ, and strcasecmp. Referenced by process_answer().
00515 { 00516 struct { 00517 const unsigned char *p; 00518 int qdcount; 00519 char *name; 00520 int namelen; 00521 int type; 00522 int dnsclass; 00523 } q, a; 00524 int i, j; 00525 00526 if (qlen < HFIXEDSZ || alen < HFIXEDSZ) 00527 return 0; 00528 00529 /* Extract qdcount from the request and reply buffers and compare them. */ 00530 q.qdcount = DNS_HEADER_QDCOUNT(qbuf); 00531 a.qdcount = DNS_HEADER_QDCOUNT(abuf); 00532 if (q.qdcount != a.qdcount) 00533 return 0; 00534 00535 /* For each question in qbuf, find it in abuf. */ 00536 q.p = qbuf + HFIXEDSZ; 00537 for (i = 0; i < q.qdcount; i++) 00538 { 00539 /* Decode the question in the query. */ 00540 if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen) 00541 != ARES_SUCCESS) 00542 return 0; 00543 q.p += q.namelen; 00544 if (q.p + QFIXEDSZ > qbuf + qlen) 00545 { 00546 free(q.name); 00547 return 0; 00548 } 00549 q.type = DNS_QUESTION_TYPE(q.p); 00550 q.dnsclass = DNS_QUESTION_CLASS(q.p); 00551 q.p += QFIXEDSZ; 00552 00553 /* Search for this question in the answer. */ 00554 a.p = abuf + HFIXEDSZ; 00555 for (j = 0; j < a.qdcount; j++) 00556 { 00557 /* Decode the question in the answer. */ 00558 if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) 00559 != ARES_SUCCESS) 00560 { 00561 free(q.name); 00562 return 0; 00563 } 00564 a.p += a.namelen; 00565 if (a.p + QFIXEDSZ > abuf + alen) 00566 { 00567 free(q.name); 00568 free(a.name); 00569 return 0; 00570 } 00571 a.type = DNS_QUESTION_TYPE(a.p); 00572 a.dnsclass = DNS_QUESTION_CLASS(a.p); 00573 a.p += QFIXEDSZ; 00574 00575 /* Compare the decoded questions. */ 00576 if (strcasecmp(q.name, a.name) == 0 && q.type == a.type 00577 && q.dnsclass == a.dnsclass) 00578 { 00579 free(a.name); 00580 break; 00581 } 00582 free(a.name); 00583 } 00584 00585 free(q.name); 00586 if (j == a.qdcount) 00587 return 0; 00588 } 00589 return 1; 00590 } |
Here is the call graph for this function:
|
Definition at line 60 of file ares_process.c. References ares_channel, FD_ISSET, free, handle_error(), malloc, ares_channeldata::nservers, NULL, and ares_channeldata::servers. Referenced by ares_process().
00061 { 00062 struct server_state *server; 00063 struct send_request *sendreq; 00064 #ifdef HAVE_WRITEV 00065 struct iovec *vec; 00066 #endif 00067 int i, n, count; 00068 00069 for (i = 0; i < channel->nservers; i++) 00070 { 00071 /* Make sure server has data to send and is selected in write_fds. */ 00072 server = &channel->servers[i]; 00073 if (!server->qhead || server->tcp_socket == -1 00074 || !FD_ISSET(server->tcp_socket, write_fds)) 00075 continue; 00076 00077 /* Count the number of send queue items. */ 00078 n = 0; 00079 for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) 00080 n++; 00081 00082 #ifdef HAVE_WRITEV 00083 /* Allocate iovecs so we can send all our data at once. */ 00084 vec = malloc(n * sizeof(struct iovec)); 00085 if (vec) 00086 { 00087 /* Fill in the iovecs and send. */ 00088 n = 0; 00089 for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) 00090 { 00091 vec[n].iov_base = (char *) sendreq->data; 00092 vec[n].iov_len = sendreq->len; 00093 n++; 00094 } 00095 count = writev(server->tcp_socket, vec, n); 00096 free(vec); 00097 if (count < 0) 00098 { 00099 handle_error(channel, i, now); 00100 continue; 00101 } 00102 00103 /* Advance the send queue by as many bytes as we sent. */ 00104 while (count) 00105 { 00106 sendreq = server->qhead; 00107 if (count >= sendreq->len) 00108 { 00109 count -= sendreq->len; 00110 server->qhead = sendreq->next; 00111 if (server->qhead == NULL) 00112 server->qtail = NULL; 00113 free(sendreq); 00114 } 00115 else 00116 { 00117 sendreq->data += count; 00118 sendreq->len -= count; 00119 break; 00120 } 00121 } 00122 } 00123 else 00124 #endif /* HAVE_WRITEV */ 00125 { 00126 /* Can't allocate iovecs; just send the first request. */ 00127 sendreq = server->qhead; 00128 count = write(server->tcp_socket, (void *) sendreq->data, sendreq->len); 00129 if (count < 0) 00130 { 00131 handle_error(channel, i, now); 00132 continue; 00133 } 00134 00135 /* Advance the send queue by as many bytes as we sent. */ 00136 if (count == sendreq->len) 00137 { 00138 server->qhead = sendreq->next; 00139 if (server->qhead == NULL) 00140 server->qtail = NULL; 00141 free(sendreq); 00142 } 00143 else 00144 { 00145 sendreq->data += count; 00146 sendreq->len -= count; 00147 } 00148 } 00149 } 00150 } |
Here is the call graph for this function: