• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

c-ares / c-ares / #53

27 Sep 2023 12:43PM UTC coverage: 88.055% (+0.02%) from 88.04%
#53

push

travis-ci

bradh352
fix #206 by allowing NULL to be passed to socket function callbacks to use defaults

21 of 21 new or added lines in 1 file covered. (100.0%)

5057 of 5743 relevant lines covered (88.06%)

11801.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.88
/src/lib/ares_process.c
1

2
/* Copyright 1998 by the Massachusetts Institute of Technology.
3
 * Copyright (C) 2004-2017 by Daniel Stenberg
4
 *
5
 * Permission to use, copy, modify, and distribute this
6
 * software and its documentation for any purpose and without
7
 * fee is hereby granted, provided that the above copyright
8
 * notice appear in all copies and that both that copyright
9
 * notice and this permission notice appear in supporting
10
 * documentation, and that the name of M.I.T. not be used in
11
 * advertising or publicity pertaining to distribution of the
12
 * software without specific, written prior permission.
13
 * M.I.T. makes no representations about the suitability of
14
 * this software for any purpose.  It is provided "as is"
15
 * without express or implied warranty.
16
 *
17
 * SPDX-License-Identifier: MIT
18
 */
19

20
#include "ares_setup.h"
21

22
#ifdef HAVE_SYS_UIO_H
23
#  include <sys/uio.h>
24
#endif
25
#ifdef HAVE_NETINET_IN_H
26
#  include <netinet/in.h>
27
#endif
28
#ifdef HAVE_NETINET_TCP_H
29
#  include <netinet/tcp.h>
30
#endif
31
#ifdef HAVE_NETDB_H
32
#  include <netdb.h>
33
#endif
34
#ifdef HAVE_ARPA_INET_H
35
#  include <arpa/inet.h>
36
#endif
37

38
#include "ares_nameser.h"
39

40
#ifdef HAVE_STRINGS_H
41
#  include <strings.h>
42
#endif
43
#ifdef HAVE_SYS_IOCTL_H
44
#  include <sys/ioctl.h>
45
#endif
46
#ifdef NETWARE
47
#  include <sys/filio.h>
48
#endif
49

50
#include <assert.h>
51
#include <fcntl.h>
52
#include <limits.h>
53

54
#include "ares.h"
55
#include "ares_dns.h"
56
#include "ares_nowarn.h"
57
#include "ares_private.h"
58

59

60
static int try_again(int errnum);
61
static void write_tcp_data(ares_channel channel, fd_set *write_fds,
62
                           ares_socket_t write_fd, struct timeval *now);
63
static void read_packets(ares_channel channel, fd_set *read_fds,
64
                         ares_socket_t read_fd, struct timeval *now);
65
static void process_timeouts(ares_channel channel, struct timeval *now);
66
static void process_answer(ares_channel channel, const unsigned char *abuf,
67
                           int alen, struct server_connection *conn, int tcp,
68
                           struct timeval *now);
69
static void handle_error(struct server_connection *conn, struct timeval *now);
70
static void skip_server(ares_channel channel, struct query *query,
71
                        struct server_state *server);
72
static int next_server(ares_channel channel, struct query *query,
73
                        struct timeval *now);
74
static int open_socket(ares_channel channel, struct server_state *server,
75
                       int is_tcp);
76
static int same_questions(const unsigned char *qbuf, int qlen,
77
                          const unsigned char *abuf, int alen);
78
static int same_address(struct sockaddr *sa, struct ares_addr *aa);
79
static int has_opt_rr(const unsigned char *abuf, int alen);
80
static void end_query(ares_channel channel, struct query *query, int status,
81
                      const unsigned char *abuf, int alen);
82
static ares_ssize_t ares__socket_write(ares_channel channel, ares_socket_t s,
83
                                       const void * data, size_t len);
84

85
/* return true if now is exactly check time or later */
86
int ares__timedout(struct timeval *now,
957✔
87
                   struct timeval *check)
88
{
89
  long secs = (now->tv_sec - check->tv_sec);
957✔
90

91
  if(secs > 0)
957✔
92
    return 1; /* yes, timed out */
×
93
  if(secs < 0)
957✔
94
    return 0; /* nope, not timed out */
905✔
95

96
  /* if the full seconds were identical, check the sub second parts */
97
  return (now->tv_usec - check->tv_usec >= 0);
52✔
98
}
99

100
/* add the specific number of milliseconds to the time in the first argument */
101
static void timeadd(struct timeval *now, int millisecs)
854✔
102
{
103
  now->tv_sec += millisecs/1000;
854✔
104
  now->tv_usec += (millisecs%1000)*1000;
854✔
105

106
  if(now->tv_usec >= 1000000) {
854✔
107
    ++(now->tv_sec);
613✔
108
    now->tv_usec -= 1000000;
613✔
109
  }
110
}
854✔
111

112
/*
113
 * generic process function
114
 */
115
static void processfds(ares_channel channel,
1,139✔
116
                       fd_set *read_fds, ares_socket_t read_fd,
117
                       fd_set *write_fds, ares_socket_t write_fd)
118
{
119
  struct timeval now = ares__tvnow();
1,139✔
120

121
  write_tcp_data(channel, write_fds, write_fd, &now);
1,139✔
122
  read_packets(channel, read_fds, read_fd, &now);
1,139✔
123
  process_timeouts(channel, &now);
1,139✔
124
}
1,139✔
125

126
/* Something interesting happened on the wire, or there was a timeout.
127
 * See what's up and respond accordingly.
128
 */
129
void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
1,139✔
130
{
131
  processfds(channel, read_fds, ARES_SOCKET_BAD, write_fds, ARES_SOCKET_BAD);
1,139✔
132
}
1,139✔
133

134
/* Something interesting happened on the wire, or there was a timeout.
135
 * See what's up and respond accordingly.
136
 */
137
void ares_process_fd(ares_channel channel,
×
138
                     ares_socket_t read_fd, /* use ARES_SOCKET_BAD or valid
139
                                               file descriptors */
140
                     ares_socket_t write_fd)
141
{
142
  processfds(channel, NULL, read_fd, NULL, write_fd);
×
143
}
144

145

146
/* Return 1 if the specified error number describes a readiness error, or 0
147
 * otherwise. This is mostly for HP-UX, which could return EAGAIN or
148
 * EWOULDBLOCK. See this man page
149
 *
150
 * http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?
151
 *     manpage=/usr/share/man/man2.Z/send.2
152
 */
153
static int try_again(int errnum)
302✔
154
{
155
#if !defined EWOULDBLOCK && !defined EAGAIN
156
#error "Neither EWOULDBLOCK nor EAGAIN defined"
157
#endif
158
  switch (errnum)
302✔
159
    {
160
#ifdef EWOULDBLOCK
161
    case EWOULDBLOCK:
302✔
162
      return 1;
302✔
163
#endif
164
#if defined EAGAIN && EAGAIN != EWOULDBLOCK
165
    case EAGAIN:
166
      return 1;
167
#endif
168
    }
169
  return 0;
×
170
}
171

172

173
/* If any TCP sockets select true for writing, write out queued data
174
 * we have for them.
175
 */
176
static void write_tcp_data(ares_channel channel,
1,139✔
177
                           fd_set *write_fds,
178
                           ares_socket_t write_fd,
179
                           struct timeval *now)
