1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#include "apr_arch_networkio.h" 18251875Speter#include "apr_network_io.h" 19251875Speter#include "apr_strings.h" 20251875Speter#include "apr_support.h" 21251875Speter#include "apr_portable.h" 22251875Speter#include "apr_arch_inherit.h" 23251875Speter 24251875Speter#ifdef BEOS_R5 25251875Speter#undef close 26251875Speter#define close closesocket 27251875Speter#endif /* BEOS_R5 */ 28251875Speter 29362181Sdim#if APR_HAVE_SOCKADDR_UN 30362181Sdim#define GENERIC_INADDR_ANY_LEN sizeof(struct sockaddr_un) 31362181Sdim#else 32362181Sdim#define GENERIC_INADDR_ANY_LEN 16 33362181Sdim#endif 34251875Speter 35362181Sdim/* big enough for IPv4, IPv6 and optionaly sun_path */ 36362181Sdimstatic char generic_inaddr_any[GENERIC_INADDR_ANY_LEN] = {0}; 37362181Sdim 38251875Speterstatic apr_status_t socket_cleanup(void *sock) 39251875Speter{ 40251875Speter apr_socket_t *thesocket = sock; 41251875Speter int sd = thesocket->socketdes; 42251875Speter 43362181Sdim#if APR_HAVE_SOCKADDR_UN 44362181Sdim if (thesocket->bound && thesocket->local_addr->family == APR_UNIX) { 45362181Sdim /* XXX: Check for return values ? */ 46362181Sdim unlink(thesocket->local_addr->hostname); 47362181Sdim } 48362181Sdim#endif 49251875Speter /* Set socket descriptor to -1 before close(), so that there is no 50251875Speter * chance of returning an already closed FD from apr_os_sock_get(). 51251875Speter */ 52251875Speter thesocket->socketdes = -1; 53251875Speter 54251875Speter if (close(sd) == 0) { 55251875Speter return APR_SUCCESS; 56251875Speter } 57251875Speter else { 58251875Speter /* Restore, close() was not successful. */ 59251875Speter thesocket->socketdes = sd; 60251875Speter 61251875Speter return errno; 62251875Speter } 63251875Speter} 64251875Speter 65362181Sdimstatic apr_status_t socket_child_cleanup(void *sock) 66362181Sdim{ 67362181Sdim apr_socket_t *thesocket = sock; 68362181Sdim if (close(thesocket->socketdes) == 0) { 69362181Sdim thesocket->socketdes = -1; 70362181Sdim return APR_SUCCESS; 71362181Sdim } 72362181Sdim else { 73362181Sdim return errno; 74362181Sdim } 75362181Sdim} 76362181Sdim 77251875Speterstatic void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) 78251875Speter{ 79251875Speter sock->type = type; 80251875Speter sock->protocol = protocol; 81251875Speter apr_sockaddr_vars_set(sock->local_addr, family, 0); 82251875Speter apr_sockaddr_vars_set(sock->remote_addr, family, 0); 83251875Speter sock->options = 0; 84251875Speter#if defined(BEOS) && !defined(BEOS_BONE) 85251875Speter /* BeOS pre-BONE has TCP_NODELAY on by default and it can't be 86251875Speter * switched off! 87251875Speter */ 88251875Speter sock->options |= APR_TCP_NODELAY; 89251875Speter#endif 90251875Speter} 91251875Speter 92251875Speterstatic void alloc_socket(apr_socket_t **new, apr_pool_t *p) 93251875Speter{ 94251875Speter *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); 95251875Speter (*new)->pool = p; 96251875Speter (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool, 97251875Speter sizeof(apr_sockaddr_t)); 98251875Speter (*new)->local_addr->pool = p; 99251875Speter (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool, 100251875Speter sizeof(apr_sockaddr_t)); 101251875Speter (*new)->remote_addr->pool = p; 102251875Speter (*new)->remote_addr_unknown = 1; 103251875Speter#ifndef WAITIO_USES_POLL 104251875Speter /* Create a pollset with room for one descriptor. */ 105251875Speter /* ### check return codes */ 106251875Speter (void) apr_pollset_create(&(*new)->pollset, 1, p, 0); 107251875Speter#endif 108251875Speter} 109251875Speter 110251875Speterapr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol) 111251875Speter{ 112251875Speter *protocol = sock->protocol; 113251875Speter return APR_SUCCESS; 114251875Speter} 115251875Speter 116251875Speterapr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, 117251875Speter int protocol, apr_pool_t *cont) 118251875Speter{ 119251875Speter int family = ofamily, flags = 0; 120362181Sdim int oprotocol = protocol; 121251875Speter 122251875Speter#ifdef HAVE_SOCK_CLOEXEC 123251875Speter flags |= SOCK_CLOEXEC; 124251875Speter#endif 125251875Speter 126251875Speter if (family == APR_UNSPEC) { 127251875Speter#if APR_HAVE_IPV6 128251875Speter family = APR_INET6; 129251875Speter#else 130251875Speter family = APR_INET; 131251875Speter#endif 132251875Speter } 133362181Sdim#if APR_HAVE_SOCKADDR_UN 134362181Sdim if (family == APR_UNIX) { 135362181Sdim protocol = 0; 136362181Sdim } 137362181Sdim#endif 138251875Speter alloc_socket(new, cont); 139251875Speter 140251875Speter#ifndef BEOS_R5 141251875Speter (*new)->socketdes = socket(family, type|flags, protocol); 142251875Speter#else 143251875Speter /* For some reason BeOS R5 has an unconventional protocol numbering, 144251875Speter * so we need to translate here. */ 145251875Speter switch (protocol) { 146251875Speter case 0: 147251875Speter (*new)->socketdes = socket(family, type|flags, 0); 148251875Speter break; 149251875Speter case APR_PROTO_TCP: 150251875Speter (*new)->socketdes = socket(family, type|flags, IPPROTO_TCP); 151251875Speter break; 152251875Speter case APR_PROTO_UDP: 153251875Speter (*new)->socketdes = socket(family, type|flags, IPPROTO_UDP); 154251875Speter break; 155251875Speter case APR_PROTO_SCTP: 156251875Speter default: 157251875Speter errno = EPROTONOSUPPORT; 158251875Speter (*new)->socketdes = -1; 159251875Speter break; 160251875Speter } 161251875Speter#endif /* BEOS_R5 */ 162251875Speter 163251875Speter#if APR_HAVE_IPV6 164251875Speter if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) { 165251875Speter family = APR_INET; 166251875Speter (*new)->socketdes = socket(family, type|flags, protocol); 167251875Speter } 168251875Speter#endif 169251875Speter 170251875Speter if ((*new)->socketdes < 0) { 171251875Speter return errno; 172251875Speter } 173362181Sdim set_socket_vars(*new, family, type, oprotocol); 174251875Speter 175251875Speter#ifndef HAVE_SOCK_CLOEXEC 176251875Speter { 177251875Speter int flags; 178286503Speter apr_status_t rv; 179251875Speter 180286503Speter if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) { 181286503Speter rv = errno; 182286503Speter close((*new)->socketdes); 183286503Speter (*new)->socketdes = -1; 184286503Speter return rv; 185286503Speter } 186251875Speter 187251875Speter flags |= FD_CLOEXEC; 188286503Speter if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) { 189286503Speter rv = errno; 190286503Speter close((*new)->socketdes); 191286503Speter (*new)->socketdes = -1; 192286503Speter return rv; 193286503Speter } 194251875Speter } 195251875Speter#endif 196251875Speter 197251875Speter (*new)->timeout = -1; 198251875Speter (*new)->inherit = 0; 199251875Speter apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup, 200362181Sdim socket_child_cleanup); 201251875Speter 202251875Speter return APR_SUCCESS; 203251875Speter} 204251875Speter 205251875Speterapr_status_t apr_socket_shutdown(apr_socket_t *thesocket, 206251875Speter apr_shutdown_how_e how) 207251875Speter{ 208251875Speter return (shutdown(thesocket->socketdes, how) == -1) ? errno : APR_SUCCESS; 209251875Speter} 210251875Speter 211251875Speterapr_status_t apr_socket_close(apr_socket_t *thesocket) 212251875Speter{ 213251875Speter return apr_pool_cleanup_run(thesocket->pool, thesocket, socket_cleanup); 214251875Speter} 215251875Speter 216251875Speterapr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa) 217251875Speter{ 218251875Speter if (bind(sock->socketdes, 219251875Speter (struct sockaddr *)&sa->sa, sa->salen) == -1) { 220251875Speter return errno; 221251875Speter } 222251875Speter else { 223251875Speter sock->local_addr = sa; 224251875Speter /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 225362181Sdim#if APR_HAVE_SOCKADDR_UN 226362181Sdim if (sock->local_addr->family == APR_UNIX) { 227362181Sdim sock->bound = 1; 228362181Sdim sock->local_port_unknown = 1; 229362181Sdim } 230362181Sdim else 231362181Sdim#endif 232251875Speter if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */ 233251875Speter sock->local_port_unknown = 1; /* kernel got us an ephemeral port */ 234251875Speter } 235251875Speter return APR_SUCCESS; 236251875Speter } 237251875Speter} 238251875Speter 239251875Speterapr_status_t apr_socket_listen(apr_socket_t *sock, apr_int32_t backlog) 240251875Speter{ 241251875Speter if (listen(sock->socketdes, backlog) == -1) 242251875Speter return errno; 243251875Speter else 244251875Speter return APR_SUCCESS; 245251875Speter} 246251875Speter 247251875Speterapr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, 248251875Speter apr_pool_t *connection_context) 249251875Speter{ 250251875Speter int s; 251251875Speter apr_sockaddr_t sa; 252251875Speter 253251875Speter sa.salen = sizeof(sa.sa); 254251875Speter 255251875Speter#ifdef HAVE_ACCEPT4 256266735Speter { 257266735Speter int flags = SOCK_CLOEXEC; 258266735Speter 259266735Speter#if defined(SOCK_NONBLOCK) && APR_O_NONBLOCK_INHERITED 260266735Speter /* With FreeBSD accept4() (avail in 10+), O_NONBLOCK is not inherited 261266735Speter * (unlike Linux). Mimic the accept() behavior here in a way that 262266735Speter * may help other platforms. 263266735Speter */ 264266735Speter if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { 265266735Speter flags |= SOCK_NONBLOCK; 266266735Speter } 267266735Speter#endif 268266735Speter s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, flags); 269266735Speter } 270251875Speter#else 271251875Speter s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen); 272251875Speter#endif 273251875Speter 274251875Speter if (s < 0) { 275251875Speter return errno; 276251875Speter } 277251875Speter#ifdef TPF 278251875Speter if (s == 0) { 279251875Speter /* 0 is an invalid socket for TPF */ 280251875Speter return APR_EINTR; 281251875Speter } 282251875Speter#endif 283251875Speter alloc_socket(new, connection_context); 284251875Speter 285251875Speter /* Set up socket variables -- note that it may be possible for 286251875Speter * *new to be an AF_INET socket when sock is AF_INET6 in some 287251875Speter * dual-stack configurations, so ensure that the remote_/local_addr 288251875Speter * structures are adjusted for the family of the accepted 289251875Speter * socket: */ 290251875Speter set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol); 291251875Speter 292251875Speter#ifndef HAVE_POLL 293251875Speter (*new)->connected = 1; 294251875Speter#endif 295251875Speter (*new)->timeout = -1; 296251875Speter 297251875Speter (*new)->remote_addr_unknown = 0; 298251875Speter 299251875Speter (*new)->socketdes = s; 300251875Speter 301251875Speter /* Copy in peer's address. */ 302251875Speter (*new)->remote_addr->sa = sa.sa; 303251875Speter (*new)->remote_addr->salen = sa.salen; 304251875Speter 305251875Speter *(*new)->local_addr = *sock->local_addr; 306251875Speter 307251875Speter /* The above assignment just overwrote the pool entry. Setting the local_addr 308251875Speter pool for the accepted socket back to what it should be. Otherwise all 309251875Speter allocations for this socket will come from a server pool that is not 310251875Speter freed until the process goes down.*/ 311251875Speter (*new)->local_addr->pool = connection_context; 312251875Speter 313251875Speter /* fix up any pointers which are no longer valid */ 314251875Speter if (sock->local_addr->sa.sin.sin_family == AF_INET) { 315251875Speter (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; 316251875Speter } 317251875Speter#if APR_HAVE_IPV6 318251875Speter else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { 319251875Speter (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; 320251875Speter } 321251875Speter#endif 322362181Sdim#if APR_HAVE_SOCKADDR_UN 323362181Sdim else if (sock->local_addr->sa.sin.sin_family == AF_UNIX) { 324362181Sdim *(*new)->remote_addr = *sock->local_addr; 325362181Sdim (*new)->local_addr->ipaddr_ptr = &((*new)->local_addr->sa.unx.sun_path); 326362181Sdim (*new)->remote_addr->ipaddr_ptr = &((*new)->remote_addr->sa.unx.sun_path); 327362181Sdim } 328362181Sdim if (sock->local_addr->sa.sin.sin_family != AF_UNIX) 329362181Sdim#endif 330251875Speter (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); 331251875Speter if (sock->local_port_unknown) { 332251875Speter /* not likely for a listening socket, but theoretically possible :) */ 333251875Speter (*new)->local_port_unknown = 1; 334251875Speter } 335251875Speter 336251875Speter#if APR_TCP_NODELAY_INHERITED 337251875Speter if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) { 338251875Speter apr_set_option(*new, APR_TCP_NODELAY, 1); 339251875Speter } 340251875Speter#endif /* TCP_NODELAY_INHERITED */ 341251875Speter#if APR_O_NONBLOCK_INHERITED 342251875Speter if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { 343251875Speter apr_set_option(*new, APR_SO_NONBLOCK, 1); 344251875Speter } 345251875Speter#endif /* APR_O_NONBLOCK_INHERITED */ 346251875Speter 347251875Speter if (sock->local_interface_unknown || 348251875Speter !memcmp(sock->local_addr->ipaddr_ptr, 349251875Speter generic_inaddr_any, 350251875Speter sock->local_addr->ipaddr_len)) { 351251875Speter /* If the interface address inside the listening socket's local_addr wasn't 352251875Speter * up-to-date, we don't know local interface of the connected socket either. 353251875Speter * 354251875Speter * If the listening socket was not bound to a specific interface, we 355251875Speter * don't know the local_addr of the connected socket. 356251875Speter */ 357251875Speter (*new)->local_interface_unknown = 1; 358251875Speter } 359251875Speter 360251875Speter#ifndef HAVE_ACCEPT4 361251875Speter { 362251875Speter int flags; 363286503Speter apr_status_t rv; 364251875Speter 365286503Speter if ((flags = fcntl((*new)->socketdes, F_GETFD)) == -1) { 366286503Speter rv = errno; 367286503Speter close((*new)->socketdes); 368286503Speter (*new)->socketdes = -1; 369286503Speter return rv; 370286503Speter } 371251875Speter 372251875Speter flags |= FD_CLOEXEC; 373286503Speter if (fcntl((*new)->socketdes, F_SETFD, flags) == -1) { 374286503Speter rv = errno; 375286503Speter close((*new)->socketdes); 376286503Speter (*new)->socketdes = -1; 377286503Speter return rv; 378286503Speter } 379251875Speter } 380251875Speter#endif 381251875Speter 382251875Speter (*new)->inherit = 0; 383251875Speter apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup, 384251875Speter socket_cleanup); 385251875Speter return APR_SUCCESS; 386251875Speter} 387251875Speter 388251875Speterapr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa) 389251875Speter{ 390251875Speter int rc; 391251875Speter 392251875Speter do { 393251875Speter rc = connect(sock->socketdes, 394251875Speter (const struct sockaddr *)&sa->sa.sin, 395251875Speter sa->salen); 396251875Speter } while (rc == -1 && errno == EINTR); 397251875Speter 398251875Speter /* we can see EINPROGRESS the first time connect is called on a non-blocking 399251875Speter * socket; if called again, we can see EALREADY 400251875Speter */ 401251875Speter if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY) 402251875Speter && (sock->timeout > 0)) { 403251875Speter rc = apr_wait_for_io_or_timeout(NULL, sock, 0); 404251875Speter if (rc != APR_SUCCESS) { 405251875Speter return rc; 406251875Speter } 407251875Speter 408251875Speter#ifdef SO_ERROR 409251875Speter { 410251875Speter int error; 411251875Speter apr_socklen_t len = sizeof(error); 412251875Speter if ((rc = getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, 413251875Speter (char *)&error, &len)) < 0) { 414251875Speter return errno; 415251875Speter } 416251875Speter if (error) { 417251875Speter return error; 418251875Speter } 419251875Speter } 420251875Speter#endif /* SO_ERROR */ 421251875Speter } 422251875Speter 423251875Speter if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) { 424251875Speter /* A real remote address was passed in. If the unspecified 425251875Speter * address was used, the actual remote addr will have to be 426251875Speter * determined using getpeername() if required. */ 427251875Speter sock->remote_addr_unknown = 0; 428251875Speter 429251875Speter /* Copy the address structure details in. */ 430251875Speter sock->remote_addr->sa = sa->sa; 431251875Speter sock->remote_addr->salen = sa->salen; 432251875Speter /* Adjust ipaddr_ptr et al. */ 433251875Speter apr_sockaddr_vars_set(sock->remote_addr, sa->family, sa->port); 434251875Speter } 435251875Speter 436251875Speter if (sock->local_addr->port == 0) { 437251875Speter /* connect() got us an ephemeral port */ 438251875Speter sock->local_port_unknown = 1; 439251875Speter } 440362181Sdim#if APR_HAVE_SOCKADDR_UN 441362181Sdim if (sock->local_addr->sa.sin.sin_family == AF_UNIX) { 442362181Sdim /* Assign connect address as local. */ 443362181Sdim sock->local_addr = sa; 444362181Sdim } 445362181Sdim else 446362181Sdim#endif 447251875Speter if (!memcmp(sock->local_addr->ipaddr_ptr, 448251875Speter generic_inaddr_any, 449251875Speter sock->local_addr->ipaddr_len)) { 450251875Speter /* not bound to specific local interface; connect() had to assign 451251875Speter * one for the socket 452251875Speter */ 453251875Speter sock->local_interface_unknown = 1; 454251875Speter } 455251875Speter 456251875Speter if (rc == -1 && errno != EISCONN) { 457251875Speter return errno; 458251875Speter } 459251875Speter 460251875Speter#ifndef HAVE_POLL 461251875Speter sock->connected=1; 462251875Speter#endif 463251875Speter return APR_SUCCESS; 464251875Speter} 465251875Speter 466251875Speterapr_status_t apr_socket_type_get(apr_socket_t *sock, int *type) 467251875Speter{ 468251875Speter *type = sock->type; 469251875Speter return APR_SUCCESS; 470251875Speter} 471251875Speter 472251875Speterapr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock) 473251875Speter{ 474251875Speter sock_userdata_t *cur = sock->userdata; 475251875Speter 476251875Speter *data = NULL; 477251875Speter 478251875Speter while (cur) { 479251875Speter if (!strcmp(cur->key, key)) { 480251875Speter *data = cur->data; 481251875Speter break; 482251875Speter } 483251875Speter cur = cur->next; 484251875Speter } 485251875Speter 486251875Speter return APR_SUCCESS; 487251875Speter} 488251875Speter 489251875Speterapr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, const char *key, 490251875Speter apr_status_t (*cleanup) (void *)) 491251875Speter{ 492251875Speter sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t)); 493251875Speter 494251875Speter new->key = apr_pstrdup(sock->pool, key); 495251875Speter new->data = data; 496251875Speter new->next = sock->userdata; 497251875Speter sock->userdata = new; 498251875Speter 499251875Speter if (cleanup) { 500251875Speter apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup); 501251875Speter } 502251875Speter 503251875Speter return APR_SUCCESS; 504251875Speter} 505251875Speter 506251875Speterapr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock) 507251875Speter{ 508251875Speter *thesock = sock->socketdes; 509251875Speter return APR_SUCCESS; 510251875Speter} 511251875Speter 512251875Speterapr_status_t apr_os_sock_make(apr_socket_t **apr_sock, 513251875Speter apr_os_sock_info_t *os_sock_info, 514251875Speter apr_pool_t *cont) 515251875Speter{ 516251875Speter alloc_socket(apr_sock, cont); 517251875Speter set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); 518251875Speter (*apr_sock)->timeout = -1; 519251875Speter (*apr_sock)->socketdes = *os_sock_info->os_sock; 520251875Speter if (os_sock_info->local) { 521251875Speter memcpy(&(*apr_sock)->local_addr->sa.sin, 522251875Speter os_sock_info->local, 523251875Speter (*apr_sock)->local_addr->salen); 524251875Speter /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 525251875Speter (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); 526251875Speter } 527251875Speter else { 528251875Speter (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; 529251875Speter } 530251875Speter if (os_sock_info->remote) { 531251875Speter#ifndef HAVE_POLL 532251875Speter (*apr_sock)->connected = 1; 533251875Speter#endif 534251875Speter memcpy(&(*apr_sock)->remote_addr->sa.sin, 535251875Speter os_sock_info->remote, 536251875Speter (*apr_sock)->remote_addr->salen); 537251875Speter /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ 538251875Speter (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); 539251875Speter } 540251875Speter else { 541251875Speter (*apr_sock)->remote_addr_unknown = 1; 542251875Speter } 543251875Speter 544251875Speter (*apr_sock)->inherit = 0; 545251875Speter apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock), 546251875Speter socket_cleanup, socket_cleanup); 547251875Speter return APR_SUCCESS; 548251875Speter} 549251875Speter 550251875Speterapr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, 551251875Speter apr_pool_t *cont) 552251875Speter{ 553251875Speter /* XXX Bogus assumption that *sock points at anything legit */ 554251875Speter if ((*sock) == NULL) { 555251875Speter alloc_socket(sock, cont); 556251875Speter /* XXX IPv6 figure out the family here! */ 557251875Speter /* XXX figure out the actual socket type here */ 558251875Speter /* *or* just decide that apr_os_sock_put() has to be told the family and type */ 559251875Speter set_socket_vars(*sock, APR_INET, SOCK_STREAM, 0); 560251875Speter (*sock)->timeout = -1; 561251875Speter } 562251875Speter (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; 563251875Speter (*sock)->remote_addr_unknown = 1; 564251875Speter (*sock)->socketdes = *thesock; 565251875Speter return APR_SUCCESS; 566251875Speter} 567251875Speter 568251875SpeterAPR_POOL_IMPLEMENT_ACCESSOR(socket) 569251875Speter 570251875SpeterAPR_IMPLEMENT_INHERIT_SET(socket, inherit, pool, socket_cleanup) 571251875Speter 572251875SpeterAPR_IMPLEMENT_INHERIT_UNSET(socket, inherit, pool, socket_cleanup) 573