sockets.c revision 289166
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_strings.h" 20#include "apr_support.h" 21#include "apr_portable.h" 22#include "apr_arch_inherit.h" 23 24#ifdef BEOS_R5 25#undef close 26#define close closesocket 27#endif /* BEOS_R5 */ 28 29static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ 30 31static apr_status_t socket_cleanup(void *sock) 32{ 33 apr_socket_t *thesocket = sock; 34 int sd = thesocket->socketdes; 35 36 /* Set socket descriptor to -1 before close(), so that there is no 37 * chance of returning an already closed FD from apr_os_sock_get(). 38 */ 39 thesocket->socketdes = -1; 40 41 if (close(sd) == 0) { 42 return APR_SUCCESS; 43 } 44 else { 45 /* Restore, close() was not successful. */ 46 thesocket->socketdes = sd; 47 48 return errno; 49 } 50} 51 52static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) 53{ 54 sock->type = type; 55 sock->protocol = protocol; 56 apr_sockaddr_vars_set(sock->local_addr, family, 0); 57 apr_sockaddr_vars_set(sock->remote_addr, family, 0); 58 sock->options = 0; 59#if defined(BEOS) && !defined(BEOS_BONE) 60 /* BeOS pre-BONE has TCP_NODELAY on by default and it can't be 61 * switched off! 62 */ 63 sock->options |= APR_TCP_NODELAY; 64#endif 65} 66 67static void alloc_socket(apr_socket_t **new, apr_pool_t *p) 68{ 69 *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); 70 (*new)->pool = p; 71 (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool, 72 sizeof(apr_sockaddr_t)); 73 (*new)->local_addr->pool = p; 74 (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool, 75 sizeof(apr_sockaddr_t)); 76 (*new)->remote_addr->pool = p; 77 (*new)->remote_addr_unknown = 1; 78#ifndef WAITIO_USES_POLL 79 /* Create a pollset with room for one descriptor. */ 80 /* ### check return codes */ 81 (void) apr_pollset_create(&(*new)->pollset, 1, p, 0); 82#endif 83} 84 85apr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol) 86{ 87 *protocol = sock->protocol; 88 return APR_SUCCESS; 89} 90 91apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, 92 int protocol, apr_pool_t *cont) 93{ 94 int family = ofamily, flags = 0; 95 96#ifdef HAVE_SOCK_CLOEXEC 97 flags |= SOCK_CLOEXEC; 98#endif 99 100 if (family == APR_UNSPEC) { 101#if APR_HAVE_IPV6 102 family = APR_INET6; 103#else 104 family = APR_INET; 105#endif 106 } 107 108 alloc_socket(new, cont); 109 110#ifndef BEOS_R5 111 (*new)->socketdes = socket(family, type|flags, protocol); 112#else 113 /* For some reason BeOS R5 has an unconventional protocol numbering, 114 * so we need to translate here. */ 115 switch (protocol) { 116 case 0: 117 (*new)->socketdes = socket(family, type|flags, 0); 118 break; 119 case APR_PROTO_TCP: 120 (*new)->socketdes = socket(family, type|flags, IPPROTO_TCP); 121 break; 122 case APR_PROTO_UDP: 123 (*new)->socketdes = socket(family, type|flags, IPPROTO_UDP); 124 break; 125 case APR_PROTO_SCTP: 126 default: 127 errno = EPROTONOSUPPORT; 128 (*new)->socketdes = -1; 129 break; 130 } 131#endif /* BEOS_R5 */ 132 133#if APR_HAVE_IPV6 134 if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) { 135 family = APR_INET; 136 (*new)->socketdes = socket(family, type|flags, protocol); 137 } 138#endif 139 140 if ((*new)->socketdes < 0) { 141 return errno; 142 } 143 set_socket_vars(*new, family, type, protocol); 144 145#ifndef HAVE_SOCK_CLOEXEC 146 { 147 int flags; 148 apr_status_t rv; 149 150 if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) { 151 rv = errno; 152 close((*new)->socketdes); 153 (*new)->socketdes = -1; 154 return rv; 155 } 156 157 flags |= FD_CLOEXEC; 158 if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) { 159 rv = errno; 160 close((*new)->socketdes); 161 (*new)->socketdes = -1; 162 return rv; 163 } 164 } 165#endif 166 167 (*new)->timeout = -1; 168 (*new)->inherit = 0; 169 apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup, 170 socket_cleanup); 171 172 return APR_SUCCESS; 173} 174 175apr_status_t apr_socket_shutdown(apr_socket_t *thesocket, 176 apr_shutdown_how_e how) 177{ 178 return (shutdown(thesocket->socketdes, how) == -1) ? errno : APR_SUCCESS; 179} 180 181apr_status_t apr_socket_close(apr_socket_t *thesocket) 182{ 183 return apr_pool_cleanup_run(thesocket->pool, thesocket, socket_cleanup); 184} 185 186apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa) 187{ 188 if (bind(sock->socketdes, 189 (struct sockaddr *)&sa->sa, sa->salen) == -1) { 190 return errno; 191 } 192 else { 193 sock->local_addr = sa; 194 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 195 if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */ 196 sock->local_port_unknown = 1; /* kernel got us an ephemeral port */ 197 } 198 return APR_SUCCESS; 199 } 200} 201 202apr_status_t apr_socket_listen(apr_socket_t *sock, apr_int32_t backlog) 203{ 204 if (listen(sock->socketdes, backlog) == -1) 205 return errno; 206 else 207 return APR_SUCCESS; 208} 209 210apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, 211 apr_pool_t *connection_context) 212{ 213 int s; 214 apr_sockaddr_t sa; 215 216 sa.salen = sizeof(sa.sa); 217 218#ifdef HAVE_ACCEPT4 219 { 220 int flags = SOCK_CLOEXEC; 221 222#if defined(SOCK_NONBLOCK) && APR_O_NONBLOCK_INHERITED 223 /* With FreeBSD accept4() (avail in 10+), O_NONBLOCK is not inherited 224 * (unlike Linux). Mimic the accept() behavior here in a way that 225 * may help other platforms. 226 */ 227 if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { 228 flags |= SOCK_NONBLOCK; 229 } 230#endif 231 s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, flags); 232 } 233#else 234 s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen); 235#endif 236 237 if (s < 0) { 238 return errno; 239 } 240#ifdef TPF 241 if (s == 0) { 242 /* 0 is an invalid socket for TPF */ 243 return APR_EINTR; 244 } 245#endif 246 alloc_socket(new, connection_context); 247 248 /* Set up socket variables -- note that it may be possible for 249 * *new to be an AF_INET socket when sock is AF_INET6 in some 250 * dual-stack configurations, so ensure that the remote_/local_addr 251 * structures are adjusted for the family of the accepted 252 * socket: */ 253 set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol); 254 255#ifndef HAVE_POLL 256 (*new)->connected = 1; 257#endif 258 (*new)->timeout = -1; 259 260 (*new)->remote_addr_unknown = 0; 261 262 (*new)->socketdes = s; 263 264 /* Copy in peer's address. */ 265 (*new)->remote_addr->sa = sa.sa; 266 (*new)->remote_addr->salen = sa.salen; 267 268 *(*new)->local_addr = *sock->local_addr; 269 270 /* The above assignment just overwrote the pool entry. Setting the local_addr 271 pool for the accepted socket back to what it should be. Otherwise all 272 allocations for this socket will come from a server pool that is not 273 freed until the process goes down.*/ 274 (*new)->local_addr->pool = connection_context; 275 276 /* fix up any pointers which are no longer valid */ 277 if (sock->local_addr->sa.sin.sin_family == AF_INET) { 278 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; 279 } 280#if APR_HAVE_IPV6 281 else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { 282 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; 283 } 284#endif 285 (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); 286 if (sock->local_port_unknown) { 287 /* not likely for a listening socket, but theoretically possible :) */ 288 (*new)->local_port_unknown = 1; 289 } 290 291#if APR_TCP_NODELAY_INHERITED 292 if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) { 293 apr_set_option(*new, APR_TCP_NODELAY, 1); 294 } 295#endif /* TCP_NODELAY_INHERITED */ 296#if APR_O_NONBLOCK_INHERITED 297 if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { 298 apr_set_option(*new, APR_SO_NONBLOCK, 1); 299 } 300#endif /* APR_O_NONBLOCK_INHERITED */ 301 302 if (sock->local_interface_unknown || 303 !memcmp(sock->local_addr->ipaddr_ptr, 304 generic_inaddr_any, 305 sock->local_addr->ipaddr_len)) { 306 /* If the interface address inside the listening socket's local_addr wasn't 307 * up-to-date, we don't know local interface of the connected socket either. 308 * 309 * If the listening socket was not bound to a specific interface, we 310 * don't know the local_addr of the connected socket. 311 */ 312 (*new)->local_interface_unknown = 1; 313 } 314 315#ifndef HAVE_ACCEPT4 316 { 317 int flags; 318 apr_status_t rv; 319 320 if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) { 321 rv = errno; 322 close((*new)->socketdes); 323 (*new)->socketdes = -1; 324 return rv; 325 } 326 327 flags |= FD_CLOEXEC; 328 if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) { 329 rv = errno; 330 close((*new)->socketdes); 331 (*new)->socketdes = -1; 332 return rv; 333 } 334 } 335#endif 336 337 (*new)->inherit = 0; 338 apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup, 339 socket_cleanup); 340 return APR_SUCCESS; 341} 342 343apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa) 344{ 345 int rc; 346 347 do { 348 rc = connect(sock->socketdes, 349 (const struct sockaddr *)&sa->sa.sin, 350 sa->salen); 351 } while (rc == -1 && errno == EINTR); 352 353 /* we can see EINPROGRESS the first time connect is called on a non-blocking 354 * socket; if called again, we can see EALREADY 355 */ 356 if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY) 357 && (sock->timeout > 0)) { 358 rc = apr_wait_for_io_or_timeout(NULL, sock, 0); 359 if (rc != APR_SUCCESS) { 360 return rc; 361 } 362 363#ifdef SO_ERROR 364 { 365 int error; 366 apr_socklen_t len = sizeof(error); 367 if ((rc = getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, 368 (char *)&error, &len)) < 0) { 369 return errno; 370 } 371 if (error) { 372 return error; 373 } 374 } 375#endif /* SO_ERROR */ 376 } 377 378 379 if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) { 380 /* A real remote address was passed in. If the unspecified 381 * address was used, the actual remote addr will have to be 382 * determined using getpeername() if required. */ 383 sock->remote_addr_unknown = 0; 384 385 /* Copy the address structure details in. */ 386 sock->remote_addr->sa = sa->sa; 387 sock->remote_addr->salen = sa->salen; 388 /* Adjust ipaddr_ptr et al. */ 389 apr_sockaddr_vars_set(sock->remote_addr, sa->family, sa->port); 390 } 391 392 if (sock->local_addr->port == 0) { 393 /* connect() got us an ephemeral port */ 394 sock->local_port_unknown = 1; 395 } 396 if (!memcmp(sock->local_addr->ipaddr_ptr, 397 generic_inaddr_any, 398 sock->local_addr->ipaddr_len)) { 399 /* not bound to specific local interface; connect() had to assign 400 * one for the socket 401 */ 402 sock->local_interface_unknown = 1; 403 } 404 405 if (rc == -1 && errno != EISCONN) { 406 return errno; 407 } 408 409#ifndef HAVE_POLL 410 sock->connected=1; 411#endif 412 return APR_SUCCESS; 413} 414 415apr_status_t apr_socket_type_get(apr_socket_t *sock, int *type) 416{ 417 *type = sock->type; 418 return APR_SUCCESS; 419} 420 421apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock) 422{ 423 sock_userdata_t *cur = sock->userdata; 424 425 *data = NULL; 426 427 while (cur) { 428 if (!strcmp(cur->key, key)) { 429 *data = cur->data; 430 break; 431 } 432 cur = cur->next; 433 } 434 435 return APR_SUCCESS; 436} 437 438apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, const char *key, 439 apr_status_t (*cleanup) (void *)) 440{ 441 sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t)); 442 443 new->key = apr_pstrdup(sock->pool, key); 444 new->data = data; 445 new->next = sock->userdata; 446 sock->userdata = new; 447 448 if (cleanup) { 449 apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup); 450 } 451 452 return APR_SUCCESS; 453} 454 455apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock) 456{ 457 *thesock = sock->socketdes; 458 return APR_SUCCESS; 459} 460 461apr_status_t apr_os_sock_make(apr_socket_t **apr_sock, 462 apr_os_sock_info_t *os_sock_info, 463 apr_pool_t *cont) 464{ 465 alloc_socket(apr_sock, cont); 466 set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); 467 (*apr_sock)->timeout = -1; 468 (*apr_sock)->socketdes = *os_sock_info->os_sock; 469 if (os_sock_info->local) { 470 memcpy(&(*apr_sock)->local_addr->sa.sin, 471 os_sock_info->local, 472 (*apr_sock)->local_addr->salen); 473 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 474 (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); 475 } 476 else { 477 (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; 478 } 479 if (os_sock_info->remote) { 480#ifndef HAVE_POLL 481 (*apr_sock)->connected = 1; 482#endif 483 memcpy(&(*apr_sock)->remote_addr->sa.sin, 484 os_sock_info->remote, 485 (*apr_sock)->remote_addr->salen); 486 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 487 (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); 488 } 489 else { 490 (*apr_sock)->remote_addr_unknown = 1; 491 } 492 493 (*apr_sock)->inherit = 0; 494 apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock), 495 socket_cleanup, socket_cleanup); 496 return APR_SUCCESS; 497} 498 499apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, 500 apr_pool_t *cont) 501{ 502 /* XXX Bogus assumption that *sock points at anything legit */ 503 if ((*sock) == NULL) { 504 alloc_socket(sock, cont); 505 /* XXX IPv6 figure out the family here! */ 506 /* XXX figure out the actual socket type here */ 507 /* *or* just decide that apr_os_sock_put() has to be told the family and type */ 508 set_socket_vars(*sock, APR_INET, SOCK_STREAM, 0); 509 (*sock)->timeout = -1; 510 } 511 (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; 512 (*sock)->remote_addr_unknown = 1; 513 (*sock)->socketdes = *thesock; 514 return APR_SUCCESS; 515} 516 517APR_POOL_IMPLEMENT_ACCESSOR(socket) 518 519APR_IMPLEMENT_INHERIT_SET(socket, inherit, pool, socket_cleanup) 520 521APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, pool, socket_cleanup) 522