reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ares_process.c
Go to the documentation of this file.
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 */
15
16#ifdef HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <sys/types.h>
21#include "rutil/ResipAssert.h"
22
23#ifndef WIN32
24#include <sys/socket.h>
25#include <sys/uio.h>
26#include <netinet/in.h>
27#ifndef __CYGWIN__
28# include "ares_nameser.h"
29#endif
30#include <unistd.h>
31#endif
32
33#include <string.h>
34#include <stdlib.h>
35#include <fcntl.h>
36#include <time.h>
37#include <errno.h>
38#include "ares.h"
39#include "ares_dns.h"
40#include "ares_private.h"
41#include "ares_local.h"
42
43#ifdef WIN32
44static int getErrno() { return WSAGetLastError(); }
45#else
46static int getErrno() { return errno; }
47#endif
48
49/* A read that would block is not a server error. When handle_error() moves
50 * a query on, the new server's socket can reuse the descriptor number of the
51 * one just closed, and so look ready to a select() or poll that ran before. */
52static int would_block(void)
53{
54#ifdef WIN32
55 return getErrno() == WSAEWOULDBLOCK;
56#else
57 return getErrno() == EAGAIN || getErrno() == EWOULDBLOCK || getErrno() == EINTR;
58#endif
59}
60
61static void write_tcp_data_core(ares_channel channel, int server_idx,
62 time_t now);
63static void write_tcp_data(ares_channel channel,
64 fd_set *write_fds, time_t now);
65static void read_tcp_data(ares_channel channel, int server_idx,
66 fd_set *read_fds, time_t now);
67static void read_udp_packets(ares_channel channel, int server_idx,
69 time_t now);
70static void process_timeouts(ares_channel channel, time_t now);
71static void process_answer(ares_channel channel, unsigned char *abuf,
72 int alen, int whichserver, int tcp, time_t now);
73static void handle_error(ares_channel channel, int whichserver, time_t now);
74static void next_server(ares_channel channel, struct query *query, time_t now);
75static int next_server_new_network(ares_channel channel, struct query *query, time_t now);
76static int open_tcp_socket(ares_channel channel, struct server_state *server);
77static int open_udp_socket(ares_channel channel, struct server_state *server);
78static int same_questions(const unsigned char *qbuf, int qlen,
79 const unsigned char *abuf, int alen);
80static void end_query(ares_channel channel, struct query *query, int status,
81 unsigned char *abuf, int alen);
82static int make_socket_non_blocking(int s);
83
84/* Something interesting happened on the wire, or there was a timeout.
85 * See what's up and respond accordingly.
86 */
88{
89 time_t now;
90
91 time(&now);
92 write_tcp_data(channel, write_fds, now);
93 read_tcp_data(channel, -1, read_fds, now);
94 read_udp_packets(channel, -1, read_fds, now);
95 process_timeouts(channel, now);
96
97 /* See if our local pseudo-db has any results. */
98 /* Querying this only on timeouts is OK (is not high-performance) */
100}
101
102/* Something happened on wire or there was a timeout. This interface
103 * is called for poll()-like systems.
104 */
106 int rdFd, int wrFd, time_t now)
107{
108 if (server_idx != -1) {
109 resip_assert(rdFd != -1 || wrFd != -1); // at least one active
110 if (wrFd != -1 && channel->servers[server_idx].tcp_socket == wrFd)
111 {
112 write_tcp_data_core(channel, server_idx, now);
113 }
114 // writes can only be for TCP (we don't ask for UDP writable events)
115 if (rdFd != -1 && channel->servers[server_idx].tcp_socket == rdFd)
116 read_tcp_data(channel, server_idx, NULL, now);
117 if (rdFd != -1 && channel->servers[server_idx].udp_socket == rdFd)
118 read_udp_packets(channel, server_idx, NULL, now);
119 }
120 else
121 {
122 process_timeouts(channel, now);
124 }
125}
126
127/* If any TCP sockets select true for writing, write out queued data
128 * we have for them.
129 */
131 time_t now)
132{
133 struct server_state* server;
134 struct send_request* sendreq;
135#ifdef WIN32
136 WSABUF* vec;
137#else
138 struct iovec* vec;
139#endif
140 int n, count;
141
142 server = &channel->servers[server_idx];
143 if (!server->qhead || server->tcp_socket == -1)
144 return;
145
146 /* Count the number of send queue items. */
147 n = 0;
148 for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
149 n++;
150
151#ifdef WIN32
152 /* Allocate iovecs so we can send all our data at once. */
153 vec = malloc(n * sizeof(WSABUF));
154 if (vec)
155 {
156 int err;
157 /* Fill in the iovecs and send. */
158 n = 0;
159 for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
160 {
161 vec[n].buf = (char*)sendreq->data;
162 vec[n].len = sendreq->len;
163 n++;
164 }
165 err = WSASend(server->tcp_socket, vec, n, &count, 0, 0, 0);
166 if (err == SOCKET_ERROR)
167 {
168 count = -1;
169 }
170 free(vec);
171#else
172 /* Allocate iovecs so we can send all our data at once. */
173 vec = malloc(n * sizeof(struct iovec));
174 if (vec)
175 {
176 // int err;
177 /* Fill in the iovecs and send. */
178 n = 0;
179 for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
180 {
181 vec[n].iov_base = (char*)sendreq->data;
182 vec[n].iov_len = sendreq->len;
183 n++;
184 }
185 count = writev(server->tcp_socket, vec, n);
186 free(vec);
187#endif
188
189 if (count < 0)
190 {
191 handle_error(channel, server_idx, now);
192 return;
193 }
194
195 /* Advance the send queue by as many bytes as we sent. */
196 while (count)
197 {
198 sendreq = server->qhead;
199 if (count >= sendreq->len)
200 {
201 count -= sendreq->len;
202 server->qhead = sendreq->next;
203 free(sendreq);
204 if (server->qhead == NULL)
205 {
206 server->qtail = NULL;
207 resip_assert(count == 0);
208 break;
209 }
210 }
211 else
212 {
213 sendreq->data += count;
214 sendreq->len -= count;
215 break;
216 }
217 }
218 }
219 else
220 {
221 /* Can't allocate iovecs; just send the first request. */
222 sendreq = server->qhead;
223#ifndef UNDER_CE
224 count = write(server->tcp_socket, sendreq->data, sendreq->len);
225#else
226 count = send(server->tcp_socket, sendreq->data, sendreq->len, 0);
227#endif
228 if (count < 0)
229 {
230 handle_error(channel, server_idx, now);
231 return;
232 }
233
234 /* Advance the send queue by as many bytes as we sent. */
235 if (count == sendreq->len)
236 {
237 server->qhead = sendreq->next;
238 if (server->qhead == NULL)
239 server->qtail = NULL;
240 free(sendreq);
241 }
242 else
243 {
244 sendreq->data += count;
245 sendreq->len -= count;
246 }
247 }
248 if (server->qhead == NULL && channel->poll_cb_func)
249 {
250 (*(channel->poll_cb_func))(channel->poll_cb_data, channel, server_idx,
252 }
253}
254
256{
257 struct server_state* server;
258 int i;
259
260 for (i = 0; i < channel->nservers; i++)
261 {
262 /* Make sure server has data to send and is selected in write_fds. */
263 server = &channel->servers[i];
264 if (!server->qhead || server->tcp_socket == -1)
265 continue;
266 if (write_fds && !FD_ISSET(server->tcp_socket, write_fds))
267 continue;
268
269 write_tcp_data_core(channel, i, now);
270 }
271}
272
273/* If any TCP socket selects true for reading, read some data,
274 * allocate a buffer if we finish reading the length word, and process
275 * a packet if we finish reading one.
276 */
278{
279 struct server_state* server;
280 int i, count;
281
282 for (i = 0; i < channel->nservers; i++)
283 {
284 /* Make sure the server has a socket and is selected in read_fds. */
285 if (server_idx >= 0 && i != server_idx)
286 continue;
287 server = &channel->servers[i];
288 if (server->tcp_socket == -1)
289 continue;
290 if (read_fds && !FD_ISSET(server->tcp_socket, read_fds))
291 continue;
292
293 if (server->tcp_lenbuf_pos != 2)
294 {
295 /* We haven't yet read a length word, so read that (or
296 * what's left to read of it).
297 */
298#if defined UNDER_CE || defined WIN32
299 count = recv(server->tcp_socket,
300 server->tcp_lenbuf + server->tcp_lenbuf_pos,
301 2 - server->tcp_lenbuf_pos, 0);
302#else
303 count = read(server->tcp_socket,
304 server->tcp_lenbuf + server->tcp_lenbuf_pos,
305 2 - server->tcp_lenbuf_pos);
306#endif
307 if (count < 0 && would_block())
308 continue;
309 if (count <= 0)
310 {
311 handle_error(channel, i, now);
312 continue;
313 }
314
315 server->tcp_lenbuf_pos += count;
316 if (server->tcp_lenbuf_pos == 2)
317 {
318 /* We finished reading the length word. Decode the
319 * length and allocate a buffer for the data.
320 */
321 server->tcp_length = server->tcp_lenbuf[0] << 8
322 | server->tcp_lenbuf[1];
323 server->tcp_buffer = malloc(server->tcp_length);
324 if (!server->tcp_buffer)
325 {
326 handle_error(channel, i, now);
327 return; /* bail out on malloc failure. TODO: make this function return error codes */
328 }
329 server->tcp_buffer_pos = 0;
330 }
331 }
332 else
333 {
334 /* Read data into the allocated buffer. */
335#if defined UNDER_CE || defined WIN32
336 count = recv(server->tcp_socket,
337 server->tcp_buffer + server->tcp_buffer_pos,
338 server->tcp_length - server->tcp_buffer_pos, 0);
339#else
340 count = read(server->tcp_socket,
341 server->tcp_buffer + server->tcp_buffer_pos,
342 server->tcp_length - server->tcp_buffer_pos);
343#endif
344
345 if (count < 0 && would_block())
346 continue;
347 if (count <= 0)
348 {
349 handle_error(channel, i, now);
350 continue;
351 }
352
353 server->tcp_buffer_pos += count;
354 if (server->tcp_buffer_pos == server->tcp_length)
355 {
356 /* We finished reading this answer; process it and
357 * prepare to read another length word.
358 */
359 process_answer(channel, server->tcp_buffer, server->tcp_length,
360 i, 1, now);
361 free(server->tcp_buffer);
362 server->tcp_buffer = NULL;
363 server->tcp_lenbuf_pos = 0;
364 }
365 }
366 }
367}
368
369/* If any UDP sockets select true for reading, process them. */
370static void read_udp_packets(ares_channel channel, int server_idx,
371 fd_set* read_fds, time_t now)
372{
373 struct server_state* server;
374 int i, count;
375 unsigned char buf[PACKETSZ + 1];
376
377 for (i = 0; i < channel->nservers; i++)
378 {
379 if (server_idx >= 0 && i != server_idx)
380 continue;
381 /* Make sure the server has a socket and is selected in read_fds. */
382 server = &channel->servers[i];
383 if (server->udp_socket == -1)
384 continue;
385 if (read_fds && !FD_ISSET(server->udp_socket, read_fds))
386 continue;
387
388 resip_assert(server->udp_socket != -1);
389
390 count = recv(server->udp_socket, buf, sizeof(buf), 0);
391 if (count <= 0)
392 {
393#if defined(WIN32)
394 //int err;
395 //err = WSAGetLastError();
396 //err = errno;
397 switch (getErrno())
398 {
399 case WSAEWOULDBLOCK:
400 if (read_fds) {
401 // read_fds is only null when using epoll
402 // which shouldn't happen under windows
403 // don't know why CLR is here anyways
404 FD_CLR(server->udp_socket, read_fds);
405 }
406 continue;
407 case WSAECONNABORTED:
408 break;
409 case WSAECONNRESET: // got an ICMP error on a previous send
410 break;
411 }
412#else
413 if (count < 0 && would_block())
414 continue;
415#endif
416 handle_error(channel, i, now);
417 }
418 else
419 {
420 process_answer(channel, buf, count, i, 0, now);
421 }
422 }
423}
424
425/* If any queries have timed out, note the timeout and move them on. */
426static void process_timeouts(ares_channel channel, time_t now)
427{
428 struct query* query, * next;
429
430 for (query = channel->queries; query; query = next)
431 {
432 next = query->next;
433 if (query->timeout != 0 && now >= query->timeout)
434 {
435 //fprintf(stderr, "kennard:ares:process_timeouts: got timeout\n");
437 next_server(channel, query, now);
438 }
439 }
440}
441
442/* Handle an answer from a server. */
443static void process_answer(ares_channel channel, unsigned char* abuf,
444 int alen, int whichserver, int tcp, time_t now)
445{
446 int id, tc, rcode;
447 struct query* query;
448
449 /* If there's no room in the answer for a header, we can't do much
450 * with it. */
451 if (alen < HFIXEDSZ)
452 return;
453
454 /* Grab the query ID, truncate bit, and response code from the packet. */
455 id = DNS_HEADER_QID(abuf);
456 tc = DNS_HEADER_TC(abuf);
457 rcode = DNS_HEADER_RCODE(abuf);
458
459 /* Find the query corresponding to this packet. */
460 for (query = channel->queries; query; query = query->next)
461 {
462 if (query->qid == id)
463 break;
464 }
465 if (!query)
466 return;
467
468 /* If we got a truncated UDP packet and are not ignoring truncation,
469 * don't accept the packet, and switch the query to TCP if we hadn't
470 * done so already.
471 */
472 if ((tc || alen > PACKETSZ) && !tcp && !(channel->flags & ARES_FLAG_IGNTC))
473 {
474 if (!query->using_tcp)
475 {
476 query->using_tcp = 1;
477 ares__send_query(channel, query, now);
478 }
479 return;
480 }
481
482 /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we
483 * are ignoring truncation.
484 */
485 if (alen > PACKETSZ && !tcp)
486 alen = PACKETSZ;
487
488 /* If we aren't passing through all error packets, discard packets
489 * with SERVFAIL, NOTIMP, or REFUSED response codes.
490 */
491 if (!(channel->flags & ARES_FLAG_NOCHECKRESP))
492 {
493 if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED)
494 {
496 if (query->server == whichserver)
497 next_server(channel, query, now);
498 return;
499 }
500 if (!same_questions((unsigned char*)query->qbuf, query->qlen, abuf, alen))
501 {
502 if (query->server == whichserver)
503 next_server(channel, query, now);
504 return;
505 }
506
507 /* 'No such name' */
509 {
510 if (query->server == whichserver)
511 {
512 if (next_server_new_network(channel, query, now))
513 return;
514 }
515 }
516 }
517
518 end_query(channel, query, ARES_SUCCESS, abuf, alen);
519}
520
521static void handle_error(ares_channel channel, int whichserver, time_t now)
522{
523 struct query* query, * next;
524
525 /* Reset communications with this server. */
526 //fprintf(stderr,"kennard:ares:handle_error: ...\n");
529
530 /* Tell all queries talking to this server to move on and not try
531 * this server again.
532 */
533 for (query = channel->queries; query != 0; query = next)
534 {
535 /* next_server() can end the query and free it. Queries it adds
536 * through the callback go on the head of the list, so next stays
537 * valid. */
538 next = query->next;
539 if (query->server == whichserver)
540 {
542 next_server(channel, query, now);
543 }
544 }
545}
546
547static void next_server(ares_channel channel, struct query* query, time_t now)
548{
549 /* Advance to the next server or try. */
550 query->server++;
551 for (; query->itry < channel->tries; query->itry++)
552 {
553 for (; query->server < channel->nservers; query->server++)
554 {
556 {
557 ares__send_query(channel, query, now);
558 return;
559 }
560 }
561 query->server = 0;
562
563 /* Only one try if we're using TCP. */
564 if (query->using_tcp)
565 break;
566 }
567 //fprintf(stderr, "kennard:ares:next_server: ran out of servers: code %d\n", query->error_status);
568 end_query(channel, query, query->error_status, NULL, 0);
569}
570
571/*
572 * Same as next_server, but only attempt the next one if it's in a different network
573 * (subnet, designated by the NIC's physical address). We don't loop around to the
574 * beginning of the servers list since server responded with reply-code of 3
575 * 'No such name'
576 * returns:
577 * 1 - query sent
578 * 0 - nothing happened
579 */
580static int next_server_new_network(ares_channel channel, struct query* query, time_t now)
581{
582 if (query->itry >= channel->tries)
583 return 0;
584
585 query->server++;
586 for (; query->server < channel->nservers; query->server++)
587 {
588 int i = 0;
589 struct server_state* nextToTry = &channel->servers[query->server];
591 continue;
592 if (nextToTry->physical_addr_len == 0)
593 continue;
594
595 // only try the next DNS server, nextToTry, if it hasn't been tried UP TO THIS POINT: query->server.
596 for (i = 0; i < query->server; i++)
597 {
598 if ((channel->servers[i].physical_addr_len == nextToTry->physical_addr_len)
599 && (memcmp(nextToTry->physical_addr, channel->servers[i].physical_addr, nextToTry->physical_addr_len) == 0))
600 {
601 // we've tried this network already, try next one (query->server++).
602 break;
603 }
604 }
605 if (i == query->server)
606 {
607 ares__send_query(channel, query, now);
608 return 1;
609 }
610 }
611 return 0;
612}
613
614void ares__send_query(ares_channel channel, struct query* query, time_t now)
615{
616 struct send_request* sendreq;
617 struct server_state* server;
618
619 server = &channel->servers[query->server];
620 if (query->using_tcp)
621 {
622 int tryWrite = 0;
623 /* Make sure the TCP socket for this server is set up and queue
624 * a send request.
625 */
626 if (server->tcp_socket == -1)
627 {
628 if (open_tcp_socket(channel, server) == -1)
629 {
631 next_server(channel, query, now);
632 return;
633 }
634 if (channel->poll_cb_func)
635 {
636 // printf("ares_send_q: pollopen tcp fd=%d\n", server->tcp_socket);
637 (*(channel->poll_cb_func))(channel->poll_cb_data, channel,
639 }
640 }
641 sendreq = malloc(sizeof(struct send_request));
642 if (!sendreq)
643 {
644 end_query(channel, query, ARES_ENOMEM, NULL, 0);
645 return;
646 }
647 sendreq->data = query->tcpbuf;
648 sendreq->len = query->tcplen;
649 sendreq->next = NULL;
650 if (server->qtail)
651 {
652 server->qtail->next = sendreq;
653 }
654 else
655 {
656 server->qhead = sendreq;
657 tryWrite = 1;
658 }
659 server->qtail = sendreq;
660 query->timeout = 0;
661 if (tryWrite)
662 {
663#if 0
664 time_t now;
665 time(&now);
666 write_tcp_data(channel, query->server, now);
667 /* XXX: the write code doesn't seem to handle EAGAIN properly! */
668#else
669 if (channel->poll_cb_func)
670 (*(channel->poll_cb_func))(channel->poll_cb_data,
671 channel, query->server,
673#endif
674 }
675 }
676 else
677 {
678 if (server->udp_socket == -1)
679 {
680 if (open_udp_socket(channel, server) == -1)
681 {
682 //fprintf(stderr,"kennard:ares:send_query:open_udp failed\n");
684 next_server(channel, query, now);
685 return;
686 }
687 if (channel->poll_cb_func)
688 {
689 // printf("ares_send_q: pollopen udp fd=%d\n", server->udp_socket);
690 (*(channel->poll_cb_func))(channel->poll_cb_data, channel,
692 }
693 }
694 if (send(server->udp_socket, query->qbuf, query->qlen, 0) == -1)
695 {
696 //fprintf(stderr,"kennard:ares:send_query:send_udp failed\n");
698 next_server(channel, query, now);
699 return;
700 }
701 }
702 // Start timeout for either UDP or TCP
703 query->timeout = now
704 + ((query->itry == 0) ? channel->timeout
705 : channel->timeout << query->itry / channel->nservers);
706}
707
708static int open_tcp_socket(ares_channel channel, struct server_state* server)
709{
710 int s;
711 struct sockaddr_in sin;
712#ifdef USE_IPV6
713 struct sockaddr_in6 sin6;
714#endif
715
716 /* Acquire a socket. */
717#ifdef USE_IPV6
718 resip_assert(server->family == AF_INET || server->family == AF_INET6);
719 s = (int)socket(server->family, SOCK_STREAM, 0);
720#else
721 s = (int)socket(AF_INET, SOCK_STREAM, 0);
722#endif
723 if (s == -1)
724 return -1;
725
727 {
729 return -1;
730 }
731
732#ifdef WIN32
733#define PORTABLE_INPROGRESS_ERR WSAEWOULDBLOCK
734#else
735#define PORTABLE_INPROGRESS_ERR EINPROGRESS
736#endif
737
738 /* Connect to the server. */
739#ifdef USE_IPV6
740 if (server->family == AF_INET6)
741 {
742 memset(&sin6, 0, sizeof(sin6));
743 sin6.sin6_family = AF_INET6;
744 sin6.sin6_addr = server->addr6;
745 sin6.sin6_port = channel->tcp_port;
746 sin6.sin6_flowinfo = 0;
747 sin6.sin6_scope_id = 0;
748 // do i need to explicitly set the length?
749
750 if (connect(s, (const struct sockaddr*)&sin6, sizeof(sin6)) == -1
752 {
754 return -1;
755 }
756 }
757 else // IPv4 DNS server
758#endif
759 {
760 memset(&sin, 0, sizeof(sin));
761 sin.sin_family = AF_INET;
762 sin.sin_addr = server->addr;
763 sin.sin_port = channel->tcp_port;
764
765 if (connect(s, (struct sockaddr*)&sin, sizeof(sin)) == -1 &&
767 {
769 return -1;
770 }
771 }
772
773 if (channel->socket_function)
774 {
775 channel->socket_function(s, 0, __FILE__, __LINE__);
776 }
777
778 server->tcp_socket = s;
779 return 0;
780}
781
782static int connect_udp_ipv4(int s, ares_channel channel, struct server_state* server) {
783 struct sockaddr_in sin;
784
785 /* Connect to the server. */
786 memset(&sin, 0, sizeof(sin));
787 sin.sin_family = AF_INET;
788 sin.sin_addr = server->addr;
789 sin.sin_port = channel->udp_port;
790
791 if (connect(s, (struct sockaddr*)&sin, sizeof(sin)) == -1)
792 {
793 //fprintf(stderr,"kennard:ares:open_udp:ipv4: connect error %d: %s\n", errno, strerror(errno));
795 return -1;
796 }
797 return 0;
798}
799
800static int open_udp_socket(ares_channel channel, struct server_state* server)
801{
802 u_int8_t family;
803 int s;
804
805#ifdef USE_IPV6
806 family = server->family;
807 resip_assert(family == AF_INET || family == AF_INET6);
808#else
809 family = AF_INET;
810#endif
811
812 /* Acquire a socket. */
813 s = (int)socket(family, SOCK_DGRAM, 0);
814
815 if (s == -1) {
816 //fprintf(stderr,"kennard:ares:open_udp: no socket %d: %s\n", errno, strerror(errno));
817 return -1;
818 }
819
821 {
822 //fprintf(stderr,"kennard:ares:open_udp: nonblocking failed %d: %s\n", errno, strerror(errno));
824 return -1;
825 }
826
827#ifdef USE_IPV6
828 // added by Rohan 7-Sept-2004
829 // should really replace sockaddr_in6 with sockaddr_storage
830
831
832 /* Connect to the server. */
833 if (server->family == AF_INET6)
834 {
835 struct sockaddr_in6 sin6;
836 memset(&sin6, 0, sizeof(sin6));
837 sin6.sin6_family = AF_INET6;
838 sin6.sin6_addr = server->addr6;
839 sin6.sin6_port = channel->udp_port;
840 sin6.sin6_flowinfo = 0;
841 sin6.sin6_scope_id = 0;
842 // do i need to explicitly set the length?
843
844 if (connect(s, (const struct sockaddr*)&sin6, sizeof(sin6)) == -1)
845 {
847 return -1;
848 }
849 }
850 else // IPv4 DNS server
851 {
852 if (connect_udp_ipv4(s, channel, server) == -1)
853 return -1;
854 }
855
856#else
857
858 if (connect_udp_ipv4(s, channel, server) == -1)
859 return -1;
860
861#endif
862 if (channel->socket_function)
863 {
864 channel->socket_function(s, 0, __FILE__, __LINE__);
865 }
866
867 server->udp_socket = s;
868 return 0;
869}
870
871static int same_questions(const unsigned char* qbuf, int qlen,
872 const unsigned char* abuf, int alen)
873{
874 struct {
875 const unsigned char* p;
876 int qdcount;
877 char* name;
878 long int namelen;
879 int type;
880 int dnsclass;
881 } q, a;
882 int i, j;
883
884 if (qlen < HFIXEDSZ || alen < HFIXEDSZ)
885 return 0;
886
887 /* Extract qdcount from the request and reply buffers and compare them. */
888 q.qdcount = DNS_HEADER_QDCOUNT(qbuf);
889 a.qdcount = DNS_HEADER_QDCOUNT(abuf);
890 if (q.qdcount != a.qdcount)
891 return 0;
892
893 /* For each question in qbuf, find it in abuf. */
894 q.p = qbuf + HFIXEDSZ;
895 for (i = 0; i < q.qdcount; i++)
896 {
897 /* Decode the question in the query. */
898 if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen)
899 != ARES_SUCCESS)
900 return 0;
901 q.p += q.namelen;
902 if (q.p + QFIXEDSZ > qbuf + qlen)
903 {
904 free(q.name);
905 return 0;
906 }
907 q.type = DNS_QUESTION_TYPE(q.p);
908 q.dnsclass = DNS_QUESTION_CLASS(q.p);
909 q.p += QFIXEDSZ;
910
911 /* Search for this question in the answer. */
912 a.p = abuf + HFIXEDSZ;
913 for (j = 0; j < a.qdcount; j++)
914 {
915 /* Decode the question in the answer. */
916 if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen)
917 != ARES_SUCCESS)
918 {
919 free(q.name);
920 return 0;
921 }
922 a.p += a.namelen;
923 if (a.p + QFIXEDSZ > abuf + alen)
924 {
925 free(q.name);
926 free(a.name);
927 return 0;
928 }
929 a.type = DNS_QUESTION_TYPE(a.p);
930 a.dnsclass = DNS_QUESTION_CLASS(a.p);
931 a.p += QFIXEDSZ;
932
933 /* Compare the decoded questions. */
934 if (strcasecmp(q.name, a.name) == 0 && q.type == a.type
935 && q.dnsclass == a.dnsclass)
936 {
937 free(a.name);
938 break;
939 }
940 free(a.name);
941 }
942
943 free(q.name);
944 if (j == a.qdcount)
945 return 0;
946 }
947 return 1;
948}
949
950static void end_query(ares_channel channel, struct query* query, int status,
951 unsigned char* abuf, int alen)
952{
953 struct query** q;
954 int i;
955
956 query->callback(query->arg, status, abuf, alen);
957 for (q = &channel->queries; *q; q = &(*q)->next)
958 {
959 if (*q == query)
960 break;
961 }
962 *q = query->next;
963 free(query->tcpbuf);
965 free(query);
966
967 /* Simple cleanup policy: if no queries are remaining, close all
968 * network sockets unless STAYOPEN is set.
969 */
970 if (!channel->queries && !(channel->flags & ARES_FLAG_STAYOPEN))
971 {
972 for (i = 0; i < channel->nservers; i++)
973 {
974 //printf("end_query: closing...\n");
975 ares__close_poll(channel, i);
976 ares__close_sockets(&channel->servers[i]);
977 }
978 }
979}
980
982{
983#ifdef WIN32
984 closesocket(s);
985#else
986 close(s);
987#endif
988}
989
991{
992#ifdef WIN32
993 unsigned long noBlock = 1;
995 if (errNoBlock != 0)
996 {
997 return -1;
998 }
999#else
1000 int flags;
1001 // WATCHOUT: F_GETTL returns the flags, it doesn't use the argument!
1002 if ((flags = fcntl(s, F_GETFL, 0)) == -1)
1003 {
1004 return -1;
1005 }
1006 flags |= O_NONBLOCK; // Fixed evil but here - used to be &=
1007 if (fcntl(s, F_SETFL, flags) == -1)
1008 {
1009 return -1;
1010 }
1011#endif
1012 return 0;
1013}
1014
1016{
1017 channel->poll_cb_func = cbf;
1018 channel->poll_cb_data = cbd;
1019}
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define SOCKET_ERROR
Definition Socket.hxx:96
static const struct nv flags[]
Definition adig.c:62
#define ARES_SUCCESS
Definition ares.h:79
#define ARES_ENOMEM
Definition ares.h:98
#define ARES_FLAG_IGNTC
Definition ares.h:104
@ ARES_POLLACTION_WRITEOFF
Definition ares.h:132
@ ARES_POLLACTION_WRITEON
Definition ares.h:131
@ ARES_POLLACTION_OPEN
Definition ares.h:129
#define ARES_ETIMEOUT
Definition ares.h:95
void() ares_poll_cb_func(void *cb_data, struct ares_channeldata *chan, int sockidx, int fd, int using_tcp, ares_poll_action_t act)
Definition ares.h:135
#define DNS_HEADER_QDCOUNT(h)
Definition ares.h:48
#define ARES_FLAG_NOCHECKRESP
Definition ares.h:109
int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, long *enclen)
#define ARES_FLAG_STAYOPEN
Definition ares.h:106
#define ARES_FLAG_TRY_NEXT_SERVER_ON_RCODE3
Definition ares.h:110
void ares__close_poll(ares_channel channel, int server_idx)
void ares__close_sockets(struct server_state *server)
#define DNS_QUESTION_CLASS(q)
Definition ares_dns.h:61
#define DNS_QUESTION_TYPE(q)
Definition ares_dns.h:60
#define DNS_HEADER_TC(h)
Definition ares_dns.h:34
#define DNS_HEADER_QID(h)
Definition ares_dns.h:30
#define DNS_HEADER_RCODE(h)
Definition ares_dns.h:38
void ares_local_process_requests()
Definition ares_local.c:27
#define QFIXEDSZ
#define NOTIMP
#define NXDOMAIN
#define REFUSED
#define SERVFAIL
#define HFIXEDSZ
#define PACKETSZ
static void read_udp_packets(ares_channel channel, int server_idx, fd_set *read_fds, time_t now)
void ares__kill_socket(int s)
static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen)
static void process_timeouts(ares_channel channel, time_t now)
static void process_answer(ares_channel channel, unsigned char *abuf, int alen, int whichserver, int tcp, time_t now)
static int getErrno()
static int open_tcp_socket(ares_channel channel, struct server_state *server)
static int next_server_new_network(ares_channel channel, struct query *query, time_t now)
void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
static void next_server(ares_channel channel, struct query *query, time_t now)
static void handle_error(ares_channel channel, int whichserver, time_t now)
static int make_socket_non_blocking(int s)
static void write_tcp_data_core(ares_channel channel, int server_idx, time_t now)
void ares_process_poll(ares_channel channel, int server_idx, int rdFd, int wrFd, time_t now)
static int would_block(void)
void ares_process_set_poll_cb(ares_channel channel, ares_poll_cb_func *cbf, void *cbd)
#define PORTABLE_INPROGRESS_ERR
static void read_tcp_data(ares_channel channel, int server_idx, fd_set *read_fds, time_t now)
static int connect_udp_ipv4(int s, ares_channel channel, struct server_state *server)
static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
static void end_query(ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen)
static int open_udp_socket(ares_channel channel, struct server_state *server)
void ares__send_query(ares_channel channel, struct query *query, time_t now)
ares_poll_cb_func * poll_cb_func
struct query * queries
socket_function_ptr socket_function
struct server_state * servers
int using_tcp
const char * qbuf
void * arg
struct query * next
int server
ares_callback callback
int qlen
int * skip_server
unsigned short qid
int tcplen
time_t timeout
char * tcpbuf
int error_status
struct send_request * next
int physical_addr_len
u_int8_t family
unsigned char tcp_lenbuf[2]
struct send_request * qhead
struct in6_addr addr6
struct send_request * qtail
unsigned char * tcp_buffer
struct in_addr addr
unsigned char physical_addr[MAX_ADAPTER_ADDRESS_LENGTH]
void list()
Definition userAdmin.cxx:66