~mmach/netext73/isl

« back to all changes in this revision

Viewing changes to crypto/bio/bss_conn.c

  • Committer: mmach
  • Date: 2019-05-14 07:37:06 UTC
  • Revision ID: netbit73@gmail.com-20190514073706-nt6iq2m3597se19c
0.21

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* crypto/bio/bss_conn.c */
 
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 
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.
 
8
 *
 
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).
 
15
 *
 
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.
 
22
 *
 
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 :-).
 
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)"
 
40
 *
 
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.
 
52
 *
 
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
 
 
59
#include <stdio.h>
 
60
#include <errno.h>
 
61
#define USE_SOCKETS
 
62
#include "cryptlib.h"
 
63
#include <openssl/bio.h>
 
64
 
 
65
#ifndef OPENSSL_NO_SOCK
 
66
 
 
67
# ifdef OPENSSL_SYS_WIN16
 
68
#  define SOCKET_PROTOCOL 0     /* more microsoft stupidity */
 
69
# else
 
70
#  define SOCKET_PROTOCOL IPPROTO_TCP
 
71
# endif
 
72
 
 
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 */
 
75
#  undef FIONBIO
 
76
# endif
 
77
 
 
78
typedef struct bio_connect_st {
 
79
    int state;
 
80
    char *param_hostname;
 
81
    char *param_port;
 
82
    int nbio;
 
83
    unsigned char ip[4];
 
84
    unsigned short port;
 
85
    struct sockaddr_in them;
 
86
    /*
 
87
     * int socket; this will be kept in bio->num so that it is compatible
 
88
     * with the bss_sock bio
 
89
     */
 
90
    /*
 
91
     * called when the connection is initially made callback(BIO,state,ret);
 
92
     * The callback should return 'ret'.  state is for compatibility with the
 
93
     * ssl info_callback
 
94
     */
 
95
    int (*info_callback) (const BIO *bio, int state, int ret);
 
96
} BIO_CONNECT;
 
97
 
 
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 *);
 
105
 
 
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);
 
110
 
 
111
static BIO_METHOD methods_connectp = {
 
112
    BIO_TYPE_CONNECT,
 
113
    "socket connect",
 
114
    conn_write,
 
115
    conn_read,
 
116
    conn_puts,
 
117
    NULL,                       /* connect_gets, */
 
118
    conn_ctrl,
 
119
    conn_new,
 
120
    conn_free,
 
121
    conn_callback_ctrl,
 
122
};
 
123
 
 
124
static int conn_state(BIO *b, BIO_CONNECT *c)
 
125
{
 
126
    int ret = -1, i;
 
127
    unsigned long l;
 
128
    char *p, *q;
 
129
    int (*cb) (const BIO *, int, int) = NULL;
 
130
 
 
131
    if (c->info_callback != NULL)
 
132
        cb = c->info_callback;
 
133
 
 
134
    for (;;) {
 
135
        switch (c->state) {
 
136
        case BIO_CONN_S_BEFORE:
 
137
            p = c->param_hostname;
 
138
            if (p == NULL) {
 
139
                BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_SPECIFIED);
 
140
                goto exit_loop;
 
141
            }
 
142
            for (; *p != '\0'; p++) {
 
143
                if ((*p == ':') || (*p == '/'))
 
144
                    break;
 
145
            }
 
146
 
 
147
            i = *p;
 
148
            if ((i == ':') || (i == '/')) {
 
149
 
 
150
                *(p++) = '\0';
 
151
                if (i == ':') {
 
152
                    for (q = p; *q; q++)
 
153
                        if (*q == '/') {
 
154
                            *q = '\0';
 
155
                            break;
 
156
                        }
 
157
                    if (c->param_port != NULL)
 
158
                        OPENSSL_free(c->param_port);
 
159
                    c->param_port = BUF_strdup(p);
 
160
                }
 
161
            }
 
162
 
 
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);
 
166
                goto exit_loop;
 
167
            }
 
168
            c->state = BIO_CONN_S_GET_IP;
 
169
            break;
 
170
 
 
171
        case BIO_CONN_S_GET_IP:
 
