SSL/COMSTACK updates. cs_rcvconnect completes SSL handshake.
[yaz-moved-to-github.git] / comstack / tcpip.c
1 /*
2  * Copyright (c) 1995-2002, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: tcpip.c,v 1.45 2002-01-21 21:50:32 adam Exp $
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #ifndef WIN32
12 #include <unistd.h>
13 #endif
14 #include <errno.h>
15 #include <fcntl.h>
16 #if HAVE_OPENSSL_SSL_H
17 #include <openssl/ssl.h>
18 #include <openssl/err.h>
19 #endif
20
21 #include <yaz/comstack.h>
22 #include <yaz/tcpip.h>
23 #include <yaz/log.h>
24
25 /* Chas added the following, so we get the definition of completeBER */
26 #include <yaz/odr.h>
27
28 int tcpip_close(COMSTACK h);
29 int tcpip_put(COMSTACK h, char *buf, int size);
30 int tcpip_get(COMSTACK h, char **buf, int *bufsize);
31 int tcpip_connect(COMSTACK h, void *address);
32 int tcpip_more(COMSTACK h);
33 int tcpip_rcvconnect(COMSTACK h);
34 int tcpip_bind(COMSTACK h, void *address, int mode);
35 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
36                  int (*check_ip)(void *cd, const char *a, int len, int type),
37                  void *cd);
38 int static tcpip_set_blocking(COMSTACK p, int blocking);
39
40 #if HAVE_OPENSSL_SSL_H
41 int ssl_get(COMSTACK h, char **buf, int *bufsize);
42 int ssl_put(COMSTACK h, char *buf, int size);
43 #endif
44
45 COMSTACK tcpip_accept(COMSTACK h);
46 char *tcpip_addrstr(COMSTACK h);
47 void *tcpip_straddr(COMSTACK h, const char *str);
48
49 #if 0
50 #define TRC(x) x
51 #else
52 #define TRC(X)
53 #endif
54
55 /* this state is used for both SSL and straight TCP/IP */
56 typedef struct tcpip_state
57 {
58     char *altbuf; /* alternate buffer for surplus data */
59     int altsize;  /* size as xmalloced */
60     int altlen;   /* length of data or 0 if none */
61
62     int written;  /* -1 if we aren't writing */
63     int towrite;  /* to verify against user input */
64     int (*complete)(const unsigned char *buf, int len); /* length/comple. */
65     struct sockaddr_in addr;  /* returned by cs_straddr */
66     char buf[128]; /* returned by cs_addrstr */
67 #if HAVE_OPENSSL_SSL_H
68     SSL_CTX *ctx;
69     SSL_CTX *ctx_alloc;
70     SSL *ssl;
71 #endif
72 } tcpip_state;
73
74 #ifdef WIN32
75 static int tcpip_init (void)
76 {
77     static int initialized = 0;
78     if (!initialized)
79     {
80         WORD requested;
81         WSADATA wd;
82
83         requested = MAKEWORD(1, 1);
84         if (WSAStartup(requested, &wd))
85             return 0;
86         initialized = 1;
87     }
88     return 1;
89 }
90 #else
91 static int tcpip_init (void)
92 {
93     return 1;
94 }
95 #endif
96
97 /*
98  * This function is always called through the cs_create() macro.
99  * s >= 0: socket has already been established for us.
100  */
101 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
102 {
103     COMSTACK p;
104     tcpip_state *state;
105     int new_socket;
106 #ifdef WIN32
107     unsigned long tru = 1;
108 #endif
109
110     if (!tcpip_init ())
111         return 0;
112     if (s < 0)
113     {
114         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
115             return 0;
116         new_socket = 1;
117     }
118     else
119         new_socket = 0;
120     if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
121         return 0;
122     if (!(state = (struct tcpip_state *)(p->cprivate =
123                                          xmalloc(sizeof(tcpip_state)))))
124         return 0;
125
126 #ifdef WIN32
127     if (!(p->blocking = blocking) && ioctlsocket(s, FIONBIO, &tru) < 0)
128 #else
129     if (!(p->blocking = blocking) && fcntl(s, F_SETFL, O_NONBLOCK) < 0)
130 #endif
131         return 0;
132
133     p->io_pending = 0;
134     p->iofile = s;
135     p->type = tcpip_type;
136     p->protocol = (enum oid_proto) protocol;
137
138     p->f_connect = tcpip_connect;
139     p->f_rcvconnect = tcpip_rcvconnect;
140     p->f_get = tcpip_get;
141     p->f_put = tcpip_put;
142     p->f_close = tcpip_close;
143     p->f_more = tcpip_more;
144     p->f_bind = tcpip_bind;
145     p->f_listen = tcpip_listen;
146     p->f_accept = tcpip_accept;
147     p->f_addrstr = tcpip_addrstr;
148     p->f_straddr = tcpip_straddr;
149     p->f_set_blocking = tcpip_set_blocking;
150
151     p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
152     p->event = CS_NONE;
153     p->cerrno = 0;
154     p->stackerr = 0;
155
156 #if HAVE_OPENSSL_SSL_H
157     state->ctx = state->ctx_alloc = 0;
158     state->ssl = 0;
159 #endif
160
161     state->altbuf = 0;
162     state->altsize = state->altlen = 0;
163     state->towrite = state->written = -1;
164     if (protocol == PROTO_WAIS)
165         state->complete = completeWAIS;
166     else
167         state->complete = completeBER;
168
169     p->timeout = COMSTACK_DEFAULT_TIMEOUT;
170     TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
171
172     return p;
173 }
174
175 #if HAVE_OPENSSL_SSL_H
176
177 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
178 {
179     tcpip_state *state;
180     COMSTACK p;
181     yaz_log(LOG_LOG, "ssl_type begin");
182
183     p = tcpip_type (s, blocking, protocol, 0);
184     if (!p)
185         return 0;
186     p->f_get = ssl_get;
187     p->f_put = ssl_put;
188     p->type = ssl_type;
189     state = (tcpip_state *) p->cprivate;
190     if (vp)
191         state->ctx = vp;
192     else
193     {
194         SSL_load_error_strings();
195         SSLeay_add_all_algorithms();
196
197         state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
198         if (!state->ctx)
199         {
200             tcpip_close(p);
201             return 0;
202         }
203     }
204     /* note: we don't handle already opened socket in SSL mode - yet */
205     yaz_log(LOG_LOG, "ssl_type end");
206     return p;
207 }
208 #endif
209
210 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add)
211 {
212     struct hostent *hp;
213     char *p, buf[512];
214     short int port = 210;
215     unsigned tmpadd;
216
217     if (!tcpip_init ())
218         return 0;
219     TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
220     add->sin_family = AF_INET;
221     strncpy(buf, str, 511);
222     buf[511] = 0;
223     if ((p = strchr(buf, '/')))
224         *p = 0;
225     if ((p = strchr(buf, ':')))
226     {
227         *p = 0;
228         port = atoi(p + 1);
229     }
230     add->sin_port = htons(port);
231     if (!strcmp("@", buf))
232         add->sin_addr.s_addr = INADDR_ANY;
233     else if ((hp = gethostbyname(buf)))
234         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
235                sizeof(struct in_addr));
236     else if ((tmpadd = (unsigned) inet_addr(buf)) != 0)
237         memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
238     else
239         return 0;
240     return 1;
241 }
242
243 void *tcpip_straddr(COMSTACK h, const char *str)
244 {
245     tcpip_state *sp = (tcpip_state *)h->cprivate;
246
247     if (!tcpip_strtoaddr_ex (str, &sp->addr))
248         return 0;
249     return &sp->addr;
250 }
251
252 struct sockaddr_in *tcpip_strtoaddr(const char *str)
253 {
254     static struct sockaddr_in add;
255     
256     if (!tcpip_strtoaddr_ex (str, &add))
257         return 0;
258     return &add;
259 }
260
261 int tcpip_more(COMSTACK h)
262 {
263     tcpip_state *sp = (tcpip_state *)h->cprivate;
264     
265     return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
266         sp->altlen);
267 }
268
269 /*
270  * connect(2) will block (sometimes) - nothing we can do short of doing
271  * weird things like spawning subprocesses or threading or some weird junk
272  * like that.
273  */
274 int tcpip_connect(COMSTACK h, void *address)
275 {
276     struct sockaddr_in *add = (struct sockaddr_in *)address;
277 #if HAVE_OPENSSL_SSL_H
278     tcpip_state *sp = (tcpip_state *)h->cprivate;
279 #endif
280     int r;
281
282     TRC(fprintf(stderr, "tcpip_connect\n"));
283     h->io_pending = 0;
284     if (h->state != CS_ST_UNBND)
285     {
286         h->cerrno = CSOUTSTATE;
287         return -1;
288     }
289     r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
290     if (r < 0)
291     {
292 #ifdef WIN32
293         if (WSAGetLastError() == WSAEWOULDBLOCK)
294         {
295             h->event = CS_CONNECT;
296             h->state = CS_ST_CONNECTING;
297             h->io_pending = CS_WANT_WRITE;
298             return 1;
299         }
300 #else
301         if (errno == EINPROGRESS)
302         {
303             h->event = CS_CONNECT;
304             h->state = CS_ST_CONNECTING;
305             h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
306             return 1;
307         }
308 #endif
309         h->cerrno = CSYSERR;
310         return -1;
311     }
312     h->event = CS_CONNECT;
313     h->state = CS_ST_CONNECTING;
314
315     return tcpip_rcvconnect (h);
316 }
317
318 /*
319  * nop
320  */
321 int tcpip_rcvconnect(COMSTACK h)
322 {
323     tcpip_state *sp = (tcpip_state *)h->cprivate;
324     TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
325
326     if (h->state == CS_ST_DATAXFER)
327         return 0;
328     if (h->state != CS_ST_CONNECTING)
329     {
330         h->cerrno = CSOUTSTATE;
331         return -1;
332     }
333 #if HAVE_OPENSSL_SSL_H
334     if (sp->ctx)
335     {
336         int res;
337
338         if (!sp->ssl)
339         {
340             sp->ssl = SSL_new (sp->ctx);
341             SSL_set_fd (sp->ssl, h->iofile);
342         }
343         res = SSL_connect (sp->ssl);
344         if (res <= 0)
345         {
346             int err = SSL_get_error(sp->ssl, res);
347             if (err == SSL_ERROR_WANT_READ)
348             {
349                 h->io_pending = CS_WANT_READ;
350                 return 1;
351             }
352             if (err == SSL_ERROR_WANT_WRITE)
353             {
354                 h->io_pending = CS_WANT_WRITE;
355                 return 1;
356             }
357             h->cerrno = CSERRORSSL;
358             return -1;
359         }
360     }
361 #endif
362     h->event = CS_DATA;
363     h->state = CS_ST_DATAXFER;
364     return 0;
365 }
366
367 #define CERTF "ztest.pem"
368 #define KEYF "ztest.pem"
369
370 int tcpip_bind(COMSTACK h, void *address, int mode)
371 {
372     struct sockaddr *addr = (struct sockaddr *)address;
373 #ifdef WIN32
374     BOOL one = 1;
375 #else
376     unsigned long one = 1;
377 #endif
378
379 #if HAVE_OPENSSL_SSL_H
380     tcpip_state *sp = (tcpip_state *)h->cprivate;
381     if (sp->ctx)
382     {
383         if (sp->ctx_alloc)
384         {
385             int res;
386             res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
387                                                 SSL_FILETYPE_PEM);
388             if (res <= 0)
389             {
390                 ERR_print_errors_fp(stderr);
391                 exit (2);
392             }
393             res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
394                                                SSL_FILETYPE_PEM);
395             if (res <= 0)
396             {
397                 ERR_print_errors_fp(stderr);
398                 exit (3);
399             }
400             res = SSL_CTX_check_private_key (sp->ctx);
401             if (res <= 0)
402             {
403                 ERR_print_errors_fp(stderr);
404                 exit(5);
405             }
406         }
407         TRC (fprintf (stderr, "ssl_bind\n"));
408     }
409     else
410     {
411         TRC (fprintf (stderr, "tcpip_bind\n"));
412     }
413 #else
414     TRC (fprintf (stderr, "tcpip_bind\n"));
415 #endif
416 #ifndef WIN32
417     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) 
418         &one, sizeof(one)) < 0)
419     {
420         h->cerrno = CSYSERR;
421         return -1;
422     }
423 #endif
424     if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
425     {
426         h->cerrno = CSYSERR;
427         return -1;
428     }
429     if (mode == CS_SERVER && listen(h->iofile, 3) < 0)
430     {
431         h->cerrno = CSYSERR;
432         return -1;
433     }
434     h->state = CS_ST_IDLE;
435     h->event = CS_LISTEN;
436     return 0;
437 }
438
439 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
440                  int (*check_ip)(void *cd, const char *a, int len, int t),
441                  void *cd)
442 {
443     struct sockaddr_in addr;
444 #ifdef __cplusplus
445     socklen_t len = sizeof(addr);
446 #else
447     int len = sizeof(addr);
448 #endif
449
450     TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
451     if (h->state != CS_ST_IDLE)
452     {
453         h->cerrno = CSOUTSTATE;
454         return -1;
455     }
456     h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len);
457     if (h->newfd < 0)
458     {
459         if (
460 #ifdef WIN32
461             WSAGetLastError() == WSAEWOULDBLOCK
462 #else
463             errno == EWOULDBLOCK 
464 #ifdef EAGAIN
465 #if EAGAIN != EWOULDBLOCK
466             || errno == EAGAIN
467 #endif
468 #endif
469 #endif
470             )
471             h->cerrno = CSNODATA;
472         else
473             h->cerrno = CSYSERR;
474         return -1;
475     }
476     if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in))
477         memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in));
478     else if (addrlen)
479         *addrlen = 0;
480     if (check_ip && (*check_ip)(cd, (const char *) &addr,
481         sizeof(addr), AF_INET))
482     {
483         h->cerrno = CSDENY;
484 #ifdef WIN32
485         closesocket(h->newfd);
486 #else
487         close(h->newfd);
488 #endif
489         h->newfd = -1;
490         return -1;
491     }
492     h->state = CS_ST_INCON;
493     return 0;
494 }
495
496 COMSTACK tcpip_accept(COMSTACK h)
497 {
498     COMSTACK cnew;
499     tcpip_state *state, *st = (tcpip_state *)h->cprivate;
500 #ifdef WIN32
501     unsigned long tru = 1;
502 #endif
503
504     TRC(fprintf(stderr, "tcpip_accept\n"));
505     if (h->state == CS_ST_INCON)
506     {
507         if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
508         {
509             h->cerrno = CSYSERR;
510 #ifdef WIN32
511             closesocket(h->newfd);
512 #else
513             close(h->newfd);
514 #endif
515             h->newfd = -1;
516             return 0;
517         }
518         memcpy(cnew, h, sizeof(*h));
519         cnew->iofile = h->newfd;
520         cnew->io_pending = 0;
521         if (!(state = (tcpip_state *)
522               (cnew->cprivate = xmalloc(sizeof(tcpip_state)))))
523         {
524             h->cerrno = CSYSERR;
525             if (h->newfd != -1)
526             {
527 #ifdef WIN32
528                 closesocket(h->newfd);
529 #else
530                 close(h->newfd);
531 #endif
532                 h->newfd = -1;
533             }
534             return 0;
535         }
536         if (!cnew->blocking && 
537 #ifdef WIN32
538             (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)
539 #else
540             (!cnew->blocking && fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)
541 #endif
542             )
543         {
544             h->cerrno = CSYSERR;
545             if (h->newfd != -1)
546             {
547 #ifdef WIN32
548                 closesocket(h->newfd);
549 #else
550                 close(h->newfd);
551 #endif
552                 h->newfd = -1;
553             }
554             xfree (cnew);
555             xfree (state);
556             return 0;
557         }
558         h->newfd = -1;
559         state->altbuf = 0;
560         state->altsize = state->altlen = 0;
561         state->towrite = state->written = -1;
562         state->complete = st->complete;
563         cnew->state = CS_ST_ACCEPT;
564         h->state = CS_ST_IDLE;
565         
566 #if HAVE_OPENSSL_SSL_H
567         state->ctx = st->ctx;
568         state->ctx_alloc = 0;
569         state->ssl = st->ssl;
570         if (state->ctx)
571         {
572             state->ssl = SSL_new (state->ctx);
573             SSL_set_fd (state->ssl, cnew->iofile);
574         }
575 #endif
576         h = cnew;
577     }
578     if (h->state == CS_ST_ACCEPT)
579     {
580 #if HAVE_OPENSSL_SSL_H
581         tcpip_state *state = (tcpip_state *)h->cprivate;
582         if (state->ctx)
583         {
584             int res = SSL_accept (state->ssl);
585             TRC(fprintf(stderr, "SSL_accept\n"));
586             if (res <= 0)
587             {
588                 int err = SSL_get_error(state->ssl, res);
589                 if (err == SSL_ERROR_WANT_READ)
590                 {
591                     h->io_pending = CS_WANT_READ;
592                     return h;
593                 }
594                 if (err == SSL_ERROR_WANT_WRITE)
595                 {
596                     h->io_pending = CS_WANT_WRITE;
597                     return h;
598                 }
599                 cs_close (h);
600                 return 0;
601             }
602         }
603 #endif
604     }
605     else
606     {
607         h->cerrno = CSOUTSTATE;
608         return 0;
609     }
610     h->io_pending = 0;
611     h->state = CS_ST_DATAXFER;
612     h->event = CS_DATA;
613     return h;
614 }
615
616 #define CS_TCPIP_BUFCHUNK 4096
617
618 /*
619  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
620  * 0=connection closed.
621  */
622 int tcpip_get(COMSTACK h, char **buf, int *bufsize)
623 {
624     tcpip_state *sp = (tcpip_state *)h->cprivate;
625     char *tmpc;
626     int tmpi, berlen, rest, req, tomove;
627     int hasread = 0, res;
628
629     TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
630     if (sp->altlen) /* switch buffers */
631     {
632         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
633             (unsigned) sp->altbuf));
634         tmpc = *buf;
635         tmpi = *bufsize;
636         *buf = sp->altbuf;
637         *bufsize = sp->altsize;
638         hasread = sp->altlen;
639         sp->altlen = 0;
640         sp->altbuf = tmpc;
641         sp->altsize = tmpi;
642     }
643     h->io_pending = 0;
644     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
645     {
646         if (!*bufsize)
647         {
648             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
649                 return -1;
650         }
651         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
652             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
653                 return -1;
654         res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
655         TRC(fprintf(stderr, "  recv res=%d, hasread=%d\n", res, hasread));
656         if (res < 0)
657         {
658 #ifdef WIN32
659             if (WSAGetLastError() == WSAEWOULDBLOCK)
660             {
661                 h->io_pending = CS_WANT_READ;
662                 break;
663             }
664             else
665                 return -1;
666 #else
667             if (errno == EWOULDBLOCK 
668 #ifdef EAGAIN   
669 #if EAGAIN != EWOULDBLOCK
670                 || errno == EAGAIN
671 #endif
672 #endif
673                 || errno == EINPROGRESS
674                 )
675             {
676                 h->io_pending = CS_WANT_READ;
677                 break;
678             }
679             else if (errno == 0)
680                 continue;
681             else
682                 return -1;
683 #endif
684         }
685         else if (!res)
686             return 0;
687         hasread += res;
688     }
689     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
690                   hasread, berlen));
691     /* move surplus buffer (or everything if we didn't get a BER rec.) */
692     if (hasread > berlen)
693     {
694         tomove = req = hasread - berlen;
695         rest = tomove % CS_TCPIP_BUFCHUNK;
696         if (rest)
697             req += CS_TCPIP_BUFCHUNK - rest;
698         if (!sp->altbuf)
699         {
700             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
701                 return -1;
702         } else if (sp->altsize < req)
703             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
704                 return -1;
705         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
706             (unsigned) sp->altbuf));
707         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
708     }
709     if (berlen < CS_TCPIP_BUFCHUNK - 1)
710         *(*buf + berlen) = '\0';
711     return berlen ? berlen : 1;
712 }
713
714
715 #if HAVE_OPENSSL_SSL_H
716 /*
717  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
718  * 0=connection closed.
719  */
720 int ssl_get(COMSTACK h, char **buf, int *bufsize)
721 {
722     tcpip_state *sp = (tcpip_state *)h->cprivate;
723     char *tmpc;
724     int tmpi, berlen, rest, req, tomove;
725     int hasread = 0, res;
726
727     TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
728     if (sp->altlen) /* switch buffers */
729     {
730         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
731             (unsigned) sp->altbuf));
732         tmpc = *buf;
733         tmpi = *bufsize;
734         *buf = sp->altbuf;
735         *bufsize = sp->altsize;
736         hasread = sp->altlen;
737         sp->altlen = 0;
738         sp->altbuf = tmpc;
739         sp->altsize = tmpi;
740     }
741     h->io_pending = 0;
742     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
743     {
744         if (!*bufsize)
745         {
746             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
747                 return -1;
748         }
749         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
750             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
751                 return -1;
752         res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
753         TRC(fprintf(stderr, "  SSL_read res=%d, hasread=%d\n", res, hasread));
754         if (res <= 0)
755         {
756             int ssl_err = SSL_get_error(sp->ssl, res);
757             if (ssl_err == SSL_ERROR_WANT_READ)
758             {
759                 h->io_pending = CS_WANT_READ;
760                 break;
761             }
762             if (ssl_err == SSL_ERROR_WANT_WRITE)
763             {
764                 h->io_pending = CS_WANT_WRITE;
765                 break;
766             }
767             if (res == 0)
768                 return 0;
769             h->cerrno = CSERRORSSL;
770             return -1;
771         }
772         hasread += res;
773     }
774     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
775         hasread, berlen));
776     /* move surplus buffer (or everything if we didn't get a BER rec.) */
777     if (hasread > berlen)
778     {
779         tomove = req = hasread - berlen;
780         rest = tomove % CS_TCPIP_BUFCHUNK;
781         if (rest)
782             req += CS_TCPIP_BUFCHUNK - rest;
783         if (!sp->altbuf)
784         {
785             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
786                 return -1;
787         } else if (sp->altsize < req)
788             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
789                 return -1;
790         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
791             (unsigned) sp->altbuf));
792         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
793     }
794     if (berlen < CS_TCPIP_BUFCHUNK - 1)
795         *(*buf + berlen) = '\0';
796     return berlen ? berlen : 1;
797 }
798 #endif
799
800 /*
801  * Returns 1, 0 or -1
802  * In nonblocking mode, you must call again with same buffer while
803  * return value is 1.
804  */
805 int tcpip_put(COMSTACK h, char *buf, int size)
806 {
807     int res;
808     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
809
810     TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
811     h->io_pending = 0;
812     h->event = CS_DATA;
813     if (state->towrite < 0)
814     {
815         state->towrite = size;
816         state->written = 0;
817     }
818     else if (state->towrite != size)
819     {
820         h->cerrno = CSWRONGBUF;
821         return -1;
822     }
823     while (state->towrite > state->written)
824     {
825         if ((res =
826              send(h->iofile, buf + state->written, size -
827                   state->written, 
828 #ifdef MSG_NOSIGNAL
829                   MSG_NOSIGNAL
830 #else
831                   0
832 #endif
833                  )) < 0)
834         {
835             if (
836 #ifdef WIN32
837                 WSAGetLastError() == WSAEWOULDBLOCK
838 #else
839                 errno == EWOULDBLOCK 
840 #ifdef EAGAIN
841 #if EAGAIN != EWOULDBLOCK
842              || errno == EAGAIN
843 #endif
844 #endif
845 #endif
846                 )
847             {
848                 TRC(fprintf(stderr, "  Flow control stop\n"));
849                 h->io_pending = CS_WANT_WRITE;
850                 return 1;
851             }
852             h->cerrno = CSYSERR;
853             return -1;
854         }
855         state->written += res;
856         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
857                     res, state->written, size));
858     }
859     state->towrite = state->written = -1;
860     TRC(fprintf(stderr, "  Ok\n"));
861     return 0;
862 }
863
864
865 #if HAVE_OPENSSL_SSL_H
866 /*
867  * Returns 1, 0 or -1
868  * In nonblocking mode, you must call again with same buffer while
869  * return value is 1.
870  */
871 int ssl_put(COMSTACK h, char *buf, int size)
872 {
873     int res;
874     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
875
876     TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
877     h->io_pending = 0;
878     h->event = CS_DATA;
879     if (state->towrite < 0)
880     {
881         state->towrite = size;
882         state->written = 0;
883     }
884     else if (state->towrite != size)
885     {
886         h->cerrno = CSWRONGBUF;
887         return -1;
888     }
889     while (state->towrite > state->written)
890     {
891         res = SSL_write (state->ssl, buf + state->written,
892                          size - state->written);
893         if (res <= 0)
894         {
895             int ssl_err = SSL_get_error(state->ssl, res);
896             if (ssl_err == SSL_ERROR_WANT_READ)
897             {
898                 h->io_pending = CS_WANT_READ;
899                 return 1;
900             }
901             if (ssl_err == SSL_ERROR_WANT_WRITE)
902             {
903                 h->io_pending = CS_WANT_WRITE;
904                 return 1;
905             }
906             h->cerrno = CSERRORSSL;
907             return -1;
908         }
909         state->written += res;
910         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
911                     res, state->written, size));
912     }
913     state->towrite = state->written = -1;
914     TRC(fprintf(stderr, "  Ok\n"));
915     return 0;
916 }
917 #endif
918
919 int tcpip_close(COMSTACK h)
920 {
921     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
922
923     TRC(fprintf(stderr, "tcpip_close\n"));
924     if (h->iofile != -1)
925     {
926 #if HAVE_OPENSSL_SSL_H
927         if (sp->ssl)
928         {
929             SSL_shutdown (sp->ssl);
930         }
931 #endif
932 #ifdef WIN32
933         closesocket(h->iofile);
934 #else
935         close(h->iofile);
936 #endif
937     }
938     if (sp->altbuf)
939         xfree(sp->altbuf);
940 #if HAVE_OPENSSL_SSL_H
941     if (sp->ssl)
942     {
943         TRC (fprintf(stderr, "SSL_free\n"));
944         SSL_free (sp->ssl);
945     }
946     sp->ssl = 0;
947     if (sp->ctx_alloc)
948         SSL_CTX_free (sp->ctx_alloc);
949 #endif
950     xfree(sp);
951     xfree(h);
952     return 0;
953 }
954
955 char *tcpip_addrstr(COMSTACK h)
956 {
957     struct sockaddr_in addr;
958     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
959     char *r, *buf = sp->buf;
960     size_t len;
961     struct hostent *host;
962     
963     len = sizeof(addr);
964     if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
965     {
966         h->cerrno = CSYSERR;
967         return 0;
968     }
969     if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
970                               AF_INET)))
971         r = (char*) host->h_name;
972     else
973         r = inet_ntoa(addr.sin_addr);
974     sprintf(buf, "tcp:%s", r);
975 #if HAVE_OPENSSL_SSL_H
976     if (sp->ctx)
977         sprintf(buf, "ssl:%s", r);
978 #endif
979     return buf;
980 }
981
982 int static tcpip_set_blocking(COMSTACK p, int blocking)
983 {
984     unsigned long flag;
985     
986     if (p->blocking == blocking)
987         return 1;
988 #ifdef WIN32
989     flag = 1;
990     if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
991         return 0;
992 #else
993     flag = fcntl(p->iofile, F_GETFL, 0);
994     if(!blocking)
995         flag = flag & ~O_NONBLOCK;
996     else
997         flag = flag | O_NONBLOCK;
998     if (fcntl(p->iofile, F_SETFL, flag) < 0)
999         return 0;
1000 #endif
1001     p->blocking = blocking;
1002     return 1;
1003 }