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

c-ares / c-ares / 12300302007

12 Dec 2024 04:09PM UTC coverage: 91.304% (-0.03%) from 91.334%
12300302007

push

github

bradh352
ARES_SOCKET_OPT_BIND_DEVICE only validate printable up to NULL terminator (#935)

See #929 for discussion

Signed-off-by: Brad House (@bradh352)

2 of 2 new or added lines in 2 files covered. (100.0%)

8 existing lines in 4 files now uncovered.

22155 of 24265 relevant lines covered (91.3%)

11909.18 hits per line

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

74.82
/src/lib/ares_set_socket_functions.c
1
/* MIT License
2
 *
3
 * Copyright (c) 2024 Brad House
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to deal
7
 * in the Software without restriction, including without limitation the rights
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 *
24
 * SPDX-License-Identifier: MIT
25
 */
26
#include "ares_private.h"
27
#ifdef HAVE_SYS_UIO_H
28
#  include <sys/uio.h>
29
#endif
30
#ifdef HAVE_NETINET_IN_H
31
#  include <netinet/in.h>
32
#endif
33
#ifdef HAVE_NETINET_TCP_H
34
#  include <netinet/tcp.h>
35
#endif
36
#ifdef HAVE_NETDB_H
37
#  include <netdb.h>
38
#endif
39
#ifdef HAVE_ARPA_INET_H
40
#  include <arpa/inet.h>
41
#endif
42

43
#ifdef HAVE_STRINGS_H
44
#  include <strings.h>
45
#endif
46
#ifdef HAVE_SYS_IOCTL_H
47
#  include <sys/ioctl.h>
48
#endif
49
#ifdef NETWARE
50
#  include <sys/filio.h>
51
#endif
52

53
#include <assert.h>
54
#include <fcntl.h>
55
#include <limits.h>
56

57

58
#if defined(__linux__) && defined(TCP_FASTOPEN_CONNECT)
59
#  define TFO_SUPPORTED      1
60
#  define TFO_SKIP_CONNECT   0
61
#  define TFO_USE_SENDTO     0
62
#  define TFO_USE_CONNECTX   0
63
#  define TFO_CLIENT_SOCKOPT TCP_FASTOPEN_CONNECT
64
#elif defined(__FreeBSD__) && defined(TCP_FASTOPEN)
65
#  define TFO_SUPPORTED      1
66
#  define TFO_SKIP_CONNECT   1
67
#  define TFO_USE_SENDTO     1
68
#  define TFO_USE_CONNECTX   0
69
#  define TFO_CLIENT_SOCKOPT TCP_FASTOPEN
70
#elif defined(__APPLE__) && defined(HAVE_CONNECTX)
71
#  define TFO_SUPPORTED    1
72
#  define TFO_SKIP_CONNECT 0
73
#  define TFO_USE_SENDTO   0
74
#  define TFO_USE_CONNECTX 1
75
#  undef TFO_CLIENT_SOCKOPT
76
#else
77
#  define TFO_SUPPORTED 0
78
#endif
79

80
#ifndef HAVE_WRITEV
81
/* Structure for scatter/gather I/O. */
82
struct iovec {
83
  void  *iov_base; /* Pointer to data. */
84
  size_t iov_len;  /* Length of data.  */
85
};
86
#endif
87

88
ares_status_t
89
  ares_set_socket_functions_ex(ares_channel_t                        *channel,
1,080✔
90
                               const struct ares_socket_functions_ex *funcs,
91
                               void                                  *user_data)
92
{
93
  unsigned int known_versions[] = { 1 };
1,080✔
94
  size_t       i;
95

96
  if (channel == NULL || funcs == NULL) {
1,080✔
97
    return ARES_EFORMERR;
×
98
  }
99

100
  /* Check to see if we know the version referenced */
101
  for (i = 0; i < sizeof(known_versions) / sizeof(*known_versions); i++) {
1,080✔
102
    if (funcs->version == known_versions[i]) {
1,080✔
103
      break;
1,080✔
104
    }
105
  }
106
  if (i == sizeof(known_versions) / sizeof(*known_versions)) {
1,080✔
107
    return ARES_EFORMERR;
×
108
  }
109

110
  memset(&channel->sock_funcs, 0, sizeof(channel->sock_funcs));
1,080✔
111

112
  /* Copy individually for ABI compliance.  memcpy() with a sizeof would do
113
   * invalid reads */
114
  if (funcs->version >= 1) {
1,080✔
115
    if (funcs->asocket == NULL || funcs->aclose == NULL ||
1,080✔
116
        funcs->asetsockopt == NULL || funcs->aconnect == NULL ||
1,080✔
117
        funcs->arecvfrom == NULL || funcs->asendto == NULL) {
1,080✔
118
      return ARES_EFORMERR;
×
119
    }
120
    channel->sock_funcs.version      = funcs->version;
1,080✔
121
    channel->sock_funcs.flags        = funcs->flags;
1,080✔
122
    channel->sock_funcs.asocket      = funcs->asocket;
1,080✔
123
    channel->sock_funcs.aclose       = funcs->aclose;
1,080✔
124
    channel->sock_funcs.asetsockopt  = funcs->asetsockopt;
1,080✔
125
    channel->sock_funcs.aconnect     = funcs->aconnect;
1,080✔
126
    channel->sock_funcs.arecvfrom    = funcs->arecvfrom;
1,080✔
127
    channel->sock_funcs.asendto      = funcs->asendto;
1,080✔
128
    channel->sock_funcs.agetsockname = funcs->agetsockname;
1,080✔
129
    channel->sock_funcs.abind        = funcs->abind;
1,080✔
130
  }
131

132
  /* Implement newer versions here ...*/
133

134

135
  channel->sock_func_cb_data = user_data;
1,080✔
136

137
  return ARES_SUCCESS;
1,080✔
138
}
139

140
static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
3,041✔
141
                           int           nonblock /* TRUE or FALSE */)
