1
/* crypto/bio/bss_conn.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
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.
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).
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.
23
* Redistribution and use in source and binary forms, with or without
24
* modification, are permitted provided that the following conditions
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 :-).
37
* 4. If you include any Windows specific code (or a derivative thereof) from
38
* the apps directory (application code) you must include an acknowledgement:
39
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
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
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.]
63
#include <openssl/bio.h>
65
#ifndef OPENSSL_NO_SOCK
67
# ifdef OPENSSL_SYS_WIN16
68
# define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
70
# define SOCKET_PROTOCOL IPPROTO_TCP
73
# if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
74
/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
78
typedef struct bio_connect_st {
85
struct sockaddr_in them;
87
* int socket; this will be kept in bio->num so that it is compatible
88
* with the bss_sock bio
91
* called when the connection is initially made callback(BIO,state,ret);
92
* The callback should return 'ret'. state is for compatibility with the
95
int (*info_callback) (const BIO *bio, int state, int ret);
98
static int conn_write(BIO *h, const char *buf, int num);
99
static int conn_read(BIO *h, char *buf, int size);
100
static int conn_puts(BIO *h, const char *str);
101
static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
102
static int conn_new(BIO *h);
103
static int conn_free(BIO *data);
104
static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *);
106
static int conn_state(BIO *b, BIO_CONNECT *c);
107
static void conn_close_socket(BIO *data);
108
BIO_CONNECT *BIO_CONNECT_new(void);
109
void BIO_CONNECT_free(BIO_CONNECT *a);
111
static BIO_METHOD methods_connectp = {
117
NULL, /* connect_gets, */
124
static int conn_state(BIO *b, BIO_CONNECT *c)
129
int (*cb) (const BIO *, int, int) = NULL;
131
if (c->info_callback != NULL)
132
cb = c->info_callback;
136
case BIO_CONN_S_BEFORE:
137
p = c->param_hostname;
139
BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_SPECIFIED);
142
for (; *p != '\0'; p++) {
143
if ((*p == ':') || (*p == '/'))
148
if ((i == ':') || (i == '/')) {
157
if (c->param_port != NULL)
158
OPENSSL_free(c->param_port);
159
c->param_port = BUF_strdup(p);
163
if (c->param_port == NULL) {
164
BIOerr(BIO_F_CONN_STATE, BIO_R_NO_PORT_SPECIFIED);
165
ERR_add_error_data(2, "host=", c->param_hostname);
168
c->state = BIO_CONN_S_GET_IP;
171
case BIO_CONN_S_GET_IP:
172
if (BIO_get_host_ip(c->param_hostname, &(c->ip[0])) <= 0)
174
c->state = BIO_CONN_S_GET_PORT;
177
case BIO_CONN_S_GET_PORT:
178
if (c->param_port == NULL) {
181
} else if (BIO_get_port(c->param_port, &c->port) <= 0)
183
c->state = BIO_CONN_S_CREATE_SOCKET;
186
case BIO_CONN_S_CREATE_SOCKET:
187
/* now setup address */
188
memset((char *)&c->them, 0, sizeof(c->them));
189
c->them.sin_family = AF_INET;
190
c->them.sin_port = htons((unsigned short)c->port);
192
((unsigned long)c->ip[0] << 24L) |
193
((unsigned long)c->ip[1] << 16L) |
194
((unsigned long)c->ip[2] << 8L) | ((unsigned long)c->ip[3]);
195
c->them.sin_addr.s_addr = htonl(l);
196
c->state = BIO_CONN_S_CREATE_SOCKET;
198
ret = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
199
if (ret == INVALID_SOCKET) {
200
SYSerr(SYS_F_SOCKET, get_last_socket_error());
201
ERR_add_error_data(4, "host=", c->param_hostname,
203
BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
207
c->state = BIO_CONN_S_NBIO;
210
case BIO_CONN_S_NBIO:
212
if (!BIO_socket_nbio(b->num, 1)) {
213
BIOerr(BIO_F_CONN_STATE, BIO_R_ERROR_SETTING_NBIO);
214
ERR_add_error_data(4, "host=",
215
c->param_hostname, ":", c->param_port);
219
c->state = BIO_CONN_S_CONNECT;
221
# if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
223
i = setsockopt(b->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
226
SYSerr(SYS_F_SOCKET, get_last_socket_error());
227
ERR_add_error_data(4, "host=", c->param_hostname,
229
BIOerr(BIO_F_CONN_STATE, BIO_R_KEEPALIVE);
235
case BIO_CONN_S_CONNECT:
236
BIO_clear_retry_flags(b);
237
ret = connect(b->num,
238
(struct sockaddr *)&c->them, sizeof(c->them));
241
if (BIO_sock_should_retry(ret)) {
242
BIO_set_retry_special(b);
243
c->state = BIO_CONN_S_BLOCKED_CONNECT;
244
b->retry_reason = BIO_RR_CONNECT;
246
SYSerr(SYS_F_CONNECT, get_last_socket_error());
247
ERR_add_error_data(4, "host=",
248
c->param_hostname, ":", c->param_port);
249
BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
253
c->state = BIO_CONN_S_OK;
256
case BIO_CONN_S_BLOCKED_CONNECT:
257
i = BIO_sock_error(b->num);
259
BIO_clear_retry_flags(b);
260
SYSerr(SYS_F_CONNECT, i);
261
ERR_add_error_data(4, "host=",
262
c->param_hostname, ":", c->param_port);
263
BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
267
c->state = BIO_CONN_S_OK;
279
if (!(ret = cb((BIO *)b, c->state, ret)))
284
/* Loop does not exit */
287
ret = cb((BIO *)b, c->state, ret);
292
BIO_CONNECT *BIO_CONNECT_new(void)
296
if ((ret = (BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL)
298
ret->state = BIO_CONN_S_BEFORE;
299
ret->param_hostname = NULL;
300
ret->param_port = NULL;
301
ret->info_callback = NULL;
308
memset((char *)&ret->them, 0, sizeof(ret->them));
312
void BIO_CONNECT_free(BIO_CONNECT *a)
317
if (a->param_hostname != NULL)
318
OPENSSL_free(a->param_hostname);
319
if (a->param_port != NULL)
320
OPENSSL_free(a->param_port);
324
BIO_METHOD *BIO_s_connect(void)
326
return (&methods_connectp);
329
static int conn_new(BIO *bi)
332
bi->num = INVALID_SOCKET;
334
if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
340
static void conn_close_socket(BIO *bio)
344
c = (BIO_CONNECT *)bio->ptr;
345
if (bio->num != INVALID_SOCKET) {
346
/* Only do a shutdown if things were established */
347
if (c->state == BIO_CONN_S_OK)
348
shutdown(bio->num, 2);
349
closesocket(bio->num);
350
bio->num = INVALID_SOCKET;
354
static int conn_free(BIO *a)
360
data = (BIO_CONNECT *)a->ptr;
363
conn_close_socket(a);
364
BIO_CONNECT_free(data);
372
static int conn_read(BIO *b, char *out, int outl)
377
data = (BIO_CONNECT *)b->ptr;
378
if (data->state != BIO_CONN_S_OK) {
379
ret = conn_state(b, data);
385
clear_socket_error();
386
ret = readsocket(b->num, out, outl);
387
BIO_clear_retry_flags(b);
389
if (BIO_sock_should_retry(ret))
390
BIO_set_retry_read(b);
396
static int conn_write(BIO *b, const char *in, int inl)
401
data = (BIO_CONNECT *)b->ptr;
402
if (data->state != BIO_CONN_S_OK) {
403
ret = conn_state(b, data);
408
clear_socket_error();
409
ret = writesocket(b->num, in, inl);
410
BIO_clear_retry_flags(b);
412
if (BIO_sock_should_retry(ret))
413
BIO_set_retry_write(b);
418
static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
422
const char **pptr = NULL;
426
data = (BIO_CONNECT *)b->ptr;
431
data->state = BIO_CONN_S_BEFORE;
432
conn_close_socket(b);
435
case BIO_C_DO_STATE_MACHINE:
436
/* use this one to start the connection */
437
if (data->state != BIO_CONN_S_OK)
438
ret = (long)conn_state(b, data);
442
case BIO_C_GET_CONNECT:
444
pptr = (const char **)ptr;
451
*pptr = data->param_hostname;
452
} else if (num == 1) {
453
*pptr = data->param_port;
454
} else if (num == 2) {
455
*pptr = (char *)&(data->ip[0]);
465
*pptr = "not initialized";
469
case BIO_C_SET_CONNECT:
473
if (data->param_hostname != NULL)
474
OPENSSL_free(data->param_hostname);
475
data->param_hostname = BUF_strdup(ptr);
476
} else if (num == 1) {
477
if (data->param_port != NULL)
478
OPENSSL_free(data->param_port);
479
data->param_port = BUF_strdup(ptr);
480
} else if (num == 2) {
482
unsigned char *p = ptr;
484
BIO_snprintf(buf, sizeof buf, "%d.%d.%d.%d",
485
p[0], p[1], p[2], p[3]);
486
if (data->param_hostname != NULL)
487
OPENSSL_free(data->param_hostname);
488
data->param_hostname = BUF_strdup(buf);
489
memcpy(&(data->ip[0]), ptr, 4);
490
} else if (num == 3) {
491
char buf[DECIMAL_SIZE(int) + 1];
493
BIO_snprintf(buf, sizeof buf, "%d", *(int *)ptr);
494
if (data->param_port != NULL)
495
OPENSSL_free(data->param_port);
496
data->param_port = BUF_strdup(buf);
497
data->port = *(int *)ptr;
502
data->nbio = (int)num;
513
case BIO_CTRL_GET_CLOSE:
516
case BIO_CTRL_SET_CLOSE:
517
b->shutdown = (int)num;
519
case BIO_CTRL_PENDING:
520
case BIO_CTRL_WPENDING:
528
if (data->param_port)
529
BIO_set_conn_port(dbio, data->param_port);
530
if (data->param_hostname)
531
BIO_set_conn_hostname(dbio, data->param_hostname);
532
BIO_set_nbio(dbio, data->nbio);
534
* FIXME: the cast of the function seems unlikely to be a good
537
(void)BIO_set_info_callback(dbio,
538
(bio_info_cb *)data->info_callback);
541
case BIO_CTRL_SET_CALLBACK:
543
# if 0 /* FIXME: Should this be used? -- Richard
545
BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
552
case BIO_CTRL_GET_CALLBACK:
554
int (**fptr) (const BIO *bio, int state, int xret);
556
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
557
*fptr = data->info_callback;
567
static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
572
data = (BIO_CONNECT *)b->ptr;
575
case BIO_CTRL_SET_CALLBACK:
577
data->info_callback =
578
(int (*)(const struct bio_st *, int, int))fp;
588
static int conn_puts(BIO *bp, const char *str)
593
ret = conn_write(bp, str, n);
597
BIO *BIO_new_connect(const char *str)
601
ret = BIO_new(BIO_s_connect());
604
if (BIO_set_conn_hostname(ret, str))