]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/bss_acpt.c
Identify and move common internal libcrypto header files
[thirdparty/openssl.git] / crypto / bio / bss_acpt.c
CommitLineData
d02b48c6 1/* crypto/bio/bss_acpt.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
0f113f3e 8 *
d02b48c6
RE
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
0f113f3e 15 *
d02b48c6
RE
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
0f113f3e 22 *
d02b48c6
RE
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
0f113f3e 37 * 4. If you include any Windows specific code (or a derivative thereof) from
d02b48c6
RE
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
0f113f3e 40 *
d02b48c6
RE
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
0f113f3e 52 *
d02b48c6
RE
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
d02b48c6
RE
59#include <stdio.h>
60#include <errno.h>
61#define USE_SOCKETS
b39fc560 62#include "internal/cryptlib.h"
ec577822 63#include <openssl/bio.h>
d02b48c6 64
9ba4cc00
RL
65#ifndef OPENSSL_NO_SOCK
66
0f113f3e 67# if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
75e0770d 68/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
0f113f3e
MC
69# undef FIONBIO
70# endif
71
72typedef struct bio_accept_st {
73 int state;
74 char *param_addr;
75 int accept_sock;
76 int accept_nbio;
77 char *addr;
78 int nbio;
79 /*
80 * If 0, it means normal, if 1, do a connect on bind failure, and if
81 * there is no-one listening, bind with SO_REUSEADDR. If 2, always use
82 * SO_REUSEADDR.
83 */
84 int bind_mode;
85 BIO *bio_chain;
86} BIO_ACCEPT;
d02b48c6 87
0e1c0612
UM
88static int acpt_write(BIO *h, const char *buf, int num);
89static int acpt_read(BIO *h, char *buf, int size);
90static int acpt_puts(BIO *h, const char *str);
91static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
d02b48c6
RE
92static int acpt_new(BIO *h);
93static int acpt_free(BIO *data);
d02b48c6
RE
94static int acpt_state(BIO *b, BIO_ACCEPT *c);
95static void acpt_close_socket(BIO *data);
0f113f3e 96static BIO_ACCEPT *BIO_ACCEPT_new(void);
b3e72fc3 97static void BIO_ACCEPT_free(BIO_ACCEPT *a);
d02b48c6 98
0f113f3e
MC
99# define ACPT_S_BEFORE 1
100# define ACPT_S_GET_ACCEPT_SOCKET 2
101# define ACPT_S_OK 3
102
103static BIO_METHOD methods_acceptp = {
104 BIO_TYPE_ACCEPT,
105 "socket accept",
106 acpt_write,
107 acpt_read,
108 acpt_puts,
109 NULL, /* connect_gets, */
110 acpt_ctrl,
111 acpt_new,
112 acpt_free,
113 NULL,
114};
d02b48c6 115
6b691a5c 116BIO_METHOD *BIO_s_accept(void)
0f113f3e
MC
117{
118 return (&methods_acceptp);
119}
d02b48c6 120
6b691a5c 121static int acpt_new(BIO *bi)
0f113f3e
MC
122{
123 BIO_ACCEPT *ba;
124
125 bi->init = 0;
126 bi->num = INVALID_SOCKET;
127 bi->flags = 0;
128 if ((ba = BIO_ACCEPT_new()) == NULL)
129 return (0);
130 bi->ptr = (char *)ba;
131 ba->state = ACPT_S_BEFORE;
132 bi->shutdown = 1;
133 return (1);
134}
d02b48c6 135
b3e72fc3 136static BIO_ACCEPT *BIO_ACCEPT_new(void)
0f113f3e
MC
137{
138 BIO_ACCEPT *ret;
d02b48c6 139
b4faea50 140 if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
0f113f3e 141 return (NULL);
d02b48c6 142
16f8d4eb 143 memset(ret, 0, sizeof(*ret));
0f113f3e
MC
144 ret->accept_sock = INVALID_SOCKET;
145 ret->bind_mode = BIO_BIND_NORMAL;
146 return (ret);
147}
d02b48c6 148
b3e72fc3 149static void BIO_ACCEPT_free(BIO_ACCEPT *a)
0f113f3e
MC
150{
151 if (a == NULL)
152 return;
153
b548a1f1
RS
154 OPENSSL_free(a->param_addr);
155 OPENSSL_free(a->addr);
ca3a82c3 156 BIO_free(a->bio_chain);
0f113f3e
MC
157 OPENSSL_free(a);
158}
d02b48c6 159
6b691a5c 160static void acpt_close_socket(BIO *bio)
0f113f3e
MC
161{
162 BIO_ACCEPT *c;
163
164 c = (BIO_ACCEPT *)bio->ptr;
165 if (c->accept_sock != INVALID_SOCKET) {
166 shutdown(c->accept_sock, 2);
167 closesocket(c->accept_sock);
168 c->accept_sock = INVALID_SOCKET;
169 bio->num = INVALID_SOCKET;
170 }
171}
d02b48c6 172
6b691a5c 173static int acpt_free(BIO *a)
0f113f3e
MC
174{
175 BIO_ACCEPT *data;
176
177 if (a == NULL)
178 return (0);
179 data = (BIO_ACCEPT *)a->ptr;
180
181 if (a->shutdown) {
182 acpt_close_socket(a);
183 BIO_ACCEPT_free(data);
184 a->ptr = NULL;
185 a->flags = 0;
186 a->init = 0;
187 }
188 return (1);
189}
190
6b691a5c 191static int acpt_state(BIO *b, BIO_ACCEPT *c)
0f113f3e
MC
192{
193 BIO *bio = NULL, *dbio;
194 int s = -1;
195 int i;
196
197 again:
198 switch (c->state) {
199 case ACPT_S_BEFORE:
200 if (c->param_addr == NULL) {
201 BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_PORT_SPECIFIED);
202 return (-1);
203 }
204 s = BIO_get_accept_socket(c->param_addr, c->bind_mode);
205 if (s == INVALID_SOCKET)
206 return (-1);
207
208 if (c->accept_nbio) {
209 if (!BIO_socket_nbio(s, 1)) {
210 closesocket(s);
211 BIOerr(BIO_F_ACPT_STATE,
212 BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET);
213 return (-1);
214 }
215 }
216 c->accept_sock = s;
217 b->num = s;
218 c->state = ACPT_S_GET_ACCEPT_SOCKET;
219 return (1);
220 /* break; */
221 case ACPT_S_GET_ACCEPT_SOCKET:
222 if (b->next_bio != NULL) {
223 c->state = ACPT_S_OK;
224 goto again;
225 }
226 BIO_clear_retry_flags(b);
227 b->retry_reason = 0;
228 i = BIO_accept(c->accept_sock, &(c->addr));
229
230 /* -2 return means we should retry */
231 if (i == -2) {
232 BIO_set_retry_special(b);
233 b->retry_reason = BIO_RR_ACCEPT;
234 return -1;
235 }
236
237 if (i < 0)
238 return (i);
239
240 bio = BIO_new_socket(i, BIO_CLOSE);
241 if (bio == NULL)
242 goto err;
243
244 BIO_set_callback(bio, BIO_get_callback(b));
245 BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
246
247 if (c->nbio) {
248 if (!BIO_socket_nbio(i, 1)) {
249 BIOerr(BIO_F_ACPT_STATE,
250 BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET);
251 goto err;
252 }
253 }
254
255 /*
256 * If the accept BIO has an bio_chain, we dup it and put the new
257 * socket at the end.
258 */
259 if (c->bio_chain != NULL) {
260 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
261 goto err;
262 if (!BIO_push(dbio, bio))
263 goto err;
264 bio = dbio;
265 }
266 if (BIO_push(b, bio) == NULL)
267 goto err;
268
269 c->state = ACPT_S_OK;
270 return (1);
271 err:
272 if (bio != NULL)
273 BIO_free(bio);
274 else if (s >= 0)
275 closesocket(s);
276 return (0);
277 /* break; */
278 case ACPT_S_OK:
279 if (b->next_bio == NULL) {
280 c->state = ACPT_S_GET_ACCEPT_SOCKET;
281 goto again;
282 }
283 return (1);
284 /* break; */
285 default:
286 return (0);
287 /* break; */
288 }
289
290}
d02b48c6 291
6b691a5c 292static int acpt_read(BIO *b, char *out, int outl)
0f113f3e
MC
293{
294 int ret = 0;
295 BIO_ACCEPT *data;
d02b48c6 296
0f113f3e
MC
297 BIO_clear_retry_flags(b);
298 data = (BIO_ACCEPT *)b->ptr;
d02b48c6 299
0f113f3e
MC
300 while (b->next_bio == NULL) {
301 ret = acpt_state(b, data);
302 if (ret <= 0)
303 return (ret);
304 }
d02b48c6 305
0f113f3e
MC
306 ret = BIO_read(b->next_bio, out, outl);
307 BIO_copy_next_retry(b);
308 return (ret);
309}
d02b48c6 310
0e1c0612 311static int acpt_write(BIO *b, const char *in, int inl)
0f113f3e
MC
312{
313 int ret;
314 BIO_ACCEPT *data;
d02b48c6 315
0f113f3e
MC
316 BIO_clear_retry_flags(b);
317 data = (BIO_ACCEPT *)b->ptr;
d02b48c6 318
0f113f3e
MC
319 while (b->next_bio == NULL) {
320 ret = acpt_state(b, data);
321 if (ret <= 0)
322 return (ret);
323 }
d02b48c6 324
0f113f3e
MC
325 ret = BIO_write(b->next_bio, in, inl);
326 BIO_copy_next_retry(b);
327 return (ret);
328}
d02b48c6 329
0e1c0612 330static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
0f113f3e
MC
331{
332 int *ip;
333 long ret = 1;
334 BIO_ACCEPT *data;
335 char **pp;
336
337 data = (BIO_ACCEPT *)b->ptr;
338
339 switch (cmd) {
340 case BIO_CTRL_RESET:
341 ret = 0;
342 data->state = ACPT_S_BEFORE;
343 acpt_close_socket(b);
344 b->flags = 0;
345 break;
346 case BIO_C_DO_STATE_MACHINE:
347 /* use this one to start the connection */
348 ret = (long)acpt_state(b, data);
349 break;
350 case BIO_C_SET_ACCEPT:
351 if (ptr != NULL) {
352 if (num == 0) {
353 b->init = 1;
b548a1f1 354 OPENSSL_free(data->param_addr);
0f113f3e
MC
355 data->param_addr = BUF_strdup(ptr);
356 } else if (num == 1) {
357 data->accept_nbio = (ptr != NULL);
358 } else if (num == 2) {
ca3a82c3 359 BIO_free(data->bio_chain);
0f113f3e
MC
360 data->bio_chain = (BIO *)ptr;
361 }
362 }
363 break;
364 case BIO_C_SET_NBIO:
365 data->nbio = (int)num;
366 break;
367 case BIO_C_SET_FD:
368 b->init = 1;
369 b->num = *((int *)ptr);
370 data->accept_sock = b->num;
371 data->state = ACPT_S_GET_ACCEPT_SOCKET;
372 b->shutdown = (int)num;
373 b->init = 1;
374 break;
375 case BIO_C_GET_FD:
376 if (b->init) {
377 ip = (int *)ptr;
378 if (ip != NULL)
379 *ip = data->accept_sock;
380 ret = data->accept_sock;
381 } else
382 ret = -1;
383 break;
384 case BIO_C_GET_ACCEPT:
385 if (b->init) {
386 if (ptr != NULL) {
387 pp = (char **)ptr;
388 *pp = data->param_addr;
389 } else
390 ret = -1;
391 } else
392 ret = -1;
393 break;
394 case BIO_CTRL_GET_CLOSE:
395 ret = b->shutdown;
396 break;
397 case BIO_CTRL_SET_CLOSE:
398 b->shutdown = (int)num;
399 break;
400 case BIO_CTRL_PENDING:
401 case BIO_CTRL_WPENDING:
402 ret = 0;
403 break;
404 case BIO_CTRL_FLUSH:
405 break;
406 case BIO_C_SET_BIND_MODE:
407 data->bind_mode = (int)num;
408 break;
409 case BIO_C_GET_BIND_MODE:
410 ret = (long)data->bind_mode;
411 break;
412 case BIO_CTRL_DUP:
35a1cc90
MC
413/*- dbio=(BIO *)ptr;
414 if (data->param_port) EAY EAY
415 BIO_set_port(dbio,data->param_port);
416 if (data->param_hostname)
417 BIO_set_hostname(dbio,data->param_hostname);
418 BIO_set_nbio(dbio,data->nbio); */
0f113f3e
MC
419 break;
420
421 default:
422 ret = 0;
423 break;
424 }
425 return (ret);
426}
d02b48c6 427
0e1c0612 428static int acpt_puts(BIO *bp, const char *str)
0f113f3e
MC
429{
430 int n, ret;
d02b48c6 431
0f113f3e
MC
432 n = strlen(str);
433 ret = acpt_write(bp, str, n);
434 return (ret);
435}
d02b48c6 436
c45a48c1 437BIO *BIO_new_accept(const char *str)
0f113f3e
MC
438{
439 BIO *ret;
440
441 ret = BIO_new(BIO_s_accept());
442 if (ret == NULL)
443 return (NULL);
444 if (BIO_set_accept_port(ret, str))
445 return (ret);
ca3a82c3
RS
446 BIO_free(ret);
447 return (NULL);
0f113f3e 448}
d02b48c6
RE
449
450#endif