142
{
143
#if defined(HAVE_FCNTL_O_NONBLOCK)
144

145
  /* most recent unix versions */
146
  int flags;
147
  flags = fcntl(sockfd, F_GETFL, 0);
3,041✔
148
  if (nonblock) {
3,041✔
149
    return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
3,041✔
150
  } else {
151
    return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); /* LCOV_EXCL_LINE */
152
  }
153

154
#elif defined(HAVE_IOCTL_FIONBIO)
155

156
  /* older unix versions */
157
  int flags = nonblock ? 1 : 0;
158
  return ioctl(sockfd, FIONBIO, &flags);
159

160
#elif defined(HAVE_IOCTLSOCKET_FIONBIO)
161

162
#  ifdef WATT32
163
  char flags = nonblock ? 1 : 0;
164
#  else
165
  /* Windows */
166
  unsigned long flags = nonblock ? 1UL : 0UL;
167
#  endif
168
  return ioctlsocket(sockfd, (long)FIONBIO, &flags);
169

170
#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO)
171

172
  /* Amiga */
173
  long flags = nonblock ? 1L : 0L;
174
  return IoctlSocket(sockfd, FIONBIO, flags);
175

176
#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK)
177

178
  /* BeOS */
179
  long b = nonblock ? 1L : 0L;
180
  return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
181

182
#else
183
#  error "no non-blocking method was found/used/set"
184
#endif
185
}
186

187
static int default_aclose(ares_socket_t sock, void *user_data)
3,065✔
188
{
189
  (void)user_data;
190

191
#if defined(HAVE_CLOSESOCKET)
192
  return closesocket(sock);
193
#elif defined(HAVE_CLOSESOCKET_CAMEL)
194
  return CloseSocket(sock);
195
#elif defined(HAVE_CLOSE_S)
196
  return close_s(sock);
197
#else
198
  return close(sock);
3,065✔
199
#endif
200
}
201