180
{
181
  struct server_state *server;
182
  int i;
183

184
  if(!write_fds && (write_fd == ARES_SOCKET_BAD))
1,139✔
185
    /* no possible action */
186
    return;
×
187

188
  for (i = 0; i < channel->nservers; i++) {
2,638✔
189
    const unsigned char *data;
190
    size_t               data_len;
191
    ares_ssize_t         count;
192

193
    /* Make sure server has data to send and is selected in write_fds or
194
       write_fd. */
195
    server = &channel->servers[i];
1,499✔
196
    if (ares__buf_len(server->tcp_send) == 0 || server->tcp_conn == NULL)
1,499✔
197
      continue;
1,389✔
198

199
    if (write_fds) {
110✔
200
      if (!FD_ISSET(server->tcp_conn->fd, write_fds))
110✔
201
        continue;
×
202
    } else {
203
      if (server->tcp_conn->fd != write_fd)
×
204
        continue;
×
205
    }
206

207
    if (write_fds) {
110✔
208
      /* If there's an error and we close this socket, then open
209
       * another with the same fd to talk to another server, then we
210
       * don't want to think that it was the new socket that was
211
       * ready. This is not disastrous, but is likely to result in
212
       * extra system calls and confusion. */
213
      FD_CLR(server->tcp_conn->fd, write_fds);
110✔
214
    }
215

216
    data  = ares__buf_peek(server->tcp_send, &data_len);
110✔
217
    count = ares__socket_write(channel, server->tcp_conn->fd, data, data_len);
110✔
218
    if (count <= 0) {
110✔
219
      if (!try_again(SOCKERRNO)) {
×
220
        handle_error(server->tcp_conn, now);
×
221
      }
222
      continue;
×
223
    }
224

225
    /* Strip data written from the buffer */
226
    ares__buf_consume(server->tcp_send, count);
110✔
227

228
    /* Notify state callback all data is written */
229
    if (ares__buf_len(server->tcp_send) == 0) {
110✔
230
      SOCK_STATE_CALLBACK(channel, server->tcp_conn->fd, 1, 0);
110✔
231
    }
232
  }
233
}
234

235

236
static ares_ssize_t socket_recvfrom(ares_channel channel,
763✔
237
   ares_socket_t s,
238
   void * data,
239
   size_t data_len,
240
   int flags,
241
   struct sockaddr *from,
242
   ares_socklen_t *from_len)
243
{
244
   if (channel->sock_funcs && channel->sock_funcs->arecvfrom)
763✔
245
      return channel->sock_funcs->arecvfrom(s, data, data_len,
20✔
246
         flags, from, from_len,
247
         channel->sock_func_cb_data);
248

249
#ifdef HAVE_RECVFROM
250
   return recvfrom(s, data, data_len, flags, from, from_len);
743✔
251
#else
252
   return sread(s, data, data_len);
253
#endif
254
}
255

256
static ares_ssize_t socket_recv(ares_channel channel,
125✔
257
   ares_socket_t s,
258
   void * data,
259
   size_t data_len)
260
{
261
   if (channel->sock_funcs && channel->sock_funcs->arecvfrom)
125✔
262
      return channel->sock_funcs->arecvfrom(s, data, data_len, 0, 0, 0,
×
263
         channel->sock_func_cb_data);
264

265
   return sread(s, data, data_len);
125✔
266
}
267

268

269
/* If any TCP socket selects true for reading, read some data,
270
 * allocate a buffer if we finish reading the length word, and process
271
 * a packet if we finish reading one.
272
 */
273
static void read_tcp_data(ares_channel channel, struct server_connection *conn,
125✔
274
                          struct timeval *now)
275
{
276
  ares_ssize_t         count;
277
  struct server_state *server   = conn->server;
125✔
278

279
  /* Fetch buffer to store data we are reading */
280
  size_t               ptr_len  = 512;
125✔
281
  unsigned char       *ptr      = ares__buf_append_start(server->tcp_parser,
125✔
282
                                                         &ptr_len);
283

284
  if (ptr == NULL) {
125✔
285
    handle_error(conn, now);
×
286
    return; /* bail out on malloc failure. TODO: make this
×
287
               function return error codes */
288
  }
289

290
  /* Read from socket */
291
  count = socket_recv(channel, conn->fd, ptr, ptr_len);
125✔
292
  if (count <= 0) {
125✔
293
    ares__buf_append_finish(server->tcp_parser, 0);
×
294
    if (!(count == -1 && try_again(SOCKERRNO)))
×
295
      handle_error(conn, now);
×
296
    return;
×
297
  }
298

299
  /* Record amount of data read */
300
  ares__buf_append_finish(server->tcp_parser, count);
125✔
301

302
  /* Process all queued answers */
303
  while (1) {
372✔
304
     unsigned short       dns_len  = 0;
497✔
305
     const unsigned char *data     = NULL;
497✔
306
     size_t               data_len = 0;
497✔
307

308
    /* Tag so we can roll back */
309
    ares__buf_tag(server->tcp_parser);
497✔
310

311
    /* Read length indicator */
312
    if (!ares__buf_fetch_be16(server->tcp_parser, &dns_len)) {
497✔
313
      ares__buf_tag_rollback(server->tcp_parser);
125✔
314
      return;
125✔
315
    }
316

317
    /* Not enough data for a full response yet */
318
    if (!ares__buf_consume(server->tcp_parser, dns_len)) {
372✔
319
      ares__buf_tag_rollback(server->tcp_parser);
×
320
      return;
×
321
    }
322

323
    /* Can't fail except for misuse */
324
    data = ares__buf_tag_fetch(server->tcp_parser, &data_len);
372✔
325
    if (data == NULL) {
372✔
326
      ares__buf_tag_clear(server->tcp_parser);
×
327
      return;
×
328
    }
329

330
    /* Strip off 2 bytes length */
331
    data     += 2;
372✔
332
    data_len -= 2;
372✔
333

334
    /* We finished reading this answer; process it */
335
    process_answer(channel, data, (int)data_len, conn, 1, now);
372✔
336

337
    /* Since we processed the answer, clear the tag so space can be reclaimed */
338
    ares__buf_tag_clear(server->tcp_parser);
372✔
339
  }
340
}
341

342

343
static int socket_list_append(ares_socket_t **socketlist, ares_socket_t fd,
3,072✔
344
                              size_t *alloc_cnt, size_t *num)
345
{
346
  if (*num >= *alloc_cnt) {
3,072✔
347
    /* Grow by powers of 2 */
348
    size_t         new_alloc = (*alloc_cnt) << 1;
×
349
    ares_socket_t *new_list  = ares_realloc(socketlist,
×
350
                                            new_alloc * sizeof(*new_list));
351
    if (new_list == NULL)
×
352
      return 0;
×
353
    *alloc_cnt  = new_alloc;
×
354
    *socketlist = new_list;
×
355
  }
356

357
  (*socketlist)[(*num)++] = fd;
3,072✔
358
  return 1;
3,072✔
359
}
360

361

362
static ares_socket_t *channel_socket_list(ares_channel channel, size_t *num)
1,139✔
363
{
364
  size_t         alloc_cnt = 1 << 4;
1,139✔
365
  int            i;
366
  ares_socket_t *out       = ares_malloc(alloc_cnt * sizeof(*out));
1,139✔
367

368
  *num = 0;
1,139✔
369

370
  if (out == NULL)
1,139✔
371
    return NULL;
2✔
372

373
  for (i=0; i<channel->nservers; i++) {
2,634✔
374
    ares__llist_node_t *node;
375
    for (node = ares__llist_node_first(channel->servers[i].connections);
4,569✔
376
         node != NULL;
377
         node = ares__llist_node_next(node)) {
3,072✔
378
      struct server_connection *conn = ares__llist_node_val(node);
3,072✔
379

380
      if (conn->fd == ARES_SOCKET_BAD)
3,072✔
381
        continue;
×
382

383
      if (!socket_list_append(&out, conn->fd, &alloc_cnt, num))
3,072✔
384
        goto fail;
×
385
    }
386
  }
387

388
  return out;
1,137✔
389

390
fail:
×
391
  ares_free(out);
×
392
  *num = 0;
×
393
  return NULL;
×
394
}
395

