Line 0
Link Here
|
|
|
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_strings.h" |
19 |
#include "apr_portable.h" |
20 |
#include "apr_thread_mutex.h" |
21 |
#include "apr_arch_inherit.h" |
22 |
|
23 |
static apr_sockaddr_t *sockaddr_dup(apr_sockaddr_t *oldaddr, |
24 |
apr_pool_t *p) |
25 |
{ |
26 |
apr_sockaddr_t *newaddr = apr_pcalloc(p, sizeof(*newaddr)); |
27 |
if (!newaddr) { |
28 |
return NULL; |
29 |
} |
30 |
newaddr->pool = p; |
31 |
newaddr->hostname = apr_pstrdup(p, oldaddr->hostname); |
32 |
newaddr->servname = apr_pstrdup(p, oldaddr->servname); |
33 |
newaddr->port = oldaddr->port; |
34 |
newaddr->family = oldaddr->family; |
35 |
newaddr->salen = oldaddr->salen; |
36 |
newaddr->ipaddr_len = oldaddr->ipaddr_len; |
37 |
newaddr->addr_str_len = oldaddr->addr_str_len; |
38 |
newaddr->ipaddr_ptr = apr_pmemdup(p, oldaddr->ipaddr_ptr, oldaddr->ipaddr_len); |
39 |
newaddr->sa = oldaddr->sa; |
40 |
if (oldaddr->next) { |
41 |
newaddr->next = sockaddr_dup(oldaddr->next, p); |
42 |
} else { |
43 |
newaddr->next = NULL; |
44 |
} |
45 |
return newaddr; |
46 |
} |
47 |
|
48 |
static apr_status_t socket_dup(apr_socket_t **new_socket, |
49 |
apr_socket_t *old_socket, apr_pool_t *p, |
50 |
int which_dup) |
51 |
{ |
52 |
int rv; |
53 |
|
54 |
if (which_dup == 2) { |
55 |
if ((*new_socket) == NULL) { |
56 |
/* We can't dup2 unless we have a valid new_socket */ |
57 |
return APR_EINVAL; |
58 |
} |
59 |
rv = dup2(old_socket->socketdes, (*new_socket)->socketdes); |
60 |
} else { |
61 |
rv = dup(old_socket->socketdes); |
62 |
} |
63 |
|
64 |
if (rv == -1) |
65 |
return errno; |
66 |
|
67 |
if (which_dup == 1) { |
68 |
(*new_socket) = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); |
69 |
(*new_socket)->pool = p; |
70 |
(*new_socket)->socketdes = rv; |
71 |
} |
72 |
|
73 |
(*new_socket)->type = old_socket->type; |
74 |
(*new_socket)->protocol = old_socket->protocol; |
75 |
(*new_socket)->local_addr = sockaddr_dup(old_socket->local_addr, p); |
76 |
(*new_socket)->remote_addr = sockaddr_dup(old_socket->remote_addr, p); |
77 |
(*new_socket)->timeout = old_socket->timeout; |
78 |
#ifndef HAVE_POLL |
79 |
(*new_socket)->connected = old_socket->connected; |
80 |
#endif |
81 |
(*new_socket)->local_port_unknown = old_socket->local_port_unknown; |
82 |
(*new_socket)->local_interface_unknown = old_socket->local_interface_unknown; |
83 |
(*new_socket)->remote_addr_unknown = old_socket->remote_addr_unknown; |
84 |
|
85 |
/* apr_socket_dup2() retains the original cleanup, reflecting |
86 |
* the existing inherit and nocleanup flags. This means, |
87 |
* that apr_socket_dup2() cannot be called against an apr_socket_t |
88 |
* already closed with apr_socket_close, because the expected |
89 |
* cleanup was already killed. |
90 |
*/ |
91 |
if (which_dup == 2) { |
92 |
return APR_SUCCESS; |
93 |
} |
94 |
|
95 |
(*new_socket)->options = old_socket->options; |
96 |
/* The user must call APR_DECLARE_INHERIT_SET(s) on the dupped |
97 |
* apr_socket_t when desired. |
98 |
*/ |
99 |
#ifndef WAITIO_USES_POLL |
100 |
/* Start out with no pollset. apr_wait_for_io_or_timeout() will |
101 |
* initialize the pollset if needed. |
102 |
*/ |
103 |
(*new_socket)->pollset = NULL; |
104 |
#endif |
105 |
return APR_SUCCESS; |
106 |
} |
107 |
|
108 |
APR_DECLARE(apr_status_t) apr_socket_dup(apr_socket_t **new_socket, |
109 |
apr_socket_t *old_socket, apr_pool_t *p) |
110 |
{ |
111 |
return socket_dup(new_socket, old_socket, p, 1); |
112 |
} |
113 |
|
114 |
APR_DECLARE(apr_status_t) apr_socket_dup2(apr_socket_t *new_socket, |
115 |
apr_socket_t *old_socket, apr_pool_t *p) |
116 |
{ |
117 |
return socket_dup(&new_socket, old_socket, p, 2); |
118 |
} |
119 |
|
120 |
APR_DECLARE(apr_status_t) apr_socket_setaside(apr_socket_t **new_socket, |
121 |
apr_socket_t *old_socket, |
122 |
apr_pool_t *p) |
123 |
{ |
124 |
*new_socket = (apr_socket_t *)apr_palloc(p, sizeof(apr_socket_t)); |
125 |
memcpy(*new_socket, old_socket, sizeof(apr_socket_t)); |
126 |
(*new_socket)->pool = p; |
127 |
(*new_socket)->local_addr = sockaddr_dup(old_socket->local_addr, p); |
128 |
(*new_socket)->remote_addr = sockaddr_dup(old_socket->remote_addr, p); |
129 |
old_socket->socketdes = -1; |
130 |
#ifndef WAITIO_USES_POLL |
131 |
(*new_socket)->pollset = NULL; |
132 |
#endif |
133 |
return APR_SUCCESS; |
134 |
} |