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
27 static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
28
socket_cleanup(void * sock)29 static 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
set_socket_vars(apr_socket_t * sock,int family,int type,int protocol)48 static 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 }
alloc_socket(apr_socket_t ** new,apr_pool_t * p)61 static 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
apr_socket_protocol_get(apr_socket_t * sock,int * protocol)79 APR_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
apr_socket_create(apr_socket_t ** new,int family,int type,int protocol,apr_pool_t * cont)86 APR_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
apr_socket_shutdown(apr_socket_t * thesocket,apr_shutdown_how_e how)169 APR_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
apr_socket_close(apr_socket_t * thesocket)200 APR_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
apr_socket_bind(apr_socket_t * sock,apr_sockaddr_t * sa)206 APR_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
apr_socket_listen(apr_socket_t * sock,apr_int32_t backlog)223 APR_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
apr_socket_accept(apr_socket_t ** new,apr_socket_t * sock,apr_pool_t * p)232 APR_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
wait_for_connect(apr_socket_t * sock)314 static apr_status_t wait_for_connect(apr_socket_t *sock)
315 {
316 int rc;
317 struct timeval tv, *tvptr;
318 fd_set wfdset, efdset;
319
320 /* wait for the connect to complete or timeout */
321 FD_ZERO(&wfdset);
322 FD_SET(sock->socketdes, &wfdset);
323 FD_ZERO(&efdset);
324 FD_SET(sock->socketdes, &efdset);
325
326 if (sock->timeout < 0) {
327 tvptr = NULL;
328 }
329 else {
330 /* casts for winsock/timeval definition */
331 tv.tv_sec = (long)apr_time_sec(sock->timeout);
332 tv.tv_usec = (int)apr_time_usec(sock->timeout);
333 tvptr = &tv;
334 }
335 rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
336 if (rc == SOCKET_ERROR) {
337 return apr_get_netos_error();
338 }
339 else if (!rc) {
340 return APR_FROM_OS_ERROR(WSAETIMEDOUT);
341 }
342 /* Evaluate the efdset */
343 if (FD_ISSET(sock->socketdes, &efdset)) {
344 /* The connect failed. */
345 int rclen = sizeof(rc);
346 if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) {
347 return apr_get_netos_error();
348 }
349 return APR_FROM_OS_ERROR(rc);
350 }
351
352 return APR_SUCCESS;
353 }
354
apr_socket_connect(apr_socket_t * sock,apr_sockaddr_t * sa)355 APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock,
356 apr_sockaddr_t *sa)
357 {
358 apr_status_t rv;
359
360 if ((sock->socketdes == INVALID_SOCKET) || (!sock->local_addr)) {
361 return APR_ENOTSOCK;
362 }
363
364 if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin,
365 sa->salen) == SOCKET_ERROR) {
366 rv = apr_get_netos_error();
367 }
368 else {
369 rv = APR_SUCCESS;
370 }
371
372 if (rv == APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
373 if (sock->timeout == 0) {
374 /* Tell the app that the connect is in progress...
375 * Gotta play some games here. connect on Unix will return
376 * EINPROGRESS under the same circumstances that Windows
377 * returns WSAEWOULDBLOCK. Do some adhoc canonicalization...
378 */
379 rv = APR_FROM_OS_ERROR(WSAEINPROGRESS);
380 }
381 else {
382 rv = wait_for_connect(sock);
383 if (rv != APR_SUCCESS) {
384 return rv;
385 }
386 }
387 }
388
389 if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
390 /* A real remote address was passed in. If the unspecified
391 * address was used, the actual remote addr will have to be
392 * determined using getpeername() if required. */
393 sock->remote_addr_unknown = 0;
394
395 /* Copy the address structure details in. */
396 sock->remote_addr = sa;
397 }
398
399 if (sock->local_addr->sa.sin.sin_port == 0) {
400 /* connect() got us an ephemeral port */
401 sock->local_port_unknown = 1;
402 }
403 if (!memcmp(sock->local_addr->ipaddr_ptr,
404 generic_inaddr_any,
405 sock->local_addr->ipaddr_len)) {
406 /* not bound to specific local interface; connect() had to assign
407 * one for the socket
408 */
409 sock->local_interface_unknown = 1;
410 }
411
412 if (rv != APR_SUCCESS && rv != APR_FROM_OS_ERROR(WSAEISCONN)) {
413 return rv;
414 }
415
416 return APR_SUCCESS;
417 }
418
apr_socket_type_get(apr_socket_t * sock,int * type)419 APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type)
420 {
421 *type = sock->type;
422 return APR_SUCCESS;
423 }
424
apr_socket_data_get(void ** data,const char * key,apr_socket_t * sock)425 APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key,
426 apr_socket_t *sock)
427 {
428 sock_userdata_t *cur = sock->userdata;
429
430 *data = NULL;
431
432 while (cur) {
433 if (!strcmp(cur->key, key)) {
434 *data = cur->data;
435 break;
436 }
437 cur = cur->next;
438 }
439
440 return APR_SUCCESS;
441 }
442
apr_socket_data_set(apr_socket_t * sock,void * data,const char * key,apr_status_t (* cleanup)(void *))443 APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data,
444 const char *key,
445 apr_status_t (*cleanup)(void *))
446 {
447 sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t));
448
449 new->key = apr_pstrdup(sock->pool, key);
450 new->data = data;
451 new->next = sock->userdata;
452 sock->userdata = new;
453
454 if (cleanup) {
455 apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup);
456 }
457
458 return APR_SUCCESS;
459 }
460
apr_os_sock_get(apr_os_sock_t * thesock,apr_socket_t * sock)461 APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock,
462 apr_socket_t *sock)
463 {
464 *thesock = sock->socketdes;
465 return APR_SUCCESS;
466 }
467
apr_os_sock_make(apr_socket_t ** apr_sock,apr_os_sock_info_t * os_sock_info,apr_pool_t * cont)468 APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock,
469 apr_os_sock_info_t *os_sock_info,
470 apr_pool_t *cont)
471 {
472 alloc_socket(apr_sock, cont);
473 set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
474 (*apr_sock)->timeout = -1;
475 (*apr_sock)->disconnected = 0;
476 (*apr_sock)->socketdes = *os_sock_info->os_sock;
477 if (os_sock_info->local) {
478 memcpy(&(*apr_sock)->local_addr->sa.sin,
479 os_sock_info->local,
480 (*apr_sock)->local_addr->salen);
481 (*apr_sock)->local_addr->pool = cont;
482 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
483 (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
484 }
485 else {
486 (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
487 }
488 if (os_sock_info->remote) {
489 memcpy(&(*apr_sock)->remote_addr->sa.sin,
490 os_sock_info->remote,
491 (*apr_sock)->remote_addr->salen);
492 (*apr_sock)->remote_addr->pool = cont;
493 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
494 (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
495 (*apr_sock)->remote_addr_unknown = 0;
496 }
497
498 apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock),
499 socket_cleanup, apr_pool_cleanup_null);
500
501 return APR_SUCCESS;
502 }
503
apr_os_sock_put(apr_socket_t ** sock,apr_os_sock_t * thesock,apr_pool_t * cont)504 APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock,
505 apr_os_sock_t *thesock,
506 apr_pool_t *cont)
507 {
508 if ((*sock) == NULL) {
509 alloc_socket(sock, cont);
510 /* XXX figure out the actual socket type here */
511 /* *or* just decide that apr_os_sock_put() has to be told the family and type */
512 set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
513 (*sock)->timeout = -1;
514 (*sock)->disconnected = 0;
515 }
516 (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
517 (*sock)->remote_addr_unknown = 1;
518 (*sock)->socketdes = *thesock;
519 return APR_SUCCESS;
520 }
521
522
523 /* Sockets cannot be inherited through the standard sockets
524 * inheritence. WSADuplicateSocket must be used.
525 * This is not trivial to implement.
526 */
527
apr_socket_inherit_set(apr_socket_t * socket)528 APR_DECLARE(apr_status_t) apr_socket_inherit_set(apr_socket_t *socket)
529 {
530 return APR_ENOTIMPL;
531 }
532
apr_socket_inherit_unset(apr_socket_t * socket)533 APR_DECLARE(apr_status_t) apr_socket_inherit_unset(apr_socket_t *socket)
534 {
535 return APR_ENOTIMPL;
536 }
537
538 APR_POOL_IMPLEMENT_ACCESSOR(socket);
539