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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "apr_arch_networkio.h"
18 #include "apr_arch_inherit.h"
19 #include "apr_network_io.h"
20 #include "apr_general.h"
21 #include "apr_portable.h"
23 #include "apr_strings.h"
26 #include <sys/socket.h>
27 #include <netinet/tcp.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
31 #include "apr_arch_os2calls.h"
33 static apr_status_t socket_cleanup(void *sock)
35 apr_socket_t *thesocket = sock;
37 if (thesocket->socketdes < 0) {
38 return APR_EINVALSOCK;
41 if (soclose(thesocket->socketdes) == 0) {
42 thesocket->socketdes = -1;
46 return APR_OS2_STATUS(sock_errno());
50 static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol)
53 sock->protocol = protocol;
54 apr_sockaddr_vars_set(sock->local_addr, family, 0);
55 apr_sockaddr_vars_set(sock->remote_addr, family, 0);
58 static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
60 *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
62 (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
63 sizeof(apr_sockaddr_t));
64 (*new)->local_addr->pool = p;
65 (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt,
66 sizeof(apr_sockaddr_t));
67 (*new)->remote_addr->pool = p;
70 APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, int *protocol)
72 *protocol = sock->protocol;
76 APR_DECLARE(apr_status_t) apr_socket_create_ex(apr_socket_t **new, int family, int type,
77 int protocol, apr_pool_t *cont)
79 int downgrade = (family == AF_UNSPEC);
81 if (family == AF_UNSPEC) {
89 alloc_socket(new, cont);
91 (*new)->socketdes = socket(family, type, protocol);
93 if ((*new)->socketdes < 0 && downgrade) {
95 (*new)->socketdes = socket(family, type, protocol);
99 if ((*new)->socketdes < 0) {
100 return APR_OS2_STATUS(sock_errno());
102 set_socket_vars(*new, family, type, protocol);
104 (*new)->timeout = -1;
105 (*new)->nonblock = FALSE;
106 apr_pool_cleanup_register((*new)->cntxt, (void *)(*new),
107 socket_cleanup, apr_pool_cleanup_null);
111 APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, int type,
114 return apr_socket_create_ex(new, family, type, 0, cont);
117 APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket,
118 apr_shutdown_how_e how)
120 if (shutdown(thesocket->socketdes, how) == 0) {
124 return APR_OS2_STATUS(sock_errno());
128 APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket)
130 apr_pool_cleanup_kill(thesocket->cntxt, thesocket, socket_cleanup);
131 return socket_cleanup(thesocket);
134 APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock,
137 if (bind(sock->socketdes,
138 (struct sockaddr *)&sa->sa,
140 return APR_OS2_STATUS(sock_errno());
142 sock->local_addr = sa;
143 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
144 if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
145 sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
151 APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock,
154 if (listen(sock->socketdes, backlog) == -1)
155 return APR_OS2_STATUS(sock_errno());
160 APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new,
162 apr_pool_t *connection_context)
164 alloc_socket(new, connection_context);
165 set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, sock->protocol);
167 (*new)->timeout = -1;
168 (*new)->nonblock = FALSE;
170 (*new)->socketdes = accept(sock->socketdes,
171 (struct sockaddr *)&(*new)->remote_addr->sa,
172 &(*new)->remote_addr->salen);
174 if ((*new)->socketdes < 0) {
175 return APR_OS2_STATUS(sock_errno());
178 *(*new)->local_addr = *sock->local_addr;
179 (*new)->local_addr->pool = connection_context;
180 (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
182 /* fix up any pointers which are no longer valid */
183 if (sock->local_addr->sa.sin.sin_family == AF_INET) {
184 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
187 apr_pool_cleanup_register((*new)->cntxt, (void *)(*new),
188 socket_cleanup, apr_pool_cleanup_null);
192 APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock,
195 if ((connect(sock->socketdes, (struct sockaddr *)&sa->sa.sin,
197 (sock_errno() != SOCEINPROGRESS)) {
198 return APR_OS2_STATUS(sock_errno());
201 int namelen = sizeof(sock->local_addr->sa.sin);
202 getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa.sin,
204 sock->remote_addr = sa;
210 APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key,
213 sock_userdata_t *cur = sock->userdata;
218 if (!strcmp(cur->key, key)) {
230 APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, const char *key,
231 apr_status_t (*cleanup) (void *))
233 sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t));
235 new->key = apr_pstrdup(sock->cntxt, key);
237 new->next = sock->userdata;
238 sock->userdata = new;
241 apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup);
247 APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock)
249 *thesock = sock->socketdes;
253 APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock,
254 apr_os_sock_info_t *os_sock_info,
257 alloc_socket(apr_sock, cont);
258 #ifdef APR_ENABLE_FOR_1_0 /* no protocol field yet */
259 set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
261 set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, 0);
263 (*apr_sock)->timeout = -1;
264 (*apr_sock)->socketdes = *os_sock_info->os_sock;
265 if (os_sock_info->local) {
266 memcpy(&(*apr_sock)->local_addr->sa.sin,
268 (*apr_sock)->local_addr->salen);
269 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
270 (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
273 (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
275 if (os_sock_info->remote) {
276 memcpy(&(*apr_sock)->remote_addr->sa.sin,
277 os_sock_info->remote,
278 (*apr_sock)->remote_addr->salen);
279 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
280 (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
283 (*apr_sock)->remote_addr_unknown = 1;
286 apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock),
287 socket_cleanup, apr_pool_cleanup_null);
292 APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, apr_pool_t *cont)
297 if ((*sock) == NULL) {
298 alloc_socket(sock, cont);
299 set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
300 (*sock)->timeout = -1;
303 (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
304 (*sock)->remote_addr_unknown = 1;
305 (*sock)->socketdes = *thesock;
309 APR_IMPLEMENT_INHERIT_SET(socket, inherit, cntxt, socket_cleanup)
311 APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, cntxt, socket_cleanup)
314 APR_DECLARE(apr_status_t) apr_shutdown(apr_socket_t *thesocket,
315 apr_shutdown_how_e how)
317 return apr_socket_shutdown(thesocket, how);
321 APR_DECLARE(apr_status_t) apr_bind(apr_socket_t *sock, apr_sockaddr_t *sa)
323 return apr_socket_bind(sock, sa);
327 APR_DECLARE(apr_status_t) apr_listen(apr_socket_t *sock, apr_int32_t backlog)
329 return apr_socket_listen(sock, backlog);
333 APR_DECLARE(apr_status_t) apr_accept(apr_socket_t **new, apr_socket_t *sock,
334 apr_pool_t *connection_context)
336 return apr_socket_accept(new, sock, connection_context);
340 APR_DECLARE(apr_status_t) apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
342 return apr_socket_connect(sock, sa);