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
ares_set_socket_functions_ex(ares_channel_t * channel,const struct ares_socket_functions_ex * funcs,void * user_data)89 ares_set_socket_functions_ex(ares_channel_t *channel,
90 const struct ares_socket_functions_ex *funcs,
91 void *user_data)
92 {
93 unsigned int known_versions[] = { 1 };
94 size_t i;
95
96 if (channel == NULL || funcs == NULL) {
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++) {
102 if (funcs->version == known_versions[i]) {
103 break;
104 }
105 }
106 if (i == sizeof(known_versions) / sizeof(*known_versions)) {
107 return ARES_EFORMERR;
108 }
109
110 memset(&channel->sock_funcs, 0, sizeof(channel->sock_funcs));
111
112 /* Copy individually for ABI compliance. memcpy() with a sizeof would do
113 * invalid reads */
114 if (funcs->version >= 1) {
115 if (funcs->asocket == NULL || funcs->aclose == NULL ||
116 funcs->asetsockopt == NULL || funcs->aconnect == NULL ||
117 funcs->arecvfrom == NULL || funcs->asendto == NULL) {
118 return ARES_EFORMERR;
119 }
120 channel->sock_funcs.version = funcs->version;
121 channel->sock_funcs.flags = funcs->flags;
122 channel->sock_funcs.asocket = funcs->asocket;
123 channel->sock_funcs.aclose = funcs->aclose;
124 channel->sock_funcs.asetsockopt = funcs->asetsockopt;
125 channel->sock_funcs.aconnect = funcs->aconnect;
126 channel->sock_funcs.arecvfrom = funcs->arecvfrom;
127 channel->sock_funcs.asendto = funcs->asendto;
128 channel->sock_funcs.agetsockname = funcs->agetsockname;
129 channel->sock_funcs.abind = funcs->abind;
130 }
131
132 /* Implement newer versions here ...*/
133
134
135 channel->sock_func_cb_data = user_data;
136
137 return ARES_SUCCESS;
138 }
139
setsocknonblock(ares_socket_t sockfd,int nonblock)140 static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
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);
148 if (nonblock) {
149 return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
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
default_aclose(ares_socket_t sock,void * user_data)187 static int default_aclose(ares_socket_t sock, void *user_data)
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);
199 #endif
200 }
201
default_asocket(int domain,int type,int protocol,void * user_data)202 static ares_socket_t default_asocket(int domain, int type, int protocol,
203 void *user_data)
204 {
205 ares_socket_t s;
206 (void)user_data;
207
208 s = socket(domain, type, protocol);
209 if (s == ARES_SOCKET_BAD) {
210 return s;
211 }
212
213 if (setsocknonblock(s, 1) != 0) {
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) {
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) {
234 int opt = 1;
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)) !=
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;
265
266 fail:
267 default_aclose(s, user_data);
268 return ARES_SOCKET_BAD;
269 }
270
default_asetsockopt(ares_socket_t sock,ares_socket_opt_t opt,const void * val,ares_socklen_t val_size,void * user_data)271 static int default_asetsockopt(ares_socket_t sock, ares_socket_opt_t opt,
272 const void *val, ares_socklen_t val_size,
273 void *user_data)
274 {
275 switch (opt) {
276 case ARES_SOCKET_OPT_SENDBUF_SIZE:
277 if (val_size != sizeof(int)) {
278 SET_SOCKERRNO(EINVAL);
279 return -1;
280 }
281 return setsockopt(sock, SOL_SOCKET, SO_SNDBUF, val, val_size);
282
283 case ARES_SOCKET_OPT_RECVBUF_SIZE:
284 if (val_size != sizeof(int)) {
285 SET_SOCKERRNO(EINVAL);
286 return -1;
287 }
288 return setsockopt(sock, SOL_SOCKET, SO_RCVBUF, val, val_size);
289
290 case ARES_SOCKET_OPT_BIND_DEVICE:
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))) {
294 SET_SOCKERRNO(EINVAL);
295 return -1;
296 }
297 #ifdef SO_BINDTODEVICE
298 return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, val, val_size);
299 #else
300 SET_SOCKERRNO(ENOSYS);
301 return -1;
302 #endif
303
304 case ARES_SOCKET_OPT_TCP_FASTOPEN:
305 if (val_size != sizeof(ares_bool_t)) {
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;
313 oval = (int)*pval;
314 return setsockopt(sock, IPPROTO_TCP, TFO_CLIENT_SOCKOPT, (void *)&oval,
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
default_aconnect(ares_socket_t sock,const struct sockaddr * address,ares_socklen_t address_len,unsigned int flags,void * user_data)330 static int default_aconnect(ares_socket_t sock, const struct sockaddr *address,
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);
358 #endif
359 }
360
default_arecvfrom(ares_socket_t sock,void * buffer,size_t length,int flags,struct sockaddr * address,ares_socklen_t * address_len,void * user_data)361 static ares_ssize_t default_arecvfrom(ares_socket_t sock, void *buffer,
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,
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
default_asendto(ares_socket_t sock,const void * buffer,size_t length,int flags,const struct sockaddr * address,ares_socklen_t address_len,void * user_data)381 static ares_ssize_t default_asendto(ares_socket_t sock, const void *buffer,
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) {
389 #ifdef HAVE_SENDTO
390 return (ares_ssize_t)sendto((SEND_TYPE_ARG1)sock, (SEND_TYPE_ARG2)buffer,
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,
399 (SEND_TYPE_ARG3)length, (SEND_TYPE_ARG4)flags);
400 }
401
default_agetsockname(ares_socket_t sock,struct sockaddr * address,ares_socklen_t * address_len,void * user_data)402 static int default_agetsockname(ares_socket_t sock, struct sockaddr *address,
403 ares_socklen_t *address_len, void *user_data)
404 {
405 (void)user_data;
406 return getsockname(sock, address, address_len);
407 }
408
default_abind(ares_socket_t sock,unsigned int flags,const struct sockaddr * address,socklen_t address_len,void * user_data)409 static int default_abind(ares_socket_t sock, unsigned int flags,
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) {
417 int opt = 1;
418 (void)setsockopt(sock, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &opt, sizeof(opt));
419 }
420 #else
421 (void)flags;
422 #endif
423
424 return bind(sock, address, address_len);
425 }
426
default_aif_nametoindex(const char * ifname,void * user_data)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
default_aif_indextoname(unsigned int ifindex,char * ifname_buf,size_t ifname_buf_len,void * user_data)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
ares_set_socket_functions_def(ares_channel_t * channel)457 void ares_set_socket_functions_def(ares_channel_t *channel)
458 {
459 ares_set_socket_functions_ex(channel, &default_socket_functions, NULL);
460 }
461
legacycb_aclose(ares_socket_t sock,void * user_data)462 static int legacycb_aclose(ares_socket_t sock, void *user_data)
463 {
464 ares_channel_t *channel = user_data;
465
466 if (channel->legacy_sock_funcs != NULL &&
467 channel->legacy_sock_funcs->aclose != NULL) {
468 return channel->legacy_sock_funcs->aclose(
469 sock, channel->legacy_sock_funcs_cb_data);
470 }
471
472 return default_aclose(sock, NULL);
473 }
474
legacycb_asocket(int domain,int type,int protocol,void * user_data)475 static ares_socket_t legacycb_asocket(int domain, int type, int protocol,
476 void *user_data)
477 {
478 ares_channel_t *channel = user_data;
479
480 if (channel->legacy_sock_funcs != NULL &&
481 channel->legacy_sock_funcs->asocket != NULL) {
482 return channel->legacy_sock_funcs->asocket(
483 domain, type, protocol, channel->legacy_sock_funcs_cb_data);
484 }
485
486 return default_asocket(domain, type, protocol, NULL);
487 }
488
legacycb_asetsockopt(ares_socket_t sock,ares_socket_opt_t opt,const void * val,ares_socklen_t val_size,void * user_data)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
legacycb_aconnect(ares_socket_t sock,const struct sockaddr * address,ares_socklen_t address_len,unsigned int flags,void * user_data)502 static int legacycb_aconnect(ares_socket_t sock, const struct sockaddr *address,
503 ares_socklen_t address_len, unsigned int flags,
504 void *user_data)
505 {
506 ares_channel_t *channel = user_data;
507
508 if (channel->legacy_sock_funcs != NULL &&
509 channel->legacy_sock_funcs->aconnect != NULL) {
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);
515 }
516
legacycb_arecvfrom(ares_socket_t sock,void * buffer,size_t length,int flags,struct sockaddr * address,ares_socklen_t * address_len,void * user_data)517 static ares_ssize_t legacycb_arecvfrom(ares_socket_t sock, void *buffer,
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;
524
525 if (channel->legacy_sock_funcs != NULL &&
526 channel->legacy_sock_funcs->arecvfrom != NULL) {
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,
537 NULL);
538 }
539
legacycb_asendto(ares_socket_t sock,const void * buffer,size_t length,int flags,const struct sockaddr * address,ares_socklen_t address_len,void * user_data)540 static ares_ssize_t legacycb_asendto(ares_socket_t sock, const void *buffer,
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;
547
548 if (channel->legacy_sock_funcs != NULL &&
549 channel->legacy_sock_funcs->asendv != NULL) {
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,
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
ares_set_socket_functions(ares_channel_t * channel,const struct ares_socket_functions * funcs,void * data)577 void ares_set_socket_functions(ares_channel_t *channel,
578 const struct ares_socket_functions *funcs,
579 void *data)
580 {
581 if (channel == NULL || channel->optmask & ARES_OPT_EVENT_THREAD) {
582 return;
583 }
584
585 channel->legacy_sock_funcs = funcs;
586 channel->legacy_sock_funcs_cb_data = data;
587 ares_set_socket_functions_ex(channel, &legacy_socket_functions, channel);
588 }
589