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