396
/* If any UDP sockets select true for reading, process them. */
397
static void read_udp_packets_fd(ares_channel channel,
460✔
398
                                struct server_connection *conn,
399
                                struct timeval *now)
400
{
401
  ares_ssize_t read_len;
402
  unsigned char buf[MAXENDSSZ + 1];
403
  ares_socket_t fd = conn->fd; /* Cache for validation */
460✔
404

405
#ifdef HAVE_RECVFROM
406
  ares_socklen_t fromlen;
407
  union {
408
    struct sockaddr     sa;
409
    struct sockaddr_in  sa4;
410
    struct sockaddr_in6 sa6;
411
  } from;
412
#endif
413

414
  /* To reduce event loop overhead, read and process as many
415
   * packets as we can. */
416
  do {
417
    if (conn->fd == ARES_SOCKET_BAD) {
763✔
418
      read_len = -1;
×
419
    } else {
420
      if (conn->server->addr.family == AF_INET) {
763✔
421
        fromlen = sizeof(from.sa4);
763✔
422
      } else {
423
        fromlen = sizeof(from.sa6);
×
424
      }
425
      read_len = socket_recvfrom(channel, conn->fd, (void *)buf,
763✔
426
                                 sizeof(buf), 0, &from.sa, &fromlen);
427
    }
428

429
    if (read_len == 0) {
763✔
430
      /* UDP is connectionless, so result code of 0 is a 0-length UDP
431
       * packet, and not an indication the connection is closed like on
432
       * tcp */
433
      continue;
×
434
    } else if (read_len < 0) {
763✔
435
      if (try_again(SOCKERRNO))
302✔
436
        continue;
302✔
437

438
      handle_error(conn, now);
×
439

440
#ifdef HAVE_RECVFROM
441
    } else if (!same_address(&from.sa, &conn->server->addr)) {
461✔
442
      /* The address the response comes from does not match the address we
443
       * sent the request to. Someone may be attempting to perform a cache
444
       * poisoning attack. */
445
      continue;
×
446
#endif
447

448
    } else {
449
      process_answer(channel, buf, (int)read_len, conn, 0, now);
461✔
450
    }
451
  /* process_answer may invalidate "conn" and close the file descriptor, so
452
   * check to see if file descriptor is still valid before looping! */
453
  } while (read_len >= 0 &&
461✔
454
           ares__htable_asvp_get_direct(channel->connnode_by_socket, fd) != NULL);
763✔
455

456
}
460✔
457

458

459
static void read_packets(ares_channel channel, fd_set *read_fds,
1,139✔
460
                        ares_socket_t read_fd, struct timeval *now)
461
{
462
  size_t                    i;
463
  ares_socket_t            *socketlist  = NULL;
1,139✔
464
  size_t                    num_sockets = 0;
1,139✔
465
  struct server_connection *conn        = NULL;
1,139✔
466
  ares__llist_node_t       *node        = NULL;
1,139✔
467

468
  if (!read_fds && (read_fd == ARES_SOCKET_BAD))
1,139✔
469
    /* no possible action */
470
    return;
×
471

472
  /* Single socket specified */
473
  if (!read_fds) {
1,139✔
474
    node = ares__htable_asvp_get_direct(channel->connnode_by_socket, read_fd);
×
475
    if (node == NULL)
×
476
      return;
×
477

478
    conn = ares__llist_node_val(node);
×
479

480
    if (conn->is_tcp) {
×
481
      read_tcp_data(channel, conn, now);
×
482
    } else {
483
      read_udp_packets_fd(channel, conn, now);
×
484
    }
485

486
    return;
×
487
  }
488

489
  /* There is no good way to iterate across an fd_set, instead we must pull a list
490
   * of all known fds, and iterate across that checking against the fd_set. */
491
  socketlist = channel_socket_list(channel, &num_sockets);
1,139✔
492

493
  for (i=0; i<num_sockets; i++) {
4,211✔
494
    if (!FD_ISSET(socketlist[i], read_fds))
3,072✔
495
      continue;
2,487✔
496

497
    /* If there's an error and we close this socket, then open
498
     * another with the same fd to talk to another server, then we
499
     * don't want to think that it was the new socket that was
500
     * ready. This is not disastrous, but is likely to result in
501
     * extra system calls and confusion. */
502
    FD_CLR(socketlist[i], read_fds);
585✔
503

504
    node = ares__htable_asvp_get_direct(channel->connnode_by_socket,
585✔
505
                                        socketlist[i]);
585✔
506
    if (node == NULL)
585✔
507
      return;
×
508

509
    conn = ares__llist_node_val(node);
585✔
510

511
    if (conn->is_tcp) {
585✔
512
      read_tcp_data(channel, conn, now);
125✔
513
    } else {
514
      read_udp_packets_fd(channel, conn, now);
460✔
515
    }
516
  }
517

518
  ares_free(socketlist);
1,139✔
519
}
520

521

522
/* If any queries have timed out, note the timeout and move them on. */
523
static void process_timeouts(ares_channel channel, struct timeval *now)
1,139✔
524
{
525
  ares__slist_node_t *node = ares__slist_node_first(channel->queries_by_timeout);
1,139✔
526
  while (node != NULL) {
1,150✔
527
    struct query       *query = ares__slist_node_val(node);
957✔
528
    /* Node might be removed, cache next */
529
    ares__slist_node_t *next  = ares__slist_node_next(node);
957✔
530
    ares_socket_t       fd;
531

532
    /* Since this is sorted, as soon as we hit a query that isn't timed out, break */
533
    if (!ares__timedout(now, &query->timeout)) {
957✔
534
      break;
946✔
535
    }
536

537
    query->error_status = ARES_ETIMEOUT;
11✔
538
    query->timeouts++;
11✔
539

540

541
    fd = query->conn->fd;
11✔
542
    next_server(channel, query, now);
11✔
543
    /* A timeout is a special case where we need to possibly cleanup a
544
     * a connection */
545
    ares__check_cleanup_conn(channel, fd);
11✔
546

547
    node = next;
11✔
548
  }
549
}
1,139✔
550

551

552
/* Handle an answer from a server. */
553
static void process_answer(ares_channel channel, const unsigned char *abuf,
833✔
554
                           int alen, struct server_connection *conn, int tcp,
555
                           struct timeval *now)