172
            if (BIO_get_host_ip(c->param_hostname, &(c->ip[0])) <= 0)
 
173
                goto exit_loop;
 
174
            c->state = BIO_CONN_S_GET_PORT;
 
175
            break;
 
176
 
 
177
        case BIO_CONN_S_GET_PORT:
 
178
            if (c->param_port == NULL) {
 
179
                /* abort(); */
 
180
                goto exit_loop;
 
181
            } else if (BIO_get_port(c->param_port, &c->port) <= 0)
 
182
                goto exit_loop;
 
183
            c->state = BIO_CONN_S_CREATE_SOCKET;
 
184
            break;
 
185
 
 
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);
 
191
            l = (unsigned long)
 
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;
 
197
 
 
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,
 
202
                                   ":", c->param_port);
 
203
                BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
 
204
                goto exit_loop;
 
205
            }
 
206
            b->num = ret;
 
207
            c->state = BIO_CONN_S_NBIO;
 
208
            break;
 
209
 
 
210
        case BIO_CONN_S_NBIO:
 
211
            if (c->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);
 
216
                    goto exit_loop;
 
217
                }
 
218
            }
 
219
            c->state = BIO_CONN_S_CONNECT;
 
220
 
 
221
# if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
 
222
            i = 1;
 
223
            i = setsockopt(b->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
 
224
                           sizeof(i));
 
225
            if (i < 0) {
 
226
                SYSerr(SYS_F_SOCKET, get_last_socket_error());
 
227
                ERR_add_error_data(4, "host=", c->param_hostname,
 
228
                                   ":", c->param_port);
 
229
                BIOerr(BIO_F_CONN_STATE, BIO_R_KEEPALIVE);
 
230
                goto exit_loop;
 
231
            }
 
232
# endif
 
233
            break;
 
234
 
 
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));
 
239
            b->retry_reason = 0;
 
240
            if (ret < 0) {
 
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;
 
245
                } else {
 
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);
 
250
                }
 
251
                goto exit_loop;
 
252
            } else
 
253
                c->state = BIO_CONN_S_OK;
 
254
            break;
 
255
 
 
256
        case BIO_CONN_S_BLOCKED_CONNECT:
 
257
            i = BIO_sock_error(b->num);
 
258
            if (i) {
 
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);
 
264
                ret = 0;
 
265
                goto exit_loop;
 
266
            } else
 
267
                c->state = BIO_CONN_S_OK;
 
268
            break;
 
269
 
 
270
        case BIO_CONN_S_OK:
 
271
            ret = 1;
 
272
            goto exit_loop;
 
273
        default:
 
274
            /* abort(); */
 
275
            goto exit_loop;
 
276
        }
 
277
 
 
278
        if (cb != NULL) {
 
279
            if (!(ret = cb((BIO *)b, c->state, ret)))
 
280
                goto end;
 
281
        }
 
282
    }
 
283
 
 
284
    /* Loop does not exit */
 
285
 exit_loop:
 
286
    if (cb != NULL)
 
287
        ret = cb((BIO *)b, c->state, ret);
 
288
 end:
 
289
    return (ret);
 
290
}
 
291
 
 
292
BIO_CONNECT *BIO_CONNECT_new(void)
 
