1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
62 #ifndef OPENSSL_NO_SOCK
64 typedef struct bio_accept_st {
67 int bind_mode; /* Socket mode for BIO_listen */
68 int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */
74 BIO_ADDRINFO *addr_first;
75 const BIO_ADDRINFO *addr_iter;
76 BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */
77 char *cache_accepting_name, *cache_accepting_serv;
78 BIO_ADDR cache_peer_addr;
79 char *cache_peer_name, *cache_peer_serv;
84 static int acpt_write(BIO *h, const char *buf, int num);
85 static int acpt_read(BIO *h, char *buf, int size);
86 static int acpt_puts(BIO *h, const char *str);
87 static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
88 static int acpt_new(BIO *h);
89 static int acpt_free(BIO *data);
90 static int acpt_state(BIO *b, BIO_ACCEPT *c);
91 static void acpt_close_socket(BIO *data);
92 static BIO_ACCEPT *BIO_ACCEPT_new(void);
93 static void BIO_ACCEPT_free(BIO_ACCEPT *a);
95 # define ACPT_S_BEFORE 1
96 # define ACPT_S_GET_ADDR 2
97 # define ACPT_S_CREATE_SOCKET 3
98 # define ACPT_S_LISTEN 4
99 # define ACPT_S_ACCEPT 5
102 static const BIO_METHOD methods_acceptp = {
108 NULL, /* connect_gets, */
115 const BIO_METHOD *BIO_s_accept(void)
117 return (&methods_acceptp);
120 static int acpt_new(BIO *bi)
125 bi->num = (int)INVALID_SOCKET;
127 if ((ba = BIO_ACCEPT_new()) == NULL)
129 bi->ptr = (char *)ba;
130 ba->state = ACPT_S_BEFORE;
135 static BIO_ACCEPT *BIO_ACCEPT_new(void)
139 if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
141 ret->accept_family = BIO_FAMILY_IPANY;
142 ret->accept_sock = (int)INVALID_SOCKET;
146 static void BIO_ACCEPT_free(BIO_ACCEPT *a)
151 OPENSSL_free(a->param_addr);
152 OPENSSL_free(a->param_serv);
153 BIO_ADDRINFO_free(a->addr_first);
154 OPENSSL_free(a->cache_accepting_name);
155 OPENSSL_free(a->cache_accepting_serv);
156 OPENSSL_free(a->cache_peer_name);
157 OPENSSL_free(a->cache_peer_serv);
158 BIO_free(a->bio_chain);
162 static void acpt_close_socket(BIO *bio)
166 c = (BIO_ACCEPT *)bio->ptr;
167 if (c->accept_sock != (int)INVALID_SOCKET) {
168 shutdown(c->accept_sock, 2);
169 closesocket(c->accept_sock);
170 c->accept_sock = (int)INVALID_SOCKET;
171 bio->num = (int)INVALID_SOCKET;
175 static int acpt_free(BIO *a)
181 data = (BIO_ACCEPT *)a->ptr;
184 acpt_close_socket(a);
185 BIO_ACCEPT_free(data);
193 static int acpt_state(BIO *b, BIO_ACCEPT *c)
195 BIO *bio = NULL, *dbio;
196 int s = -1, ret = -1;
201 if (c->param_addr == NULL && c->param_serv == NULL) {
202 BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED);
203 ERR_add_error_data(4,
204 "hostname=", c->param_addr,
205 " service=", c->param_serv);
209 /* Because we're starting a new bind, any cached name and serv
210 * are now obsolete and need to be cleaned out.
211 * QUESTION: should this be done in acpt_close_socket() instead?
213 OPENSSL_free(c->cache_accepting_name);
214 c->cache_accepting_name = NULL;
215 OPENSSL_free(c->cache_accepting_serv);
216 c->cache_accepting_serv = NULL;
217 OPENSSL_free(c->cache_peer_name);
218 c->cache_peer_name = NULL;
219 OPENSSL_free(c->cache_peer_serv);
220 c->cache_peer_serv = NULL;
222 c->state = ACPT_S_GET_ADDR;
225 case ACPT_S_GET_ADDR:
227 int family = AF_UNSPEC;
228 switch (c->accept_family) {
229 case BIO_FAMILY_IPV6:
230 if (1) { /* This is a trick we use to avoid bit rot.
231 * at least the "else" part will always be
238 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
242 case BIO_FAMILY_IPV4:
245 case BIO_FAMILY_IPANY:
249 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
252 if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
253 family, SOCK_STREAM, &c->addr_first) == 0)
256 if (c->addr_first == NULL) {
257 BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
260 /* We're currently not iterating, but set this as preparation
261 * for possible future development in that regard
263 c->addr_iter = c->addr_first;
264 c->state = ACPT_S_CREATE_SOCKET;
267 case ACPT_S_CREATE_SOCKET:
268 ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
269 BIO_ADDRINFO_socktype(c->addr_iter),
270 BIO_ADDRINFO_protocol(c->addr_iter), 0);
271 if (ret == (int)INVALID_SOCKET) {
272 SYSerr(SYS_F_SOCKET, get_last_socket_error());
273 ERR_add_error_data(4,
274 "hostname=", c->param_addr,
275 " service=", c->param_serv);
276 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
279 c->accept_sock = ret;
281 c->state = ACPT_S_LISTEN;
286 if (!BIO_listen(c->accept_sock,
287 BIO_ADDRINFO_address(c->addr_iter),
289 BIO_closesocket(c->accept_sock);
295 union BIO_sock_info_u info;
297 info.addr = &c->cache_accepting_addr;
298 if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
300 BIO_closesocket(c->accept_sock);
305 c->cache_accepting_name =
306 BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
307 c->cache_accepting_serv =
308 BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
309 c->state = ACPT_S_ACCEPT;
315 if (b->next_bio != NULL) {
316 c->state = ACPT_S_OK;
319 BIO_clear_retry_flags(b);
322 s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
325 /* If the returned socket is invalid, this might still be
329 if (BIO_sock_should_retry(s)) {
330 BIO_set_retry_special(b);
331 b->retry_reason = BIO_RR_ACCEPT;
336 /* If it wasn't retryable, we fail */
342 bio = BIO_new_socket(s, BIO_CLOSE);
346 BIO_set_callback(bio, BIO_get_callback(b));
347 BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
350 * If the accept BIO has an bio_chain, we dup it and put the new
353 if (c->bio_chain != NULL) {
354 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
356 if (!BIO_push(dbio, bio))
360 if (BIO_push(b, bio) == NULL)
364 BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
366 BIO_ADDR_service_string(&c->cache_peer_addr, 1);
367 c->state = ACPT_S_OK;
373 if (b->next_bio == NULL) {
374 c->state = ACPT_S_ACCEPT;
395 static int acpt_read(BIO *b, char *out, int outl)
400 BIO_clear_retry_flags(b);
401 data = (BIO_ACCEPT *)b->ptr;
403 while (b->next_bio == NULL) {
404 ret = acpt_state(b, data);
409 ret = BIO_read(b->next_bio, out, outl);
410 BIO_copy_next_retry(b);
414 static int acpt_write(BIO *b, const char *in, int inl)
419 BIO_clear_retry_flags(b);
420 data = (BIO_ACCEPT *)b->ptr;
422 while (b->next_bio == NULL) {
423 ret = acpt_state(b, data);
428 ret = BIO_write(b->next_bio, in, inl);
429 BIO_copy_next_retry(b);
433 static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
440 data = (BIO_ACCEPT *)b->ptr;
445 data->state = ACPT_S_BEFORE;
446 acpt_close_socket(b);
447 BIO_ADDRINFO_free(data->addr_first);
448 data->addr_first = NULL;
451 case BIO_C_DO_STATE_MACHINE:
452 /* use this one to start the connection */
453 ret = (long)acpt_state(b, data);
455 case BIO_C_SET_ACCEPT:
458 char *hold_serv = data->param_serv;
459 /* We affect the hostname regardless. However, the input
460 * string might contain a host:service spec, so we must
461 * parse it, which might or might not affect the service
463 OPENSSL_free(data->param_addr);
464 data->param_addr = NULL;
465 ret = BIO_parse_hostserv(ptr,
468 BIO_PARSE_PRIO_SERV);
469 if (hold_serv != data->param_serv)
470 OPENSSL_free(hold_serv);
472 } else if (num == 1) {
473 OPENSSL_free(data->param_serv);
474 data->param_serv = BUF_strdup(ptr);
476 } else if (num == 2) {
477 data->bind_mode |= BIO_SOCK_NONBLOCK;
478 } else if (num == 3) {
479 BIO_free(data->bio_chain);
480 data->bio_chain = (BIO *)ptr;
481 } else if (num == 4) {
482 data->accept_family = *(int *)ptr;
486 data->bind_mode &= ~BIO_SOCK_NONBLOCK;
492 data->accepted_mode |= BIO_SOCK_NONBLOCK;
494 data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
498 b->num = *((int *)ptr);
499 data->accept_sock = b->num;
500 data->state = ACPT_S_ACCEPT;
501 b->shutdown = (int)num;
508 *ip = data->accept_sock;
509 ret = data->accept_sock;
513 case BIO_C_GET_ACCEPT:
515 if (num == 0 && ptr != NULL) {
517 *pp = data->cache_accepting_name;
518 } else if (num == 1 && ptr != NULL) {
520 *pp = data->cache_accepting_serv;
521 } else if (num == 2 && ptr != NULL) {
523 *pp = data->cache_peer_name;
524 } else if (num == 3 && ptr != NULL) {
526 *pp = data->cache_peer_serv;
527 } else if (num == 4) {
528 switch (BIO_ADDRINFO_family(data->addr_iter)) {
531 ret = BIO_FAMILY_IPV6;
535 ret = BIO_FAMILY_IPV4;
538 ret = data->accept_family;
549 case BIO_CTRL_GET_CLOSE:
552 case BIO_CTRL_SET_CLOSE:
553 b->shutdown = (int)num;
555 case BIO_CTRL_PENDING:
556 case BIO_CTRL_WPENDING:
561 case BIO_C_SET_BIND_MODE:
562 data->bind_mode = (int)num;
564 case BIO_C_GET_BIND_MODE:
565 ret = (long)data->bind_mode;
569 if (data->param_port) EAY EAY
570 BIO_set_port(dbio,data->param_port);
571 if (data->param_hostname)
572 BIO_set_hostname(dbio,data->param_hostname);
573 BIO_set_nbio(dbio,data->nbio); */
583 static int acpt_puts(BIO *bp, const char *str)
588 ret = acpt_write(bp, str, n);
592 BIO *BIO_new_accept(const char *str)
596 ret = BIO_new(BIO_s_accept());
599 if (BIO_set_accept_port(ret, str))