202
static ares_socket_t default_asocket(int domain, int type, int protocol,
3,041✔
203
                                     void *user_data)
204
{
205
  ares_socket_t s;
206
  (void)user_data;
207

208
  s = socket(domain, type, protocol);
3,041✔
209
  if (s == ARES_SOCKET_BAD) {
3,041✔
210
    return s;
×
211
  }
212

213
  if (setsocknonblock(s, 1) != 0) {
3,041✔
214
    goto fail; /* LCOV_EXCL_LINE */
215
  }
216

217
#if defined(FD_CLOEXEC) && !defined(MSDOS)
218
  /* Configure the socket fd as close-on-exec. */
219
  if (fcntl(s, F_SETFD, FD_CLOEXEC) != 0) {
3,041✔
220
    goto fail; /* LCOV_EXCL_LINE */
221
  }
222
#endif
223

224
  /* No need to emit SIGPIPE on socket errors */
225
#if defined(SO_NOSIGPIPE)
226
  {
227
    int opt = 1;
228
    (void)setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt));
229
  }
230
#endif
231

232

233
  if (type == SOCK_STREAM) {
3,041✔
234
    int opt = 1;
784✔
235

236
#ifdef TCP_NODELAY
237
    /*
238
     * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not
239
     * in configure_socket). In general, in DNS lookups we're pretty much
240
     * interested in firing off a single request and then waiting for a reply,
241
     * so batching isn't very interesting.
242
     */
243
    if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)) !=
784✔
244
        0) {
245
      goto fail;
×
246
    }
247
#endif
248
  }
249

250
#if defined(IPV6_V6ONLY) && defined(USE_WINSOCK)
251
  /* Support for IPv4-mapped IPv6 addresses.
252
   * Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
253
   * Windows Vista and later: default is on;
254
   * DragonFly BSD: acts like off, and dummy setting;
255
   * OpenBSD and earlier Windows: unsupported.
256
   * Linux: controlled by /proc/sys/net/ipv6/bindv6only.
257
   */
258
  if (domain == PF_INET6) {
259
    int on = 0;
260
    (void)setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on));
261
  }
262
#endif
263

264
  return s;
3,041✔
265

266
fail:
×
267
  default_aclose(s, user_data);
×
268
  return ARES_SOCKET_BAD;
×
269
}
270

271
static int default_asetsockopt(ares_socket_t sock, ares_socket_opt_t opt,
896✔
272
                               const void *val, ares_socklen_t val_size,
273
                               void *user_data)
274
{
275
  switch (opt) {
896✔
276
    case ARES_SOCKET_OPT_SENDBUF_SIZE:
44✔
277
      if (val_size != sizeof(int)) {
44✔
278
        SET_SOCKERRNO(EINVAL);
×
279
        return -1;
×
280
      }
281
      return setsockopt(sock, SOL_SOCKET, SO_SNDBUF, val, val_size);
44✔
282

283
    case ARES_SOCKET_OPT_RECVBUF_SIZE:
44✔
284
      if (val_size != sizeof(int)) {
44✔
285
        SET_SOCKERRNO(EINVAL);
×
286
        return -1;
×
287
      }
288
      return setsockopt(sock, SOL_SOCKET, SO_RCVBUF, val, val_size);
44✔
289

290
    case ARES_SOCKET_OPT_BIND_DEVICE:
24✔
291
      /* Count the number of characters before NULL terminator then
292
       * validate those are all printable */
293
      if (!ares_str_isprint(val, ares_strnlen(val, (size_t)val_size))) {
24✔
UNCOV
294
        SET_SOCKERRNO(EINVAL);
×
UNCOV
295
        return -1;
×
296
      }
297
#ifdef SO_BINDTODEVICE
298
      return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, val, val_size);
24✔
299
#else
300
      SET_SOCKERRNO(ENOSYS);
301
      return -1;
302
#endif
303

304
    case ARES_SOCKET_OPT_TCP_FASTOPEN:
784✔
305
      if (val_size != sizeof(ares_bool_t)) {
784✔
306
        SET_SOCKERRNO(EINVAL);
×
307
        return -1;
×
308
      }
309
#if defined(TFO_CLIENT_SOCKOPT)
310
      {
311
        int                oval;
312
        const ares_bool_t *pval = val;
784✔
313
        oval                    = (int)*pval;
784✔
314
        return setsockopt(sock, IPPROTO_TCP, TFO_CLIENT_SOCKOPT, (void *)&oval,
784✔
315
                          sizeof(oval));
316
      }
317
#elif TFO_SUPPORTED
318
      return 0;
319
#else
320
      SET_SOCKERRNO(ENOSYS);
321
      return -1;
322
#endif
323
  }