293
{
 
294
    BIO_CONNECT *ret;
 
295
 
 
296
    if ((ret = (BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL)
 
297
        return (NULL);
 
298
    ret->state = BIO_CONN_S_BEFORE;
 
299
    ret->param_hostname = NULL;
 
300
    ret->param_port = NULL;
 
301
    ret->info_callback = NULL;
 
302
    ret->nbio = 0;
 
303
    ret->ip[0] = 0;
 
304
    ret->ip[1] = 0;
 
305
    ret->ip[2] = 0;
 
306
    ret->ip[3] = 0;
 
307
    ret->port = 0;
 
308
    memset((char *)&ret->them, 0, sizeof(ret->them));
 
309
    return (ret);
 
310
}
 
311
 
 
312
void BIO_CONNECT_free(BIO_CONNECT *a)
 
313
{
 
314
    if (a == NULL)
 
315
        return;
 
316
 
 
317
    if (a->param_hostname != NULL)
 
318
        OPENSSL_free(a->param_hostname);
 
319
    if (a->param_port != NULL)
 
320
        OPENSSL_free(a->param_port);
 
321
    OPENSSL_free(a);
 
322
}
 
323
 
 
324
BIO_METHOD *BIO_s_connect(void)
 
325
{
 
326
    return (&methods_connectp);
 
327
}
 
328
 
 
329
static int conn_new(BIO *bi)
 
330
{
 
331
    bi->init = 0;
 
332
    bi->num = INVALID_SOCKET;
 
333
    bi->flags = 0;
 
334
    if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
 
335
        return (0);
 
336
    else
 
337
        return (1);
 
338
}
 
339
 
 
340
static void conn_close_socket(BIO *bio)
 
341
{
 
342
    BIO_CONNECT *c;
 
343
 
 
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;
 
351
    }
 
352
}
 
353
 
 
354
static int conn_free(BIO *a)
 
355
{
 
356
    BIO_CONNECT *data;
 
357
 
 
358
    if (a == NULL)
 
359
        return (0);
 
360
    data = (BIO_CONNECT *)a->ptr;
 
361
 
 
362
    if (a->shutdown) {
 
363
        conn_close_socket(a);
 
364
        BIO_CONNECT_free(data);
 
365
        a->ptr = NULL;
 
366
        a->flags = 0;
 
367
        a->init = 0;
 
368
    }
 
369
    return (1);
 
370
}
 
371
 
 
372
static int conn_read(BIO *b, char *out, int outl)
 
373
{
 
374
    int ret = 0;
 
375
    BIO_CONNECT *data;
 
376
 
 
377
    data = (BIO_CONNECT *)b->ptr;
 
378
    if (data->state != BIO_CONN_S_OK) {
 
379
        ret = conn_state(b, data);
 
380
        if (ret <= 0)
 
381
            return (ret);
 
382
    }
 
383
 
 
384
    if (out != NULL) {
 
385
        clear_socket_error();
 
386
        ret = readsocket(b->num, out, outl);
 
387
        BIO_clear_retry_flags(b);
 
388
        if (ret <= 0) {
 
389
            if (BIO_sock_should_retry(ret))
 
390
                BIO_set_retry_read(b);
 
391
        }
 
392
    }
 
393
    return (ret);
 
394
}
 
395
 
 
396
static int conn_write(BIO *b, const char *in, int inl)
 
397
{
 
398
    int ret;
 
399
    BIO_CONNECT *data;
 
400
 
 
401
    data = (BIO_CONNECT *)b->ptr;
 
402
    if (data->state != BIO_CONN_S_OK) {
 
403
        ret = conn_state(b, data);
 
404
        if (ret <= 0)
 
405
            return (ret);
 
406
    }
 
407
 
 
408
    clear_socket_error();
 
409
    ret = writesocket(b->num, in, inl);
 
410
    BIO_clear_retry_flags(b);
 
411
    if (ret <= 0) {
 
412
        if (BIO_sock_should_retry(ret))
 
413
            BIO_set_retry_write(b);
 
414
    }
 
415
    return (ret);
 
416
}
 
417
 
 
418
static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
 
419
{
 
420
    BIO *dbio;
 
421
    int *ip;
 
422
    const char **pptr = NULL;
 
423
    long ret = 1;
 
424
    BIO_CONNECT *data;
 
425
 
 
426
    data = (BIO_CONNECT *)b->ptr;
 
427
 
 
428
    switch (cmd) {
 
429
    case BIO_CTRL_RESET:
 
430
        ret = 0;
 
431
        data->state = BIO_CONN_S_BEFORE;
 
432
        conn_close_socket(b);
 
433
        b->flags = 0;
 
434
        break;
 
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);
 
439
        else
 
440
            ret = 1;
 
441
        break;
 
442
    case BIO_C_GET_CONNECT:
 
443
        if (ptr != NULL) {
 
444
            pptr = (const char **)ptr;
 
445
        }
 
446
 
 
447
        if (b->init) {
 
448
            if (pptr != NULL) {
 
449
                ret = 1;
 
450
                if (num == 0) {
 
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]);
 
456
                } else {
 
457
                    ret = 0;
 
458
                }
 
459
            }
 
460
            if (num == 3) {
 
461
                ret = data->port;
 
462
            }
 
463
        } else {
 
464
            if (pptr != NULL)
 
465
                *pptr = "not initialized";
 
466
            ret = 0;
 
467
        }
 
