9feb4558f7560d4a27847787eef8e35162fbfc39
[yaz-moved-to-github.git] / comstack / tcpip.c
1 /*
2  * Copyright (c) 1995-2001, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Log: tcpip.c,v $
6  * Revision 1.39  2001-07-19 19:49:40  adam
7  * Fixed bug in tcpip_set_blocking.
8  *
9  * Revision 1.38  2001/03/21 12:43:36  adam
10  * Implemented cs_create_host. Better error reporting for SSL comstack.
11  *
12  * Revision 1.37  2001/03/08 20:18:55  adam
13  * Added cs_set_blocking. Patch from Matthew Carey.
14  *
15  * Revision 1.36  2001/02/21 13:46:53  adam
16  * C++ fixes.
17  *
18  * Revision 1.35  2000/11/27 15:17:40  adam
19  * Using SSLeay_add_all_algorithms instead of OpenSSL_add_all_algorithms.
20  *
21  * Revision 1.34  2000/11/23 10:58:32  adam
22  * SSL comstack support. Separate POSIX thread support library.
23  *
24  * Revision 1.33  2000/09/04 08:27:11  adam
25  * Work on error handling for tcpip_accept.
26  *
27  * Revision 1.32  1999/11/30 13:47:11  adam
28  * Improved installation. Moved header files to include/yaz.
29  *
30  * Revision 1.31  1999/04/29 07:31:23  adam
31  * Changed tcpip_strtoaddr_ex so that only part 'till '/' is considered
32  * part of hostname.
33  *
34  * Revision 1.30  1999/04/20 09:56:48  adam
35  * Added 'name' paramter to encoder/decoder routines (typedef Odr_fun).
36  * Modified all encoders/decoders to reflect this change.
37  *
38  * Revision 1.29  1999/04/16 14:45:55  adam
39  * Added interface for tcpd wrapper for access control.
40  *
41  * Revision 1.28  1999/03/31 11:11:14  adam
42  * Function getprotobyname only called once. Minor change in tcpip_get
43  * to handle multi-threaded conditions.
44  *
45  * Revision 1.27  1999/02/02 13:57:31  adam
46  * Uses preprocessor define WIN32 instead of WINDOWS to build code
47  * for Microsoft WIN32.
48  *
49  * Revision 1.26  1999/01/08 11:23:14  adam
50  * Added const modifier to some of the BER/ODR encoding routines.
51  *
52  * Revision 1.25  1998/07/07 15:49:23  adam
53  * Added braces to avoid warning.
54  *
55  * Revision 1.24  1998/06/29 07:59:17  adam
56  * Minor fix.
57  *
58  * Revision 1.23  1998/06/23 15:37:50  adam
59  * Added type cast to prevent warning.
60  *
61  * Revision 1.22  1998/06/22 11:32:36  adam
62  * Added 'conditional cs_listen' feature.
63  *
64  * Revision 1.21  1998/05/20 09:55:32  adam
65  * Function tcpip_get treats EINPROGRESS error in the same way as
66  * EWOULDBLOCK. EINPROGRESS shouldn't be returned - but it is on
67  * Solaris in some cases.
68  *
69  * Revision 1.20  1998/05/18 10:10:40  adam
70  * Minor change to avoid C++ warning.
71  *
72  * Revision 1.19  1998/02/11 11:53:33  adam
73  * Changed code so that it compiles as C++.
74  *
75  * Revision 1.18  1997/09/29 07:15:25  adam
76  * Changed use of setsockopt to avoid warnings on MSVC.
77  *
78  * Revision 1.17  1997/09/17 12:10:30  adam
79  * YAZ version 1.4.
80  *
81  * Revision 1.16  1997/09/01 08:49:14  adam
82  * New windows NT/95 port using MSV5.0. Minor changes only.
83  *
84  * Revision 1.15  1997/05/14 06:53:33  adam
85  * C++ support.
86  *
87  * Revision 1.14  1997/05/01 15:06:32  adam
88  * Moved WINSOCK init. code to tcpip_init routine.
89  *
90  * Revision 1.13  1996/11/01 08:45:18  adam
91  * Bug fix: used close on MS-Windows. Fixed to closesocket.
92  *
93  * Revision 1.12  1996/07/06 19:58:30  quinn
94  * System headerfiles gathered in yconfig
95  *
96  * Revision 1.11  1996/02/23  10:00:39  quinn
97  * WAIS Work
98  *
99  * Revision 1.10  1996/02/20  12:52:11  quinn
100  * WAIS protocol support.
101  *
102  * Revision 1.9  1996/02/10  12:23:11  quinn
103  * Enablie inetd operations fro TCP/IP stack
104  *
105  * Revision 1.8  1995/11/01  13:54:27  quinn
106  * Minor adjustments
107  *
108  * Revision 1.7  1995/10/30  12:41:16  quinn
109  * Added hostname lookup for server.
110  *
111  * Revision 1.6  1995/09/29  17:12:00  quinn
112  * Smallish
113  *
114  * Revision 1.5  1995/09/29  17:01:48  quinn
115  * More Windows work
116  *
117  * Revision 1.4  1995/09/28  10:12:26  quinn
118  * Windows-support changes
119  *
120  * Revision 1.3  1995/09/27  15:02:45  quinn
121  * Modified function heads & prototypes.
122  *
123  * Revision 1.2  1995/06/15  12:30:06  quinn
124  * Added @ as hostname alias for INADDR ANY.
125  *
126  * Revision 1.1  1995/06/14  09:58:20  quinn
127  * Renamed yazlib to comstack.
128  *
129  * Revision 1.20  1995/05/16  08:51:16  quinn
130  * License, documentation, and memory fixes
131  *
132  * Revision 1.19  1995/04/10  10:24:08  quinn
133  * Some bug-fixes.
134  *
135  * Revision 1.18  1995/03/30  13:29:27  quinn
136  * Added REUSEADDR in tcpip_bind
137  *
138  * Revision 1.17  1995/03/27  08:36:10  quinn
139  * Some work on nonblocking operation in xmosi.c and rfct.c.
140  * Added protocol parameter to cs_create()
141  *
142  * Revision 1.16  1995/03/21  15:53:41  quinn
143  * Added rcvconnect
144  *
145  * Revision 1.15  1995/03/21  12:31:27  quinn
146  * Added check for EINPROGRESS on connect.
147  *
148  * Revision 1.14  1995/03/20  09:47:21  quinn
149  * Added server-side support to xmosi.c
150  * Fixed possible problems in rfct
151  * Other little mods
152  *
153  * Revision 1.13  1995/03/15  16:15:13  adam
154  * Removed p_write.
155  *
156  * Revision 1.12  1995/03/15  15:36:27  quinn
157  * Mods to support nonblocking I/O
158  *
159  * Revision 1.11  1995/03/15  08:37:57  quinn
160  * Now we're pretty much set for nonblocking I/O.
161  *
162  * Revision 1.10  1995/03/14  17:00:07  quinn
163  * Bug-fixes - added tracing info to tcpip.c
164  *
165  * Revision 1.9  1995/03/14  10:28:42  quinn
166  * Adding server-side support to tcpip.c and fixing bugs in nonblocking I/O
167  *
168  * Revision 1.8  1995/03/10  14:22:50  quinn
169  * Removed debug output.
170  *
171  * Revision 1.7  1995/03/10  11:44:59  quinn
172  * Fixes and debugging
173  *
174  * Revision 1.6  1995/03/07  10:26:55  quinn
175  * Initialized type field in the comstacks.
176  *
177  * Revision 1.5  1995/02/14  20:40:07  quinn
178  * Various stuff.
179  *
180  * Revision 1.4  1995/02/14  11:54:49  quinn
181  * Beginning to add full CCL.
182  *
183  * Revision 1.3  1995/02/10  18:58:10  quinn
184  * Fixed tcpip_get (formerly tcpip_read).
185  * Turned tst (cli) into a proper, event-driven thingy.
186  *
187  * Revision 1.2  1995/02/10  15:55:47  quinn
188  * Small things.
189  *
190  * Revision 1.1  1995/02/09  15:51:52  quinn
191  * Works better now.
192  *
193  */
194
195 #include <stdio.h>
196 #include <string.h>
197 #include <stdlib.h>
198 #ifndef WIN32
199 #include <unistd.h>
200 #endif
201 #include <errno.h>
202 #include <fcntl.h>
203 #if HAVE_OPENSSL_SSL_H
204 #include <openssl/ssl.h>
205 #include <openssl/err.h>
206 #endif
207
208 #include <yaz/comstack.h>
209 #include <yaz/tcpip.h>
210 #include <yaz/log.h>
211
212 /* Chas added the following, so we get the definition of completeBER */
213 #include <yaz/odr.h>
214
215 int tcpip_close(COMSTACK h);
216 int tcpip_put(COMSTACK h, char *buf, int size);
217 int tcpip_get(COMSTACK h, char **buf, int *bufsize);
218 int tcpip_connect(COMSTACK h, void *address);
219 int tcpip_more(COMSTACK h);
220 int tcpip_rcvconnect(COMSTACK h);
221 int tcpip_bind(COMSTACK h, void *address, int mode);
222 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
223                  int (*check_ip)(void *cd, const char *a, int len, int type),
224                  void *cd);
225 int static tcpip_set_blocking(COMSTACK p, int blocking);
226
227 #if HAVE_OPENSSL_SSL_H
228 int ssl_get(COMSTACK h, char **buf, int *bufsize);
229 int ssl_put(COMSTACK h, char *buf, int size);
230 #endif
231
232 COMSTACK tcpip_accept(COMSTACK h);
233 char *tcpip_addrstr(COMSTACK h);
234 void *tcpip_straddr(COMSTACK h, const char *str);
235
236 #if 0
237 #define TRC(x) x
238 #else
239 #define TRC(X)
240 #endif
241
242 /* this state is used for both SSL and straight TCP/IP */
243 typedef struct tcpip_state
244 {
245     char *altbuf; /* alternate buffer for surplus data */
246     int altsize;  /* size as xmalloced */
247     int altlen;   /* length of data or 0 if none */
248
249     int written;  /* -1 if we aren't writing */
250     int towrite;  /* to verify against user input */
251     int (*complete)(const unsigned char *buf, int len); /* length/comple. */
252     struct sockaddr_in addr;  /* returned by cs_straddr */
253     char buf[128]; /* returned by cs_addrstr */
254 #if HAVE_OPENSSL_SSL_H
255     SSL_CTX *ctx;
256     SSL_CTX *ctx_alloc;
257     SSL *ssl;
258 #endif
259 } tcpip_state;
260
261 #ifdef WIN32
262 static int tcpip_init (void)
263 {
264     static int initialized = 0;
265     if (!initialized)
266     {
267         WORD requested;
268         WSADATA wd;
269
270         requested = MAKEWORD(1, 1);
271         if (WSAStartup(requested, &wd))
272             return 0;
273         initialized = 1;
274     }
275     return 1;
276 }
277 #else
278 static int proto_number = 0;
279
280 static int tcpip_init (void)
281 {
282     struct protoent *proto;
283     /* only call getprotobyname once, in case it allocates memory */
284     if (!(proto = getprotobyname("tcp")))
285         return 0;
286     proto_number = proto->p_proto;
287     return 1;
288 }
289 #endif
290
291 /*
292  * This function is always called through the cs_create() macro.
293  * s >= 0: socket has already been established for us.
294  */
295 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
296 {
297     COMSTACK p;
298     tcpip_state *state;
299     int new_socket;
300 #ifdef WIN32
301     unsigned long tru = 1;
302 #endif
303
304     if (!tcpip_init ())
305         return 0;
306     if (s < 0)
307     {
308 #ifdef WIN32
309         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
310             return 0;
311 #else
312         if ((s = socket(AF_INET, SOCK_STREAM, proto_number)) < 0)
313             return 0;
314 #endif
315         new_socket = 1;
316     }
317     else
318         new_socket = 0;
319     if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
320         return 0;
321     if (!(state = (struct tcpip_state *)(p->cprivate =
322                                          xmalloc(sizeof(tcpip_state)))))
323         return 0;
324
325 #ifdef WIN32
326     if (!(p->blocking = blocking) && ioctlsocket(s, FIONBIO, &tru) < 0)
327 #else
328     if (!(p->blocking = blocking) && fcntl(s, F_SETFL, O_NONBLOCK) < 0)
329 #endif
330         return 0;
331
332     p->io_pending = 0;
333     p->iofile = s;
334     p->type = tcpip_type;
335     p->protocol = (enum oid_proto) protocol;
336
337     p->f_connect = tcpip_connect;
338     p->f_rcvconnect = tcpip_rcvconnect;
339     p->f_get = tcpip_get;
340     p->f_put = tcpip_put;
341     p->f_close = tcpip_close;
342     p->f_more = tcpip_more;
343     p->f_bind = tcpip_bind;
344     p->f_listen = tcpip_listen;
345     p->f_accept = tcpip_accept;
346     p->f_addrstr = tcpip_addrstr;
347     p->f_straddr = tcpip_straddr;
348     p->f_set_blocking = tcpip_set_blocking;
349
350     p->state = new_socket ? CS_UNBND : CS_IDLE; /* state of line */
351     p->event = CS_NONE;
352     p->cerrno = 0;
353     p->stackerr = 0;
354
355 #if HAVE_OPENSSL_SSL_H
356     state->ctx = state->ctx_alloc = 0;
357     state->ssl = 0;
358 #endif
359
360     state->altbuf = 0;
361     state->altsize = state->altlen = 0;
362     state->towrite = state->written = -1;
363     if (protocol == PROTO_WAIS)
364         state->complete = completeWAIS;
365     else
366         state->complete = completeBER;
367
368     p->timeout = COMSTACK_DEFAULT_TIMEOUT;
369     TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
370
371     return p;
372 }
373
374 #if HAVE_OPENSSL_SSL_H
375
376 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
377 {
378     tcpip_state *state;
379     COMSTACK p;
380     yaz_log(LOG_LOG, "ssl_type begin");
381
382     p = tcpip_type (s, blocking, protocol, 0);
383     if (!p)
384         return 0;
385     p->f_get = ssl_get;
386     p->f_put = ssl_put;
387     p->type = ssl_type;
388     state = (tcpip_state *) p->cprivate;
389     if (vp)
390         state->ctx = vp;
391     else
392     {
393         SSL_load_error_strings();
394         SSLeay_add_all_algorithms();
395
396         state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method());
397         if (!state->ctx)
398         {
399             tcpip_close(p);
400             return 0;
401         }
402     }
403     /* note: we don't handle already opened socket in SSL mode - yet */
404     yaz_log(LOG_LOG, "ssl_type end");
405     return p;
406 }
407 #endif
408
409 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add)
410 {
411     struct hostent *hp;
412     char *p, buf[512];
413     short int port = 210;
414     unsigned tmpadd;
415
416     if (!tcpip_init ())
417         return 0;
418     TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
419     add->sin_family = AF_INET;
420     strncpy(buf, str, 511);
421     buf[511] = 0;
422     if ((p = strchr(buf, '/')))
423         *p = 0;
424     if ((p = strchr(buf, ':')))
425     {
426         *p = 0;
427         port = atoi(p + 1);
428     }
429     add->sin_port = htons(port);
430     if (!strcmp("@", buf))
431         add->sin_addr.s_addr = INADDR_ANY;
432     else if ((hp = gethostbyname(buf)))
433         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
434                sizeof(struct in_addr));
435     else if ((tmpadd = (unsigned) inet_addr(buf)) != 0)
436         memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
437     else
438         return 0;
439     return 1;
440 }
441
442 void *tcpip_straddr(COMSTACK h, const char *str)
443 {
444     tcpip_state *sp = (tcpip_state *)h->cprivate;
445
446     if (!tcpip_strtoaddr_ex (str, &sp->addr))
447         return 0;
448     return &sp->addr;
449 }
450
451 struct sockaddr_in *tcpip_strtoaddr(const char *str)
452 {
453     static struct sockaddr_in add;
454     
455     if (!tcpip_strtoaddr_ex (str, &add))
456         return 0;
457     return &add;
458 }
459
460 int tcpip_more(COMSTACK h)
461 {
462     tcpip_state *sp = (tcpip_state *)h->cprivate;
463     
464     return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
465         sp->altlen);
466 }
467
468 /*
469  * connect(2) will block (sometimes) - nothing we can do short of doing
470  * weird things like spawning subprocesses or threading or some weird junk
471  * like that.
472  */
473 int tcpip_connect(COMSTACK h, void *address)
474 {
475     struct sockaddr_in *add = (struct sockaddr_in *)address;
476 #if HAVE_OPENSSL_SSL_H
477         tcpip_state *sp = (tcpip_state *)h->cprivate;
478 #endif
479     int r;
480
481     TRC(fprintf(stderr, "tcpip_connect\n"));
482     h->io_pending = 0;
483     if (h->state == CS_UNBND)
484     {
485         r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
486         if (r < 0)
487         {
488 #ifdef WIN32
489             if (WSAGetLastError() == WSAEWOULDBLOCK)
490             {
491                 h->state = CS_CONNECTING;
492                 h->io_pending = CS_WANT_WRITE;
493                 return 1;
494             }
495 #else
496             if (errno == EINPROGRESS)
497             {
498                 h->state = CS_CONNECTING;
499                 h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
500                 return 1;
501             }
502 #endif
503             h->cerrno = CSYSERR;
504             return -1;
505         }
506         h->state = CS_CONNECTING;
507     }
508     if (h->state != CS_CONNECTING)
509     {
510         h->cerrno = CSOUTSTATE;
511         return -1;
512     }
513 #if HAVE_OPENSSL_SSL_H
514     if (sp->ctx)
515     {
516         int res;
517
518         if (!sp->ssl)
519         {
520             sp->ssl = SSL_new (sp->ctx);
521             SSL_set_fd (sp->ssl, h->iofile);
522         }
523         res = SSL_connect (sp->ssl);
524         if (res <= 0)
525         {
526             int err = SSL_get_error(sp->ssl, res);
527             if (err == SSL_ERROR_WANT_READ)
528             {
529                 yaz_log (LOG_LOG, "SSL_connect. want_read");
530                 h->io_pending = CS_WANT_READ;
531                 return 1;
532             }
533             if (err == SSL_ERROR_WANT_WRITE)
534             {
535                 yaz_log (LOG_LOG, "SSL_connect. want_write");
536                 h->io_pending = CS_WANT_WRITE;
537                 return 1;
538             }
539             h->cerrno = CSERRORSSL;
540             return -1;
541         }
542     }
543 #endif
544     h->state = CS_DATAXFER;
545     return 0;
546 }
547
548 /*
549  * nop
550  */
551 int tcpip_rcvconnect(COMSTACK h)
552 {
553     TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
554     return 0;
555 }
556
557 #define CERTF "ztest.pem"
558 #define KEYF "ztest.pem"
559
560 int tcpip_bind(COMSTACK h, void *address, int mode)
561 {
562     struct sockaddr *addr = (struct sockaddr *)address;
563 #ifdef WIN32
564     BOOL one = 1;
565 #else
566     unsigned long one = 1;
567 #endif
568
569 #if HAVE_OPENSSL_SSL_H
570     tcpip_state *sp = (tcpip_state *)h->cprivate;
571     if (sp->ctx)
572     {
573         if (sp->ctx_alloc)
574         {
575             int res;
576             res = SSL_CTX_use_certificate_file (sp->ctx, CERTF,
577                                                 SSL_FILETYPE_PEM);
578             if (res <= 0)
579             {
580                 ERR_print_errors_fp(stderr);
581                 exit (2);
582             }
583             res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF,
584                                                SSL_FILETYPE_PEM);
585             if (res <= 0)
586             {
587                 ERR_print_errors_fp(stderr);
588                 exit (3);
589             }
590             res = SSL_CTX_check_private_key (sp->ctx);
591             if (res <= 0)
592             {
593                 ERR_print_errors_fp(stderr);
594                 exit(5);
595             }
596         }
597         TRC (fprintf (stderr, "ssl_bind\n"));
598     }
599     else
600     {
601         TRC (fprintf (stderr, "tcpip_bind\n"));
602     }
603 #else
604     TRC (fprintf (stderr, "tcpip_bind\n"));
605 #endif
606     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) 
607         &one, sizeof(one)) < 0)
608     {
609         h->cerrno = CSYSERR;
610         return -1;
611     }
612     if (bind(h->iofile, addr, sizeof(struct sockaddr_in)) < 0)
613     {
614         h->cerrno = CSYSERR;
615         return -1;
616     }
617     if (mode == CS_SERVER && listen(h->iofile, 3) < 0)
618     {
619         h->cerrno = CSYSERR;
620         return -1;
621     }
622     h->state = CS_IDLE;
623     return 0;
624 }
625
626 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
627                  int (*check_ip)(void *cd, const char *a, int len, int t),
628                  void *cd)
629 {
630     struct sockaddr_in addr;
631 #ifdef __cplusplus
632     socklen_t len = sizeof(addr);
633 #else
634     int len = sizeof(addr);
635 #endif
636
637     TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
638     if (h->state != CS_IDLE)
639     {
640         h->cerrno = CSOUTSTATE;
641         return -1;
642     }
643     h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len);
644     if (h->newfd < 0)
645     {
646         if (
647 #ifdef WIN32
648             WSAGetLastError() == WSAEWOULDBLOCK
649 #else
650             errno == EWOULDBLOCK
651 #endif
652             )
653             h->cerrno = CSNODATA;
654         else
655             h->cerrno = CSYSERR;
656         return -1;
657     }
658     if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in))
659         memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in));
660     else if (addrlen)
661         *addrlen = 0;
662     if (check_ip && (*check_ip)(cd, (const char *) &addr,
663         sizeof(addr), AF_INET))
664     {
665         h->cerrno = CSDENY;
666 #ifdef WIN32
667         closesocket(h->newfd);
668 #else
669         close(h->newfd);
670 #endif
671         h->newfd = -1;
672         return -1;
673     }
674     h->state = CS_INCON;
675     return 0;
676 }
677
678 COMSTACK tcpip_accept(COMSTACK h)
679 {
680     COMSTACK cnew;
681     tcpip_state *state, *st = (tcpip_state *)h->cprivate;
682 #ifdef WIN32
683     unsigned long tru = 1;
684 #endif
685
686     TRC(fprintf(stderr, "tcpip_accept\n"));
687     if (h->state == CS_INCON)
688     {
689         if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
690         {
691             h->cerrno = CSYSERR;
692 #ifdef WIN32
693             closesocket(h->newfd);
694 #else
695             close(h->newfd);
696 #endif
697             h->newfd = -1;
698             return 0;
699         }
700         memcpy(cnew, h, sizeof(*h));
701         cnew->iofile = h->newfd;
702         cnew->io_pending = 0;
703         if (!(state = (tcpip_state *)
704               (cnew->cprivate = xmalloc(sizeof(tcpip_state)))))
705         {
706             h->cerrno = CSYSERR;
707             if (h->newfd != -1)
708             {
709 #ifdef WIN32
710                 closesocket(h->newfd);
711 #else
712                 close(h->newfd);
713 #endif
714                 h->newfd = -1;
715             }
716             return 0;
717         }
718         if (!cnew->blocking && 
719 #ifdef WIN32
720             (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)
721 #else
722             (!cnew->blocking && fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)
723 #endif
724             )
725         {
726             h->cerrno = CSYSERR;
727             if (h->newfd != -1)
728             {
729 #ifdef WIN32
730                 closesocket(h->newfd);
731 #else
732                 close(h->newfd);
733 #endif
734                 h->newfd = -1;
735             }
736             xfree (cnew);
737             xfree (state);
738             return 0;
739         }
740         h->newfd = -1;
741         state->altbuf = 0;
742         state->altsize = state->altlen = 0;
743         state->towrite = state->written = -1;
744         state->complete = st->complete;
745         cnew->state = CS_ACCEPT;
746         h->state = CS_IDLE;
747         
748 #if HAVE_OPENSSL_SSL_H
749         state->ctx = st->ctx;
750         state->ctx_alloc = 0;
751         state->ssl = st->ssl;
752         if (state->ctx)
753         {
754             state->ssl = SSL_new (state->ctx);
755             SSL_set_fd (state->ssl, cnew->iofile);
756         }
757 #endif
758         h = cnew;
759     }
760     if (h->state == CS_ACCEPT)
761     {
762 #if HAVE_OPENSSL_SSL_H
763         tcpip_state *state = (tcpip_state *)h->cprivate;
764         if (state->ctx)
765         {
766             int res = SSL_accept (state->ssl);
767             TRC(fprintf(stderr, "SSL_accept\n"));
768             if (res <= 0)
769             {
770                 int err = SSL_get_error(state->ssl, res);
771                 if (err == SSL_ERROR_WANT_READ)
772                 {
773                     h->io_pending = CS_WANT_READ;
774                     yaz_log (LOG_LOG, "SSL_accept. want_read");
775                     return h;
776                 }
777                 if (err == SSL_ERROR_WANT_WRITE)
778                 {
779                     h->io_pending = CS_WANT_WRITE;
780                     yaz_log (LOG_LOG, "SSL_accept. want_write");
781                     return h;
782                 }
783                 cs_close (h);
784                 return 0;
785             }
786         }
787 #endif
788     }
789     else
790     {
791         h->cerrno = CSOUTSTATE;
792         return 0;
793     }
794     h->io_pending = 0;
795     h->state = CS_DATAXFER;
796     return h;
797 }
798
799 #define CS_TCPIP_BUFCHUNK 4096
800
801 /*
802  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
803  * 0=connection closed.
804  */
805 int tcpip_get(COMSTACK h, char **buf, int *bufsize)
806 {
807     tcpip_state *sp = (tcpip_state *)h->cprivate;
808     char *tmpc;
809     int tmpi, berlen, rest, req, tomove;
810     int hasread = 0, res;
811
812     TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
813     if (sp->altlen) /* switch buffers */
814     {
815         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
816             (unsigned) sp->altbuf));
817         tmpc = *buf;
818         tmpi = *bufsize;
819         *buf = sp->altbuf;
820         *bufsize = sp->altsize;
821         hasread = sp->altlen;
822         sp->altlen = 0;
823         sp->altbuf = tmpc;
824         sp->altsize = tmpi;
825     }
826     h->io_pending = 0;
827     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
828     {
829         if (!*bufsize)
830         {
831             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
832                 return -1;
833         }
834         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
835             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
836                 return -1;
837         res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
838         TRC(fprintf(stderr, "  recv res=%d, hasread=%d\n", res, hasread));
839         if (res < 0)
840         {
841 #ifdef WIN32
842             if (WSAGetLastError() == WSAEWOULDBLOCK)
843             {
844                 h->io_pending = CS_WANT_READ;
845                 break;
846             }
847             else
848                 return -1;
849 #else
850             if (errno == EWOULDBLOCK
851 #ifdef EINPROGRESS
852                 || errno == EINPROGRESS
853 #endif
854                 )
855             {
856                 h->io_pending = CS_WANT_READ;
857                 break;
858             }
859             else if (errno == 0)
860                 continue;
861             else
862                 return -1;
863 #endif
864         }
865         else if (!res)
866             return 0;
867         hasread += res;
868     }
869     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
870                   hasread, berlen));
871     /* move surplus buffer (or everything if we didn't get a BER rec.) */
872     if (hasread > berlen)
873     {
874         tomove = req = hasread - berlen;
875         rest = tomove % CS_TCPIP_BUFCHUNK;
876         if (rest)
877             req += CS_TCPIP_BUFCHUNK - rest;
878         if (!sp->altbuf)
879         {
880             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
881                 return -1;
882         } else if (sp->altsize < req)
883             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
884                 return -1;
885         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
886             (unsigned) sp->altbuf));
887         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
888     }
889     if (berlen < CS_TCPIP_BUFCHUNK - 1)
890         *(*buf + berlen) = '\0';
891     return berlen ? berlen : 1;
892 }
893
894
895 #if HAVE_OPENSSL_SSL_H
896 /*
897  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
898  * 0=connection closed.
899  */
900 int ssl_get(COMSTACK h, char **buf, int *bufsize)
901 {
902     tcpip_state *sp = (tcpip_state *)h->cprivate;
903     char *tmpc;
904     int tmpi, berlen, rest, req, tomove;
905     int hasread = 0, res;
906
907     TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
908     if (sp->altlen) /* switch buffers */
909     {
910         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
911             (unsigned) sp->altbuf));
912         tmpc = *buf;
913         tmpi = *bufsize;
914         *buf = sp->altbuf;
915         *bufsize = sp->altsize;
916         hasread = sp->altlen;
917         sp->altlen = 0;
918         sp->altbuf = tmpc;
919         sp->altsize = tmpi;
920     }
921     h->io_pending = 0;
922     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
923     {
924         if (!*bufsize)
925         {
926             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
927                 return -1;
928         }
929         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
930             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
931                 return -1;
932         res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
933         TRC(fprintf(stderr, "  SSL_read res=%d, hasread=%d\n", res, hasread));
934         if (res <= 0)
935         {
936             int ssl_err = SSL_get_error(sp->ssl, res);
937             if (ssl_err == SSL_ERROR_WANT_READ)
938             {
939                 h->io_pending = CS_WANT_READ;
940                 yaz_log (LOG_LOG, "SSL_read. want_read");
941                 break;
942             }
943             if (ssl_err == SSL_ERROR_WANT_WRITE)
944             {
945                 h->io_pending = CS_WANT_WRITE;
946                 yaz_log (LOG_LOG, "SSL_read. want_write");
947                 break;
948             }
949             if (res == 0)
950                 return 0;
951             h->cerrno = CSERRORSSL;
952             return -1;
953         }
954         hasread += res;
955     }
956     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
957         hasread, berlen));
958     /* move surplus buffer (or everything if we didn't get a BER rec.) */
959     if (hasread > berlen)
960     {
961         tomove = req = hasread - berlen;
962         rest = tomove % CS_TCPIP_BUFCHUNK;
963         if (rest)
964             req += CS_TCPIP_BUFCHUNK - rest;
965         if (!sp->altbuf)
966         {
967             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
968                 return -1;
969         } else if (sp->altsize < req)
970             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
971                 return -1;
972         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
973             (unsigned) sp->altbuf));
974         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
975     }
976     if (berlen < CS_TCPIP_BUFCHUNK - 1)
977         *(*buf + berlen) = '\0';
978     return berlen ? berlen : 1;
979 }
980 #endif
981
982 /*
983  * Returns 1, 0 or -1
984  * In nonblocking mode, you must call again with same buffer while
985  * return value is 1.
986  */
987 int tcpip_put(COMSTACK h, char *buf, int size)
988 {
989     int res;
990     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
991
992     TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
993     h->io_pending = 0;
994     if (state->towrite < 0)
995     {
996         state->towrite = size;
997         state->written = 0;
998     }
999     else if (state->towrite != size)
1000     {
1001         h->cerrno = CSWRONGBUF;
1002         return -1;
1003     }
1004     while (state->towrite > state->written)
1005     {
1006         if ((res = send(h->iofile, buf + state->written, size -
1007                         state->written, 0)) < 0)
1008         {
1009             if (
1010 #ifdef WIN32
1011                 WSAGetLastError() == WSAEWOULDBLOCK
1012 #else
1013                 errno == EAGAIN
1014 #endif
1015                 )
1016             {
1017                 TRC(fprintf(stderr, "  Flow control stop\n"));
1018                 h->io_pending = CS_WANT_WRITE;
1019                 return 1;
1020             }
1021             h->cerrno = CSYSERR;
1022             return -1;
1023         }
1024         state->written += res;
1025         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
1026                     res, state->written, size));
1027     }
1028     state->towrite = state->written = -1;
1029     TRC(fprintf(stderr, "  Ok\n"));
1030     return 0;
1031 }
1032
1033
1034 #if HAVE_OPENSSL_SSL_H
1035 /*
1036  * Returns 1, 0 or -1
1037  * In nonblocking mode, you must call again with same buffer while
1038  * return value is 1.
1039  */
1040 int ssl_put(COMSTACK h, char *buf, int size)
1041 {
1042     int res;
1043     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
1044
1045     TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
1046     h->io_pending = 0;
1047     if (state->towrite < 0)
1048     {
1049         state->towrite = size;
1050         state->written = 0;
1051     }
1052     else if (state->towrite != size)
1053     {
1054         h->cerrno = CSWRONGBUF;
1055         return -1;
1056     }
1057     while (state->towrite > state->written)
1058     {
1059         res = SSL_write (state->ssl, buf + state->written,
1060                          size - state->written);
1061         if (res <= 0)
1062         {
1063             int ssl_err = SSL_get_error(state->ssl, res);
1064             if (ssl_err == SSL_ERROR_WANT_READ)
1065             {
1066                 h->io_pending = CS_WANT_READ;
1067                 yaz_log (LOG_LOG, "SSL_write. want_read");
1068                 return 1;
1069             }
1070             if (ssl_err == SSL_ERROR_WANT_WRITE)
1071             {
1072                 h->io_pending = CS_WANT_WRITE;
1073                 yaz_log (LOG_LOG, "SSL_write. want_write");
1074                 return 1;
1075             }
1076             h->cerrno = CSERRORSSL;
1077             return -1;
1078         }
1079         state->written += res;
1080         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
1081                     res, state->written, size));
1082     }
1083     state->towrite = state->written = -1;
1084     TRC(fprintf(stderr, "  Ok\n"));
1085     return 0;
1086 }
1087 #endif
1088
1089 int tcpip_close(COMSTACK h)
1090 {
1091     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1092
1093     TRC(fprintf(stderr, "tcpip_close\n"));
1094     if (h->iofile != -1)
1095     {
1096 #if HAVE_OPENSSL_SSL_H
1097         if (sp->ssl)
1098         {
1099             SSL_shutdown (sp->ssl);
1100         }
1101 #endif
1102 #ifdef WIN32
1103         closesocket(h->iofile);
1104 #else
1105         close(h->iofile);
1106 #endif
1107     }
1108     if (sp->altbuf)
1109         xfree(sp->altbuf);
1110 #if HAVE_OPENSSL_SSL_H
1111     if (sp->ssl)
1112     {
1113         TRC (fprintf(stderr, "SSL_free\n"));
1114         SSL_free (sp->ssl);
1115     }
1116     sp->ssl = 0;
1117     if (sp->ctx_alloc)
1118         SSL_CTX_free (sp->ctx_alloc);
1119 #endif
1120     xfree(sp);
1121     xfree(h);
1122     return 0;
1123 }
1124
1125 char *tcpip_addrstr(COMSTACK h)
1126 {
1127     struct sockaddr_in addr;
1128     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1129     char *r, *buf = sp->buf;
1130     size_t len;
1131     struct hostent *host;
1132     
1133     len = sizeof(addr);
1134     if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
1135     {
1136         h->cerrno = CSYSERR;
1137         return 0;
1138     }
1139     if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
1140                               AF_INET)))
1141         r = (char*) host->h_name;
1142     else
1143         r = inet_ntoa(addr.sin_addr);
1144     sprintf(buf, "tcp:%s", r);
1145 #if HAVE_OPENSSL_SSL_H
1146     if (sp->ctx)
1147         sprintf(buf, "ssl:%s", r);
1148 #endif
1149     return buf;
1150 }
1151
1152 int static tcpip_set_blocking(COMSTACK p, int blocking)
1153 {
1154     unsigned long flag;
1155     
1156     if (p->blocking == blocking)
1157         return 1;
1158 #ifdef WIN32
1159     flag = 1;
1160     if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
1161         return 0;
1162 #else
1163     flag = fcntl(p->iofile, F_GETFL, 0);
1164     if(!blocking)
1165         flag = flag & ~O_NONBLOCK;
1166     else
1167         flag = flag | O_NONBLOCK;
1168     if (fcntl(p->iofile, F_SETFL, flag) < 0)
1169         return 0;
1170 #endif
1171     p->blocking = blocking;
1172     return 1;
1173 }