556
{
557
  int tc, rcode, packetsz;
558
  unsigned short id;
559
  struct query *query;
560
  /* Cache these as once ares__send_query() gets called, it may end up
561
   * invalidating the connection all-together */
562
  struct server_state *server = conn->server;
833✔
563
  ares_socket_t fd = conn->fd;
833✔
564

565
  /* If there's no room in the answer for a header, we can't do much
566
   * with it. */
567
  if (alen < HFIXEDSZ) {
833✔
568
    return;
2✔
569
  }
570

571
  /* Grab the query ID, truncate bit, and response code from the packet. */
572
  id = DNS_HEADER_QID(abuf); /* Converts to host byte order */
831✔
573
  tc = DNS_HEADER_TC(abuf);
831✔
574
  rcode = DNS_HEADER_RCODE(abuf);
831✔
575

576
  /* Find the query corresponding to this packet. The queries are
577
   * hashed/bucketed by query id, so this lookup should be quick.  
578
   */
579
  query = ares__htable_stvp_get_direct(channel->queries_by_qid, id);
831✔
580
  if (!query) {
831✔
581
    return;
2✔
582
  }
583

584
  /* Both the query id and the questions must be the same. We will drop any
585
   * replies that aren't for the same query as this is considered invalid. */
586
  if (!same_questions(query->qbuf, query->qlen, abuf, alen)) {
829✔
587
    return;
2✔
588
  }
589

590
  /* At this point we know we've received an answer for this query, so we should
591
   * remove it from the connection's queue so we can possibly invalidate the
592
   * connection. Delay cleaning up the connection though as we may enqueue
593
   * something new.  */
594
  ares__llist_node_destroy(query->node_queries_to_conn);
827✔
595
  query->node_queries_to_conn = NULL;
827✔
596

597
  packetsz = PACKETSZ;
827✔
598
  /* If we use EDNS and server answers with FORMERR without an OPT RR, the protocol
599
   * extension is not understood by the responder. We must retry the query
600
   * without EDNS enabled. */
601
  if (channel->flags & ARES_FLAG_EDNS)
827✔
602
  {
603
      packetsz = channel->ednspsz;
4✔
604
      if (rcode == FORMERR && has_opt_rr(abuf, alen) != 1)
4✔
605
      {
606
          int qlen = (query->tcplen - 2) - EDNSFIXEDSZ;
4✔
607
          channel->flags ^= ARES_FLAG_EDNS;
4✔
608
          query->tcplen -= EDNSFIXEDSZ;
4✔
609
          query->qlen -= EDNSFIXEDSZ;
4✔
610
          query->tcpbuf[0] = (unsigned char)((qlen >> 8) & 0xff);
4✔
611
          query->tcpbuf[1] = (unsigned char)(qlen & 0xff);
4✔
612
          DNS_HEADER_SET_ARCOUNT(query->tcpbuf + 2, 0);
4✔
613
          query->tcpbuf = ares_realloc(query->tcpbuf, query->tcplen);
4✔
614
          query->qbuf = query->tcpbuf + 2;
4✔
615
          ares__send_query(channel, query, now);
4✔
616
          ares__check_cleanup_conn(channel, fd);
4✔
617
          return;
4✔
618
      }
619
  }
620

621
  /* If we got a truncated UDP packet and are not ignoring truncation,
622
   * don't accept the packet, and switch the query to TCP if we hadn't
623
   * done so already.
624
   */
625
  if ((tc || alen > packetsz) && !tcp && !(channel->flags & ARES_FLAG_IGNTC))
823✔
626
    {
627
      if (!query->using_tcp)
2✔
628
        {
629
          query->using_tcp = 1;
2✔
630
          ares__send_query(channel, query, now);
2✔
631
        }
632
      ares__check_cleanup_conn(channel, fd);
2✔
633
      return;
2✔
634
    }
635

636
  /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we
637
   * are ignoring truncation.
638
   */
639
  if (alen > packetsz && !tcp)
821✔
640
      alen = packetsz;
×
641

642
  /* If we aren't passing through all error packets, discard packets
643
   * with SERVFAIL, NOTIMP, or REFUSED response codes.
644
   */
645
  if (!(channel->flags & ARES_FLAG_NOCHECKRESP))
821✔
646
    {
647
      if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED)
808✔
648
        {
649
          switch (rcode) {
57✔
650
            case SERVFAIL:
29✔
651
              query->error_status = ARES_ESERVFAIL;
29✔
652
              break;
29✔
653
            case NOTIMP:
26✔
654
              query->error_status = ARES_ENOTIMP;
26✔
655
              break;
26✔
656
            case REFUSED:
2✔
657
              query->error_status = ARES_EREFUSED;
2✔
658
              break;
2✔
659
          }
660
          skip_server(channel, query, server);
57✔
661
          if (query->server == (int)server->idx) /* Is this ever not true? */
57✔
662
            next_server(channel, query, now);
57✔
663
          ares__check_cleanup_conn(channel, fd);
57✔
664
          return;
57✔
665
        }
666
    }
667

668
  end_query(channel, query, ARES_SUCCESS, abuf, alen);
764✔
669

670
  ares__check_cleanup_conn(channel, fd);
764✔
671
}
672

673

674
static void handle_error(struct server_connection *conn,
675
                         struct timeval *now)
676
{
677
  ares_channel        channel = conn->server->channel;
×
678
  ares__llist_t      *list_copy;
679
  ares__llist_node_t *node;
680

681
  /* We steal the list from the connection then close the connection, then
682
   * iterate across the list to requeue any inflight queries with the broken
683
   * connection.  Destroying the connection prior to requeuing ensures requests
684
   * won't go back to the broken connection */
685
  list_copy             = conn->queries_to_conn;
×
686
  conn->queries_to_conn = NULL;
×
687
  ares__close_connection(conn);
×
688

689
  while ((node = ares__llist_node_first(list_copy)) != NULL) {
×
690
    struct query       *query = ares__llist_node_val(node);
×
691

692
    assert(query->server == (int)conn->server->idx);
693
    skip_server(channel, query, conn->server);
×
694
    /* next_server will remove the current node from the list */
695
    next_server(channel, query, now);
×
696
  }
697

698
  ares__llist_destroy(list_copy);
×
699
}
700

701

702
static void skip_server(ares_channel channel, struct query *query,
69✔
703
                        struct server_state *server)
704
{
705
  /* The given server gave us problems with this query, so if we have the
706
   * luxury of using other servers, then let's skip the potentially broken
707
   * server and just use the others. If we only have one server and we need to
708
   * retry then we should just go ahead and re-use that server, since it's our
709
   * only hope; perhaps we just got unlucky, and retrying will work (eg, the
710
   * server timed out our TCP connection just as we were sending another
711
   * request).
712
   */
713
  if (channel->nservers > 1)
69✔
714
    {
715
      query->server_info[server->idx].skip_server = 1;
48✔
716
    }
717
}
69✔
718

719
static int next_server(ares_channel channel, struct query *query,
80✔
720
                        struct timeval *now)
721
{
722
  int status;
723
  /* We need to try each server channel->tries times. We have channel->nservers
724
   * servers to try. In total, we need to do channel->nservers * channel->tries
725
   * attempts. Use query->try to remember how many times we already attempted
726
   * this query. Use modular arithmetic to find the next server to try.
727
   * A query can be requested be terminated at the next interval by setting
728
   * query->no_retries */
729
  while (++(query->try_count) < (channel->nservers * channel->tries) &&
96✔
730
         !query->no_retries) {
83✔
731
    struct server_state *server;
732

733
    /* Move on to the next server. */
734
    query->server = (query->server + 1) % channel->nservers;
82✔
735
    server = &channel->servers[query->server];
82✔
736

737
    /* We don't want to use this server if (1) we've decided to skip this
738
     * server because of earlier errors we encountered, or (2) we already
739
     * sent this query over this exact connection.
740
     */
741
    if (!query->server_info[query->server].skip_server &&
82✔
742
        !(query->using_tcp &&
82✔
743
         (query->server_info[query->server].tcp_connection_generation ==
44✔
744
            server->tcp_connection_generation))) {
44✔
745
      return ares__send_query(channel, query, now);
66✔
746
    }
747

748
    /* You might think that with TCP we only need one try. However, even
749
     * when using TCP, servers can time-out our connection just as we're
750
     * sending a request, or close our connection because they die, or never
751
     * send us a reply because they get wedged or tickle a bug that drops
752
     * our request.
753
     */
754
  }
755

756
  /* If we are here, all attempts to perform query failed. */
757
  status = query->error_status;
14✔
758
  end_query(channel, query, query->error_status, NULL, 0);
14✔
759
  return status;
14✔
760
}
761