468
        break;
 
469
    case BIO_C_SET_CONNECT:
 
470
        if (ptr != NULL) {
 
471
            b->init = 1;
 
472
            if (num == 0) {
 
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) {
 
481
                char buf[16];
 
482
                unsigned char *p = ptr;
 
483
 
 
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];
 
492
 
 
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;
 
498
            }
 
499
        }
 
500
        break;
 
501
    case BIO_C_SET_NBIO:
 
502
        data->nbio = (int)num;
 
503
        break;
 
504
    case BIO_C_GET_FD:
 
505
        if (b->init) {
 
506
            ip = (int *)ptr;
 
507
            if (ip != NULL)
 
508
                *ip = b->num;
 
509
            ret = b->num;
 
510
        } else
 
511
            ret = -1;
 
512
        break;
 
513
    case BIO_CTRL_GET_CLOSE:
 
514
        ret = b->shutdown;
 
515
        break;
 
516
    case BIO_CTRL_SET_CLOSE:
 
517
        b->shutdown = (int)num;
 
518
        break;
 
519
    case BIO_CTRL_PENDING:
 
520
    case BIO_CTRL_WPENDING:
 
521
        ret = 0;
 
522
        break;
 
523
    case BIO_CTRL_FLUSH:
 
524
        break;
 
525
    case BIO_CTRL_DUP:
 
526
        {
 
527
            dbio = (BIO *)ptr;
 
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);
 
533
            /*
 
534
             * FIXME: the cast of the function seems unlikely to be a good
 
535
             * idea
 
536
             */
 
537
            (void)BIO_set_info_callback(dbio,
 
538
                                        (bio_info_cb *)data->info_callback);
 
539
        }
 
540
        break;
 
541
    case BIO_CTRL_SET_CALLBACK:
 
542
        {
 
543
# if 0                          /* FIXME: Should this be used? -- Richard
 
544
                                 * Levitte */
 
545
            BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
 
546
            ret = -1;
 
547
# else
 
548
            ret = 0;
 
549
# endif
 
550
        }
 
551
        break;
 
552
    case BIO_CTRL_GET_CALLBACK:
 
553
        {
 
554
            int (**fptr) (const BIO *bio, int state, int xret);
 
555
 
 
556
            fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
 
557
            *fptr = data->info_callback;
 
558
        }
 
559
        break;
 
560
    default:
 
561
        ret = 0;
 
562
        break;
 
563
    }
 
564
    return (ret);
 
565
}
 
566
 
 
567
static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
 
568
{
 
569
    long ret = 1;
 
570
    BIO_CONNECT *data;
 
571
 
 
572
    data = (BIO_CONNECT *)b->ptr;
 
573
 
 
574
    switch (cmd) {
 
575
    case BIO_CTRL_SET_CALLBACK:
 
576
        {
 
577
            data->info_callback =
 
578
                (int (*)(const struct bio_st *, int, int))fp;
 
579
        }
 
580
        break;
 
581
    default:
 
582
        ret = 0;
 
583
        break;
 
584
    }
 
585
    return (ret);
 
586
}
 
587
 
 
588
static int conn_puts(BIO *bp, const char *str)
 
589
{
 
590
    int n, ret;
 
591
 
 
592
    n = strlen(str);
 
593
    ret = conn_write(bp, str, n);
 
594
    return (ret);
 
595
}
 
596
 
 
597
BIO *BIO_new_connect(const char *str)
 
598
{
 
599
    BIO *ret;
 
600
 
 
601
    ret = BIO_new(BIO_s_connect());
 
602
    if (ret == NULL)
 
603
        return (NULL);
 
604
    if (BIO_set_conn_hostname(ret, str))
 
605
        return (ret);
 
606
    else {
 
607
        BIO_free(ret);
 
608
        return (NULL);
 
609
    }
 
610
}
 
611
 
 
612
#endif