1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_arch_networkio.h" 18#include "apr_network_io.h" 19#include "apr_general.h" 20#include "apr_lib.h" 21#include "apr_portable.h" 22#include "apr_strings.h" 23#include <string.h> 24#include "apr_arch_inherit.h" 25#include "apr_arch_misc.h" 26 27static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ 28 29static apr_status_t socket_cleanup(void *sock) 30{ 31 apr_socket_t *thesocket = sock; 32 33 if (thesocket->socketdes != INVALID_SOCKET) { 34 if (closesocket(thesocket->socketdes) == SOCKET_ERROR) { 35 return apr_get_netos_error(); 36 } 37 thesocket->socketdes = INVALID_SOCKET; 38 } 39#if APR_HAS_SENDFILE 40 if (thesocket->overlapped) { 41 CloseHandle(thesocket->overlapped->hEvent); 42 thesocket->overlapped = NULL; 43 } 44#endif 45 return APR_SUCCESS; 46} 47 48static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) 49{ 50 sock->type = type; 51 sock->protocol = protocol; 52 apr_sockaddr_vars_set(sock->local_addr, family, 0); 53 apr_sockaddr_vars_set(sock->remote_addr, family, 0); 54#if APR_HAVE_IPV6 55 /* hard-coded behavior for older Windows IPv6 */ 56 if (apr_os_level < APR_WIN_VISTA && family == AF_INET6) { 57 apr_set_option(sock, APR_IPV6_V6ONLY, 1); 58 } 59#endif 60} 61static void alloc_socket(apr_socket_t **new, apr_pool_t *p) 62{ 63 *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); 64 (*new)->pool = p; 65 (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool, 66 sizeof(apr_sockaddr_t)); 67 (*new)->local_addr->pool = p; 68 69 (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool, 70 sizeof(apr_sockaddr_t)); 71 (*new)->remote_addr->pool = p; 72 (*new)->remote_addr_unknown = 1; 73 74 /* Create a pollset with room for one descriptor. */ 75 /* ### check return codes */ 76 (void) apr_pollset_create(&(*new)->pollset, 1, p, 0); 77} 78 79APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, 80 int *protocol) 81{ 82 *protocol = sock->protocol; 83 return APR_SUCCESS; 84} 85 86APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, 87 int type, int protocol, 88 apr_pool_t *cont) 89{ 90#if APR_HAVE_IPV6 91 int downgrade = (family == AF_UNSPEC); 92#endif 93 94 if (family == AF_UNSPEC) { 95#if APR_HAVE_IPV6 96 family = AF_INET6; 97#else 98 family = AF_INET; 99#endif 100 } 101 102 alloc_socket(new, cont); 103 104 /* For right now, we are not using socket groups. We may later. 105 * No flags to use when creating a socket, so use 0 for that parameter as well. 106 */ 107 (*new)->socketdes = socket(family, type, protocol); 108#if APR_HAVE_IPV6 109 if ((*new)->socketdes == INVALID_SOCKET && downgrade) { 110 family = AF_INET; 111 (*new)->socketdes = socket(family, type, protocol); 112 } 113#endif 114 115 if ((*new)->socketdes == INVALID_SOCKET) { 116 return apr_get_netos_error(); 117 } 118 119#ifdef WIN32 120 /* Socket handles are never truly inheritable, there are too many 121 * bugs associated. WSADuplicateSocket will copy them, but for our 122 * purposes, always transform the socket() created as a non-inherited 123 * handle 124 */ 125#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE) 126 IF_WIN_OS_IS_UNICODE { 127 /* A different approach. Many users report errors such as 128 * (32538)An operation was attempted on something that is not 129 * a socket. : Parent: WSADuplicateSocket failed... 130 * 131 * This appears that the duplicated handle is no longer recognized 132 * as a socket handle. SetHandleInformation should overcome that 133 * problem by not altering the handle identifier. But this won't 134 * work on 9x - it's unsupported. 135 */ 136 SetHandleInformation((HANDLE) (*new)->socketdes, 137 HANDLE_FLAG_INHERIT, 0); 138 } 139#if APR_HAS_ANSI_FS 140 /* only if APR_HAS_ANSI_FS && APR_HAS_UNICODE_FS */ 141 ELSE_WIN_OS_IS_ANSI 142#endif 143#endif 144#if APR_HAS_ANSI_FS || defined(_WIN32_WCE) 145 { 146 HANDLE hProcess = GetCurrentProcess(); 147 HANDLE dup; 148 if (DuplicateHandle(hProcess, (HANDLE) (*new)->socketdes, hProcess, 149 &dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { 150 closesocket((*new)->socketdes); 151 (*new)->socketdes = (SOCKET) dup; 152 } 153 } 154#endif 155 156#endif /* def WIN32 */ 157 158 set_socket_vars(*new, family, type, protocol); 159 160 (*new)->timeout = -1; 161 (*new)->disconnected = 0; 162 163 apr_pool_cleanup_register((*new)->pool, (void *)(*new), 164 socket_cleanup, apr_pool_cleanup_null); 165 166 return APR_SUCCESS; 167} 168 169APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, 170 apr_shutdown_how_e how) 171{ 172 int winhow = 0; 173 174#ifdef SD_RECEIVE 175 switch (how) { 176 case APR_SHUTDOWN_READ: { 177 winhow = SD_RECEIVE; 178 break; 179 } 180 case APR_SHUTDOWN_WRITE: { 181 winhow = SD_SEND; 182 break; 183 } 184 case APR_SHUTDOWN_READWRITE: { 185 winhow = SD_BOTH; 186 break; 187 } 188 default: 189 return APR_BADARG; 190 } 191#endif 192 if (shutdown(thesocket->socketdes, winhow) == 0) { 193 return APR_SUCCESS; 194 } 195 else { 196 return apr_get_netos_error(); 197 } 198} 199 200APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket) 201{ 202 apr_pool_cleanup_kill(thesocket->pool, thesocket, socket_cleanup); 203 return socket_cleanup(thesocket); 204} 205 206APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, 207 apr_sockaddr_t *sa) 208{ 209 if (bind(sock->socketdes, 210 (struct sockaddr *)&sa->sa, 211 sa->salen) == -1) { 212 return apr_get_netos_error(); 213 } 214 else { 215 sock->local_addr = sa; 216 if (sock->local_addr->sa.sin.sin_port == 0) { 217 sock->local_port_unknown = 1; /* ephemeral port */ 218 } 219 return APR_SUCCESS; 220 } 221} 222 223APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, 224 apr_int32_t backlog) 225{ 226 if (listen(sock->socketdes, backlog) == SOCKET_ERROR) 227 return apr_get_netos_error(); 228 else 229 return APR_SUCCESS; 230} 231 232APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, 233 apr_socket_t *sock, apr_pool_t *p) 234{ 235 SOCKET s; 236#if APR_HAVE_IPV6 237 struct sockaddr_storage sa; 238#else 239 struct sockaddr sa; 240#endif 241 int salen = sizeof(sock->remote_addr->sa); 242 243 /* Don't allocate the memory until after we call accept. This allows 244 us to work with nonblocking sockets. */ 245 s = accept(sock->socketdes, (struct sockaddr *)&sa, &salen); 246 if (s == INVALID_SOCKET) { 247 return apr_get_netos_error(); 248 } 249 250 alloc_socket(new, p); 251 set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, 252 sock->protocol); 253 254 (*new)->timeout = -1; 255 (*new)->disconnected = 0; 256 257 (*new)->socketdes = s; 258 /* XXX next line looks bogus w.r.t. AF_INET6 support */ 259 (*new)->remote_addr->salen = sizeof((*new)->remote_addr->sa); 260 memcpy (&(*new)->remote_addr->sa, &sa, salen); 261 *(*new)->local_addr = *sock->local_addr; 262 (*new)->remote_addr_unknown = 0; 263 264 /* The above assignment just overwrote the pool entry. Setting the local_addr 265 pool for the accepted socket back to what it should be. Otherwise all 266 allocations for this socket will come from a server pool that is not 267 freed until the process goes down.*/ 268 (*new)->local_addr->pool = p; 269 270 /* fix up any pointers which are no longer valid */ 271 if (sock->local_addr->sa.sin.sin_family == AF_INET) { 272 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; 273 } 274#if APR_HAVE_IPV6 275 else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { 276 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; 277 } 278#endif 279 (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); 280 if (sock->local_port_unknown) { 281 /* not likely for a listening socket, but theoretically possible :) */ 282 (*new)->local_port_unknown = 1; 283 } 284 285#if APR_TCP_NODELAY_INHERITED 286 if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) { 287 apr_set_option(*new, APR_TCP_NODELAY, 1); 288 } 289#endif /* TCP_NODELAY_INHERITED */ 290#if APR_O_NONBLOCK_INHERITED 291 if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { 292 apr_set_option(*new, APR_SO_NONBLOCK, 1); 293 } 294#endif /* APR_O_NONBLOCK_INHERITED */ 295 296 if (sock->local_interface_unknown || 297 !memcmp(sock->local_addr->ipaddr_ptr, 298 generic_inaddr_any, 299 sock->local_addr->ipaddr_len)) { 300 /* If the interface address inside the listening socket's local_addr wasn't 301 * up-to-date, we don't know local interface of the connected socket either. 302 * 303 * If the listening socket was not bound to a specific interface, we 304 * don't know the local_addr of the connected socket. 305 */ 306 (*new)->local_interface_unknown = 1; 307 } 308 309 apr_pool_cleanup_register((*new)->pool, (void *)(*new), 310 socket_cleanup, apr_pool_cleanup_null); 311 return APR_SUCCESS; 312} 313 314APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, 315 apr_sockaddr_t *sa) 316{ 317 apr_status_t rv; 318 319 if ((sock->socketdes == INVALID_SOCKET) || (!sock->local_addr)) { 320 return APR_ENOTSOCK; 321 } 322 323 if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin, 324 sa->salen) == SOCKET_ERROR) { 325 int rc; 326 struct timeval tv, *tvptr; 327 fd_set wfdset, efdset; 328 329 rv = apr_get_netos_error(); 330 if (rv != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) { 331 return rv; 332 } 333 334 if (sock->timeout == 0) { 335 /* Tell the app that the connect is in progress... 336 * Gotta play some games here. connect on Unix will return 337 * EINPROGRESS under the same circumstances that Windows 338 * returns WSAEWOULDBLOCK. Do some adhoc canonicalization... 339 */ 340 return APR_FROM_OS_ERROR(WSAEINPROGRESS); 341 } 342 343 /* wait for the connect to complete or timeout */ 344 FD_ZERO(&wfdset); 345 FD_SET(sock->socketdes, &wfdset); 346 FD_ZERO(&efdset); 347 FD_SET(sock->socketdes, &efdset); 348 349 if (sock->timeout < 0) { 350 tvptr = NULL; 351 } 352 else { 353 /* casts for winsock/timeval definition */ 354 tv.tv_sec = (long)apr_time_sec(sock->timeout); 355 tv.tv_usec = (int)apr_time_usec(sock->timeout); 356 tvptr = &tv; 357 } 358 rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr); 359 if (rc == SOCKET_ERROR) { 360 return apr_get_netos_error(); 361 } 362 else if (!rc) { 363 return APR_FROM_OS_ERROR(WSAETIMEDOUT); 364 } 365 /* Evaluate the efdset */ 366 if (FD_ISSET(sock->socketdes, &efdset)) { 367 /* The connect failed. */ 368 int rclen = sizeof(rc); 369 if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) { 370 return apr_get_netos_error(); 371 } 372 return APR_FROM_OS_ERROR(rc); 373 } 374 } 375 /* connect was OK .. amazing */ 376 sock->remote_addr = sa; 377 if (sock->local_addr->sa.sin.sin_port == 0) { 378 sock->local_port_unknown = 1; 379 } 380 if (!memcmp(sock->local_addr->ipaddr_ptr, 381 generic_inaddr_any, 382 sock->local_addr->ipaddr_len)) { 383 /* not bound to specific local interface; connect() had to assign 384 * one for the socket 385 */ 386 sock->local_interface_unknown = 1; 387 } 388 return APR_SUCCESS; 389} 390 391APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type) 392{ 393 *type = sock->type; 394 return APR_SUCCESS; 395} 396 397APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key, 398 apr_socket_t *sock) 399{ 400 sock_userdata_t *cur = sock->userdata; 401 402 *data = NULL; 403 404 while (cur) { 405 if (!strcmp(cur->key, key)) { 406 *data = cur->data; 407 break; 408 } 409 cur = cur->next; 410 } 411 412 return APR_SUCCESS; 413} 414 415APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, 416 const char *key, 417 apr_status_t (*cleanup)(void *)) 418{ 419 sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t)); 420 421 new->key = apr_pstrdup(sock->pool, key); 422 new->data = data; 423 new->next = sock->userdata; 424 sock->userdata = new; 425 426 if (cleanup) { 427 apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup); 428 } 429 430 return APR_SUCCESS; 431} 432 433APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, 434 apr_socket_t *sock) 435{ 436 *thesock = sock->socketdes; 437 return APR_SUCCESS; 438} 439 440APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, 441 apr_os_sock_info_t *os_sock_info, 442 apr_pool_t *cont) 443{ 444 alloc_socket(apr_sock, cont); 445 set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); 446 (*apr_sock)->timeout = -1; 447 (*apr_sock)->disconnected = 0; 448 (*apr_sock)->socketdes = *os_sock_info->os_sock; 449 if (os_sock_info->local) { 450 memcpy(&(*apr_sock)->local_addr->sa.sin, 451 os_sock_info->local, 452 (*apr_sock)->local_addr->salen); 453 (*apr_sock)->local_addr->pool = cont; 454 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 455 (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); 456 } 457 else { 458 (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; 459 } 460 if (os_sock_info->remote) { 461 memcpy(&(*apr_sock)->remote_addr->sa.sin, 462 os_sock_info->remote, 463 (*apr_sock)->remote_addr->salen); 464 (*apr_sock)->remote_addr->pool = cont; 465 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 466 (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); 467 (*apr_sock)->remote_addr_unknown = 0; 468 } 469 470 apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock), 471 socket_cleanup, apr_pool_cleanup_null); 472 473 return APR_SUCCESS; 474} 475 476APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, 477 apr_os_sock_t *thesock, 478 apr_pool_t *cont) 479{ 480 if ((*sock) == NULL) { 481 alloc_socket(sock, cont); 482 /* XXX figure out the actual socket type here */ 483 /* *or* just decide that apr_os_sock_put() has to be told the family and type */ 484 set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0); 485 (*sock)->timeout = -1; 486 (*sock)->disconnected = 0; 487 } 488 (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; 489 (*sock)->remote_addr_unknown = 1; 490 (*sock)->socketdes = *thesock; 491 return APR_SUCCESS; 492} 493 494 495/* Sockets cannot be inherited through the standard sockets 496 * inheritence. WSADuplicateSocket must be used. 497 * This is not trivial to implement. 498 */ 499 500APR_DECLARE(apr_status_t) apr_socket_inherit_set(apr_socket_t *socket) 501{ 502 return APR_ENOTIMPL; 503} 504 505APR_DECLARE(apr_status_t) apr_socket_inherit_unset(apr_socket_t *socket) 506{ 507 return APR_ENOTIMPL; 508} 509 510APR_POOL_IMPLEMENT_ACCESSOR(socket); 511