762
int ares__send_query(ares_channel channel, struct query *query,
871✔
763
                      struct timeval *now)
764
{
765
  struct server_state *server;
766
  struct server_connection *conn;
767
  int timeplus;
768

769
  server = &channel->servers[query->server];
871✔
770
  if (query->using_tcp) {
871✔
771
    size_t prior_len = 0;
383✔
772
    /* Make sure the TCP socket for this server is set up and queue
773
     * a send request.
774
     */
775
    if (server->tcp_conn == NULL) {
383✔
776
      int err = open_socket(channel, server, 1);
102✔
777
      switch (err) {
102✔
778
        /* Good result, continue on */
779
        case ARES_SUCCESS:
96✔
780
          break;
96✔
781

782
        /* These conditions are retryable as they are server-specific
783
         * error codes */
784
        case ARES_ECONNREFUSED:
6✔
785
        case ARES_EBADFAMILY:
786
          skip_server(channel, query, server);
6✔
787
          return next_server(channel, query, now);
6✔
788

789
        /* Anything else is not retryable, likely ENOMEM */
790
        default:
×
791
          end_query(channel, query, err, NULL, 0);
×
792
          return err;
×
793
      }
794
    }
281✔
795

796
    conn = server->tcp_conn;
377✔
797

798
    prior_len = ares__buf_len(server->tcp_send);
377✔
799

800
    if (!ares__buf_append(server->tcp_send, query->tcpbuf, query->tcplen)) {
377✔
801
      end_query(channel, query, ARES_ENOMEM, NULL, 0);
×
802
      return ARES_ENOMEM;
×
803
    }
804

805
    if (prior_len == 0) {
377✔
806
      SOCK_STATE_CALLBACK(channel, conn->fd, 1, 1);
115✔
807
    }
808

809
    query->server_info[query->server].tcp_connection_generation =
377✔
810
      server->tcp_connection_generation;
377✔
811
  } else {
812
    ares__llist_node_t *node = ares__llist_node_first(server->connections);
488✔
813

814
    /* Don't use the found connection if we've gone over the maximum number
815
     * of queries. Also, skip over the TCP connection if it is the first in
816
     * the list */
817
    if (node != NULL) {
488✔
818
      conn = ares__llist_node_val(node);
324✔
819
      if (conn->is_tcp) {
324✔
820
        node = NULL;
×
821
      } else if (channel->udp_max_queries > 0 &&
324✔
822
                 conn->total_queries >= (size_t)channel->udp_max_queries) {
255✔
823
        node = NULL;
15✔
824
      }
825
    }
826

827
    if (node == NULL) {
488✔
828
      int err = open_socket(channel, server, 0);
179✔
829
      switch (err) {
179✔
830
        /* Good result, continue on */
831
        case ARES_SUCCESS:
168✔
832
          break;
168✔
833

834
        /* These conditions are retryable as they are server-specific
835
         * error codes */
836
        case ARES_ECONNREFUSED:
6✔
837
        case ARES_EBADFAMILY:
838
          skip_server(channel, query, server);
6✔
839
          return next_server(channel, query, now);
6✔
840

841
        /* Anything else is not retryable, likely ENOMEM */
842
        default:
5✔
843
          end_query(channel, query, err, NULL, 0);
5✔
844
          return err;
5✔
845
      }
846
      node = ares__llist_node_first(server->connections);
168✔
847
    }
848

849
    conn = ares__llist_node_val(node);
477✔
850
    if (ares__socket_write(channel, conn->fd, query->qbuf, query->qlen) == -1) {
477✔
851
      /* FIXME: Handle EAGAIN here since it likely can happen. */
852
      skip_server(channel, query, server);
×
853
      return next_server(channel, query, now);
×
854
    }
855
  }
856

857
  /* For each trip through the entire server list, double the channel's
858
   * assigned timeout, avoiding overflow.  If channel->timeout is negative,
859
   * leave it as-is, even though that should be impossible here.
860
   */
861
  timeplus = channel->timeout;
854✔
862
  {
863
    /* How many times do we want to double it?  Presume sane values here. */
864
    const int shift = query->try_count / channel->nservers;
854✔
865

866
    /* Is there enough room to shift timeplus left that many times?
867
     *
868
     * To find out, confirm that all of the bits we'll shift away are zero.
869
     * Stop considering a shift if we get to the point where we could shift
870
     * a 1 into the sign bit (i.e. when shift is within two of the bit
871
     * count).
872
     *
873
     * This has the side benefit of leaving negative numbers unchanged.
874
     */
875
    if(shift <= (int)(sizeof(int) * CHAR_BIT - 1)
854✔
876
       && (timeplus >> (sizeof(int) * CHAR_BIT - 1 - shift)) == 0)
854✔
877
    {
878
      timeplus <<= shift;
854✔
879
    }
880
  }
881

882
  /* Keep track of queries bucketed by timeout, so we can process
883
   * timeout events quickly.
884
   */
885
  ares__slist_node_destroy(query->node_queries_by_timeout);
854✔
886
  query->timeout = *now;
854✔
887
  timeadd(&query->timeout, timeplus);
854✔
888
  query->node_queries_by_timeout = ares__slist_insert(channel->queries_by_timeout, query);
854✔
889
  if (!query->node_queries_by_timeout) {
854✔
890
    end_query(channel, query, ARES_ENOMEM, NULL, 0);
2✔
891
    return ARES_ENOMEM;
2✔
892
  }
893

894
  /* Keep track of queries bucketed by connection, so we can process errors
895
   * quickly. */
896
  ares__llist_node_destroy(query->node_queries_to_conn);
852✔
897
  query->node_queries_to_conn =
852✔
898
    ares__llist_insert_last(conn->queries_to_conn, query);
852✔
899
  query->conn = conn;
852✔
900
  conn->total_queries++;
852✔
901
  return ARES_SUCCESS;
852✔
902
}
903

904
/*
905
 * setsocknonblock sets the given socket to either blocking or non-blocking
906
 * mode based on the 'nonblock' boolean argument. This function is highly
907
 * portable.
908
 */
909
static int setsocknonblock(ares_socket_t sockfd,    /* operate on this */
261✔
910
                           int nonblock   /* TRUE or FALSE */)
911
{
912
#if defined(USE_BLOCKING_SOCKETS)
913

914
  return 0; /* returns success */
915

916
#elif defined(HAVE_FCNTL_O_NONBLOCK)
917

918
  /* most recent unix versions */
919
  int flags;
920
  flags = fcntl(sockfd, F_GETFL, 0);
261✔
921
  if (FALSE != nonblock)
261✔
922
    return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
261✔
923
  else
924
    return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));  /* LCOV_EXCL_LINE */
925

926
#elif defined(HAVE_IOCTL_FIONBIO)
927

928
  /* older unix versions */
929
  int flags = nonblock ? 1 : 0;
930
  return ioctl(sockfd, FIONBIO, &flags);
931

932
#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
933

934
#ifdef WATT32
935
  char flags = nonblock ? 1 : 0;
936
#else
937
  /* Windows */
938
  unsigned long flags = nonblock ? 1UL : 0UL;
939
#endif
940
  return ioctlsocket(sockfd, FIONBIO, &flags);
941

942
#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
943