324

325
  (void)user_data;
326
  SET_SOCKERRNO(ENOSYS);
×
327
  return -1;
×
328
}
329

330
static int default_aconnect(ares_socket_t sock, const struct sockaddr *address,
3,053✔
331
                            ares_socklen_t address_len, unsigned int flags,
332
                            void *user_data)
333
{
334
  (void)user_data;
335

336
#if defined(TFO_SKIP_CONNECT) && TFO_SKIP_CONNECT
337
  if (flags & ARES_SOCKET_CONN_TCP_FASTOPEN) {
338
    return 0;
339
  }
340
  return connect(sock, address, address_len);
341
#elif defined(TFO_USE_CONNECTX) && TFO_USE_CONNECTX
342
  if (flags & ARES_SOCKET_CONN_TCP_FASTOPEN) {
343
    sa_endpoints_t endpoints;
344

345
    memset(&endpoints, 0, sizeof(endpoints));
346
    endpoints.sae_dstaddr    = address;
347
    endpoints.sae_dstaddrlen = address_len;
348

349
    return connectx(sock, &endpoints, SAE_ASSOCID_ANY,
350
                    CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE,
351
                    NULL, 0, NULL, NULL);
352
  } else {
353
    return connect(sock, address, address_len);
354
  }
355
#else
356
  (void)flags;
357
  return connect(sock, address, address_len);
3,053✔
358
#endif
359
}
360

361
static ares_ssize_t default_arecvfrom(ares_socket_t sock, void *buffer,
3,684✔
362
                                      size_t length, int flags,
363
                                      struct sockaddr *address,
364
                                      ares_socklen_t  *address_len,
365
                                      void            *user_data)
366
{
367
  (void)user_data;
368

369
#ifdef HAVE_RECVFROM
370
  return (ares_ssize_t)recvfrom(sock, buffer, (RECVFROM_TYPE_ARG3)length, flags,
3,684✔
371
                                address, address_len);
372
#else
373
  if (address != NULL && address_len != NULL) {
374
    memset(address, 0, (size_t)*address_len);
375
    address->sa_family = AF_UNSPEC;
376
  }
377
  return (ares_ssize_t)recv(sock, buffer, (RECVFROM_TYPE_ARG3)length, flags);
378
#endif
379
}
380

381
static ares_ssize_t default_asendto(ares_socket_t sock, const void *buffer,
4,172✔
382
                                    size_t length, int flags,
383
                                    const struct sockaddr *address,
384
                                    ares_socklen_t address_len, void *user_data)
385
{
386
  (void)user_data;
387

388
  if (address != NULL) {
4,172✔
389
#ifdef HAVE_SENDTO
390
    return (ares_ssize_t)sendto((SEND_TYPE_ARG1)sock, (SEND_TYPE_ARG2)buffer,
736✔
391
                                (SEND_TYPE_ARG3)length, (SEND_TYPE_ARG4)flags,
392
                                address, address_len);
393
#else
394
    (void)address_len;
395
#endif
396
  }
397

398
  return (ares_ssize_t)send((SEND_TYPE_ARG1)sock, (SEND_TYPE_ARG2)buffer,
3,436✔
399
                            (SEND_TYPE_ARG3)length, (SEND_TYPE_ARG4)flags);
400
}
401

