RT4660: BIO_METHODs should be const.
[openssl.git] / crypto / bio / bss_conn.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
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.
7  *
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).
14  *
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.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
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)"
39  *
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
50  * SUCH DAMAGE.
51  *
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.]
56  */
57
58 #include <stdio.h>
59 #include <errno.h>
60
61 #include "bio_lcl.h"
62
63 #ifndef OPENSSL_NO_SOCK
64
65 typedef struct bio_connect_st {
66     int state;
67     int connect_family;
68     char *param_hostname;
69     char *param_service;
70     int connect_mode;
71
72     BIO_ADDRINFO *addr_first;
73     const BIO_ADDRINFO *addr_iter;
74     /*
75      * int socket; this will be kept in bio->num so that it is compatible
76      * with the bss_sock bio
77      */
78     /*
79      * called when the connection is initially made callback(BIO,state,ret);
80      * The callback should return 'ret'.  state is for compatibility with the
81      * ssl info_callback
82      */
83     int (*info_callback) (const BIO *bio, int state, int ret);
84 } BIO_CONNECT;
85
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 *);
93
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);
98
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
105
106 static const BIO_METHOD methods_connectp = {
107     BIO_TYPE_CONNECT,
108     "socket connect",
109     conn_write,
110     conn_read,
111     conn_puts,
112     NULL,                       /* connect_gets, */
113     conn_ctrl,
114     conn_new,
115     conn_free,
116     conn_callback_ctrl,
117 };
118
119 static int conn_state(BIO *b, BIO_CONNECT *c)
120 {
121     int ret = -1, i;
122     int (*cb) (const BIO *, int, int) = NULL;
123
124     if (c->info_callback != NULL)
125         cb = c->info_callback;
126
127     for (;;) {
128         switch (c->state) {
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);
135                 goto exit_loop;
136             }
137             c->state = BIO_CONN_S_GET_ADDR;
138             break;
139
140         case BIO_CONN_S_GET_ADDR:
141             {
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
147                               * compiled.
148                               */
149 #ifdef AF_INET6
150                         family = AF_INET6;
151                     } else {
152 #endif
153                         BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
154                         goto exit_loop;
155                     }
156                     break;
157                 case BIO_FAMILY_IPV4:
158                     family = AF_INET;
159                     break;
160                 case BIO_FAMILY_IPANY:
161                     family = AF_UNSPEC;
162                     break;
163                 default:
164                     BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
165                     goto exit_loop;
166                 }
167                 if (BIO_lookup(c->param_hostname, c->param_service,
168                                BIO_LOOKUP_CLIENT,
169                                family, SOCK_STREAM, &c->addr_first) == 0)
170                     goto exit_loop;
171             }
172             if (c->addr_first == NULL) {
173                 BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
174                 goto exit_loop;
175             }
176             c->addr_iter = c->addr_first;
177             c->state = BIO_CONN_S_CREATE_SOCKET;
178             break;
179
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);
190                 goto exit_loop;
191             }
192             b->num = ret;
193             c->state = BIO_CONN_S_CONNECT;
194             break;
195
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);
200             b->retry_reason = 0;
201             if (ret < 0) {
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;
206                     ERR_clear_error();
207                 } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
208                            != NULL) {
209                     /*
210                      * if there are more addresses to try, do that first
211                      */
212                     BIO_closesocket(b->num);
213                     c->state = BIO_CONN_S_CREATE_SOCKET;
214                     ERR_clear_error();
215                     break;
216                 } else {
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);
222                 }
223                 goto exit_loop;
224             } else {
225                 c->state = BIO_CONN_S_OK;
226             }
227             break;
228
229         case BIO_CONN_S_BLOCKED_CONNECT:
230             i = BIO_sock_error(b->num);
231             if (i) {
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);
238                 ret = 0;
239                 goto exit_loop;
240             } else
241                 c->state = BIO_CONN_S_OK;
242             break;
243
244         case BIO_CONN_S_OK:
245             ret = 1;
246             goto exit_loop;
247         default:
248             /* abort(); */
249             goto exit_loop;
250         }
251
252         if (cb != NULL) {
253             if ((ret = cb((BIO *)b, c->state, ret)) == 0)
254                 goto end;
255         }
256     }
257
258     /* Loop does not exit */
259  exit_loop:
260     if (cb != NULL)
261         ret = cb((BIO *)b, c->state, ret);
262  end:
263     return (ret);
264 }
265
266 BIO_CONNECT *BIO_CONNECT_new(void)
267 {
268     BIO_CONNECT *ret;
269
270     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
271         return (NULL);
272     ret->state = BIO_CONN_S_BEFORE;
273     ret->connect_family = BIO_FAMILY_IPANY;
274     return (ret);
275 }
276
277 void BIO_CONNECT_free(BIO_CONNECT *a)
278 {
279     if (a == NULL)
280         return;
281
282     OPENSSL_free(a->param_hostname);
283     OPENSSL_free(a->param_service);
284     BIO_ADDRINFO_free(a->addr_first);
285     OPENSSL_free(a);
286 }
287
288 const BIO_METHOD *BIO_s_connect(void)
289 {
290     return (&methods_connectp);
291 }
292
293 static int conn_new(BIO *bi)
294 {
295     bi->init = 0;
296     bi->num = (int)INVALID_SOCKET;
297     bi->flags = 0;
298     if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
299         return (0);
300     else
301         return (1);
302 }
303
304 static void conn_close_socket(BIO *bio)
305 {
306     BIO_CONNECT *c;
307
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;
315     }
316 }
317
318 static int conn_free(BIO *a)
319 {
320     BIO_CONNECT *data;
321
322     if (a == NULL)
323         return (0);
324     data = (BIO_CONNECT *)a->ptr;
325
326     if (a->shutdown) {
327         conn_close_socket(a);
328         BIO_CONNECT_free(data);
329         a->ptr = NULL;
330         a->flags = 0;
331         a->init = 0;
332     }
333     return (1);
334 }
335
336 static int conn_read(BIO *b, char *out, int outl)
337 {
338     int ret = 0;
339     BIO_CONNECT *data;
340
341     data = (BIO_CONNECT *)b->ptr;
342     if (data->state != BIO_CONN_S_OK) {
343         ret = conn_state(b, data);
344         if (ret <= 0)
345             return (ret);
346     }
347
348     if (out != NULL) {
349         clear_socket_error();
350         ret = readsocket(b->num, out, outl);
351         BIO_clear_retry_flags(b);
352         if (ret <= 0) {
353             if (BIO_sock_should_retry(ret))
354                 BIO_set_retry_read(b);
355         }
356     }
357     return (ret);
358 }
359
360 static int conn_write(BIO *b, const char *in, int inl)
361 {
362     int ret;
363     BIO_CONNECT *data;
364
365     data = (BIO_CONNECT *)b->ptr;
366     if (data->state != BIO_CONN_S_OK) {
367         ret = conn_state(b, data);
368         if (ret <= 0)
369             return (ret);
370     }
371
372     clear_socket_error();
373     ret = writesocket(b->num, in, inl);
374     BIO_clear_retry_flags(b);
375     if (ret <= 0) {
376         if (BIO_sock_should_retry(ret))
377             BIO_set_retry_write(b);
378     }
379     return (ret);
380 }
381
382 static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
383 {
384     BIO *dbio;
385     int *ip;
386     const char **pptr = NULL;
387     long ret = 1;
388     BIO_CONNECT *data;
389
390     data = (BIO_CONNECT *)b->ptr;
391
392     switch (cmd) {
393     case BIO_CTRL_RESET:
394         ret = 0;
395         data->state = BIO_CONN_S_BEFORE;
396         conn_close_socket(b);
397         BIO_ADDRINFO_free(data->addr_first);
398         data->addr_first = NULL;
399         b->flags = 0;
400         break;
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);
405         else
406             ret = 1;
407         break;
408     case BIO_C_GET_CONNECT:
409         if (ptr != NULL) {
410             pptr = (const char **)ptr;
411             if (num == 0) {
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)) {
419 # ifdef AF_INET6
420                 case AF_INET6:
421                     ret = BIO_FAMILY_IPV6;
422                     break;
423 # endif
424                 case AF_INET:
425                     ret = BIO_FAMILY_IPV4;
426                     break;
427                 case 0:
428                     ret = data->connect_family;
429                     break;
430                 default:
431                     ret = -1;
432                     break;
433                 }
434             } else {
435                 ret = 0;
436             }
437         } else {
438             ret = 0;
439         }
440         break;
441     case BIO_C_SET_CONNECT:
442         if (ptr != NULL) {
443             b->init = 1;
444             if (num == 0) {
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
449                  */
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;
463                 if (ret) {
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;
469                 }
470             } else if (num == 3) {
471                 data->connect_family = *(int *)ptr;
472             } else {
473                 ret = 0;
474             }
475         }
476         break;
477     case BIO_C_SET_NBIO:
478         if (num != 0)
479             data->connect_mode |= BIO_SOCK_NONBLOCK;
480         else
481             data->connect_mode &= ~BIO_SOCK_NONBLOCK;
482         break;
483     case BIO_C_SET_CONNECT_MODE:
484         data->connect_mode = (int)num;
485         break;
486     case BIO_C_GET_FD:
487         if (b->init) {
488             ip = (int *)ptr;
489             if (ip != NULL)
490                 *ip = b->num;
491             ret = b->num;
492         } else
493             ret = -1;
494         break;
495     case BIO_CTRL_GET_CLOSE:
496         ret = b->shutdown;
497         break;
498     case BIO_CTRL_SET_CLOSE:
499         b->shutdown = (int)num;
500         break;
501     case BIO_CTRL_PENDING:
502     case BIO_CTRL_WPENDING:
503         ret = 0;
504         break;
505     case BIO_CTRL_FLUSH:
506         break;
507     case BIO_CTRL_DUP:
508         {
509             dbio = (BIO *)ptr;
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);
516             /*
517              * FIXME: the cast of the function seems unlikely to be a good
518              * idea
519              */
520             (void)BIO_set_info_callback(dbio,
521                                         (bio_info_cb *)data->info_callback);
522         }
523         break;
524     case BIO_CTRL_SET_CALLBACK:
525         {
526 # if 0                          /* FIXME: Should this be used? -- Richard
527                                  * Levitte */
528             BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
529             ret = -1;
530 # else
531             ret = 0;
532 # endif
533         }
534         break;
535     case BIO_CTRL_GET_CALLBACK:
536         {
537             int (**fptr) (const BIO *bio, int state, int xret);
538
539             fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
540             *fptr = data->info_callback;
541         }
542         break;
543     default:
544         ret = 0;
545         break;
546     }
547     return (ret);
548 }
549
550 static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
551 {
552     long ret = 1;
553     BIO_CONNECT *data;
554
555     data = (BIO_CONNECT *)b->ptr;
556
557     switch (cmd) {
558     case BIO_CTRL_SET_CALLBACK:
559         {
560             data->info_callback =
561                 (int (*)(const struct bio_st *, int, int))fp;
562         }
563         break;
564     default:
565         ret = 0;
566         break;
567     }
568     return (ret);
569 }
570
571 static int conn_puts(BIO *bp, const char *str)
572 {
573     int n, ret;
574
575     n = strlen(str);
576     ret = conn_write(bp, str, n);
577     return (ret);
578 }
579
580 BIO *BIO_new_connect(const char *str)
581 {
582     BIO *ret;
583
584     ret = BIO_new(BIO_s_connect());
585     if (ret == NULL)
586         return (NULL);
587     if (BIO_set_conn_hostname(ret, str))
588         return (ret);
589     BIO_free(ret);
590     return (NULL);
591 }
592
593 #endif