944
  /* Amiga */
945
  long flags = nonblock ? 1L : 0L;
946
  return IoctlSocket(sockfd, FIONBIO, flags);
947

948
#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
949

950
  /* BeOS */
951
  long b = nonblock ? 1L : 0L;
952
  return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
953

954
#else
955
#  error "no non-blocking method was found/used/set"
956
#endif
957
}
958

959
#if defined(IPV6_V6ONLY) && defined(WIN32)
960
/* It makes support for IPv4-mapped IPv6 addresses.
961
 * Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
962
 * Windows Vista and later: default is on;
963
 * DragonFly BSD: acts like off, and dummy setting;
964
 * OpenBSD and earlier Windows: unsupported.
965
 * Linux: controlled by /proc/sys/net/ipv6/bindv6only.
966
 */
967
static void set_ipv6_v6only(ares_socket_t sockfd, int on)
968
{
969
  (void)setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on));
970
}
971
#else
972
#define set_ipv6_v6only(s,v)
973
#endif
974

975
static int configure_socket(ares_socket_t s, int family, ares_channel channel)
281✔
976
{
977
  union {
978
    struct sockaddr     sa;
979
    struct sockaddr_in  sa4;
980
    struct sockaddr_in6 sa6;
981
  } local;
982

983
  /* do not set options for user-managed sockets */
984
  if (channel->sock_funcs && channel->sock_funcs->asocket)
281✔
985
    return 0;
20✔
986

987
  (void)setsocknonblock(s, TRUE);
261✔
988

989
#if defined(FD_CLOEXEC) && !defined(MSDOS)
990
  /* Configure the socket fd as close-on-exec. */
991
  if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1)
261✔
992
    return -1;  /* LCOV_EXCL_LINE */
993
#endif
994

995
  /* Set the socket's send and receive buffer sizes. */
996
  if ((channel->socket_send_buffer_size > 0) &&
267✔
997
      setsockopt(s, SOL_SOCKET, SO_SNDBUF,
6✔
998
                 (void *)&channel->socket_send_buffer_size,
6✔
999
                 sizeof(channel->socket_send_buffer_size)) == -1)
1000
    return -1;
×
1001

1002
  if ((channel->socket_receive_buffer_size > 0) &&
267✔
1003
      setsockopt(s, SOL_SOCKET, SO_RCVBUF,
6✔
1004
                 (void *)&channel->socket_receive_buffer_size,
6✔
1005
                 sizeof(channel->socket_receive_buffer_size)) == -1)
1006
    return -1;
×
1007

1008
#ifdef SO_BINDTODEVICE
1009
  if (channel->local_dev_name[0]) {
261✔
1010
    if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
6✔
1011
                   channel->local_dev_name, sizeof(channel->local_dev_name))) {
6✔
1012
      /* Only root can do this, and usually not fatal if it doesn't work, so */
1013
      /* just continue on. */
1014
    }
1015
  }
1016
#endif
1017

1018
  if (family == AF_INET) {
261✔
1019
    if (channel->local_ip4) {
261✔
1020
      memset(&local.sa4, 0, sizeof(local.sa4));
6✔
1021
      local.sa4.sin_family = AF_INET;
6✔
1022
      local.sa4.sin_addr.s_addr = htonl(channel->local_ip4);
6✔
1023
      if (bind(s, &local.sa, sizeof(local.sa4)) < 0)
6✔
1024
        return -1;
×
1025
    }
1026
  }
1027
  else if (family == AF_INET6) {
×
1028
    if (memcmp(channel->local_ip6, &ares_in6addr_any,
×
1029
               sizeof(channel->local_ip6)) != 0) {
1030
      memset(&local.sa6, 0, sizeof(local.sa6));
×
1031
      local.sa6.sin6_family = AF_INET6;
×
1032
      memcpy(&local.sa6.sin6_addr, channel->local_ip6,
×
1033
             sizeof(channel->local_ip6));
1034
      if (bind(s, &local.sa, sizeof(local.sa6)) < 0)
×
1035
        return -1;
×
1036
    }
1037
    set_ipv6_v6only(s, 0);
1038
  }
1039

1040
  return 0;
261✔
1041
}
1042

1043
static int open_socket(ares_channel channel, struct server_state *server,
281✔
1044
                       int is_tcp)
1045
{
1046
  ares_socket_t s;
1047
  int opt;
1048
  ares_socklen_t salen;
1049
  union {
1050
    struct sockaddr_in  sa4;
1051
    struct sockaddr_in6 sa6;
1052
  } saddr;
1053
  struct sockaddr *sa;
1054
  unsigned short port;
1055
  struct server_connection *conn;
1056
  ares__llist_node_t *node;
1057

1058
  if (is_tcp) {
281✔
1059
    port = aresx_sitous(server->addr.tcp_port?
102✔
1060
                        server->addr.tcp_port:channel->tcp_port);
1061
  } else {
1062
    port = aresx_sitous(server->addr.udp_port?
179✔
1063
                        server->addr.udp_port:channel->udp_port);
1064
  }
1065

1066
  switch (server->addr.family) {
281✔
1067
    case AF_INET:
281✔
1068
      sa = (void *)&saddr.sa4;
281✔
1069
      salen = sizeof(saddr.sa4);
281✔
1070
      memset(sa, 0, salen);
281✔
1071
      saddr.sa4.sin_family = AF_INET;
281✔
1072
      saddr.sa4.sin_port   = port;
281✔
1073
      memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4,
281✔
1074
             sizeof(server->addr.addrV4));
1075
      break;
281✔
1076
    case AF_INET6:
×
1077
      sa = (void *)&saddr.sa6;
×
1078
      salen = sizeof(saddr.sa6);
×
1079
      memset(sa, 0, salen);
×
1080
      saddr.sa6.sin6_family = AF_INET6;
×
1081
      saddr.sa6.sin6_port   = port;
×
1082
      memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6,
×
1083
             sizeof(server->addr.addrV6));
1084
      break;
×
1085
    default:
×
1086
      return ARES_EBADFAMILY;  /* LCOV_EXCL_LINE */
1087
  }
1088

1089
  /* Acquire a socket. */
1090
  s = ares__open_socket(channel, server->addr.family,
281✔
1091
                        is_tcp?SOCK_STREAM:SOCK_DGRAM, 0);
1092
  if (s == ARES_SOCKET_BAD)
281✔
1093
    return ARES_ECONNREFUSED;
×
1094

1095
  /* Configure it. */
1096
  if (configure_socket(s, server->addr.family, channel) < 0) {
281✔
1097
    ares__close_socket(channel, s);
×
1098
    return ARES_ECONNREFUSED;
×
1099
  }
1100

1101
#ifdef TCP_NODELAY
1102
  if (is_tcp) {
281✔
1103
    /*
1104
     * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not
1105
     * in configure_socket). In general, in DNS lookups we're pretty much
1106
     * interested in firing off a single request and then waiting for a reply,
1107
     * so batching isn't very interesting.
1108
     */
1109
    opt = 1;
102✔
1110
    if (!channel->sock_funcs || !channel->sock_funcs->asocket) {
102✔
1111
      if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt))
102✔
1112
          == -1) {
1113
        ares__close_socket(channel, s);
×
1114
        return ARES_ECONNREFUSED;
×
1115
      }
1116
    }
1117
  }
1118
#endif
1119

1120
  if (channel->sock_config_cb) {
281✔
1121
    int err = channel->sock_config_cb(s, SOCK_STREAM,
8✔
1122
                                      channel->sock_config_cb_data);
1123
    if (err < 0) {
8✔
1124
      ares__close_socket(channel, s);
6✔
1125
      return ARES_ECONNREFUSED;
6✔
1126
    }
1127
  }