402
static int default_agetsockname(ares_socket_t sock, struct sockaddr *address,
2,900✔
403
                                ares_socklen_t *address_len, void *user_data)
404
{
405
  (void)user_data;
406
  return getsockname(sock, address, address_len);
2,900✔
407
}
408

409
static int default_abind(ares_socket_t sock, unsigned int flags,
24✔
410
                         const struct sockaddr *address, socklen_t address_len,
411
                         void *user_data)
412
{
413
  (void)user_data;
414

415
#ifdef IP_BIND_ADDRESS_NO_PORT
416
  if (flags & ARES_SOCKET_BIND_TCP && flags & ARES_SOCKET_BIND_CLIENT) {
24✔
417
    int opt = 1;
12✔
418
    (void)setsockopt(sock, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &opt, sizeof(opt));
12✔
419
  }
420
#else
421
  (void)flags;
422
#endif
423

424
  return bind(sock, address, address_len);
24✔
425
}
426

427
static unsigned int default_aif_nametoindex(const char *ifname, void *user_data)
×
428
{
429
  (void)user_data;
430
  return ares_os_if_nametoindex(ifname);
×
431
}
432

433
static const char *default_aif_indextoname(unsigned int ifindex,
×
434
                                           char        *ifname_buf,
435
                                           size_t       ifname_buf_len,
436
                                           void        *user_data)
437
{
438
  (void)user_data;
439
  return ares_os_if_indextoname(ifindex, ifname_buf, ifname_buf_len);
×
440
}
441

442
static const struct ares_socket_functions_ex default_socket_functions = {
443
  1,
444
  ARES_SOCKFUNC_FLAG_NONBLOCKING,
445
  default_asocket,
446
  default_aclose,
447
  default_asetsockopt,
448
  default_aconnect,
449
  default_arecvfrom,
450
  default_asendto,
451
  default_agetsockname,
452
  default_abind,
453
  default_aif_nametoindex,
454
  default_aif_indextoname
455
};
456

457
void ares_set_socket_functions_def(ares_channel_t *channel)
1,023✔
458
{
459
  ares_set_socket_functions_ex(channel, &default_socket_functions, NULL);
1,023✔
460
}
1,023✔
461

462
static int legacycb_aclose(ares_socket_t sock, void *user_data)
24✔
463
{
464
  ares_channel_t *channel = user_data;
24✔
465

466
  if (channel->legacy_sock_funcs != NULL &&
24✔
467
      channel->legacy_sock_funcs->aclose != NULL) {
24✔
468
    return channel->legacy_sock_funcs->aclose(
×
469
      sock, channel->legacy_sock_funcs_cb_data);
470
  }
471

472
  return default_aclose(sock, NULL);
24✔
473
}
474

475
static ares_socket_t legacycb_asocket(int domain, int type, int protocol,
24✔
476
                                      void *user_data)
477
{
478
  ares_channel_t *channel = user_data;
24✔
479

480
  if (channel->legacy_sock_funcs != NULL &&
24✔
481
      channel->legacy_sock_funcs->asocket != NULL) {
24✔
482
    return channel->legacy_sock_funcs->asocket(
24✔
483
      domain, type, protocol, channel->legacy_sock_funcs_cb_data);
484
  }
485

486
  return default_asocket(domain, type, protocol, NULL);
×
487
}
488

489
static int legacycb_asetsockopt(ares_socket_t sock, ares_socket_opt_t opt,
×
490
                                const void *val, ares_socklen_t val_size,
491
                                void *user_data)
