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.]
63 #ifndef OPENSSL_NO_SOCK
65 typedef struct bio_connect_st
{
72 BIO_ADDRINFO
*addr_first
;
73 const BIO_ADDRINFO
*addr_iter
;
75 * int socket; this will be kept in bio->num so that it is compatible
76 * with the bss_sock bio
79 * called when the connection is initially made callback(BIO,state,ret);
80 * The callback should return 'ret'. state is for compatibility with the
83 int (*info_callback
) (const BIO
*bio
, int state
, int ret
);
86 static int conn_write(BIO
*h
, const char *buf
, int num
);
87 static int conn_read(BIO
*h
, char *buf
, int size
);
88 static int conn_puts(BIO
*h
, const char *str
);
89 static long conn_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
90 static int conn_new(BIO
*h
);
91 static int conn_free(BIO
*data
);
92 static long conn_callback_ctrl(BIO
*h
, int cmd
, bio_info_cb
*);
94 static int conn_state(BIO
*b
, BIO_CONNECT
*c
);
95 static void conn_close_socket(BIO
*data
);
96 BIO_CONNECT
*BIO_CONNECT_new(void);
97 void BIO_CONNECT_free(BIO_CONNECT
*a
);
99 #define BIO_CONN_S_BEFORE 1
100 #define BIO_CONN_S_GET_ADDR 2
101 #define BIO_CONN_S_CREATE_SOCKET 3
102 #define BIO_CONN_S_CONNECT 4
103 #define BIO_CONN_S_OK 5
104 #define BIO_CONN_S_BLOCKED_CONNECT 6
106 static const BIO_METHOD methods_connectp
= {
112 NULL
, /* connect_gets, */
119 static int conn_state(BIO
*b
, BIO_CONNECT
*c
)
122 int (*cb
) (const BIO
*, int, int) = NULL
;
124 if (c
->info_callback
!= NULL
)
125 cb
= c
->info_callback
;
129 case BIO_CONN_S_BEFORE
:
130 if (c
->param_hostname
== NULL
&& c
->param_service
== NULL
) {
131 BIOerr(BIO_F_CONN_STATE
, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED
);
132 ERR_add_error_data(4,
133 "hostname=", c
->param_hostname
,
134 " service=", c
->param_service
);
137 c
->state
= BIO_CONN_S_GET_ADDR
;
140 case BIO_CONN_S_GET_ADDR
:
142 int family
= AF_UNSPEC
;
143 switch (c
->connect_family
) {
144 case BIO_FAMILY_IPV6
:
145 if (1) { /* This is a trick we use to avoid bit rot.
146 * at least the "else" part will always be
153 BIOerr(BIO_F_CONN_STATE
, BIO_R_UNAVAILABLE_IP_FAMILY
);
157 case BIO_FAMILY_IPV4
:
160 case BIO_FAMILY_IPANY
:
164 BIOerr(BIO_F_CONN_STATE
, BIO_R_UNSUPPORTED_IP_FAMILY
);
167 if (BIO_lookup(c
->param_hostname
, c
->param_service
,
169 family
, SOCK_STREAM
, &c
->addr_first
) == 0)
172 if (c
->addr_first
== NULL
) {
173 BIOerr(BIO_F_CONN_STATE
, BIO_R_LOOKUP_RETURNED_NOTHING
);
176 c
->addr_iter
= c
->addr_first
;
177 c
->state
= BIO_CONN_S_CREATE_SOCKET
;
180 case BIO_CONN_S_CREATE_SOCKET
:
181 ret
= BIO_socket(BIO_ADDRINFO_family(c
->addr_iter
),
182 BIO_ADDRINFO_socktype(c
->addr_iter
),
183 BIO_ADDRINFO_protocol(c
->addr_iter
), 0);
184 if (ret
== (int)INVALID_SOCKET
) {
185 SYSerr(SYS_F_SOCKET
, get_last_socket_error());
186 ERR_add_error_data(4,
187 "hostname=", c
->param_hostname
,
188 " service=", c
->param_service
);
189 BIOerr(BIO_F_CONN_STATE
, BIO_R_UNABLE_TO_CREATE_SOCKET
);
193 c
->state
= BIO_CONN_S_CONNECT
;
196 case BIO_CONN_S_CONNECT
:
197 BIO_clear_retry_flags(b
);
198 ret
= BIO_connect(b
->num
, BIO_ADDRINFO_address(c
->addr_iter
),
199 BIO_SOCK_KEEPALIVE
| c
->connect_mode
);
202 if (BIO_sock_should_retry(ret
)) {
203 BIO_set_retry_special(b
);
204 c
->state
= BIO_CONN_S_BLOCKED_CONNECT
;
205 b
->retry_reason
= BIO_RR_CONNECT
;
207 } else if ((c
->addr_iter
= BIO_ADDRINFO_next(c
->addr_iter
))
210 * if there are more addresses to try, do that first
212 BIO_closesocket(b
->num
);
213 c
->state
= BIO_CONN_S_CREATE_SOCKET
;
217 SYSerr(SYS_F_CONNECT
, get_last_socket_error());
218 ERR_add_error_data(4,
219 "hostname=", c
->param_hostname
,
220 " service=", c
->param_service
);
221 BIOerr(BIO_F_CONN_STATE
, BIO_R_CONNECT_ERROR
);
225 c
->state
= BIO_CONN_S_OK
;
229 case BIO_CONN_S_BLOCKED_CONNECT
:
230 i
= BIO_sock_error(b
->num
);
232 BIO_clear_retry_flags(b
);
233 SYSerr(SYS_F_CONNECT
, i
);
234 ERR_add_error_data(4,
235 "hostname=", c
->param_hostname
,
236 " service=", c
->param_service
);
237 BIOerr(BIO_F_CONN_STATE
, BIO_R_NBIO_CONNECT_ERROR
);
241 c
->state
= BIO_CONN_S_OK
;
253 if ((ret
= cb((BIO
*)b
, c
->state
, ret
)) == 0)
258 /* Loop does not exit */
261 ret
= cb((BIO
*)b
, c
->state
, ret
);
266 BIO_CONNECT
*BIO_CONNECT_new(void)
270 if ((ret
= OPENSSL_zalloc(sizeof(*ret
))) == NULL
)
272 ret
->state
= BIO_CONN_S_BEFORE
;
273 ret
->connect_family
= BIO_FAMILY_IPANY
;
277 void BIO_CONNECT_free(BIO_CONNECT
*a
)
282 OPENSSL_free(a
->param_hostname
);
283 OPENSSL_free(a
->param_service
);
284 BIO_ADDRINFO_free(a
->addr_first
);
288 const BIO_METHOD
*BIO_s_connect(void)
290 return (&methods_connectp
);
293 static int conn_new(BIO
*bi
)
296 bi
->num
= (int)INVALID_SOCKET
;
298 if ((bi
->ptr
= (char *)BIO_CONNECT_new()) == NULL
)
304 static void conn_close_socket(BIO
*bio
)
308 c
= (BIO_CONNECT
*)bio
->ptr
;
309 if (bio
->num
!= (int)INVALID_SOCKET
) {
310 /* Only do a shutdown if things were established */
311 if (c
->state
== BIO_CONN_S_OK
)
312 shutdown(bio
->num
, 2);
313 BIO_closesocket(bio
->num
);
314 bio
->num
= (int)INVALID_SOCKET
;
318 static int conn_free(BIO
*a
)
324 data
= (BIO_CONNECT
*)a
->ptr
;
327 conn_close_socket(a
);
328 BIO_CONNECT_free(data
);
336 static int conn_read(BIO
*b
, char *out
, int outl
)
341 data
= (BIO_CONNECT
*)b
->ptr
;
342 if (data
->state
!= BIO_CONN_S_OK
) {
343 ret
= conn_state(b
, data
);
349 clear_socket_error();
350 ret
= readsocket(b
->num
, out
, outl
);
351 BIO_clear_retry_flags(b
);
353 if (BIO_sock_should_retry(ret
))
354 BIO_set_retry_read(b
);
360 static int conn_write(BIO
*b
, const char *in
, int inl
)
365 data
= (BIO_CONNECT
*)b
->ptr
;
366 if (data
->state
!= BIO_CONN_S_OK
) {
367 ret
= conn_state(b
, data
);
372 clear_socket_error();
373 ret
= writesocket(b
->num
, in
, inl
);
374 BIO_clear_retry_flags(b
);
376 if (BIO_sock_should_retry(ret
))
377 BIO_set_retry_write(b
);
382 static long conn_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
386 const char **pptr
= NULL
;
390 data
= (BIO_CONNECT
*)b
->ptr
;
395 data
->state
= BIO_CONN_S_BEFORE
;
396 conn_close_socket(b
);
397 BIO_ADDRINFO_free(data
->addr_first
);
398 data
->addr_first
= NULL
;
401 case BIO_C_DO_STATE_MACHINE
:
402 /* use this one to start the connection */
403 if (data
->state
!= BIO_CONN_S_OK
)
404 ret
= (long)conn_state(b
, data
);
408 case BIO_C_GET_CONNECT
:
410 pptr
= (const char **)ptr
;
412 *pptr
= data
->param_hostname
;
413 } else if (num
== 1) {
414 *pptr
= data
->param_service
;
415 } else if (num
== 2) {
416 *pptr
= (const char *)BIO_ADDRINFO_address(data
->addr_iter
);
417 } else if (num
== 3) {
418 switch (BIO_ADDRINFO_family(data
->addr_iter
)) {
421 ret
= BIO_FAMILY_IPV6
;
425 ret
= BIO_FAMILY_IPV4
;
428 ret
= data
->connect_family
;
441 case BIO_C_SET_CONNECT
:
445 char *hold_service
= data
->param_service
;
446 /* We affect the hostname regardless. However, the input
447 * string might contain a host:service spec, so we must
448 * parse it, which might or might not affect the service
450 OPENSSL_free(data
->param_hostname
);
451 data
->param_hostname
= NULL
;
452 ret
= BIO_parse_hostserv(ptr
,
453 &data
->param_hostname
,
454 &data
->param_service
,
455 BIO_PARSE_PRIO_HOST
);
456 if (hold_service
!= data
->param_service
)
457 OPENSSL_free(hold_service
);
458 } else if (num
== 1) {
459 OPENSSL_free(data
->param_service
);
460 data
->param_service
= BUF_strdup(ptr
);
461 } else if (num
== 2) {
462 const BIO_ADDR
*addr
= (const BIO_ADDR
*)ptr
;
464 data
->param_hostname
= BIO_ADDR_hostname_string(addr
, 1);
465 data
->param_service
= BIO_ADDR_service_string(addr
, 1);
466 BIO_ADDRINFO_free(data
->addr_first
);
467 data
->addr_first
= NULL
;
468 data
->addr_iter
= NULL
;
470 } else if (num
== 3) {
471 data
->connect_family
= *(int *)ptr
;
479 data
->connect_mode
|= BIO_SOCK_NONBLOCK
;
481 data
->connect_mode
&= ~BIO_SOCK_NONBLOCK
;
483 case BIO_C_SET_CONNECT_MODE
:
484 data
->connect_mode
= (int)num
;
495 case BIO_CTRL_GET_CLOSE
:
498 case BIO_CTRL_SET_CLOSE
:
499 b
->shutdown
= (int)num
;
501 case BIO_CTRL_PENDING
:
502 case BIO_CTRL_WPENDING
:
510 if (data
->param_hostname
)
511 BIO_set_conn_hostname(dbio
, data
->param_hostname
);
512 if (data
->param_service
)
513 BIO_set_conn_port(dbio
, data
->param_service
);
514 BIO_set_conn_ip_family(dbio
, data
->connect_family
);
515 BIO_set_conn_mode(dbio
, data
->connect_mode
);
517 * FIXME: the cast of the function seems unlikely to be a good
520 (void)BIO_set_info_callback(dbio
,
521 (bio_info_cb
*)data
->info_callback
);
524 case BIO_CTRL_SET_CALLBACK
:
526 # if 0 /* FIXME: Should this be used? -- Richard
528 BIOerr(BIO_F_CONN_CTRL
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
535 case BIO_CTRL_GET_CALLBACK
:
537 int (**fptr
) (const BIO
*bio
, int state
, int xret
);
539 fptr
= (int (**)(const BIO
*bio
, int state
, int xret
))ptr
;
540 *fptr
= data
->info_callback
;
550 static long conn_callback_ctrl(BIO
*b
, int cmd
, bio_info_cb
*fp
)
555 data
= (BIO_CONNECT
*)b
->ptr
;
558 case BIO_CTRL_SET_CALLBACK
:
560 data
->info_callback
=
561 (int (*)(const struct bio_st
*, int, int))fp
;
571 static int conn_puts(BIO
*bp
, const char *str
)
576 ret
= conn_write(bp
, str
, n
);
580 BIO
*BIO_new_connect(const char *str
)
584 ret
= BIO_new(BIO_s_connect());
587 if (BIO_set_conn_hostname(ret
, str
))