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