492
{
493
  (void)sock;
494
  (void)opt;
495
  (void)val;
496
  (void)val_size;
497
  (void)user_data;
498
  SET_SOCKERRNO(ENOSYS);
×
499
  return -1;
×
500
}
501

502
static int legacycb_aconnect(ares_socket_t sock, const struct sockaddr *address,
24✔
503
                             ares_socklen_t address_len, unsigned int flags,
504
                             void *user_data)
505
{
506
  ares_channel_t *channel = user_data;
24✔
507

508
  if (channel->legacy_sock_funcs != NULL &&
24✔
509
      channel->legacy_sock_funcs->aconnect != NULL) {
24✔
510
    return channel->legacy_sock_funcs->aconnect(
×
511
      sock, address, address_len, channel->legacy_sock_funcs_cb_data);
512
  }
513

514
  return default_aconnect(sock, address, address_len, flags, NULL);
24✔
515
}
516

517
static ares_ssize_t legacycb_arecvfrom(ares_socket_t sock, void *buffer,
19✔
518
                                       size_t length, int flags,
519
                                       struct sockaddr *address,
520
                                       ares_socklen_t  *address_len,
521
                                       void            *user_data)
522
{
523
  ares_channel_t *channel = user_data;
19✔
524

525
  if (channel->legacy_sock_funcs != NULL &&
19✔
526
      channel->legacy_sock_funcs->arecvfrom != NULL) {
19✔
527
    if (address != NULL && address_len != NULL) {
×
528
      memset(address, 0, (size_t)*address_len);
×
529
      address->sa_family = AF_UNSPEC;
×
530
    }
531
    return channel->legacy_sock_funcs->arecvfrom(
×
532
      sock, buffer, length, flags, address, address_len,
533
      channel->legacy_sock_funcs_cb_data);
534
  }
535

536
  return default_arecvfrom(sock, buffer, length, flags, address, address_len,
19✔
537
                           NULL);
538
}
539

540
static ares_ssize_t legacycb_asendto(ares_socket_t sock, const void *buffer,
19✔
541
                                     size_t length, int flags,
542
                                     const struct sockaddr *address,
543
                                     ares_socklen_t         address_len,
544
                                     void                  *user_data)
545
{
546
  ares_channel_t *channel = user_data;
19✔
547

548
  if (channel->legacy_sock_funcs != NULL &&
19✔
549
      channel->legacy_sock_funcs->asendv != NULL) {
19✔
550
    struct iovec vec;
551
    vec.iov_base = (void *)((size_t)buffer); /* Cast off const */
×
552
    vec.iov_len  = length;
×
553
    return channel->legacy_sock_funcs->asendv(
×
554
      sock, &vec, 1, channel->legacy_sock_funcs_cb_data);
555
  }
556

557
  return default_asendto(sock, buffer, length, flags, address, address_len,
19✔
558
                         NULL);
559
}
560

561

562
static const struct ares_socket_functions_ex legacy_socket_functions = {
563
  1,
564
  0,
565
  legacycb_asocket,
566
  legacycb_aclose,
567
  legacycb_asetsockopt,
568
  legacycb_aconnect,
569
  legacycb_arecvfrom,
570
  legacycb_asendto,
571
  NULL, /* agetsockname */
572
  NULL, /* abind */
573
  NULL, /* aif_nametoindex */
574
  NULL  /* aif_indextoname */
575
};
576

577
void ares_set_socket_functions(ares_channel_t                     *channel,
58✔
578
                               const struct ares_socket_functions *funcs,
579
                               void                               *data)
580
{
581
  if (channel == NULL || channel->optmask & ARES_OPT_EVENT_THREAD) {
58✔
582
    return;
1✔
583
  }
584

585
  channel->legacy_sock_funcs         = funcs;
57✔
586
  channel->legacy_sock_funcs_cb_data = data;
57✔
587
  ares_set_socket_functions_ex(channel, &legacy_socket_functions, channel);
57✔
588
}
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

© 2026 Coveralls, Inc