1128

1129
  /* Connect to the server. */
1130
  if (ares__connect_socket(channel, s, sa, salen) == -1) {
275✔
1131
    int err = SOCKERRNO;
99✔
1132

1133
    if (err != EINPROGRESS && err != EWOULDBLOCK) {
99✔
1134
      ares__close_socket(channel, s);
×
1135
      return ARES_ECONNREFUSED;
×
1136
    }
1137
  }
1138

1139
  if (channel->sock_create_cb) {
275✔
1140
    int err = channel->sock_create_cb(s, SOCK_STREAM,
25✔
1141
                                      channel->sock_create_cb_data);
1142
    if (err < 0) {
25✔
1143
      ares__close_socket(channel, s);
6✔
1144
      return ARES_ECONNREFUSED;
6✔
1145
    }
1146
  }
1147

1148
  conn = ares_malloc(sizeof(*conn));
269✔
1149
  if (conn == NULL) {
269✔
1150
    ares__close_socket(channel, s);
1✔
1151
    return ARES_ENOMEM;
1✔
1152
  }
1153
  memset(conn, 0, sizeof(*conn));
268✔
1154
  conn->fd     = s;
268✔
1155
  conn->server = server;
268✔
1156
  conn->queries_to_conn = ares__llist_create(NULL);
268✔
1157
  conn->is_tcp = is_tcp;
268✔
1158
  if (conn->queries_to_conn == NULL) {
268✔
1159
    ares__close_socket(channel, s);
2✔
1160
    ares_free(conn);
2✔
1161
    return ARES_ENOMEM;
2✔
1162
  }
1163

1164
  /* TCP connections are thrown to the end as we don't spawn multiple TCP
1165
   * connections. UDP connections are put on front where the newest connection
1166
   * can be quickly pulled */
1167
  if (is_tcp) {
266✔
1168
    node = ares__llist_insert_last(server->connections, conn);
96✔
1169
  } else {
1170
    node = ares__llist_insert_first(server->connections, conn);
170✔
1171
  }
1172
  if (node == NULL) {
266✔
1173
    ares__close_socket(channel, s);
×
1174
    ares__llist_destroy(conn->queries_to_conn);
×
1175
    ares_free(conn);
×
1176
    return ARES_ENOMEM;
×
1177
  }
1178

1179
  /* Register globally to quickly map event on file descriptor to connection
1180
   * node object */
1181
  if (!ares__htable_asvp_insert(channel->connnode_by_socket, s, node)) {
266✔
1182
    ares__close_socket(channel, s);
2✔
1183
    ares__llist_destroy(conn->queries_to_conn);
2✔
1184
    ares__llist_node_claim(node);
2✔
1185
    ares_free(conn);
2✔
1186
    return ARES_ENOMEM;
2✔
1187
  }
1188

1189
  SOCK_STATE_CALLBACK(channel, s, 1, 0);
264✔
1190

1191
  if (is_tcp) {
264✔
1192
    server->tcp_connection_generation = ++channel->tcp_connection_generation;
96✔
1193
    server->tcp_conn = conn;
96✔
1194
  }
1195

1196
  return ARES_SUCCESS;
264✔
1197
}
1198

1199

1200
static int same_questions(const unsigned char *qbuf, int qlen,
829✔
1201
                          const unsigned char *abuf, int alen)
1202
{
1203
  struct {
1204
    const unsigned char *p;
1205
    int qdcount;
1206
    char *name;
1207
    long namelen;
1208
    int type;
1209
    int dnsclass;
1210
  } q, a;
1211
  int i, j;
1212

1213
  if (qlen < HFIXEDSZ || alen < HFIXEDSZ)
829✔
1214
    return 0;
×
1215

1216
  /* Extract qdcount from the request and reply buffers and compare them. */
1217
  q.qdcount = DNS_HEADER_QDCOUNT(qbuf);
829✔
1218
  a.qdcount = DNS_HEADER_QDCOUNT(abuf);
829✔
1219
  if (q.qdcount != a.qdcount)
829✔
1220
    return 0;
×
1221

1222
  /* For each question in qbuf, find it in abuf. */
1223
  q.p = qbuf + HFIXEDSZ;
829✔
1224
  for (i = 0; i < q.qdcount; i++)
1,656✔
1225
    {
1226
      /* Decode the question in the query. */
1227
      if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen)
829✔
1228
          != ARES_SUCCESS)
1229
        return 0;
1✔
1230
      q.p += q.namelen;
828✔
1231
      if (q.p + QFIXEDSZ > qbuf + qlen)
828✔
1232
        {
1233
          ares_free(q.name);
×
1234
          return 0;
×
1235
        }
1236
      q.type = DNS_QUESTION_TYPE(q.p);
828✔
1237
      q.dnsclass = DNS_QUESTION_CLASS(q.p);
828✔
1238
      q.p += QFIXEDSZ;
828✔
1239

1240
      /* Search for this question in the answer. */
1241
      a.p = abuf + HFIXEDSZ;
828✔
1242
      for (j = 0; j < a.qdcount; j++)
828✔
1243
        {
1244
          /* Decode the question in the answer. */
1245
          if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen)
828✔
1246
              != ARES_SUCCESS)
1247
            {
1248
              ares_free(q.name);
1✔
1249
              return 0;
1✔
1250
            }
1251
          a.p += a.namelen;
827✔
1252
          if (a.p + QFIXEDSZ > abuf + alen)
827✔
1253
            {
1254
              ares_free(q.name);
×
1255
              ares_free(a.name);
×
1256
              return 0;
×
1257
            }
1258
          a.type = DNS_QUESTION_TYPE(a.p);
827✔
1259
          a.dnsclass = DNS_QUESTION_CLASS(a.p);
827✔
1260
          a.p += QFIXEDSZ;
827✔
1261

1262
          /* Compare the decoded questions. */
1263
          if (strcasecmp(q.name, a.name) == 0 && q.type == a.type
827✔
1264
              && q.dnsclass == a.dnsclass)
827✔
1265
            {
1266
              ares_free(a.name);
827✔
1267
              break;
827✔
1268
            }
1269
          ares_free(a.name);
×
1270
        }
1271

1272
      ares_free(q.name);
827✔
1273
      if (j == a.qdcount)
827✔
1274
        return 0;
×
1275
    }
1276
  return 1;
827✔
1277
}
1278

1279
static int same_address(struct sockaddr *sa, struct ares_addr *aa)
461✔
1280
{
1281
  void *addr1;
1282
  void *addr2;
1283

1284
  if (sa->sa_family == aa->family)
461✔
1285
    {
1286
      switch (aa->family)
461✔
1287
        {
1288
          case AF_INET:
461✔
1289
            addr1 = &aa->addrV4;
461✔
1290
            addr2 = &(CARES_INADDR_CAST(struct sockaddr_in *, sa))->sin_addr;
461✔
1291
            if (memcmp(addr1, addr2, sizeof(aa->addrV4)) == 0)
461✔
1292
              return 1; /* match */
461✔
1293
            break;
×
1294
          case AF_INET6:
×
1295
            addr1 = &aa->addrV6;
×
1296
            addr2 = &(CARES_INADDR_CAST(struct sockaddr_in6 *, sa))->sin6_addr;
×
1297
            if (memcmp(addr1, addr2, sizeof(aa->addrV6)) == 0)
×
1298
              return 1; /* match */
×
1299
            break;
×
1300
          default:
×
1301
            break;  /* LCOV_EXCL_LINE */
1302
        }
1303
    }
1304
  return 0; /* different */
×
1305
}
1306

