1/* MIT License 2 * 3 * Copyright (c) Massachusetts Institute of Technology 4 * Copyright (c) The c-ares project and its contributors 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * SPDX-License-Identifier: MIT 26 */ 27#include "ares_setup.h" 28 29#ifdef HAVE_SYS_UIO_H 30# include <sys/uio.h> 31#endif 32#ifdef HAVE_NETINET_IN_H 33# include <netinet/in.h> 34#endif 35#ifdef HAVE_NETINET_TCP_H 36# include <netinet/tcp.h> 37#endif 38#ifdef HAVE_NETDB_H 39# include <netdb.h> 40#endif 41#ifdef HAVE_ARPA_INET_H 42# include <arpa/inet.h> 43#endif 44 45#ifdef HAVE_STRINGS_H 46# include <strings.h> 47#endif 48#ifdef HAVE_SYS_IOCTL_H 49# include <sys/ioctl.h> 50#endif 51#ifdef NETWARE 52# include <sys/filio.h> 53#endif 54 55#include <assert.h> 56#include <fcntl.h> 57#include <limits.h> 58 59#include "ares.h" 60#include "ares_private.h" 61 62ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s, 63 void *data, size_t data_len, int flags, 64 struct sockaddr *from, 65 ares_socklen_t *from_len) 66{ 67 if (channel->sock_funcs && channel->sock_funcs->arecvfrom) { 68 return channel->sock_funcs->arecvfrom(s, data, data_len, flags, from, 69 from_len, channel->sock_func_cb_data); 70 } 71 72#ifdef HAVE_RECVFROM 73 return (ares_ssize_t)recvfrom(s, data, (RECVFROM_TYPE_ARG3)data_len, flags, 74 from, from_len); 75#else 76 return sread(s, data, data_len); 77#endif 78} 79 80ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s, 81 void *data, size_t data_len) 82{ 83 if (channel->sock_funcs && channel->sock_funcs->arecvfrom) { 84 return channel->sock_funcs->arecvfrom(s, data, data_len, 0, 0, 0, 85 channel->sock_func_cb_data); 86 } 87 88 /* sread() is a wrapper for read() or recv() depending on the system */ 89 return sread(s, data, data_len); 90} 91 92/* 93 * setsocknonblock sets the given socket to either blocking or non-blocking 94 * mode based on the 'nonblock' boolean argument. This function is highly 95 * portable. 96 */ 97static int setsocknonblock(ares_socket_t sockfd, /* operate on this */ 98 int nonblock /* TRUE or FALSE */) 99{ 100#if defined(USE_BLOCKING_SOCKETS) 101 102 return 0; /* returns success */ 103 104#elif defined(HAVE_FCNTL_O_NONBLOCK) 105 106 /* most recent unix versions */ 107 int flags; 108 flags = fcntl(sockfd, F_GETFL, 0); 109 if (nonblock) { 110 return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 111 } else { 112 return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); /* LCOV_EXCL_LINE */ 113 } 114 115#elif defined(HAVE_IOCTL_FIONBIO) 116 117 /* older unix versions */ 118 int flags = nonblock ? 1 : 0; 119 return ioctl(sockfd, FIONBIO, &flags); 120 121#elif defined(HAVE_IOCTLSOCKET_FIONBIO) 122 123# ifdef WATT32 124 char flags = nonblock ? 1 : 0; 125# else 126 /* Windows */ 127 unsigned long flags = nonblock ? 1UL : 0UL; 128# endif 129 return ioctlsocket(sockfd, (long)FIONBIO, &flags); 130 131#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) 132 133 /* Amiga */ 134 long flags = nonblock ? 1L : 0L; 135 return IoctlSocket(sockfd, FIONBIO, flags); 136 137#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) 138 139 /* BeOS */ 140 long b = nonblock ? 1L : 0L; 141 return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); 142 143#else 144# error "no non-blocking method was found/used/set" 145#endif 146} 147 148#if defined(IPV6_V6ONLY) && defined(WIN32) 149/* It makes support for IPv4-mapped IPv6 addresses. 150 * Linux kernel, NetBSD, FreeBSD and Darwin: default is off; 151 * Windows Vista and later: default is on; 152 * DragonFly BSD: acts like off, and dummy setting; 153 * OpenBSD and earlier Windows: unsupported. 154 * Linux: controlled by /proc/sys/net/ipv6/bindv6only. 155 */ 156static void set_ipv6_v6only(ares_socket_t sockfd, int on) 157{ 158 (void)setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on)); 159} 160#else 161# define set_ipv6_v6only(s, v) 162#endif 163 164static int configure_socket(ares_socket_t s, struct server_state *server) 165{ 166 union { 167 struct sockaddr sa; 168 struct sockaddr_in sa4; 169 struct sockaddr_in6 sa6; 170 } local; 171 172 ares_socklen_t bindlen = 0; 173 ares_channel_t *channel = server->channel; 174 175 /* do not set options for user-managed sockets */ 176 if (channel->sock_funcs && channel->sock_funcs->asocket) { 177 return 0; 178 } 179 180 (void)setsocknonblock(s, 1); 181 182#if defined(FD_CLOEXEC) && !defined(MSDOS) 183 /* Configure the socket fd as close-on-exec. */ 184 if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) { 185 return -1; /* LCOV_EXCL_LINE */ 186 } 187#endif 188 189 /* Set the socket's send and receive buffer sizes. */ 190 if ((channel->socket_send_buffer_size > 0) && 191 setsockopt(s, SOL_SOCKET, SO_SNDBUF, 192 (void *)&channel->socket_send_buffer_size, 193 sizeof(channel->socket_send_buffer_size)) == -1) { 194 return -1; 195 } 196 197 if ((channel->socket_receive_buffer_size > 0) && 198 setsockopt(s, SOL_SOCKET, SO_RCVBUF, 199 (void *)&channel->socket_receive_buffer_size, 200 sizeof(channel->socket_receive_buffer_size)) == -1) { 201 return -1; 202 } 203 204#ifdef SO_BINDTODEVICE 205 if (channel->local_dev_name[0] && 206 setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, channel->local_dev_name, 207 sizeof(channel->local_dev_name))) { 208 /* Only root can do this, and usually not fatal if it doesn't work, so */ 209 /* just continue on. */ 210 } 211#endif 212 213 if (server->addr.family == AF_INET && channel->local_ip4) { 214 memset(&local.sa4, 0, sizeof(local.sa4)); 215 local.sa4.sin_family = AF_INET; 216 local.sa4.sin_addr.s_addr = htonl(channel->local_ip4); 217 bindlen = sizeof(local.sa4); 218 } else if (server->addr.family == AF_INET6 && server->ll_scope == 0 && 219 memcmp(channel->local_ip6, ares_in6addr_any._S6_un._S6_u8, 220 sizeof(channel->local_ip6)) != 0) { 221 /* Only if not link-local and an ip other than "::" is specified */ 222 memset(&local.sa6, 0, sizeof(local.sa6)); 223 local.sa6.sin6_family = AF_INET6; 224 memcpy(&local.sa6.sin6_addr, channel->local_ip6, 225 sizeof(channel->local_ip6)); 226 bindlen = sizeof(local.sa6); 227 } 228 229 if (bindlen && bind(s, &local.sa, bindlen) < 0) { 230 return -1; 231 } 232 233 if (server->addr.family == AF_INET6) { 234 set_ipv6_v6only(s, 0); 235 } 236 237 return 0; 238} 239 240ares_status_t ares__open_connection(ares_channel_t *channel, 241 struct server_state *server, 242 ares_bool_t is_tcp) 243{ 244 ares_socket_t s; 245 int opt; 246 ares_socklen_t salen; 247 248 union { 249 struct sockaddr_in sa4; 250 struct sockaddr_in6 sa6; 251 } saddr; 252 struct sockaddr *sa; 253 struct server_connection *conn; 254 ares__llist_node_t *node; 255 int type = is_tcp ? SOCK_STREAM : SOCK_DGRAM; 256#ifdef __OpenBSD__ 257 if ((is_tcp && server->tcp_port == 53) || 258 (!is_tcp && server->udp_port == 53)) { 259 type |= SOCK_DNS; 260 } 261#endif 262 263 switch (server->addr.family) { 264 case AF_INET: 265 sa = (void *)&saddr.sa4; 266 salen = sizeof(saddr.sa4); 267 memset(sa, 0, (size_t)salen); 268 saddr.sa4.sin_family = AF_INET; 269 saddr.sa4.sin_port = htons(is_tcp ? server->tcp_port : server->udp_port); 270 memcpy(&saddr.sa4.sin_addr, &server->addr.addr.addr4, 271 sizeof(saddr.sa4.sin_addr)); 272 break; 273 case AF_INET6: 274 sa = (void *)&saddr.sa6; 275 salen = sizeof(saddr.sa6); 276 memset(sa, 0, (size_t)salen); 277 saddr.sa6.sin6_family = AF_INET6; 278 saddr.sa6.sin6_port = htons(is_tcp ? server->tcp_port : server->udp_port); 279 memcpy(&saddr.sa6.sin6_addr, &server->addr.addr.addr6, 280 sizeof(saddr.sa6.sin6_addr)); 281#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 282 saddr.sa6.sin6_scope_id = server->ll_scope; 283#endif 284 break; 285 default: 286 return ARES_EBADFAMILY; /* LCOV_EXCL_LINE */ 287 } 288 289 /* Acquire a socket. */ 290 s = ares__open_socket(channel, server->addr.family, type, 0); 291 if (s == ARES_SOCKET_BAD) { 292 return ARES_ECONNREFUSED; 293 } 294 295 /* Configure it. */ 296 if (configure_socket(s, server) < 0) { 297 ares__close_socket(channel, s); 298 return ARES_ECONNREFUSED; 299 } 300 301#ifdef TCP_NODELAY 302 if (is_tcp) { 303 /* 304 * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not 305 * in configure_socket). In general, in DNS lookups we're pretty much 306 * interested in firing off a single request and then waiting for a reply, 307 * so batching isn't very interesting. 308 */ 309 opt = 1; 310 if ((!channel->sock_funcs || !channel->sock_funcs->asocket) && 311 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)) == 312 -1) { 313 ares__close_socket(channel, s); 314 return ARES_ECONNREFUSED; 315 } 316 } 317#endif 318 319 if (channel->sock_config_cb) { 320 int err = channel->sock_config_cb(s, type, channel->sock_config_cb_data); 321 if (err < 0) { 322 ares__close_socket(channel, s); 323 return ARES_ECONNREFUSED; 324 } 325 } 326 327 /* Connect to the server. */ 328 if (ares__connect_socket(channel, s, sa, salen) == -1) { 329 int err = SOCKERRNO; 330 331 if (err != EINPROGRESS && err != EWOULDBLOCK) { 332 ares__close_socket(channel, s); 333 return ARES_ECONNREFUSED; 334 } 335 } 336 337 if (channel->sock_create_cb) { 338 int err = channel->sock_create_cb(s, type, channel->sock_create_cb_data); 339 if (err < 0) { 340 ares__close_socket(channel, s); 341 return ARES_ECONNREFUSED; 342 } 343 } 344 345 conn = ares_malloc(sizeof(*conn)); 346 if (conn == NULL) { 347 ares__close_socket(channel, s); 348 return ARES_ENOMEM; 349 } 350 memset(conn, 0, sizeof(*conn)); 351 conn->fd = s; 352 conn->server = server; 353 conn->queries_to_conn = ares__llist_create(NULL); 354 conn->is_tcp = is_tcp; 355 if (conn->queries_to_conn == NULL) { 356 ares__close_socket(channel, s); 357 ares_free(conn); 358 return ARES_ENOMEM; 359 } 360 361 /* TCP connections are thrown to the end as we don't spawn multiple TCP 362 * connections. UDP connections are put on front where the newest connection 363 * can be quickly pulled */ 364 if (is_tcp) { 365 node = ares__llist_insert_last(server->connections, conn); 366 } else { 367 node = ares__llist_insert_first(server->connections, conn); 368 } 369 if (node == NULL) { 370 ares__close_socket(channel, s); 371 ares__llist_destroy(conn->queries_to_conn); 372 ares_free(conn); 373 return ARES_ENOMEM; 374 } 375 376 /* Register globally to quickly map event on file descriptor to connection 377 * node object */ 378 if (!ares__htable_asvp_insert(channel->connnode_by_socket, s, node)) { 379 ares__close_socket(channel, s); 380 ares__llist_destroy(conn->queries_to_conn); 381 ares__llist_node_claim(node); 382 ares_free(conn); 383 return ARES_ENOMEM; 384 } 385 386 SOCK_STATE_CALLBACK(channel, s, 1, 0); 387 388 if (is_tcp) { 389 server->tcp_conn = conn; 390 } 391 392 return ARES_SUCCESS; 393} 394 395ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type, 396 int protocol) 397{ 398 if (channel->sock_funcs && channel->sock_funcs->asocket) { 399 return channel->sock_funcs->asocket(af, type, protocol, 400 channel->sock_func_cb_data); 401 } 402 403 return socket(af, type, protocol); 404} 405 406int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, 407 const struct sockaddr *addr, ares_socklen_t addrlen) 408{ 409 if (channel->sock_funcs && channel->sock_funcs->aconnect) { 410 return channel->sock_funcs->aconnect(sockfd, addr, addrlen, 411 channel->sock_func_cb_data); 412 } 413 414 return connect(sockfd, addr, addrlen); 415} 416 417void ares__close_socket(ares_channel_t *channel, ares_socket_t s) 418{ 419 if (s == ARES_SOCKET_BAD) { 420 return; 421 } 422 423 if (channel->sock_funcs && channel->sock_funcs->aclose) { 424 channel->sock_funcs->aclose(s, channel->sock_func_cb_data); 425 } else { 426 sclose(s); 427 } 428} 429 430#ifndef HAVE_WRITEV 431/* Structure for scatter/gather I/O. */ 432struct iovec { 433 void *iov_base; /* Pointer to data. */ 434 size_t iov_len; /* Length of data. */ 435}; 436#endif 437 438ares_ssize_t ares__socket_write(ares_channel_t *channel, ares_socket_t s, 439 const void *data, size_t len) 440{ 441 if (channel->sock_funcs && channel->sock_funcs->asendv) { 442 struct iovec vec; 443 vec.iov_base = (void *)((size_t)data); /* Cast off const */ 444 vec.iov_len = len; 445 return channel->sock_funcs->asendv(s, &vec, 1, channel->sock_func_cb_data); 446 } 447 return swrite(s, data, len); 448} 449 450void ares_set_socket_callback(ares_channel_t *channel, 451 ares_sock_create_callback cb, void *data) 452{ 453 if (channel == NULL) { 454 return; 455 } 456 channel->sock_create_cb = cb; 457 channel->sock_create_cb_data = data; 458} 459 460void ares_set_socket_configure_callback(ares_channel_t *channel, 461 ares_sock_config_callback cb, 462 void *data) 463{ 464 if (channel == NULL || channel->optmask & ARES_OPT_EVENT_THREAD) { 465 return; 466 } 467 channel->sock_config_cb = cb; 468 channel->sock_config_cb_data = data; 469} 470 471void ares_set_socket_functions(ares_channel_t *channel, 472 const struct ares_socket_functions *funcs, 473 void *data) 474{ 475 if (channel == NULL || channel->optmask & ARES_OPT_EVENT_THREAD) { 476 return; 477 } 478 channel->sock_funcs = funcs; 479 channel->sock_func_cb_data = data; 480} 481