1968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
2968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Copyright 1998 by the Massachusetts Institute of Technology.
3968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Copyright (C) 2004-2010 by Daniel Stenberg
4968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *
5968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Permission to use, copy, modify, and distribute this
6968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software and its documentation for any purpose and without
7968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * fee is hereby granted, provided that the above copyright
8968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice appear in all copies and that both that copyright
9968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice and this permission notice appear in supporting
10968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * documentation, and that the name of M.I.T. not be used in
11968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * advertising or publicity pertaining to distribution of the
12968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software without specific, written prior permission.
13968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * M.I.T. makes no representations about the suitability of
14968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this software for any purpose.  It is provided "as is"
15968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * without express or implied warranty.
16968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
17968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
18968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_setup.h"
19968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
20968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_SOCKET_H
21968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <sys/socket.h>
22968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
23968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_UIO_H
24968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <sys/uio.h>
25968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
26968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_IN_H
27968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <netinet/in.h>
28968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
29968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_TCP_H
30968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <netinet/tcp.h>
31968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
32968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETDB_H
33968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <netdb.h>
34968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
35968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_H
36968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <arpa/nameser.h>
37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else
38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include "nameser.h"
39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_COMPAT_H
41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <arpa/nameser_compat.h>
42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_TIME_H
45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <sys/time.h>
46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_STRINGS_H
49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <strings.h>
50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_UNISTD_H
52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <unistd.h>
53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_IOCTL_H
55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <sys/ioctl.h>
56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef NETWARE
58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  include <sys/filio.h>
59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <assert.h>
62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <string.h>
63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdlib.h>
64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <fcntl.h>
65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <time.h>
66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares.h"
68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_dns.h"
69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_nowarn.h"
70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h"
71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int try_again(int errnum);
74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void write_tcp_data(ares_channel channel, fd_set *write_fds,
75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           ares_socket_t write_fd, struct timeval *now);
76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_tcp_data(ares_channel channel, fd_set *read_fds,
77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                          ares_socket_t read_fd, struct timeval *now);
78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_udp_packets(ares_channel channel, fd_set *read_fds,
79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                             ares_socket_t read_fd, struct timeval *now);
80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void advance_tcp_send_queue(ares_channel channel, int whichserver,
81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                   ssize_t num_bytes);
82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_timeouts(ares_channel channel, struct timeval *now);
83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_broken_connections(ares_channel channel,
84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                       struct timeval *now);
85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_answer(ares_channel channel, unsigned char *abuf,
86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           int alen, int whichserver, int tcp,
87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           struct timeval *now);
88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void handle_error(ares_channel channel, int whichserver,
89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                         struct timeval *now);
90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void skip_server(ares_channel channel, struct query *query,
91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        int whichserver);
92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void next_server(ares_channel channel, struct query *query,
93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        struct timeval *now);
94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_tcp_socket(ares_channel channel, struct server_state *server);
95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_udp_socket(ares_channel channel, struct server_state *server);
96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_questions(const unsigned char *qbuf, int qlen,
97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                          const unsigned char *abuf, int alen);
98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_address(struct sockaddr *sa, struct ares_addr *aa);
99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void end_query(ares_channel channel, struct query *query, int status,
100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                      unsigned char *abuf, int alen);
101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* return true if now is exactly check time or later */
103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint ares__timedout(struct timeval *now,
104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                   struct timeval *check)
105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  long secs = (now->tv_sec - check->tv_sec);
107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if(secs > 0)
109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return 1; /* yes, timed out */
110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if(secs < 0)
111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return 0; /* nope, not timed out */
112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* if the full seconds were identical, check the sub second parts */
114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return (now->tv_usec - check->tv_usec >= 0);
115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* add the specific number of milliseconds to the time in the first argument */
118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint ares__timeadd(struct timeval *now,
119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                  int millisecs)
120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  now->tv_sec += millisecs/1000;
122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  now->tv_usec += (millisecs%1000)*1000;
123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if(now->tv_usec >= 1000000) {
125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    ++(now->tv_sec);
126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    now->tv_usec -= 1000000;
127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0;
130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* return time offset between now and (future) check, in milliseconds */
133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldlong ares__timeoffset(struct timeval *now,
134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                      struct timeval *check)
135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return (check->tv_sec - now->tv_sec)*1000 +
137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         (check->tv_usec - now->tv_usec)/1000;
138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/*
142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * generic process function
143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void processfds(ares_channel channel,
145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                       fd_set *read_fds, ares_socket_t read_fd,
146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                       fd_set *write_fds, ares_socket_t write_fd)
147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct timeval now = ares__tvnow();
149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  write_tcp_data(channel, write_fds, write_fd, &now);
151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  read_tcp_data(channel, read_fds, read_fd, &now);
152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  read_udp_packets(channel, read_fds, read_fd, &now);
153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  process_timeouts(channel, &now);
154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  process_broken_connections(channel, &now);
155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Something interesting happened on the wire, or there was a timeout.
158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * See what's up and respond accordingly.
159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  processfds(channel, read_fds, ARES_SOCKET_BAD, write_fds, ARES_SOCKET_BAD);
163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Something interesting happened on the wire, or there was a timeout.
166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * See what's up and respond accordingly.
167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares_process_fd(ares_channel channel,
169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                     ares_socket_t read_fd, /* use ARES_SOCKET_BAD or valid
170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                               file descriptors */
171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                     ares_socket_t write_fd)
172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  processfds(channel, NULL, read_fd, NULL, write_fd);
174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Return 1 if the specified error number describes a readiness error, or 0
178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * otherwise. This is mostly for HP-UX, which could return EAGAIN or
179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * EWOULDBLOCK. See this man page
180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *
181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?
182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *     manpage=/usr/share/man/man2.Z/send.2
183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int try_again(int errnum)
185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if !defined EWOULDBLOCK && !defined EAGAIN
187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#error "Neither EWOULDBLOCK nor EAGAIN defined"
188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  switch (errnum)
190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef EWOULDBLOCK
192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    case EWOULDBLOCK:
193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return 1;
194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if defined EAGAIN && EAGAIN != EWOULDBLOCK
196968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    case EAGAIN:
197968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return 1;
198968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
199968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
200968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0;
201968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
202968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
203968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any TCP sockets select true for writing, write out queued data
204968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * we have for them.
205968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
206968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void write_tcp_data(ares_channel channel,
207968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           fd_set *write_fds,
208968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           ares_socket_t write_fd,
209968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           struct timeval *now)
210968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
211968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct server_state *server;
212968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct send_request *sendreq;
213968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct iovec *vec;
214968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i;
215968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ssize_t scount;
216968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ssize_t wcount;
217968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  size_t n;
218968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
219968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if(!write_fds && (write_fd == ARES_SOCKET_BAD))
220968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    /* no possible action */
221968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return;
222968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
223968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < channel->nservers; i++)
224968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
225968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Make sure server has data to send and is selected in write_fds or
226968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         write_fd. */
227968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      server = &channel->servers[i];
228968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD ||
229968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          server->is_broken)
230968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        continue;
231968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
232968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if(write_fds) {
233968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if(!FD_ISSET(server->tcp_socket, write_fds))
234968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
235968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
236968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      else {
237968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if(server->tcp_socket != write_fd)
238968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
239968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
240968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
241968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if(write_fds)
242968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        /* If there's an error and we close this socket, then open
243968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * another with the same fd to talk to another server, then we
244968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * don't want to think that it was the new socket that was
245968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * ready. This is not disastrous, but is likely to result in
246968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * extra system calls and confusion. */
247968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        FD_CLR(server->tcp_socket, write_fds);
248968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
249968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Count the number of send queue items. */
250968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      n = 0;
251968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
252968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        n++;
253968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
254968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Allocate iovecs so we can send all our data at once. */
255968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      vec = malloc(n * sizeof(struct iovec));
256968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (vec)
257968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
258968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Fill in the iovecs and send. */
259968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          n = 0;
260968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
261968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
262968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              vec[n].iov_base = (char *) sendreq->data;
263968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              vec[n].iov_len = sendreq->len;
264968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              n++;
265968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
266968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          wcount = (ssize_t)writev(server->tcp_socket, vec, (int)n);
267968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          free(vec);
268968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (wcount < 0)
269968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
270968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              if (!try_again(SOCKERRNO))
271968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                  handle_error(channel, i, now);
272968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              continue;
273968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
274968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
275968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Advance the send queue by as many bytes as we sent. */
276968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          advance_tcp_send_queue(channel, i, wcount);
277968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
278968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      else
279968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
280968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Can't allocate iovecs; just send the first request. */
281968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          sendreq = server->qhead;
282968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
283968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          scount = swrite(server->tcp_socket, sendreq->data, sendreq->len);
284968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (scount < 0)
285968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
286968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              if (!try_again(SOCKERRNO))
287968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                  handle_error(channel, i, now);
288968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              continue;
289968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
290968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
291968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Advance the send queue by as many bytes as we sent. */
292968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          advance_tcp_send_queue(channel, i, scount);
293968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
294968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
295968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
296968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
297968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Consume the given number of bytes from the head of the TCP send queue. */
298968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void advance_tcp_send_queue(ares_channel channel, int whichserver,
299968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                   ssize_t num_bytes)
300968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
301968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct send_request *sendreq;
302968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct server_state *server = &channel->servers[whichserver];
303968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  while (num_bytes > 0) {
304968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    sendreq = server->qhead;
305968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    if ((size_t)num_bytes >= sendreq->len) {
306968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      num_bytes -= sendreq->len;
307968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      server->qhead = sendreq->next;
308968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (sendreq->data_storage)
309968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        free(sendreq->data_storage);
310968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      free(sendreq);
311968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->qhead == NULL) {
312968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0);
313968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        server->qtail = NULL;
314968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
315968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        /* qhead is NULL so we cannot continue this loop */
316968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        break;
317968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
318968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
319968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    else {
320968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->data += num_bytes;
321968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->len -= num_bytes;
322968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      num_bytes = 0;
323968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
324968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
325968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
326968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
327968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any TCP socket selects true for reading, read some data,
328968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * allocate a buffer if we finish reading the length word, and process
329968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * a packet if we finish reading one.
330968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
331968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_tcp_data(ares_channel channel, fd_set *read_fds,
332968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                          ares_socket_t read_fd, struct timeval *now)
333968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
334968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct server_state *server;
335968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i;
336968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ssize_t count;
337968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
338968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if(!read_fds && (read_fd == ARES_SOCKET_BAD))
339968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    /* no possible action */
340968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return;
341968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
342968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < channel->nservers; i++)
343968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
344968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Make sure the server has a socket and is selected in read_fds. */
345968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      server = &channel->servers[i];
346968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->tcp_socket == ARES_SOCKET_BAD || server->is_broken)
347968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        continue;
348968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
349968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if(read_fds) {
350968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if(!FD_ISSET(server->tcp_socket, read_fds))
351968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
352968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
353968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      else {
354968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if(server->tcp_socket != read_fd)
355968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
356968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
357968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
358968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if(read_fds)
359968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        /* If there's an error and we close this socket, then open
360968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * another with the same fd to talk to another server, then we
361968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * don't want to think that it was the new socket that was
362968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * ready. This is not disastrous, but is likely to result in
363968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * extra system calls and confusion. */
364968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        FD_CLR(server->tcp_socket, read_fds);
365968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
366968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->tcp_lenbuf_pos != 2)
367968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
368968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* We haven't yet read a length word, so read that (or
369968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           * what's left to read of it).
370968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           */
371968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          count = sread(server->tcp_socket,
372968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        server->tcp_lenbuf + server->tcp_lenbuf_pos,
373968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        2 - server->tcp_lenbuf_pos);
374968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (count <= 0)
375968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
376968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              if (!(count == -1 && try_again(SOCKERRNO)))
377968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                  handle_error(channel, i, now);
378968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              continue;
379968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
380968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
381968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          server->tcp_lenbuf_pos += (int)count;
382968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (server->tcp_lenbuf_pos == 2)
383968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
384968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              /* We finished reading the length word.  Decode the
385968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               * length and allocate a buffer for the data.
386968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               */
387968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_length = server->tcp_lenbuf[0] << 8
388968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                | server->tcp_lenbuf[1];
389968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_buffer = malloc(server->tcp_length);
390968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              if (!server->tcp_buffer)
391968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                handle_error(channel, i, now);
392968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_buffer_pos = 0;
393968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
394968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
395968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      else
396968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
397968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Read data into the allocated buffer. */
398968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          count = sread(server->tcp_socket,
399968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        server->tcp_buffer + server->tcp_buffer_pos,
400968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        server->tcp_length - server->tcp_buffer_pos);
401968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (count <= 0)
402968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
403968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              if (!(count == -1 && try_again(SOCKERRNO)))
404968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                  handle_error(channel, i, now);
405968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              continue;
406968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
407968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
408968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          server->tcp_buffer_pos += (int)count;
409968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (server->tcp_buffer_pos == server->tcp_length)
410968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
411968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              /* We finished reading this answer; process it and
412968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               * prepare to read another length word.
413968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               */
414968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              process_answer(channel, server->tcp_buffer, server->tcp_length,
415968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                             i, 1, now);
416968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (server->tcp_buffer)
417968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        free(server->tcp_buffer);
418968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_buffer = NULL;
419968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_lenbuf_pos = 0;
420968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_buffer_pos = 0;
421968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
422968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
423968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
424968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
425968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
426968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any UDP sockets select true for reading, process them. */
427968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_udp_packets(ares_channel channel, fd_set *read_fds,
428968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                             ares_socket_t read_fd, struct timeval *now)
429968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
430968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct server_state *server;
431968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i;
432968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ssize_t count;
433968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  unsigned char buf[PACKETSZ + 1];
434968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_RECVFROM
435968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares_socklen_t fromlen;
436968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  union {
437968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr     sa;
438968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in  sa4;
439968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in6 sa6;
440968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  } from;
441968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
442968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
443968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if(!read_fds && (read_fd == ARES_SOCKET_BAD))
444968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    /* no possible action */
445968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return;
446968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
447968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < channel->nservers; i++)
448968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
449968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Make sure the server has a socket and is selected in read_fds. */
450968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      server = &channel->servers[i];
451968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
452968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->udp_socket == ARES_SOCKET_BAD || server->is_broken)
453968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        continue;
454968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
455968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if(read_fds) {
456968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if(!FD_ISSET(server->udp_socket, read_fds))
457968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
458968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
459968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      else {
460968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if(server->udp_socket != read_fd)
461968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
462968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      }
463968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
464968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if(read_fds)
465968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        /* If there's an error and we close this socket, then open
466968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * another with the same fd to talk to another server, then we
467968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * don't want to think that it was the new socket that was
468968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * ready. This is not disastrous, but is likely to result in
469968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold         * extra system calls and confusion. */
470968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        FD_CLR(server->udp_socket, read_fds);
471968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
472968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* To reduce event loop overhead, read and process as many
473968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * packets as we can. */
474968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      do {
475968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_RECVFROM
476968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if (server->addr.family == AF_INET)
477968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          fromlen = sizeof(from.sa4);
478968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        else
479968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          fromlen = sizeof(from.sa6);
480968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        count = (ssize_t)recvfrom(server->udp_socket, (void *)buf, sizeof(buf),
481968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                  0, &from.sa, &fromlen);
482968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else
483968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        count = sread(server->udp_socket, buf, sizeof(buf));
484968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
485968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if (count == -1 && try_again(SOCKERRNO))
486968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          continue;
487968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        else if (count <= 0)
488968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          handle_error(channel, i, now);
489968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_RECVFROM
490968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        else if (!same_address(&from.sa, &server->addr))
491968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* The address the response comes from does not match
492968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           * the address we sent the request to. Someone may be
493968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           * attempting to perform a cache poisoning attack. */
494968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          break;
495968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
496968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        else
497968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          process_answer(channel, buf, (int)count, i, 0, now);
498968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       } while (count > 0);
499968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
500968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
501968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
502968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any queries have timed out, note the timeout and move them on. */
503968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_timeouts(ares_channel channel, struct timeval *now)
504968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
505968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  time_t t;  /* the time of the timeouts we're processing */
506968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct query *query;
507968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct list_node* list_head;
508968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct list_node* list_node;
509968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
510968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Process all the timeouts that have fired since the last time we
511968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * processed timeouts. If things are going well, then we'll have
512968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * hundreds/thousands of queries that fall into future buckets, and
513968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * only a handful of requests that fall into the "now" bucket, so
514968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * this should be quite quick.
515968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
516968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (t = channel->last_timeout_processed; t <= now->tv_sec; t++)
517968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
518968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      list_head = &(channel->queries_by_timeout[t % ARES_TIMEOUT_TABLE_SIZE]);
519968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (list_node = list_head->next; list_node != list_head; )
520968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
521968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          query = list_node->data;
522968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          list_node = list_node->next;  /* in case the query gets deleted */
523968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (query->timeout.tv_sec && ares__timedout(now, &query->timeout))
524968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
525968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              query->error_status = ARES_ETIMEOUT;
526968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              ++query->timeouts;
527968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              next_server(channel, query, now);
528968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
529968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
530968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold     }
531968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  channel->last_timeout_processed = now->tv_sec;
532968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
533968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
534968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Handle an answer from a server. */
535968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_answer(ares_channel channel, unsigned char *abuf,
536968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           int alen, int whichserver, int tcp,
537968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                           struct timeval *now)
538968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
539968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int tc, rcode;
540968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  unsigned short id;
541968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct query *query;
542968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct list_node* list_head;
543968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct list_node* list_node;
544968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
545968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* If there's no room in the answer for a header, we can't do much
546968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * with it. */
547968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (alen < HFIXEDSZ)
548968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return;
549968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
550968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Grab the query ID, truncate bit, and response code from the packet. */
551968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  id = DNS_HEADER_QID(abuf);
552968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  tc = DNS_HEADER_TC(abuf);
553968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  rcode = DNS_HEADER_RCODE(abuf);
554968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
555968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Find the query corresponding to this packet. The queries are
556968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * hashed/bucketed by query id, so this lookup should be quick.
557968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * Note that both the query id and the questions must be the same;
558968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * when the query id wraps around we can have multiple outstanding
559968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * queries with the same query id, so we need to check both the id and
560968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * question.
561968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
562968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query = NULL;
563968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  list_head = &(channel->queries_by_qid[id % ARES_QID_TABLE_SIZE]);
564968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (list_node = list_head->next; list_node != list_head;
565968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       list_node = list_node->next)
566968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
567968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      struct query *q = list_node->data;
568968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if ((q->qid == id) && same_questions(q->qbuf, q->qlen, abuf, alen))
569968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
570968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          query = q;
571968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          break;
572968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
573968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
574968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!query)
575968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return;
576968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
577968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* If we got a truncated UDP packet and are not ignoring truncation,
578968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * don't accept the packet, and switch the query to TCP if we hadn't
579968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * done so already.
580968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
581968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if ((tc || alen > PACKETSZ) && !tcp && !(channel->flags & ARES_FLAG_IGNTC))
582968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
583968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (!query->using_tcp)
584968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
585968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          query->using_tcp = 1;
586968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          ares__send_query(channel, query, now);
587968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
588968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      return;
589968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
590968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
591968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we
592968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * are ignoring truncation.
593968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
594968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (alen > PACKETSZ && !tcp)
595968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    alen = PACKETSZ;
596968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
597968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* If we aren't passing through all error packets, discard packets
598968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * with SERVFAIL, NOTIMP, or REFUSED response codes.
599968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
600968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!(channel->flags & ARES_FLAG_NOCHECKRESP))
601968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
602968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED)
603968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
604968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          skip_server(channel, query, whichserver);
605968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (query->server == whichserver)
606968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            next_server(channel, query, now);
607968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return;
608968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
609968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
610968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
611968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  end_query(channel, query, ARES_SUCCESS, abuf, alen);
612968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
613968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
614968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Close all the connections that are no longer usable. */
615968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_broken_connections(ares_channel channel,
616968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                       struct timeval *now)
617968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
618968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i;
619968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < channel->nservers; i++)
620968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
621968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      struct server_state *server = &channel->servers[i];
622968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->is_broken)
623968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
624968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          handle_error(channel, i, now);
625968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
626968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
627968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
628968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
629968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void handle_error(ares_channel channel, int whichserver,
630968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                         struct timeval *now)
631968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
632968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct server_state *server;
633968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct query *query;
634968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct list_node list_head;
635968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct list_node* list_node;
636968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
637968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  server = &channel->servers[whichserver];
638968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
639968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Reset communications with this server. */
640968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__close_sockets(channel, server);
641968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
642968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Tell all queries talking to this server to move on and not try
643968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * this server again. We steal the current list of queries that were
644968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * in-flight to this server, since when we call next_server this can
645968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * cause the queries to be re-sent to this server, which will
646968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * re-insert these queries in that same server->queries_to_server
647968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * list.
648968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
649968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__init_list_head(&list_head);
650968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__swap_lists(&list_head, &(server->queries_to_server));
651968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (list_node = list_head.next; list_node != &list_head; )
652968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
653968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      query = list_node->data;
654968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      list_node = list_node->next;  /* in case the query gets deleted */
655968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      assert(query->server == whichserver);
656968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      skip_server(channel, query, whichserver);
657968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      next_server(channel, query, now);
658968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
659968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Each query should have removed itself from our temporary list as
660968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * it re-sent itself or finished up...
661968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
662968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  assert(ares__is_list_empty(&list_head));
663968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
664968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
665968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void skip_server(ares_channel channel, struct query *query,
666968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        int whichserver) {
667968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* The given server gave us problems with this query, so if we have
668968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * the luxury of using other servers, then let's skip the
669968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * potentially broken server and just use the others. If we only
670968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * have one server and we need to retry then we should just go ahead
671968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * and re-use that server, since it's our only hope; perhaps we
672968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * just got unlucky, and retrying will work (eg, the server timed
673968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * out our TCP connection just as we were sending another request).
674968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
675968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (channel->nservers > 1)
676968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
677968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      query->server_info[whichserver].skip_server = 1;
678968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
679968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
680968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
681968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void next_server(ares_channel channel, struct query *query,
682968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                        struct timeval *now)
683968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
684968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* We need to try each server channel->tries times. We have channel->nservers
685968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * servers to try. In total, we need to do channel->nservers * channel->tries
686968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * attempts. Use query->try to remember how many times we already attempted
687968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * this query. Use modular arithmetic to find the next server to try. */
688968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  while (++(query->try_count) < (channel->nservers * channel->tries))
689968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
690968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      struct server_state *server;
691968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
692968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Move on to the next server. */
693968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      query->server = (query->server + 1) % channel->nservers;
694968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      server = &channel->servers[query->server];
695968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
696968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* We don't want to use this server if (1) we decided this
697968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * connection is broken, and thus about to be closed, (2)
698968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * we've decided to skip this server because of earlier
699968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * errors we encountered, or (3) we already sent this query
700968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * over this exact connection.
701968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       */
702968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (!server->is_broken &&
703968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           !query->server_info[query->server].skip_server &&
704968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           !(query->using_tcp &&
705968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold             (query->server_info[query->server].tcp_connection_generation ==
706968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              server->tcp_connection_generation)))
707968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
708968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           ares__send_query(channel, query, now);
709968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold           return;
710968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
711968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
712968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* You might think that with TCP we only need one try. However,
713968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * even when using TCP, servers can time-out our connection just
714968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * as we're sending a request, or close our connection because
715968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * they die, or never send us a reply because they get wedged or
716968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * tickle a bug that drops our request.
717968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       */
718968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
719968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
720968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* If we are here, all attempts to perform query failed. */
721968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  end_query(channel, query, query->error_status, NULL, 0);
722968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
723968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
724968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares__send_query(ares_channel channel, struct query *query,
725968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                      struct timeval *now)
726968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
727968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct send_request *sendreq;
728968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct server_state *server;
729968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int timeplus;
730968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
731968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  server = &channel->servers[query->server];
732968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (query->using_tcp)
733968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
734968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Make sure the TCP socket for this server is set up and queue
735968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * a send request.
736968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       */
737968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->tcp_socket == ARES_SOCKET_BAD)
738968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
739968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (open_tcp_socket(channel, server) == -1)
740968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
741968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              skip_server(channel, query, query->server);
742968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              next_server(channel, query, now);
743968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              return;
744968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
745968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
746968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq = calloc(1, sizeof(struct send_request));
747968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (!sendreq)
748968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
749968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        end_query(channel, query, ARES_ENOMEM, NULL, 0);
750968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return;
751968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
752968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* To make the common case fast, we avoid copies by using the
753968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * query's tcpbuf for as long as the query is alive. In the rare
754968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * case where the query ends while it's queued for transmission,
755968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * then we give the sendreq its own copy of the request packet
756968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       * and put it in sendreq->data_storage.
757968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       */
758968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->data_storage = NULL;
759968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->data = query->tcpbuf;
760968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->len = query->tcplen;
761968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->owner_query = query;
762968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      sendreq->next = NULL;
763968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->qtail)
764968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        server->qtail->next = sendreq;
765968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      else
766968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
767968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 1);
768968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          server->qhead = sendreq;
769968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
770968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      server->qtail = sendreq;
771968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      query->server_info[query->server].tcp_connection_generation =
772968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        server->tcp_connection_generation;
773968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
774968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  else
775968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
776968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (server->udp_socket == ARES_SOCKET_BAD)
777968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
778968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (open_udp_socket(channel, server) == -1)
779968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
780968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              skip_server(channel, query, query->server);
781968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              next_server(channel, query, now);
782968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              return;
783968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
784968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
785968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (swrite(server->udp_socket, query->qbuf, query->qlen) == -1)
786968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
787968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* FIXME: Handle EAGAIN here since it likely can happen. */
788968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          skip_server(channel, query, query->server);
789968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          next_server(channel, query, now);
790968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return;
791968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
792968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
793968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    timeplus = channel->timeout << (query->try_count / channel->nservers);
794968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    timeplus = (timeplus * (9 + (rand () & 7))) / 16;
795968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    query->timeout = *now;
796968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    ares__timeadd(&query->timeout,
797968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                  timeplus);
798968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    /* Keep track of queries bucketed by timeout, so we can process
799968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold     * timeout events quickly.
800968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold     */
801968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    ares__remove_from_list(&(query->queries_by_timeout));
802968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    ares__insert_in_list(
803968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        &(query->queries_by_timeout),
804968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        &(channel->queries_by_timeout[query->timeout.tv_sec %
805968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                      ARES_TIMEOUT_TABLE_SIZE]));
806968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
807968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    /* Keep track of queries bucketed by server, so we can process server
808968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold     * errors quickly.
809968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold     */
810968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    ares__remove_from_list(&(query->queries_to_server));
811968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    ares__insert_in_list(&(query->queries_to_server),
812968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                         &(server->queries_to_server));
813968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
814968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
815968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/*
816968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * setsocknonblock sets the given socket to either blocking or non-blocking
817968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * mode based on the 'nonblock' boolean argument. This function is highly
818968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * portable.
819968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */
820968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int setsocknonblock(ares_socket_t sockfd,    /* operate on this */
821968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                    int nonblock   /* TRUE or FALSE */)
822968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
823968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if defined(USE_BLOCKING_SOCKETS)
824968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
825968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0; /* returns success */
826968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
827968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_FCNTL_O_NONBLOCK)
828968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
829968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* most recent unix versions */
830968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int flags;
831968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  flags = fcntl(sockfd, F_GETFL, 0);
832968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (FALSE != nonblock)
833968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
834968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  else
835968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
836968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
837968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_IOCTL_FIONBIO)
838968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
839968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* older unix versions */
840968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int flags;
841968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  flags = nonblock;
842968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return ioctl(sockfd, FIONBIO, &flags);
843968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
844968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
845968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
846968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef WATT32
847968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  char flags;
848968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else
849968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Windows */
850968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  unsigned long flags;
851968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
852968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  flags = nonblock;
853968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return ioctlsocket(sockfd, FIONBIO, &flags);
854968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
855968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
856968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
857968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Amiga */
858968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return IoctlSocket(sockfd, FIONBIO, (long)nonblock);
859968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
860968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
861968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
862968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* BeOS */
863968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  long b = nonblock ? 1 : 0;
864968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
865968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
866968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else
867968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#  error "no non-blocking method was found/used/set"
868968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
869968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
870968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
871968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int configure_socket(ares_socket_t s, int family, ares_channel channel)
872968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
873968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  union {
874968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr     sa;
875968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in  sa4;
876968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in6 sa6;
877968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  } local;
878968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
879968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  setsocknonblock(s, TRUE);
880968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
881968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if defined(FD_CLOEXEC) && !defined(MSDOS)
882968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Configure the socket fd as close-on-exec. */
883968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1)
884968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return -1;
885968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
886968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
887968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Set the socket's send and receive buffer sizes. */
888968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if ((channel->socket_send_buffer_size > 0) &&
889968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      setsockopt(s, SOL_SOCKET, SO_SNDBUF,
890968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 (void *)&channel->socket_send_buffer_size,
891968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 sizeof(channel->socket_send_buffer_size)) == -1)
892968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return -1;
893968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
894968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if ((channel->socket_receive_buffer_size > 0) &&
895968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      setsockopt(s, SOL_SOCKET, SO_RCVBUF,
896968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 (void *)&channel->socket_receive_buffer_size,
897968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 sizeof(channel->socket_receive_buffer_size)) == -1)
898968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return -1;
899968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
900968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef SO_BINDTODEVICE
901968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (channel->local_dev_name[0]) {
902968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
903968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                   channel->local_dev_name, sizeof(channel->local_dev_name))) {
904968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Only root can do this, and usually not fatal if it doesn't work, so */
905968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* just continue on. */
906968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
907968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
908968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
909968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
910968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (family == AF_INET) {
911968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    if (channel->local_ip4) {
912968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      memset(&local.sa4, 0, sizeof(local.sa4));
913968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      local.sa4.sin_family = AF_INET;
914968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      local.sa4.sin_addr.s_addr = htonl(channel->local_ip4);
915968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (bind(s, &local.sa, sizeof(local.sa4)) < 0)
916968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return -1;
917968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
918968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
919968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  else if (family == AF_INET6) {
920968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    if (memcmp(channel->local_ip6, &ares_in6addr_any, sizeof(channel->local_ip6)) != 0) {
921968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      memset(&local.sa6, 0, sizeof(local.sa6));
922968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      local.sa6.sin6_family = AF_INET6;
923968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      memcpy(&local.sa6.sin6_addr, channel->local_ip6, sizeof(channel->local_ip6));
924968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (bind(s, &local.sa, sizeof(local.sa6)) < 0)
925968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return -1;
926968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
927968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  }
928968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
929968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0;
930968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
931968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
932968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_tcp_socket(ares_channel channel, struct server_state *server)
933968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
934968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares_socket_t s;
935968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int opt;
936968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares_socklen_t salen;
937968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  union {
938968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in  sa4;
939968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in6 sa6;
940968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  } saddr;
941968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct sockaddr *sa;
942968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
943968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  switch (server->addr.family)
944968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
945968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      case AF_INET:
946968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        sa = (void *)&saddr.sa4;
947968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        salen = sizeof(saddr.sa4);
948968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memset(sa, 0, salen);
949968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa4.sin_family = AF_INET;
950968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa4.sin_port = (unsigned short)(channel->tcp_port & 0xffff);
951968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4,
952968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sizeof(server->addr.addrV4));
953968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        break;
954968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      case AF_INET6:
955968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        sa = (void *)&saddr.sa6;
956968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        salen = sizeof(saddr.sa6);
957968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memset(sa, 0, salen);
958968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa6.sin6_family = AF_INET6;
959968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa6.sin6_port = (unsigned short)(channel->tcp_port & 0xffff);
960968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6,
961968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sizeof(server->addr.addrV6));
962968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        break;
963968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      default:
964968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return -1;
965968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
966968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
967968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Acquire a socket. */
968968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  s = socket(server->addr.family, SOCK_STREAM, 0);
969968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (s == ARES_SOCKET_BAD)
970968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return -1;
971968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
972968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Configure it. */
973968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (configure_socket(s, server->addr.family, channel) < 0)
974968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
975968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       sclose(s);
976968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       return -1;
977968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
978968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
979968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef TCP_NODELAY
980968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /*
981968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not
982968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * in configure_socket). In general, in DNS lookups we're pretty much
983968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * interested in firing off a single request and then waiting for a reply,
984968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * so batching isn't very interesting.
985968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
986968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  opt = 1;
987968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
988968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 (void *)&opt, sizeof(opt)) == -1)
989968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
990968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       sclose(s);
991968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       return -1;
992968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
993968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif
994968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
995968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Connect to the server. */
996968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (connect(s, sa, salen) == -1)
997968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
998968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      int err = SOCKERRNO;
999968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1000968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (err != EINPROGRESS && err != EWOULDBLOCK)
1001968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1002968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          sclose(s);
1003968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return -1;
1004968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1005968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1006968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1007968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (channel->sock_create_cb)
1008968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1009968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      int err = channel->sock_create_cb(s, SOCK_STREAM,
1010968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                        channel->sock_create_cb_data);
1011968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (err < 0)
1012968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1013968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          sclose(s);
1014968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return err;
1015968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1016968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1017968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1018968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  SOCK_STATE_CALLBACK(channel, s, 1, 0);
1019968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  server->tcp_buffer_pos = 0;
1020968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  server->tcp_socket = s;
1021968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  server->tcp_connection_generation = ++channel->tcp_connection_generation;
1022968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0;
1023968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
1024968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1025968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_udp_socket(ares_channel channel, struct server_state *server)
1026968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
1027968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares_socket_t s;
1028968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares_socklen_t salen;
1029968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  union {
1030968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in  sa4;
1031968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    struct sockaddr_in6 sa6;
1032968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  } saddr;
1033968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct sockaddr *sa;
1034968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1035968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  switch (server->addr.family)
1036968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1037968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      case AF_INET:
1038968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        sa = (void *)&saddr.sa4;
1039968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        salen = sizeof(saddr.sa4);
1040968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memset(sa, 0, salen);
1041968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa4.sin_family = AF_INET;
1042968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa4.sin_port = (unsigned short)(channel->udp_port & 0xffff);
1043968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4,
1044968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sizeof(server->addr.addrV4));
1045968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        break;
1046968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      case AF_INET6:
1047968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        sa = (void *)&saddr.sa6;
1048968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        salen = sizeof(saddr.sa6);
1049968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memset(sa, 0, salen);
1050968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa6.sin6_family = AF_INET6;
1051968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        saddr.sa6.sin6_port = (unsigned short)(channel->udp_port & 0xffff);
1052968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6,
1053968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sizeof(server->addr.addrV6));
1054968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        break;
1055968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      default:
1056968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return -1;
1057968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1058968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1059968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Acquire a socket. */
1060968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  s = socket(server->addr.family, SOCK_DGRAM, 0);
1061968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (s == ARES_SOCKET_BAD)
1062968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return -1;
1063968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1064968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Set the socket non-blocking. */
1065968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (configure_socket(s, server->addr.family, channel) < 0)
1066968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1067968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       sclose(s);
1068968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold       return -1;
1069968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1070968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1071968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Connect to the server. */
1072968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (connect(s, sa, salen) == -1)
1073968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1074968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      int err = SOCKERRNO;
1075968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1076968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (err != EINPROGRESS && err != EWOULDBLOCK)
1077968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1078968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          sclose(s);
1079968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return -1;
1080968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1081968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1082968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1083968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (channel->sock_create_cb)
1084968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1085968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      int err = channel->sock_create_cb(s, SOCK_DGRAM,
1086968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                                        channel->sock_create_cb_data);
1087968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (err < 0)
1088968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1089968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          sclose(s);
1090968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return err;
1091968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1092968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1093968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1094968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  SOCK_STATE_CALLBACK(channel, s, 1, 0);
1095968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1096968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  server->udp_socket = s;
1097968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0;
1098968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
1099968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_questions(const unsigned char *qbuf, int qlen,
1101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                          const unsigned char *abuf, int alen)
1102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
1103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  struct {
1104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    const unsigned char *p;
1105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    int qdcount;
1106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    char *name;
1107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    long namelen;
1108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    int type;
1109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    int dnsclass;
1110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  } q, a;
1111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i, j;
1112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (qlen < HFIXEDSZ || alen < HFIXEDSZ)
1114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return 0;
1115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Extract qdcount from the request and reply buffers and compare them. */
1117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  q.qdcount = DNS_HEADER_QDCOUNT(qbuf);
1118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  a.qdcount = DNS_HEADER_QDCOUNT(abuf);
1119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (q.qdcount != a.qdcount)
1120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    return 0;
1121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* For each question in qbuf, find it in abuf. */
1123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  q.p = qbuf + HFIXEDSZ;
1124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < q.qdcount; i++)
1125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Decode the question in the query. */
1127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen)
1128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          != ARES_SUCCESS)
1129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return 0;
1130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      q.p += q.namelen;
1131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (q.p + QFIXEDSZ > qbuf + qlen)
1132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          free(q.name);
1134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          return 0;
1135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      q.type = DNS_QUESTION_TYPE(q.p);
1137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      q.dnsclass = DNS_QUESTION_CLASS(q.p);
1138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      q.p += QFIXEDSZ;
1139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      /* Search for this question in the answer. */
1141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      a.p = abuf + HFIXEDSZ;
1142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (j = 0; j < a.qdcount; j++)
1143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Decode the question in the answer. */
1145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen)
1146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              != ARES_SUCCESS)
1147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
1148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              free(q.name);
1149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              return 0;
1150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
1151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          a.p += a.namelen;
1152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (a.p + QFIXEDSZ > abuf + alen)
1153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
1154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              free(q.name);
1155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              free(a.name);
1156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              return 0;
1157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
1158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          a.type = DNS_QUESTION_TYPE(a.p);
1159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          a.dnsclass = DNS_QUESTION_CLASS(a.p);
1160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          a.p += QFIXEDSZ;
1161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          /* Compare the decoded questions. */
1163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          if (strcasecmp(q.name, a.name) == 0 && q.type == a.type
1164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              && q.dnsclass == a.dnsclass)
1165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            {
1166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              free(a.name);
1167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              break;
1168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            }
1169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          free(a.name);
1170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      free(q.name);
1173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      if (j == a.qdcount)
1174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        return 0;
1175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 1;
1177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
1178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_address(struct sockaddr *sa, struct ares_addr *aa)
1180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
1181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  void *addr1;
1182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  void *addr2;
1183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (sa->sa_family == aa->family)
1185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      switch (aa->family)
1187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        {
1188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          case AF_INET:
1189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            addr1 = &aa->addrV4;
1190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            addr2 = &((struct sockaddr_in *)sa)->sin_addr;
1191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            if (memcmp(addr1, addr2, sizeof(aa->addrV4)) == 0)
1192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              return 1; /* match */
1193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            break;
1194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          case AF_INET6:
1195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            addr1 = &aa->addrV6;
1196968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            addr2 = &((struct sockaddr_in6 *)sa)->sin6_addr;
1197968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            if (memcmp(addr1, addr2, sizeof(aa->addrV6)) == 0)
1198968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              return 1; /* match */
1199968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            break;
1200968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          default:
1201968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            break;
1202968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        }
1203968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1204968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  return 0; /* different */
1205968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
1206968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1207968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void end_query (ares_channel channel, struct query *query, int status,
1208968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                       unsigned char *abuf, int alen)
1209968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
1210968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  int i;
1211968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1212968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* First we check to see if this query ended while one of our send
1213968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * queues still has pointers to it.
1214968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
1215968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  for (i = 0; i < channel->nservers; i++)
1216968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1217968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      struct server_state *server = &channel->servers[i];
1218968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      struct send_request *sendreq;
1219968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
1220968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        if (sendreq->owner_query == query)
1221968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          {
1222968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            sendreq->owner_query = NULL;
1223968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            assert(sendreq->data_storage == NULL);
1224968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            if (status == ARES_SUCCESS)
1225968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              {
1226968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                /* We got a reply for this query, but this queued
1227968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * sendreq points into this soon-to-be-gone query's
1228968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * tcpbuf. Probably this means we timed out and queued
1229968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * the query for retransmission, then received a
1230968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * response before actually retransmitting. This is
1231968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * perfectly fine, so we want to keep the connection
1232968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * running smoothly if we can. But in the worst case
1233968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * we may have sent only some prefix of the query,
1234968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * with some suffix of the query left to send. Also,
1235968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * the buffer may be queued on multiple queues. To
1236968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * prevent dangling pointers to the query's tcpbuf and
1237968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * handle these cases, we just give such sendreqs
1238968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * their own copy of the query packet.
1239968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 */
1240968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sendreq->data_storage = malloc(sendreq->len);
1241968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               if (sendreq->data_storage != NULL)
1242968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 {
1243968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                   memcpy(sendreq->data_storage, sendreq->data, sendreq->len);
1244968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                   sendreq->data = sendreq->data_storage;
1245968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 }
1246968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              }
1247968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold            if ((status != ARES_SUCCESS) || (sendreq->data_storage == NULL))
1248968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold              {
1249968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                /* We encountered an error (probably a timeout,
1250968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * suggesting the DNS server we're talking to is
1251968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * probably unreachable, wedged, or severely
1252968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * overloaded) or we couldn't copy the request, so
1253968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * mark the connection as broken. When we get to
1254968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * process_broken_connections() we'll close the
1255968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * connection and try to re-send requests to another
1256968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 * server.
1257968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold                 */
1258968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               server->is_broken = 1;
1259968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               /* Just to be paranoid, zero out this sendreq... */
1260968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sendreq->data = NULL;
1261968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold               sendreq->len = 0;
1262968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold             }
1263968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold          }
1264968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1265968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1266968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Invoke the callback */
1267968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->callback(query->arg, status, query->timeouts, abuf, alen);
1268968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__free_query(query);
1269968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1270968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Simple cleanup policy: if no queries are remaining, close all
1271968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   * network sockets unless STAYOPEN is set.
1272968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold   */
1273968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  if (!(channel->flags & ARES_FLAG_STAYOPEN) &&
1274968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      ares__is_list_empty(&(channel->all_queries)))
1275968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    {
1276968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold      for (i = 0; i < channel->nservers; i++)
1277968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold        ares__close_sockets(channel, &channel->servers[i]);
1278968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold    }
1279968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
1280968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold
1281968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares__free_query(struct query *query)
1282968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{
1283968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Remove the query from all the lists in which it is linked */
1284968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__remove_from_list(&(query->queries_by_qid));
1285968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__remove_from_list(&(query->queries_by_timeout));
1286968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__remove_from_list(&(query->queries_to_server));
1287968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  ares__remove_from_list(&(query->all_queries));
1288968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Zero out some important stuff, to help catch bugs */
1289968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->callback = NULL;
1290968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  query->arg = NULL;
1291968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  /* Deallocate the memory associated with the query */
1292968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  free(query->tcpbuf);
1293968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  free(query->server_info);
1294968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold  free(query);
1295968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}
1296