1c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* crypto/bio/bss_conn.c */
2c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * All rights reserved.
4c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
5c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This package is an SSL implementation written
6c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * by Eric Young (eay@cryptsoft.com).
7c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * The implementation was written so as to conform with Netscapes SSL.
8c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
9c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This library is free for commercial and non-commercial use as long as
10c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * the following conditions are aheared to.  The following conditions
11c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * apply to all code found in this distribution, be it the RC4, RSA,
12c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * included with this distribution is covered by the same copyright terms
14c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
16c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Copyright remains Eric Young's, and as such any Copyright notices in
17c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * the code are not to be removed.
18c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * If this package is used in a product, Eric Young should be given attribution
19c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * as the author of the parts of the library used.
20c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This can be in the form of a textual message at program startup or
21c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * in documentation (online or textual) provided with the package.
22c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
23c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Redistribution and use in source and binary forms, with or without
24c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * modification, are permitted provided that the following conditions
25c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * are met:
26c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 1. Redistributions of source code must retain the copyright
27c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer.
28c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
29c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer in the
30c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    documentation and/or other materials provided with the distribution.
31c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 3. All advertising materials mentioning features or use of this software
32c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    must display the following acknowledgement:
33c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes cryptographic software written by
34c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *     Eric Young (eay@cryptsoft.com)"
35c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    The word 'cryptographic' can be left out if the rouines from the library
36c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    being used are not cryptographic related :-).
37c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 4. If you include any Windows specific code (or a derivative thereof) from
38c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    the apps directory (application code) you must include an acknowledgement:
39c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
41c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * SUCH DAMAGE.
52c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
53c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * The licence and distribution terms for any publically available version or
54c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * derivative of this code cannot be changed.  i.e. this code cannot simply be
55c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * copied and put under another distribution licence
56c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * [including the GNU Public Licence.]
57c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
58c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
59c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <stdio.h>
60c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <errno.h>
61c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define USE_SOCKETS
62c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include "cryptlib.h"
63c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/bio.h>
64c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
65c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifndef OPENSSL_NO_SOCK
66c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
67c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#ifdef OPENSSL_SYS_WIN16
68c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
69c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
70c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#define SOCKET_PROTOCOL IPPROTO_TCP
71c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
72c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
73c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
74c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
75c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#undef FIONBIO
76c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
77c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
78c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
79c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgtypedef struct bio_connect_st
80c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
81c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int state;
82c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
83c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	char *param_hostname;
84c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	char *param_port;
85c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int nbio;
86c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
87c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	unsigned char ip[4];
88c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	unsigned short port;
89c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
90c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	struct sockaddr_in them;
91c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
92c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* int socket; this will be kept in bio->num so that it is
93c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * compatible with the bss_sock bio */
94c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
95c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* called when the connection is initially made
96c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 *  callback(BIO,state,ret);  The callback should return
97c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * 'ret'.  state is for compatibility with the ssl info_callback */
98c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int (*info_callback)(const BIO *bio,int state,int ret);
99c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	} BIO_CONNECT;
100c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
101c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_write(BIO *h, const char *buf, int num);
102c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_read(BIO *h, char *buf, int size);
103c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_puts(BIO *h, const char *str);
104c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
105c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_new(BIO *h);
106c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_free(BIO *data);
107c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *);
108c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
109c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_state(BIO *b, BIO_CONNECT *c);
110c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void conn_close_socket(BIO *data);
111c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO_CONNECT *BIO_CONNECT_new(void );
112c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgvoid BIO_CONNECT_free(BIO_CONNECT *a);
113c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
114c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic BIO_METHOD methods_connectp=
115c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
116c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_TYPE_CONNECT,
117c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	"socket connect",
118c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_write,
119c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_read,
120c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_puts,
121c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	NULL, /* connect_gets, */
122c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_ctrl,
123c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_new,
124c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_free,
125c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	conn_callback_ctrl,
126c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	};
127c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
128c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_state(BIO *b, BIO_CONNECT *c)
129c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
130c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret= -1,i;
131c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	unsigned long l;
132c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	char *p,*q;
133c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int (*cb)(const BIO *,int,int)=NULL;
134c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
135c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (c->info_callback != NULL)
136c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		cb=c->info_callback;
137c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
138c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (;;)
139c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
140c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		switch (c->state)
141c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
142c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_BEFORE:
143c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			p=c->param_hostname;
144c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (p == NULL)
145c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
146c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED);
147c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
148c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
149c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			for ( ; *p != '\0'; p++)
150c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
151c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if ((*p == ':') || (*p == '/')) break;
152c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
153c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
154c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			i= *p;
155c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((i == ':') || (i == '/'))
156c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
157c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
158c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*(p++)='\0';
159c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (i == ':')
160c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
161c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					for (q=p; *q; q++)
162c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						if (*q == '/')
163c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							{
164c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							*q='\0';
165c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							break;
166c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org							}
167c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					if (c->param_port != NULL)
168c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						OPENSSL_free(c->param_port);
169c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					c->param_port=BUF_strdup(p);
170c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
171c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
172c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
173c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (c->param_port == NULL)
174c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
175c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
176c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ERR_add_error_data(2,"host=",c->param_hostname);
177c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
178c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
179c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->state=BIO_CONN_S_GET_IP;
180c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
181c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
182c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_GET_IP:
183c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
184c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
185c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->state=BIO_CONN_S_GET_PORT;
186c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
187c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
188c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_GET_PORT:
189c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (c->param_port == NULL)
190c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
191c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				/* abort(); */
192c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
193c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
194c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (BIO_get_port(c->param_port,&c->port) <= 0)
195c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
196c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->state=BIO_CONN_S_CREATE_SOCKET;
197c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
198c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
199c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_CREATE_SOCKET:
200c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* now setup address */
201c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			memset((char *)&c->them,0,sizeof(c->them));
202c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->them.sin_family=AF_INET;
203c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->them.sin_port=htons((unsigned short)c->port);
204c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			l=(unsigned long)
205c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				((unsigned long)c->ip[0]<<24L)|
206c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				((unsigned long)c->ip[1]<<16L)|
207c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				((unsigned long)c->ip[2]<< 8L)|
208c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				((unsigned long)c->ip[3]);
209c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->them.sin_addr.s_addr=htonl(l);
210c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->state=BIO_CONN_S_CREATE_SOCKET;
211c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
212c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
213c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (ret == INVALID_SOCKET)
214c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
215c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				SYSerr(SYS_F_SOCKET,get_last_socket_error());
216c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ERR_add_error_data(4,"host=",c->param_hostname,
217c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					":",c->param_port);
218c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
219c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
220c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
221c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			b->num=ret;
222c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->state=BIO_CONN_S_NBIO;
223c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
224c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
225c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_NBIO:
226c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (c->nbio)
227c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
228c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (!BIO_socket_nbio(b->num,1))
229c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
230c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
231c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					ERR_add_error_data(4,"host=",
232c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						c->param_hostname,
233c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						":",c->param_port);
234c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					goto exit_loop;
235c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
236c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
237c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			c->state=BIO_CONN_S_CONNECT;
238c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
239c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
240c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			i=1;
241c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
242c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (i < 0)
243c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
244c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				SYSerr(SYS_F_SOCKET,get_last_socket_error());
245c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ERR_add_error_data(4,"host=",c->param_hostname,
246c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					":",c->param_port);
247c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE);
248c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
249c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
250c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
251c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
252c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
253c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_CONNECT:
254c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_clear_retry_flags(b);
255c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=connect(b->num,
256c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				(struct sockaddr *)&c->them,
257c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				sizeof(c->them));
258c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			b->retry_reason=0;
259c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (ret < 0)
260c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
261c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (BIO_sock_should_retry(ret))
262c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
263c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					BIO_set_retry_special(b);
264c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					c->state=BIO_CONN_S_BLOCKED_CONNECT;
265c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					b->retry_reason=BIO_RR_CONNECT;
266c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
267c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				else
268c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
269c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					SYSerr(SYS_F_CONNECT,get_last_socket_error());
270c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					ERR_add_error_data(4,"host=",
271c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						c->param_hostname,
272c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org						":",c->param_port);
273c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
274c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
275c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
276c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
277c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else
278c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				c->state=BIO_CONN_S_OK;
279c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
280c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
281c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_BLOCKED_CONNECT:
282c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			i=BIO_sock_error(b->num);
283c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (i)
284c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
285c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_clear_retry_flags(b);
286c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				SYSerr(SYS_F_CONNECT,i);
287c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ERR_add_error_data(4,"host=",
288c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					c->param_hostname,
289c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					":",c->param_port);
290c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
291c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				ret=0;
292c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto exit_loop;
293c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
294c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else
295c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				c->state=BIO_CONN_S_OK;
296c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			break;
297c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
298c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		case BIO_CONN_S_OK:
299c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=1;
300c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto exit_loop;
301c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		default:
302c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			/* abort(); */
303c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto exit_loop;
304c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
305c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
306c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (cb != NULL)
307c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
308c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (!(ret=cb((BIO *)b,c->state,ret)))
309c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				goto end;
310c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
311c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
312c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
313c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Loop does not exit */
314c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgexit_loop:
315c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (cb != NULL)
316c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=cb((BIO *)b,c->state,ret);
317c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgend:
318c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
319c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
320c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
321c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO_CONNECT *BIO_CONNECT_new(void)
322c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
323c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *ret;
324c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
325c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ((ret=(BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL)
326c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(NULL);
327c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->state=BIO_CONN_S_BEFORE;
328c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->param_hostname=NULL;
329c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->param_port=NULL;
330c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->info_callback=NULL;
331c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->nbio=0;
332c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->ip[0]=0;
333c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->ip[1]=0;
334c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->ip[2]=0;
335c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->ip[3]=0;
336c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret->port=0;
337c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	memset((char *)&ret->them,0,sizeof(ret->them));
338c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
339c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
340c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
341c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgvoid BIO_CONNECT_free(BIO_CONNECT *a)
342c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
343c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if(a == NULL)
344c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	    return;
345c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
346c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a->param_hostname != NULL)
347c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		OPENSSL_free(a->param_hostname);
348c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a->param_port != NULL)
349c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		OPENSSL_free(a->param_port);
350c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	OPENSSL_free(a);
351c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
352c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
353c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO_METHOD *BIO_s_connect(void)
354c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
355c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(&methods_connectp);
356c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
357c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
358c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_new(BIO *bi)
359c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
360c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bi->init=0;
361c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bi->num=INVALID_SOCKET;
362c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	bi->flags=0;
363c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ((bi->ptr=(char *)BIO_CONNECT_new()) == NULL)
364c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(0);
365c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
366c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(1);
367c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
368c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
369c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic void conn_close_socket(BIO *bio)
370c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
371c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *c;
372c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
373c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	c=(BIO_CONNECT *)bio->ptr;
374c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (bio->num != INVALID_SOCKET)
375c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
376c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* Only do a shutdown if things were established */
377c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (c->state == BIO_CONN_S_OK)
378c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			shutdown(bio->num,2);
379c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		closesocket(bio->num);
380c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		bio->num=INVALID_SOCKET;
381c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
382c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
383c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
384c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_free(BIO *a)
385c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
386c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *data;
387c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
388c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a == NULL) return(0);
389c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data=(BIO_CONNECT *)a->ptr;
390c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
391c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (a->shutdown)
392c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
393c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		conn_close_socket(a);
394c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_CONNECT_free(data);
395c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		a->ptr=NULL;
396c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		a->flags=0;
397c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		a->init=0;
398c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
399c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(1);
400c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
401c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
402c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_read(BIO *b, char *out, int outl)
403c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
404c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret=0;
405c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *data;
406c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
407c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data=(BIO_CONNECT *)b->ptr;
408c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (data->state != BIO_CONN_S_OK)
409c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
410c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=conn_state(b,data);
411c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ret <= 0)
412c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return(ret);
413c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
414c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
415c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (out != NULL)
416c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
417c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		clear_socket_error();
418c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=readsocket(b->num,out,outl);
419c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_clear_retry_flags(b);
420c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ret <= 0)
421c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
422c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (BIO_sock_should_retry(ret))
423c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_set_retry_read(b);
424c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
425c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
426c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
427c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
428c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
429c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_write(BIO *b, const char *in, int inl)
430c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
431c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int ret;
432c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *data;
433c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
434c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data=(BIO_CONNECT *)b->ptr;
435c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (data->state != BIO_CONN_S_OK)
436c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
437c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=conn_state(b,data);
438c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ret <= 0) return(ret);
439c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
440c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
441c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	clear_socket_error();
442c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret=writesocket(b->num,in,inl);
443c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_clear_retry_flags(b);
444c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret <= 0)
445c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
446c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (BIO_sock_should_retry(ret))
447c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_retry_write(b);
448c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
449c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
450c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
451c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
452c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
453c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
454c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *dbio;
455c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int *ip;
456c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	const char **pptr;
457c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	long ret=1;
458c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *data;
459c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
460c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data=(BIO_CONNECT *)b->ptr;
461c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
462c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (cmd)
463c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
464c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_RESET:
465c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
466c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data->state=BIO_CONN_S_BEFORE;
467c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		conn_close_socket(b);
468c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		b->flags=0;
469c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
470c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_DO_STATE_MACHINE:
471c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* use this one to start the connection */
472c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (data->state != BIO_CONN_S_OK)
473c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=(long)conn_state(b,data);
474c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
475c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=1;
476c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
477c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_GET_CONNECT:
478c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ptr != NULL)
479c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
480c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			pptr=(const char **)ptr;
481c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (num == 0)
482c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
483c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*pptr=data->param_hostname;
484c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
485c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
486c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (num == 1)
487c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
488c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*pptr=data->param_port;
489c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
490c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (num == 2)
491c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
492c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*pptr= (char *)&(data->ip[0]);
493c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
494c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (num == 3)
495c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
496c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*((int *)ptr)=data->port;
497c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
498c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if ((!b->init) || (ptr == NULL))
499c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*pptr="not initialized";
500c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=1;
501c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
502c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
503c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_SET_CONNECT:
504c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (ptr != NULL)
505c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
506c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			b->init=1;
507c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (num == 0)
508c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
509c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (data->param_hostname != NULL)
510c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					OPENSSL_free(data->param_hostname);
511c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->param_hostname=BUF_strdup(ptr);
512c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
513c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (num == 1)
514c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
515c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (data->param_port != NULL)
516c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					OPENSSL_free(data->param_port);
517c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->param_port=BUF_strdup(ptr);
518c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
519c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (num == 2)
520c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
521c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				char buf[16];
522c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				unsigned char *p = ptr;
523c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
524c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_snprintf(buf,sizeof buf,"%d.%d.%d.%d",
525c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					     p[0],p[1],p[2],p[3]);
526c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (data->param_hostname != NULL)
527c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					OPENSSL_free(data->param_hostname);
528c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->param_hostname=BUF_strdup(buf);
529c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				memcpy(&(data->ip[0]),ptr,4);
530c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
531c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			else if (num == 3)
532c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				{
533c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				char buf[DECIMAL_SIZE(int)+1];
534c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
535c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				BIO_snprintf(buf,sizeof buf,"%d",*(int *)ptr);
536c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (data->param_port != NULL)
537c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					OPENSSL_free(data->param_port);
538c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->param_port=BUF_strdup(buf);
539c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				data->port= *(int *)ptr;
540c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				}
541c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
542c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
543c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_SET_NBIO:
544c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data->nbio=(int)num;
545c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
546c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_C_GET_FD:
547c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (b->init)
548c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
549c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ip=(int *)ptr;
550c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if (ip != NULL)
551c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				*ip=b->num;
552c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret=b->num;
553c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
554c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else
555c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			ret= -1;
556c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
557c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_GET_CLOSE:
558c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=b->shutdown;
559c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
560c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_SET_CLOSE:
561c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		b->shutdown=(int)num;
562c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
563c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_PENDING:
564c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_WPENDING:
565c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
566c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
567c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_FLUSH:
568c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
569c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_DUP:
570c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
571c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		dbio=(BIO *)ptr;
572c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (data->param_port)
573c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_conn_port(dbio,data->param_port);
574c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (data->param_hostname)
575c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			BIO_set_conn_hostname(dbio,data->param_hostname);
576c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_set_nbio(dbio,data->nbio);
577c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		/* FIXME: the cast of the function seems unlikely to be a good idea */
578c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org                (void)BIO_set_info_callback(dbio,(bio_info_cb *)data->info_callback);
579c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
580c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
581c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_SET_CALLBACK:
582c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
583c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#if 0 /* FIXME: Should this be used?  -- Richard Levitte */
584c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
585c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret = -1;
586c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#else
587c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
588c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
589c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
590c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
591c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_GET_CALLBACK:
592c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
593c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		int (**fptr)(const BIO *bio,int state,int xret);
594c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
595c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		fptr=(int (**)(const BIO *bio,int state,int xret))ptr;
596c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*fptr=data->info_callback;
597c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
598c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
599c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
600c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
601c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
602c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
603c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
604c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
605c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
606c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
607c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
608c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	long ret=1;
609c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO_CONNECT *data;
610c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
611c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	data=(BIO_CONNECT *)b->ptr;
612c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
613c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (cmd)
614c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
615c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case BIO_CTRL_SET_CALLBACK:
616c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
617c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		data->info_callback=(int (*)(const struct bio_st *, int, int))fp;
618c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
619c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
620c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
621c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		ret=0;
622c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		break;
623c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
624c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
625c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
626c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
627c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int conn_puts(BIO *bp, const char *str)
628c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
629c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int n,ret;
630c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
631c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	n=strlen(str);
632c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret=conn_write(bp,str,n);
633c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return(ret);
634c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
635c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
636c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgBIO *BIO_new_connect(char *str)
637c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
638c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	BIO *ret;
639c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
640c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ret=BIO_new(BIO_s_connect());
641c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (ret == NULL) return(NULL);
642c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (BIO_set_conn_hostname(ret,str))
643c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(ret);
644c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	else
645c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
646c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		BIO_free(ret);
647c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return(NULL);
648c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
649c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
650c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
651c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#endif
652c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
653