00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "ares_private.h"
00024 #include "ares_dns.h"
00025
00026 static void write_tcp_data(ares_channel channel, fd_set *write_fds,
00027 time_t now);
00028 static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now);
00029 static void read_udp_packets(ares_channel channel, fd_set *read_fds,
00030 time_t now);
00031 static void process_timeouts(ares_channel channel, time_t now);
00032 static void process_answer(ares_channel channel, unsigned char *abuf,
00033 int alen, int whichserver, int tcp, int now);
00034 static void handle_error(ares_channel channel, int whichserver, time_t now);
00035 static void next_server(ares_channel channel, struct query *query, time_t now);
00036 static int open_tcp_socket(ares_channel channel, struct server_state *server);
00037 static int open_udp_socket(ares_channel channel, struct server_state *server);
00038 static int same_questions(const unsigned char *qbuf, int qlen,
00039 const unsigned char *abuf, int alen);
00040 static void end_query(ares_channel channel, struct query *query, int status,
00041 unsigned char *abuf, int alen);
00042
00043
00044
00045
00046 void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
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 }
00056
00057
00058
00059
00060 static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
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
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
00078 n = 0;
00079 for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
00080 n++;
00081
00082 #ifdef HAVE_WRITEV
00083
00084 vec = malloc(n * sizeof(struct iovec));
00085 if (vec)
00086 {
00087
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
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
00125 {
00126
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
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 }
00151
00152
00153
00154
00155
00156 static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
00157 {
00158 struct server_state *server;
00159 int i, count;
00160
00161 for (i = 0; i < channel->nservers; i++)
00162 {
00163
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
00171
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
00186
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
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
00212
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 }
00223
00224
00225 static void read_udp_packets(ares_channel channel, fd_set *read_fds,
00226 time_t now)
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
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 }
00246
00247
00248 static void process_timeouts(ares_channel channel, time_t now)
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 }
00262
00263
00264 static void process_answer(ares_channel channel, unsigned char *abuf,
00265 int alen, int whichserver, int tcp, int now)
00266 {
00267 int id, tc, rcode;
00268 struct query *query;
00269
00270
00271
00272 if (alen < HFIXEDSZ)
00273 return;
00274
00275
00276 id = DNS_HEADER_QID(abuf);
00277 tc = DNS_HEADER_TC(abuf);
00278 rcode = DNS_HEADER_RCODE(abuf);
00279
00280
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
00290
00291
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
00304
00305
00306 if (alen > PACKETSZ && !tcp)
00307 alen = PACKETSZ;
00308
00309
00310
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 }
00331
00332 static void handle_error(ares_channel channel, int whichserver, time_t now)
00333 {
00334 struct query *query;
00335
00336
00337 ares__close_sockets(&channel->servers[whichserver]);
00338
00339
00340
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 }
00351
00352 static void next_server(ares_channel channel, struct query *query, time_t now)
00353 {
00354
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
00369 if (query->using_tcp)
00370 break;
00371 }
00372 end_query(channel, query, query->error_status, NULL, 0);
00373 }
00374
00375 void ares__send_query(ares_channel channel, struct query *query, time_t now)
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
00385
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 }
00431
00432 static int open_tcp_socket(ares_channel channel, struct server_state *server)
00433 {
00434 int s;
00435 struct sockaddr_in sin;
00436
00437
00438 s = socket(AF_INET, SOCK_STREAM, 0);
00439 if (s == -1)
00440 return -1;
00441
00442
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
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 }
00487
00488 static int open_udp_socket(ares_channel channel, struct server_state *server)
00489 {
00490 int s;
00491 struct sockaddr_in sin;
00492
00493
00494 s = socket(AF_INET, SOCK_DGRAM, 0);
00495 if (s == -1)
00496 return -1;
00497
00498
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 }
00512
00513 static int same_questions(const unsigned char *qbuf, int qlen,
00514 const unsigned char *abuf, int alen)
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
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
00536 q.p = qbuf + HFIXEDSZ;
00537 for (i = 0; i < q.qdcount; i++)
00538 {
00539
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
00554 a.p = abuf + HFIXEDSZ;
00555 for (j = 0; j < a.qdcount; j++)
00556 {
00557
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
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 }
00591
00592 static void end_query(ares_channel channel, struct query *query, int status,
00593 unsigned char *abuf, int alen)
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
00610
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 }