1307
/* search for an OPT RR in the response */
1308
static int has_opt_rr(const unsigned char *abuf, int alen)
4✔
1309
{
1310
  unsigned int qdcount, ancount, nscount, arcount, i;
1311
  const unsigned char *aptr;
1312
  int status;
1313

1314
  if (alen < HFIXEDSZ)
4✔
1315
    return -1;
×
1316

1317
  /* Parse the answer header. */
1318
  qdcount = DNS_HEADER_QDCOUNT(abuf);
4✔
1319
  ancount = DNS_HEADER_ANCOUNT(abuf);
4✔
1320
  nscount = DNS_HEADER_NSCOUNT(abuf);
4✔
1321
  arcount = DNS_HEADER_ARCOUNT(abuf);
4✔
1322

1323
  aptr = abuf + HFIXEDSZ;
4✔
1324

1325
  /* skip the questions */
1326
  for (i = 0; i < qdcount; i++)
8✔
1327
    {
1328
      char* name;
1329
      long len;
1330
      status = ares_expand_name(aptr, abuf, alen, &name, &len);
4✔
1331
      if (status != ARES_SUCCESS)
4✔
1332
        return -1;
×
1333
      ares_free_string(name);
4✔
1334
      if (aptr + len + QFIXEDSZ > abuf + alen)
4✔
1335
        return -1;
×
1336
      aptr += len + QFIXEDSZ;
4✔
1337
    }
1338

1339
  /* skip the ancount and nscount */
1340
  for (i = 0; i < ancount + nscount; i++)
4✔
1341
    {
1342
      char* name;
1343
      long len;
1344
      int dlen;
1345
      status = ares_expand_name(aptr, abuf, alen, &name, &len);
×
1346
      if (status != ARES_SUCCESS)
×
1347
        return -1;
×
1348
      ares_free_string(name);
×
1349
      if (aptr + len + RRFIXEDSZ > abuf + alen)
×
1350
        return -1;
×
1351
      aptr += len;
×
1352
      dlen = DNS_RR_LEN(aptr);
×
1353
      aptr += RRFIXEDSZ;
×
1354
      if (aptr + dlen > abuf + alen)
×
1355
        return -1;
×
1356
      aptr += dlen;
×
1357
    }
1358

1359
  /* search for rr type (41) - opt */
1360
  for (i = 0; i < arcount; i++)
4✔
1361
    {
1362
      char* name;
1363
      long len;
1364
      int dlen;
1365
      status = ares_expand_name(aptr, abuf, alen, &name, &len);
×
1366
      if (status != ARES_SUCCESS)
×
1367
        return -1;
×
1368
      ares_free_string(name);
×
1369
      if (aptr + len + RRFIXEDSZ > abuf + alen)
×
1370
        return -1;
×
1371
      aptr += len;
×
1372

1373
      if (DNS_RR_TYPE(aptr) == T_OPT)
×
1374
        return 1;
×
1375

1376
      dlen = DNS_RR_LEN(aptr);
×
1377
      aptr += RRFIXEDSZ;
×
1378
      if (aptr + dlen > abuf + alen)
×
1379
        return -1;
×
1380
      aptr += dlen;
×
1381
    }
1382

1383
  return 0;
4✔
1384
}
1385

1386
static void ares_detach_query(struct query *query)
1,587✔
1387
{
1388
  /* Remove the query from all the lists in which it is linked */
1389
  ares__htable_stvp_remove(query->channel->queries_by_qid, query->qid);
1,587✔
1390
  ares__slist_node_destroy(query->node_queries_by_timeout);
1,587✔
1391
  ares__llist_node_destroy(query->node_queries_to_conn);
1,587✔
1392
  ares__llist_node_destroy(query->node_all_queries);
1,587✔
1393
  query->node_queries_by_timeout = NULL;
1,587✔
1394
  query->node_queries_to_conn    = NULL;
1,587✔
1395
  query->node_all_queries        = NULL;
1,587✔
1396
}
1,587✔
1397

1398
static void end_query(ares_channel channel, struct query *query, int status,
785✔
1399
                      const unsigned char *abuf, int alen)
1400
{
1401
  (void)channel;
1402

1403
  ares_detach_query(query);
785✔
1404

1405
  /* Invoke the callback. */
1406
  query->callback(query->arg, status, query->timeouts,
785✔
1407
                  /* due to prior design flaws, abuf isn't meant to be modified,
1408
                   * but bad prototypes, ugh.  Lets cast off constfor compat. */
1409
                  (unsigned char *)((void *)((size_t)abuf)),
1410
                  alen);
1411
  ares__free_query(query);
785✔
1412
}
785✔
1413

1414
void ares__free_query(struct query *query)
802✔
1415
{
1416
  ares_detach_query(query);
802✔
1417
  /* Zero out some important stuff, to help catch bugs */
1418
  query->callback = NULL;
802✔
1419
  query->arg = NULL;
802✔
1420
  /* Deallocate the memory associated with the query */
1421
  ares_free(query->tcpbuf);
802✔
1422
  ares_free(query->server_info);
802✔
1423
  ares_free(query);
802✔
1424
}
802✔
1425

1426
ares_socket_t ares__open_socket(ares_channel channel,
953✔
1427
                                int af, int type, int protocol)
1428
{
1429
  if (channel->sock_funcs && channel->sock_funcs->asocket) {
953✔
1430
    return channel->sock_funcs->asocket(af,
48✔
1431
                                        type,
1432
                                        protocol,
1433
                                        channel->sock_func_cb_data);
1434
  }
1435

1436
  return socket(af, type, protocol);
905✔
1437
}
1438

1439
int ares__connect_socket(ares_channel channel,
947✔
1440
                         ares_socket_t sockfd,
1441
                         const struct sockaddr *addr,
1442
                         ares_socklen_t addrlen)
1443
{
1444
  if (channel->sock_funcs && channel->sock_funcs->aconnect) {
947✔
1445
    return channel->sock_funcs->aconnect(sockfd,
48✔
1446
                                         addr,
1447
                                         addrlen,
1448
                                         channel->sock_func_cb_data);
1449
  }
1450

1451
  return connect(sockfd, addr, addrlen);
899✔
1452
}
1453

1454
void ares__close_socket(ares_channel channel, ares_socket_t s)
953✔
1455
{
1456
  if (channel->sock_funcs && channel->sock_funcs->aclose) {
953✔
1457
    channel->sock_funcs->aclose(s, channel->sock_func_cb_data);
48✔
1458
  } else {
1459
    sclose(s);
905✔
1460
  }
1461
}
953✔
1462

1463
#ifndef HAVE_WRITEV
1464
/* Structure for scatter/gather I/O. */
1465
struct iovec
1466
{
1467
  void *iov_base;  /* Pointer to data. */
1468
  size_t iov_len;  /* Length of data.  */
1469
};
1470
#endif
1471

1472
static ares_ssize_t ares__socket_write(ares_channel channel, ares_socket_t s, const void * data, size_t len)
587✔
1473
{
1474
  if (channel->sock_funcs && channel->sock_funcs->asendv) {
587✔
1475
    struct iovec vec;
1476
    vec.iov_base = (void*)data;
20✔
1477
    vec.iov_len = len;
20✔
1478
    return channel->sock_funcs->asendv(s, &vec, 1, channel->sock_func_cb_data);
20✔
1479
  }
1480
  return swrite(s, data, len);
567✔
1481
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc