/src/openssl/crypto/bio/bss_conn.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | # 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 | 0 | { |
126 | 0 | int ret = -1, i; |
127 | 0 | unsigned long l; |
128 | 0 | char *p, *q; |
129 | 0 | int (*cb) (const BIO *, int, int) = NULL; |
130 | |
|
131 | 0 | if (c->info_callback != NULL) |
132 | 0 | cb = c->info_callback; |
133 | |
|
134 | 0 | for (;;) { |
135 | 0 | switch (c->state) { |
136 | 0 | case BIO_CONN_S_BEFORE: |
137 | 0 | p = c->param_hostname; |
138 | 0 | if (p == NULL) { |
139 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_SPECIFIED); |
140 | 0 | goto exit_loop; |
141 | 0 | } |
142 | 0 | for (; *p != '\0'; p++) { |
143 | 0 | if ((*p == ':') || (*p == '/')) |
144 | 0 | break; |
145 | 0 | } |
146 | |
|
147 | 0 | i = *p; |
148 | 0 | if ((i == ':') || (i == '/')) { |
149 | |
|
150 | 0 | *(p++) = '\0'; |
151 | 0 | if (i == ':') { |
152 | 0 | for (q = p; *q; q++) |
153 | 0 | if (*q == '/') { |
154 | 0 | *q = '\0'; |
155 | 0 | break; |
156 | 0 | } |
157 | 0 | if (c->param_port != NULL) |
158 | 0 | OPENSSL_free(c->param_port); |
159 | 0 | c->param_port = BUF_strdup(p); |
160 | 0 | } |
161 | 0 | } |
162 | |
|
163 | 0 | if (c->param_port == NULL) { |
164 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_NO_PORT_SPECIFIED); |
165 | 0 | ERR_add_error_data(2, "host=", c->param_hostname); |
166 | 0 | goto exit_loop; |
167 | 0 | } |
168 | 0 | c->state = BIO_CONN_S_GET_IP; |
169 | 0 | break; |
170 | | |
171 | 0 | case BIO_CONN_S_GET_IP: |
172 | 0 | if (BIO_get_host_ip(c->param_hostname, &(c->ip[0])) <= 0) |
173 | 0 | goto exit_loop; |
174 | 0 | c->state = BIO_CONN_S_GET_PORT; |
175 | 0 | break; |
176 | | |
177 | 0 | case BIO_CONN_S_GET_PORT: |
178 | 0 | if (c->param_port == NULL) { |
179 | | /* abort(); */ |
180 | 0 | goto exit_loop; |
181 | 0 | } else if (BIO_get_port(c->param_port, &c->port) <= 0) |
182 | 0 | goto exit_loop; |
183 | 0 | c->state = BIO_CONN_S_CREATE_SOCKET; |
184 | 0 | break; |
185 | | |
186 | 0 | case BIO_CONN_S_CREATE_SOCKET: |
187 | | /* now setup address */ |
188 | 0 | memset((char *)&c->them, 0, sizeof(c->them)); |
189 | 0 | c->them.sin_family = AF_INET; |
190 | 0 | c->them.sin_port = htons((unsigned short)c->port); |
191 | 0 | l = (unsigned long) |
192 | 0 | ((unsigned long)c->ip[0] << 24L) | |
193 | 0 | ((unsigned long)c->ip[1] << 16L) | |
194 | 0 | ((unsigned long)c->ip[2] << 8L) | ((unsigned long)c->ip[3]); |
195 | 0 | c->them.sin_addr.s_addr = htonl(l); |
196 | 0 | c->state = BIO_CONN_S_CREATE_SOCKET; |
197 | |
|
198 | 0 | ret = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL); |
199 | 0 | if (ret == INVALID_SOCKET) { |
200 | 0 | SYSerr(SYS_F_SOCKET, get_last_socket_error()); |
201 | 0 | ERR_add_error_data(4, "host=", c->param_hostname, |
202 | 0 | ":", c->param_port); |
203 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); |
204 | 0 | goto exit_loop; |
205 | 0 | } |
206 | 0 | b->num = ret; |
207 | 0 | c->state = BIO_CONN_S_NBIO; |
208 | 0 | break; |
209 | | |
210 | 0 | case BIO_CONN_S_NBIO: |
211 | 0 | if (c->nbio) { |
212 | 0 | if (!BIO_socket_nbio(b->num, 1)) { |
213 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_ERROR_SETTING_NBIO); |
214 | 0 | ERR_add_error_data(4, "host=", |
215 | 0 | c->param_hostname, ":", c->param_port); |
216 | 0 | goto exit_loop; |
217 | 0 | } |
218 | 0 | } |
219 | 0 | c->state = BIO_CONN_S_CONNECT; |
220 | |
|
221 | 0 | # if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) |
222 | 0 | i = 1; |
223 | 0 | i = setsockopt(b->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, |
224 | 0 | sizeof(i)); |
225 | 0 | if (i < 0) { |
226 | 0 | SYSerr(SYS_F_SOCKET, get_last_socket_error()); |
227 | 0 | ERR_add_error_data(4, "host=", c->param_hostname, |
228 | 0 | ":", c->param_port); |
229 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_KEEPALIVE); |
230 | 0 | goto exit_loop; |
231 | 0 | } |
232 | 0 | # endif |
233 | 0 | break; |
234 | | |
235 | 0 | case BIO_CONN_S_CONNECT: |
236 | 0 | BIO_clear_retry_flags(b); |
237 | 0 | ret = connect(b->num, |
238 | 0 | (struct sockaddr *)&c->them, sizeof(c->them)); |
239 | 0 | b->retry_reason = 0; |
240 | 0 | if (ret < 0) { |
241 | 0 | if (BIO_sock_should_retry(ret)) { |
242 | 0 | BIO_set_retry_special(b); |
243 | 0 | c->state = BIO_CONN_S_BLOCKED_CONNECT; |
244 | 0 | b->retry_reason = BIO_RR_CONNECT; |
245 | 0 | } else { |
246 | 0 | SYSerr(SYS_F_CONNECT, get_last_socket_error()); |
247 | 0 | ERR_add_error_data(4, "host=", |
248 | 0 | c->param_hostname, ":", c->param_port); |
249 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR); |
250 | 0 | } |
251 | 0 | goto exit_loop; |
252 | 0 | } else |
253 | 0 | c->state = BIO_CONN_S_OK; |
254 | 0 | break; |
255 | | |
256 | 0 | case BIO_CONN_S_BLOCKED_CONNECT: |
257 | 0 | i = BIO_sock_error(b->num); |
258 | 0 | if (i) { |
259 | 0 | BIO_clear_retry_flags(b); |
260 | 0 | SYSerr(SYS_F_CONNECT, i); |
261 | 0 | ERR_add_error_data(4, "host=", |
262 | 0 | c->param_hostname, ":", c->param_port); |
263 | 0 | BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR); |
264 | 0 | ret = 0; |
265 | 0 | goto exit_loop; |
266 | 0 | } else |
267 | 0 | c->state = BIO_CONN_S_OK; |
268 | 0 | break; |
269 | | |
270 | 0 | case BIO_CONN_S_OK: |
271 | 0 | ret = 1; |
272 | 0 | goto exit_loop; |
273 | 0 | default: |
274 | | /* abort(); */ |
275 | 0 | goto exit_loop; |
276 | 0 | } |
277 | | |
278 | 0 | if (cb != NULL) { |
279 | 0 | if (!(ret = cb((BIO *)b, c->state, ret))) |
280 | 0 | goto end; |
281 | 0 | } |
282 | 0 | } |
283 | | |
284 | | /* Loop does not exit */ |
285 | 0 | exit_loop: |
286 | 0 | if (cb != NULL) |
287 | 0 | ret = cb((BIO *)b, c->state, ret); |
288 | 0 | end: |
289 | 0 | return (ret); |
290 | 0 | } |
291 | | |
292 | | BIO_CONNECT *BIO_CONNECT_new(void) |
293 | 0 | { |
294 | 0 | BIO_CONNECT *ret; |
295 | |
|
296 | 0 | if ((ret = (BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL) |
297 | 0 | return (NULL); |
298 | 0 | ret->state = BIO_CONN_S_BEFORE; |
299 | 0 | ret->param_hostname = NULL; |
300 | 0 | ret->param_port = NULL; |
301 | 0 | ret->info_callback = NULL; |
302 | 0 | ret->nbio = 0; |
303 | 0 | ret->ip[0] = 0; |
304 | 0 | ret->ip[1] = 0; |
305 | 0 | ret->ip[2] = 0; |
306 | 0 | ret->ip[3] = 0; |
307 | 0 | ret->port = 0; |
308 | 0 | memset((char *)&ret->them, 0, sizeof(ret->them)); |
309 | 0 | return (ret); |
310 | 0 | } |
311 | | |
312 | | void BIO_CONNECT_free(BIO_CONNECT *a) |
313 | 0 | { |
314 | 0 | if (a == NULL) |
315 | 0 | return; |
316 | | |
317 | 0 | if (a->param_hostname != NULL) |
318 | 0 | OPENSSL_free(a->param_hostname); |
319 | 0 | if (a->param_port != NULL) |
320 | 0 | OPENSSL_free(a->param_port); |
321 | 0 | OPENSSL_free(a); |
322 | 0 | } |
323 | | |
324 | | BIO_METHOD *BIO_s_connect(void) |
325 | 0 | { |
326 | 0 | return (&methods_connectp); |
327 | 0 | } |
328 | | |
329 | | static int conn_new(BIO *bi) |
330 | 0 | { |
331 | 0 | bi->init = 0; |
332 | 0 | bi->num = INVALID_SOCKET; |
333 | 0 | bi->flags = 0; |
334 | 0 | if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL) |
335 | 0 | return (0); |
336 | 0 | else |
337 | 0 | return (1); |
338 | 0 | } |
339 | | |
340 | | static void conn_close_socket(BIO *bio) |
341 | 0 | { |
342 | 0 | BIO_CONNECT *c; |
343 | |
|
344 | 0 | c = (BIO_CONNECT *)bio->ptr; |
345 | 0 | if (bio->num != INVALID_SOCKET) { |
346 | | /* Only do a shutdown if things were established */ |
347 | 0 | if (c->state == BIO_CONN_S_OK) |
348 | 0 | shutdown(bio->num, 2); |
349 | 0 | closesocket(bio->num); |
350 | 0 | bio->num = INVALID_SOCKET; |
351 | 0 | } |
352 | 0 | } |
353 | | |
354 | | static int conn_free(BIO *a) |
355 | 0 | { |
356 | 0 | BIO_CONNECT *data; |
357 | |
|
358 | 0 | if (a == NULL) |
359 | 0 | return (0); |
360 | 0 | data = (BIO_CONNECT *)a->ptr; |
361 | |
|
362 | 0 | if (a->shutdown) { |
363 | 0 | conn_close_socket(a); |
364 | 0 | BIO_CONNECT_free(data); |
365 | 0 | a->ptr = NULL; |
366 | 0 | a->flags = 0; |
367 | 0 | a->init = 0; |
368 | 0 | } |
369 | 0 | return (1); |
370 | 0 | } |
371 | | |
372 | | static int conn_read(BIO *b, char *out, int outl) |
373 | 0 | { |
374 | 0 | int ret = 0; |
375 | 0 | BIO_CONNECT *data; |
376 | |
|
377 | 0 | data = (BIO_CONNECT *)b->ptr; |
378 | 0 | if (data->state != BIO_CONN_S_OK) { |
379 | 0 | ret = conn_state(b, data); |
380 | 0 | if (ret <= 0) |
381 | 0 | return (ret); |
382 | 0 | } |
383 | | |
384 | 0 | if (out != NULL) { |
385 | 0 | clear_socket_error(); |
386 | 0 | ret = readsocket(b->num, out, outl); |
387 | 0 | BIO_clear_retry_flags(b); |
388 | 0 | if (ret <= 0) { |
389 | 0 | if (BIO_sock_should_retry(ret)) |
390 | 0 | BIO_set_retry_read(b); |
391 | 0 | } |
392 | 0 | } |
393 | 0 | return (ret); |
394 | 0 | } |
395 | | |
396 | | static int conn_write(BIO *b, const char *in, int inl) |
397 | 0 | { |
398 | 0 | int ret; |
399 | 0 | BIO_CONNECT *data; |
400 | |
|
401 | 0 | data = (BIO_CONNECT *)b->ptr; |
402 | 0 | if (data->state != BIO_CONN_S_OK) { |
403 | 0 | ret = conn_state(b, data); |
404 | 0 | if (ret <= 0) |
405 | 0 | return (ret); |
406 | 0 | } |
407 | | |
408 | 0 | clear_socket_error(); |
409 | 0 | ret = writesocket(b->num, in, inl); |
410 | 0 | BIO_clear_retry_flags(b); |
411 | 0 | if (ret <= 0) { |
412 | 0 | if (BIO_sock_should_retry(ret)) |
413 | 0 | BIO_set_retry_write(b); |
414 | 0 | } |
415 | 0 | return (ret); |
416 | 0 | } |
417 | | |
418 | | static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) |
419 | 0 | { |
420 | 0 | BIO *dbio; |
421 | 0 | int *ip; |
422 | 0 | const char **pptr = NULL; |
423 | 0 | long ret = 1; |
424 | 0 | BIO_CONNECT *data; |
425 | |
|
426 | 0 | data = (BIO_CONNECT *)b->ptr; |
427 | |
|
428 | 0 | switch (cmd) { |
429 | 0 | case BIO_CTRL_RESET: |
430 | 0 | ret = 0; |
431 | 0 | data->state = BIO_CONN_S_BEFORE; |
432 | 0 | conn_close_socket(b); |
433 | 0 | b->flags = 0; |
434 | 0 | break; |
435 | 0 | case BIO_C_DO_STATE_MACHINE: |
436 | | /* use this one to start the connection */ |
437 | 0 | if (data->state != BIO_CONN_S_OK) |
438 | 0 | ret = (long)conn_state(b, data); |
439 | 0 | else |
440 | 0 | ret = 1; |
441 | 0 | break; |
442 | 0 | case BIO_C_GET_CONNECT: |
443 | 0 | if (ptr != NULL) { |
444 | 0 | pptr = (const char **)ptr; |
445 | 0 | } |
446 | |
|
447 | 0 | if (b->init) { |
448 | 0 | if (pptr != NULL) { |
449 | 0 | ret = 1; |
450 | 0 | if (num == 0) { |
451 | 0 | *pptr = data->param_hostname; |
452 | 0 | } else if (num == 1) { |
453 | 0 | *pptr = data->param_port; |
454 | 0 | } else if (num == 2) { |
455 | 0 | *pptr = (char *)&(data->ip[0]); |
456 | 0 | } else { |
457 | 0 | ret = 0; |
458 | 0 | } |
459 | 0 | } |
460 | 0 | if (num == 3) { |
461 | 0 | ret = data->port; |
462 | 0 | } |
463 | 0 | } else { |
464 | 0 | if (pptr != NULL) |
465 | 0 | *pptr = "not initialized"; |
466 | 0 | ret = 0; |
467 | 0 | } |
468 | 0 | break; |
469 | 0 | case BIO_C_SET_CONNECT: |
470 | 0 | if (ptr != NULL) { |
471 | 0 | b->init = 1; |
472 | 0 | if (num == 0) { |
473 | 0 | if (data->param_hostname != NULL) |
474 | 0 | OPENSSL_free(data->param_hostname); |
475 | 0 | data->param_hostname = BUF_strdup(ptr); |
476 | 0 | } else if (num == 1) { |
477 | 0 | if (data->param_port != NULL) |
478 | 0 | OPENSSL_free(data->param_port); |
479 | 0 | data->param_port = BUF_strdup(ptr); |
480 | 0 | } else if (num == 2) { |
481 | 0 | char buf[16]; |
482 | 0 | unsigned char *p = ptr; |
483 | |
|
484 | 0 | BIO_snprintf(buf, sizeof buf, "%d.%d.%d.%d", |
485 | 0 | p[0], p[1], p[2], p[3]); |
486 | 0 | if (data->param_hostname != NULL) |
487 | 0 | OPENSSL_free(data->param_hostname); |
488 | 0 | data->param_hostname = BUF_strdup(buf); |
489 | 0 | memcpy(&(data->ip[0]), ptr, 4); |
490 | 0 | } else if (num == 3) { |
491 | 0 | char buf[DECIMAL_SIZE(int) + 1]; |
492 | |
|
493 | 0 | BIO_snprintf(buf, sizeof buf, "%d", *(int *)ptr); |
494 | 0 | if (data->param_port != NULL) |
495 | 0 | OPENSSL_free(data->param_port); |
496 | 0 | data->param_port = BUF_strdup(buf); |
497 | 0 | data->port = *(int *)ptr; |
498 | 0 | } |
499 | 0 | } |
500 | 0 | break; |
501 | 0 | case BIO_C_SET_NBIO: |
502 | 0 | data->nbio = (int)num; |
503 | 0 | break; |
504 | 0 | case BIO_C_GET_FD: |
505 | 0 | if (b->init) { |
506 | 0 | ip = (int *)ptr; |
507 | 0 | if (ip != NULL) |
508 | 0 | *ip = b->num; |
509 | 0 | ret = b->num; |
510 | 0 | } else |
511 | 0 | ret = -1; |
512 | 0 | break; |
513 | 0 | case BIO_CTRL_GET_CLOSE: |
514 | 0 | ret = b->shutdown; |
515 | 0 | break; |
516 | 0 | case BIO_CTRL_SET_CLOSE: |
517 | 0 | b->shutdown = (int)num; |
518 | 0 | break; |
519 | 0 | case BIO_CTRL_PENDING: |
520 | 0 | case BIO_CTRL_WPENDING: |
521 | 0 | ret = 0; |
522 | 0 | break; |
523 | 0 | case BIO_CTRL_FLUSH: |
524 | 0 | break; |
525 | 0 | case BIO_CTRL_DUP: |
526 | 0 | { |
527 | 0 | dbio = (BIO *)ptr; |
528 | 0 | if (data->param_port) |
529 | 0 | BIO_set_conn_port(dbio, data->param_port); |
530 | 0 | if (data->param_hostname) |
531 | 0 | BIO_set_conn_hostname(dbio, data->param_hostname); |
532 | 0 | BIO_set_nbio(dbio, data->nbio); |
533 | | /* |
534 | | * FIXME: the cast of the function seems unlikely to be a good |
535 | | * idea |
536 | | */ |
537 | 0 | (void)BIO_set_info_callback(dbio, |
538 | 0 | (bio_info_cb *)data->info_callback); |
539 | 0 | } |
540 | 0 | break; |
541 | 0 | case BIO_CTRL_SET_CALLBACK: |
542 | 0 | { |
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 | 0 | ret = 0; |
549 | 0 | # endif |
550 | 0 | } |
551 | 0 | break; |
552 | 0 | case BIO_CTRL_GET_CALLBACK: |
553 | 0 | { |
554 | 0 | int (**fptr) (const BIO *bio, int state, int xret); |
555 | |
|
556 | 0 | fptr = (int (**)(const BIO *bio, int state, int xret))ptr; |
557 | 0 | *fptr = data->info_callback; |
558 | 0 | } |
559 | 0 | break; |
560 | 0 | default: |
561 | 0 | ret = 0; |
562 | 0 | break; |
563 | 0 | } |
564 | 0 | return (ret); |
565 | 0 | } |
566 | | |
567 | | static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) |
568 | 0 | { |
569 | 0 | long ret = 1; |
570 | 0 | BIO_CONNECT *data; |
571 | |
|
572 | 0 | data = (BIO_CONNECT *)b->ptr; |
573 | |
|
574 | 0 | switch (cmd) { |
575 | 0 | case BIO_CTRL_SET_CALLBACK: |
576 | 0 | { |
577 | 0 | data->info_callback = |
578 | 0 | (int (*)(const struct bio_st *, int, int))fp; |
579 | 0 | } |
580 | 0 | break; |
581 | 0 | default: |
582 | 0 | ret = 0; |
583 | 0 | break; |
584 | 0 | } |
585 | 0 | return (ret); |
586 | 0 | } |
587 | | |
588 | | static int conn_puts(BIO *bp, const char *str) |
589 | 0 | { |
590 | 0 | int n, ret; |
591 | |
|
592 | 0 | n = strlen(str); |
593 | 0 | ret = conn_write(bp, str, n); |
594 | 0 | return (ret); |
595 | 0 | } |
596 | | |
597 | | BIO *BIO_new_connect(const char *str) |
598 | 0 | { |
599 | 0 | BIO *ret; |
600 | |
|
601 | 0 | ret = BIO_new(BIO_s_connect()); |
602 | 0 | if (ret == NULL) |
603 | 0 | return (NULL); |
604 | 0 | if (BIO_set_conn_hostname(ret, str)) |
605 | 0 | return (ret); |
606 | 0 | else { |
607 | 0 | BIO_free(ret); |
608 | 0 | return (NULL); |
609 | 0 | } |
610 | 0 | } |
611 | | |
612 | | #endif |