Define INADDR_NONE to -1 if undefined
[yaz-moved-to-github.git] / src / tcpip.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: tcpip.c,v 1.22 2006-08-30 12:55:12 adam Exp $
6  */
7 /**
8  * \file tcpip.c
9  * \brief Implements TCP/IP + SSL COMSTACK.
10  */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <signal.h>
18 #if HAVE_SYS_TYPES_H
19 #include <sys/types.h>
20 #endif
21 #if HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #ifdef WIN32
29 #include <winsock.h>
30 #else
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #include <arpa/inet.h>
34 #include <netinet/tcp.h>
35 #endif
36
37 #if HAVE_SYS_SOCKET_H
38 #include <sys/socket.h>
39 #endif
40 #if HAVE_SYS_SELECT_H
41 #include <sys/select.h>
42 #endif
43 #if HAVE_SYS_WAIT_H
44 #include <sys/wait.h>
45 #endif
46
47 #if HAVE_OPENSSL_SSL_H
48 #include <openssl/ssl.h>
49 #include <openssl/err.h>
50 #endif
51
52 #include <yaz/comstack.h>
53 #include <yaz/tcpip.h>
54 #include <yaz/nmem.h>
55
56 static int tcpip_close(COMSTACK h);
57 static int tcpip_put(COMSTACK h, char *buf, int size);
58 static int tcpip_get(COMSTACK h, char **buf, int *bufsize);
59 static int tcpip_connect(COMSTACK h, void *address);
60 static int tcpip_more(COMSTACK h);
61 static int tcpip_rcvconnect(COMSTACK h);
62 static int tcpip_bind(COMSTACK h, void *address, int mode);
63 static int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
64                  int (*check_ip)(void *cd, const char *a, int len, int type),
65                  void *cd);
66 static int tcpip_set_blocking(COMSTACK p, int blocking);
67
68 #if HAVE_OPENSSL_SSL_H
69 static int ssl_get(COMSTACK h, char **buf, int *bufsize);
70 static int ssl_put(COMSTACK h, char *buf, int size);
71 #endif
72
73 static COMSTACK tcpip_accept(COMSTACK h);
74 static char *tcpip_addrstr(COMSTACK h);
75 static void *tcpip_straddr(COMSTACK h, const char *str);
76
77 #if 0
78 #define TRC(x) x
79 #else
80 #define TRC(X)
81 #endif
82
83 #ifndef YAZ_SOCKLEN_T
84 #define YAZ_SOCKLEN_T int
85 #endif
86
87 /* this state is used for both SSL and straight TCP/IP */
88 typedef struct tcpip_state
89 {
90     char *altbuf; /* alternate buffer for surplus data */
91     int altsize;  /* size as xmalloced */
92     int altlen;   /* length of data or 0 if none */
93
94     int written;  /* -1 if we aren't writing */
95     int towrite;  /* to verify against user input */
96     int (*complete)(const unsigned char *buf, int len); /* length/comple. */
97     struct sockaddr_in addr;  /* returned by cs_straddr */
98     char buf[128]; /* returned by cs_addrstr */
99 #if HAVE_OPENSSL_SSL_H
100     SSL_CTX *ctx;       /* current CTX. */
101     SSL_CTX *ctx_alloc; /* If =ctx it is owned by CS. If 0 it is not owned */
102     SSL *ssl;
103     char cert_fname[256];
104 #endif
105 } tcpip_state;
106
107 #ifdef WIN32
108 static int tcpip_init (void)
109 {
110     static int initialized = 0;
111     if (!initialized)
112     {
113         WORD requested;
114         WSADATA wd;
115
116         requested = MAKEWORD(1, 1);
117         if (WSAStartup(requested, &wd))
118             return 0;
119         initialized = 1;
120     }
121     return 1;
122 }
123 #else
124 static int tcpip_init (void)
125 {
126     return 1;
127 }
128 #endif
129
130 /*
131  * This function is always called through the cs_create() macro.
132  * s >= 0: socket has already been established for us.
133  */
134 COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp)
135 {
136     COMSTACK p;
137     tcpip_state *sp;
138     int new_socket;
139 #ifdef WIN32
140     unsigned long tru = 1;
141 #endif
142
143     if (!tcpip_init ())
144         return 0;
145     if (s < 0)
146     {
147         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
148             return 0;
149         new_socket = 1;
150     }
151     else
152         new_socket = 0;
153     if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack))))
154         return 0;
155     if (!(sp = (struct tcpip_state *)(p->cprivate =
156                                          xmalloc(sizeof(tcpip_state)))))
157         return 0;
158
159     if (!((p->blocking = blocking)&1))
160     {
161 #ifdef WIN32
162         if (ioctlsocket(s, FIONBIO, &tru) < 0)
163             return 0;
164 #else
165         if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
166             return 0;
167 #ifndef MSG_NOSIGNAL
168         signal (SIGPIPE, SIG_IGN);
169 #endif
170 #endif
171     }
172
173     p->io_pending = 0;
174     p->iofile = s;
175     p->type = tcpip_type;
176     p->protocol = (enum oid_proto) protocol;
177
178     p->f_connect = tcpip_connect;
179     p->f_rcvconnect = tcpip_rcvconnect;
180     p->f_get = tcpip_get;
181     p->f_put = tcpip_put;
182     p->f_close = tcpip_close;
183     p->f_more = tcpip_more;
184     p->f_bind = tcpip_bind;
185     p->f_listen = tcpip_listen;
186     p->f_accept = tcpip_accept;
187     p->f_addrstr = tcpip_addrstr;
188     p->f_straddr = tcpip_straddr;
189     p->f_set_blocking = tcpip_set_blocking;
190     p->max_recv_bytes = 5000000;
191
192     p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */
193     p->event = CS_NONE;
194     p->cerrno = 0;
195     p->stackerr = 0;
196     p->user = 0;
197
198 #if HAVE_OPENSSL_SSL_H
199     sp->ctx = sp->ctx_alloc = 0;
200     sp->ssl = 0;
201     strcpy(sp->cert_fname, "yaz.pem");
202 #endif
203
204     sp->altbuf = 0;
205     sp->altsize = sp->altlen = 0;
206     sp->towrite = sp->written = -1;
207     if (protocol == PROTO_WAIS)
208         sp->complete = completeWAIS;
209     else
210         sp->complete = cs_complete_auto;
211
212     p->timeout = COMSTACK_DEFAULT_TIMEOUT;
213     TRC(fprintf(stderr, "Created new TCPIP comstack\n"));
214
215     return p;
216 }
217
218 #if HAVE_OPENSSL_SSL_H
219
220 COMSTACK ssl_type(int s, int blocking, int protocol, void *vp)
221 {
222     tcpip_state *sp;
223     COMSTACK p;
224
225     p = tcpip_type (s, blocking, protocol, 0);
226     if (!p)
227         return 0;
228     p->f_get = ssl_get;
229     p->f_put = ssl_put;
230     p->type = ssl_type;
231     sp = (tcpip_state *) p->cprivate;
232
233     sp->ctx = (SSL_CTX *) vp;  /* may be NULL */
234
235     /* note: we don't handle already opened socket in SSL mode - yet */
236     return p;
237 }
238 #endif
239
240 int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add,
241                        int default_port)
242 {
243     struct hostent *hp;
244 #if HAVE_GETHOSTBYNAME_R
245     struct hostent h;
246     char hbuf[1024];
247     int h_error;
248 #endif
249     char *p, buf[512];
250     short int port = default_port;
251 #ifdef WIN32
252     unsigned long tmpadd;
253 #else
254     in_addr_t tmpadd;
255 #endif
256
257 #ifndef INADDR_NONE
258 #define INADDR_NONE -1
259 #endif
260
261     if (!tcpip_init ())
262         return 0;
263     TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL"));
264     add->sin_family = AF_INET;
265     strncpy(buf, str, 511);
266     buf[511] = 0;
267     if ((p = strchr(buf, '/')))
268         *p = 0;
269     if ((p = strchr(buf, ':')))
270     {
271         *p = 0;
272         port = atoi(p + 1);
273     }
274     add->sin_port = htons(port);
275     if (!strcmp("@", buf))
276     {
277         add->sin_addr.s_addr = INADDR_ANY;
278     }
279     else if ((tmpadd = inet_addr(buf)) != INADDR_NONE)
280     {
281         memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
282     }
283 #if HAVE_GETHOSTBYNAME_R
284     else if (gethostbyname_r(buf, &h, hbuf, sizeof(hbuf), &hp, &h_error) == 0)
285     {
286         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
287                sizeof(struct in_addr));
288     }
289 #else
290     else if ((hp = gethostbyname(buf)))
291     {
292         memcpy(&add->sin_addr.s_addr, *hp->h_addr_list,
293                sizeof(struct in_addr));
294     }
295 #endif
296     else
297         return 0;
298     return 1;
299 }
300
301 void *tcpip_straddr(COMSTACK h, const char *str)
302 {
303     tcpip_state *sp = (tcpip_state *)h->cprivate;
304     int port = 210;
305
306     if (h->protocol == PROTO_HTTP)
307         port = 80;
308
309     if (!tcpip_strtoaddr_ex (str, &sp->addr, port))
310         return 0;
311     return &sp->addr;
312 }
313
314 struct sockaddr_in *tcpip_strtoaddr(const char *str)
315 {
316     static struct sockaddr_in add;
317     
318     if (!tcpip_strtoaddr_ex (str, &add, 210))
319         return 0;
320     return &add;
321 }
322
323 int tcpip_more(COMSTACK h)
324 {
325     tcpip_state *sp = (tcpip_state *)h->cprivate;
326     
327     return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf,
328         sp->altlen);
329 }
330
331 /*
332  * connect(2) will block (sometimes) - nothing we can do short of doing
333  * weird things like spawning subprocesses or threading or some weird junk
334  * like that.
335  */
336 int tcpip_connect(COMSTACK h, void *address)
337 {
338     struct sockaddr_in *add = (struct sockaddr_in *)address;
339     int r;
340 #ifdef __sun__
341     int recbuflen;
342     YAZ_SOCKLEN_T rbufsize = sizeof(recbuflen);
343 #endif
344     TRC(fprintf(stderr, "tcpip_connect\n"));
345     h->io_pending = 0;
346     if (h->state != CS_ST_UNBND)
347     {
348         h->cerrno = CSOUTSTATE;
349         return -1;
350     }
351 #ifdef __sun__
352     /* On Suns, you must set a bigger Receive Buffer BEFORE a call to connect
353      * This gives the connect a chance to negotiate with the other side
354      * (see 'man tcp') 
355      */
356     if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) < 0 )
357     {
358         h->cerrno = CSYSERR;
359         return -1;
360     }
361     TRC(fprintf( stderr, "Current Size of TCP Receive Buffer= %d\n",
362                  recbuflen ));
363     recbuflen *= 10; /* lets be optimistic */
364     if ( setsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, rbufsize ) < 0 )
365     {
366         h->cerrno = CSYSERR;
367         return -1;
368     }
369     if ( getsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, &rbufsize ) )
370     {
371         h->cerrno = CSYSERR;
372         return -1;
373     }
374     TRC(fprintf( stderr, "New Size of TCP Receive Buffer = %d\n",
375                  recbuflen ));
376 #endif
377     r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add));
378     if (r < 0)
379     {
380 #ifdef WIN32
381         if (WSAGetLastError() == WSAEWOULDBLOCK)
382         {
383             h->event = CS_CONNECT;
384             h->state = CS_ST_CONNECTING;
385             h->io_pending = CS_WANT_WRITE;
386             return 1;
387         }
388 #else
389         if (yaz_errno() == EINPROGRESS)
390         {
391             h->event = CS_CONNECT;
392             h->state = CS_ST_CONNECTING;
393             h->io_pending = CS_WANT_WRITE|CS_WANT_READ;
394             return 1;
395         }
396 #endif
397         h->cerrno = CSYSERR;
398         return -1;
399     }
400     h->event = CS_CONNECT;
401     h->state = CS_ST_CONNECTING;
402
403     return tcpip_rcvconnect (h);
404 }
405
406 /*
407  * nop
408  */
409 int tcpip_rcvconnect(COMSTACK h)
410 {
411 #if HAVE_OPENSSL_SSL_H
412     tcpip_state *sp = (tcpip_state *)h->cprivate;
413 #endif
414     TRC(fprintf(stderr, "tcpip_rcvconnect\n"));
415
416     if (h->state == CS_ST_DATAXFER)
417         return 0;
418     if (h->state != CS_ST_CONNECTING)
419     {
420         h->cerrno = CSOUTSTATE;
421         return -1;
422     }
423 #if HAVE_OPENSSL_SSL_H
424     if (h->type == ssl_type && !sp->ctx)
425     {
426         SSL_load_error_strings();
427         SSLeay_add_all_algorithms();
428
429         sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method());
430         if (!sp->ctx)
431         {
432             h->cerrno = CSERRORSSL;
433             return -1;
434         }
435     }
436     if (sp->ctx)
437     {
438         int res;
439
440         if (!sp->ssl)
441         {
442             sp->ssl = SSL_new (sp->ctx);
443             SSL_set_fd (sp->ssl, h->iofile);
444         }
445         res = SSL_connect (sp->ssl);
446         if (res <= 0)
447         {
448             int err = SSL_get_error(sp->ssl, res);
449             if (err == SSL_ERROR_WANT_READ)
450             {
451                 h->io_pending = CS_WANT_READ;
452                 return 1;
453             }
454             if (err == SSL_ERROR_WANT_WRITE)
455             {
456                 h->io_pending = CS_WANT_WRITE;
457                 return 1;
458             }
459             h->cerrno = CSERRORSSL;
460             return -1;
461         }
462     }
463 #endif
464     h->event = CS_DATA;
465     h->state = CS_ST_DATAXFER;
466     return 0;
467 }
468
469 #define CERTF "ztest.pem"
470 #define KEYF "ztest.pem"
471
472 static void tcpip_setsockopt (int fd)
473 {
474 #if 0
475     int len = 4096;
476     int set = 1;
477     
478     if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
479     {
480         yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt TCP_NODELAY");
481     }
482     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
483     {
484         yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt SNDBUF");
485     }
486     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
487     {
488         yaz_log(LOG_WARN|LOG_ERRNO, "setsockopt RCVBUF");
489     }
490 #endif
491 }
492
493 static int tcpip_bind(COMSTACK h, void *address, int mode)
494 {
495     struct sockaddr *addr = (struct sockaddr *)address;
496 #ifdef WIN32
497     BOOL one = 1;
498 #else
499     unsigned long one = 1;
500 #endif
501
502 #if HAVE_OPENSSL_SSL_H
503     tcpip_state *sp = (tcpip_state *)h->cprivate;
504     if (h->type == ssl_type && !sp->ctx)
505     {
506         SSL_load_error_strings();
507         SSLeay_add_all_algorithms();
508
509         sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method());
510         if (!sp->ctx)
511         {
512             h->cerrno = CSERRORSSL;
513             return -1;
514         }
515     }
516     if (sp->ctx)
517     {
518         if (sp->ctx_alloc)
519         {
520             int res;
521             res = SSL_CTX_use_certificate_chain_file(sp->ctx, sp->cert_fname);
522             if (res <= 0)
523             {
524                 ERR_print_errors_fp(stderr);
525                 exit (2);
526             }
527             res = SSL_CTX_use_PrivateKey_file (sp->ctx, sp->cert_fname,
528                                                SSL_FILETYPE_PEM);
529             if (res <= 0)
530             {
531                 ERR_print_errors_fp(stderr);
532                 exit (3);
533             }
534             res = SSL_CTX_check_private_key (sp->ctx);
535             if (res <= 0)
536             {
537                 ERR_print_errors_fp(stderr);
538                 exit(5);
539             }
540         }
541         TRC (fprintf (stderr, "ssl_bind\n"));
542     }
543     else
544     {
545         TRC (fprintf (stderr, "tcpip_bind\n"));
546     }
547 #else
548     TRC (fprintf (stderr, "tcpip_bind\n"));
549 #endif
550 #ifndef WIN32
551     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) 
552         &one, sizeof(one)) < 0)
553     {
554         h->cerrno = CSYSERR;
555         return -1;
556     }
557 #endif
558     tcpip_setsockopt(h->iofile);
559     if (bind(h->iofile, addr, sizeof(struct sockaddr_in)))
560     {
561         h->cerrno = CSYSERR;
562         return -1;
563     }
564     /* Allow a maximum-sized backlog of waiting-to-connect clients */
565     if (mode == CS_SERVER && listen(h->iofile, SOMAXCONN) < 0)
566     {
567         h->cerrno = CSYSERR;
568         return -1;
569     }
570     h->state = CS_ST_IDLE;
571     h->event = CS_LISTEN;
572     return 0;
573 }
574
575 int tcpip_listen(COMSTACK h, char *raddr, int *addrlen,
576                  int (*check_ip)(void *cd, const char *a, int len, int t),
577                  void *cd)
578 {
579     struct sockaddr_in addr;
580     YAZ_SOCKLEN_T len = sizeof(addr);
581
582     TRC(fprintf(stderr, "tcpip_listen pid=%d\n", getpid()));
583     if (h->state != CS_ST_IDLE)
584     {
585         h->cerrno = CSOUTSTATE;
586         return -1;
587     }
588     h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len);
589     if (h->newfd < 0)
590     {
591         if (
592 #ifdef WIN32
593             WSAGetLastError() == WSAEWOULDBLOCK
594 #else
595             yaz_errno() == EWOULDBLOCK 
596 #ifdef EAGAIN
597 #if EAGAIN != EWOULDBLOCK
598             || yaz_errno() == EAGAIN
599 #endif
600 #endif
601 #endif
602             )
603             h->cerrno = CSNODATA;
604         else
605             h->cerrno = CSYSERR;
606         return -1;
607     }
608     if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in))
609         memcpy(raddr, &addr, *addrlen = sizeof(struct sockaddr_in));
610     else if (addrlen)
611         *addrlen = 0;
612     if (check_ip && (*check_ip)(cd, (const char *) &addr,
613         sizeof(addr), AF_INET))
614     {
615         h->cerrno = CSDENY;
616 #ifdef WIN32
617         closesocket(h->newfd);
618 #else
619         close(h->newfd);
620 #endif
621         h->newfd = -1;
622         return -1;
623     }
624     h->state = CS_ST_INCON;
625     tcpip_setsockopt (h->newfd);
626     return 0;
627 }
628
629 COMSTACK tcpip_accept(COMSTACK h)
630 {
631     COMSTACK cnew;
632     tcpip_state *state, *st = (tcpip_state *)h->cprivate;
633 #ifdef WIN32
634     unsigned long tru = 1;
635 #endif
636
637     TRC(fprintf(stderr, "tcpip_accept\n"));
638     if (h->state == CS_ST_INCON)
639     {
640         if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew))))
641         {
642             h->cerrno = CSYSERR;
643 #ifdef WIN32
644             closesocket(h->newfd);
645 #else
646             close(h->newfd);
647 #endif
648             h->newfd = -1;
649             return 0;
650         }
651         memcpy(cnew, h, sizeof(*h));
652         cnew->iofile = h->newfd;
653         cnew->io_pending = 0;
654         if (!(state = (tcpip_state *)
655               (cnew->cprivate = xmalloc(sizeof(tcpip_state)))))
656         {
657             h->cerrno = CSYSERR;
658             if (h->newfd != -1)
659             {
660 #ifdef WIN32
661                 closesocket(h->newfd);
662 #else
663                 close(h->newfd);
664 #endif
665                 h->newfd = -1;
666             }
667             return 0;
668         }
669         if (!(cnew->blocking&1) && 
670 #ifdef WIN32
671             (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0)
672 #else
673             (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0)
674 #endif
675             )
676         {
677             h->cerrno = CSYSERR;
678             if (h->newfd != -1)
679             {
680 #ifdef WIN32
681                 closesocket(h->newfd);
682 #else
683                 close(h->newfd);
684 #endif
685                 h->newfd = -1;
686             }
687             xfree (cnew);
688             xfree (state);
689             return 0;
690         }
691         h->newfd = -1;
692         state->altbuf = 0;
693         state->altsize = state->altlen = 0;
694         state->towrite = state->written = -1;
695         state->complete = st->complete;
696         cnew->state = CS_ST_ACCEPT;
697         h->state = CS_ST_IDLE;
698         
699 #if HAVE_OPENSSL_SSL_H
700         state->ctx = st->ctx;
701         state->ctx_alloc = 0;
702         state->ssl = st->ssl;
703         if (state->ctx)
704         {
705             state->ssl = SSL_new (state->ctx);
706             SSL_set_fd (state->ssl, cnew->iofile);
707         }
708 #endif
709         h = cnew;
710     }
711     if (h->state == CS_ST_ACCEPT)
712     {
713 #if HAVE_OPENSSL_SSL_H
714         tcpip_state *state = (tcpip_state *)h->cprivate;
715         if (state->ctx)
716         {
717             int res = SSL_accept (state->ssl);
718             TRC(fprintf(stderr, "SSL_accept\n"));
719             if (res <= 0)
720             {
721                 int err = SSL_get_error(state->ssl, res);
722                 if (err == SSL_ERROR_WANT_READ)
723                 {
724                     h->io_pending = CS_WANT_READ;
725                     return h;
726                 }
727                 if (err == SSL_ERROR_WANT_WRITE)
728                 {
729                     h->io_pending = CS_WANT_WRITE;
730                     return h;
731                 }
732                 cs_close (h);
733                 return 0;
734             }
735         }
736 #endif
737     }
738     else
739     {
740         h->cerrno = CSOUTSTATE;
741         return 0;
742     }
743     h->io_pending = 0;
744     h->state = CS_ST_DATAXFER;
745     h->event = CS_DATA;
746     return h;
747 }
748
749 #define CS_TCPIP_BUFCHUNK 4096
750
751 /*
752  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
753  * 0=connection closed.
754  */
755 int tcpip_get(COMSTACK h, char **buf, int *bufsize)
756 {
757     tcpip_state *sp = (tcpip_state *)h->cprivate;
758     char *tmpc;
759     int tmpi, berlen, rest, req, tomove;
760     int hasread = 0, res;
761
762     TRC(fprintf(stderr, "tcpip_get: bufsize=%d\n", *bufsize));
763     if (sp->altlen) /* switch buffers */
764     {
765         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
766             (unsigned) sp->altbuf));
767         tmpc = *buf;
768         tmpi = *bufsize;
769         *buf = sp->altbuf;
770         *bufsize = sp->altsize;
771         hasread = sp->altlen;
772         sp->altlen = 0;
773         sp->altbuf = tmpc;
774         sp->altsize = tmpi;
775     }
776     h->io_pending = 0;
777     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
778     {
779         if (!*bufsize)
780         {
781             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
782             {
783                 h->cerrno = CSYSERR;
784                 return -1;
785             }
786         }
787         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
788             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
789             {
790                 h->cerrno = CSYSERR;
791                 return -1;
792             }
793 #ifdef __sun__
794         yaz_set_errno( 0 );
795         /* unfortunatly, sun sometimes forgets to set errno in recv
796            when EWOULDBLOCK etc. would be required (res = -1) */
797 #endif
798         res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0);
799         TRC(fprintf(stderr, "  recv res=%d, hasread=%d\n", res, hasread));
800         if (res < 0)
801         {
802           TRC(fprintf(stderr, "  recv errno=%d, (%s)\n", yaz_errno(), 
803                       strerror(yaz_errno())));
804 #ifdef WIN32
805             if (WSAGetLastError() == WSAEWOULDBLOCK)
806             {
807                 h->io_pending = CS_WANT_READ;
808                 break;
809             }
810             else
811                 return -1;
812 #else
813             if (yaz_errno() == EWOULDBLOCK 
814 #ifdef EAGAIN   
815 #if EAGAIN != EWOULDBLOCK
816                 || yaz_errno() == EAGAIN
817 #endif
818 #endif
819                 || yaz_errno() == EINPROGRESS
820 #ifdef __sun__
821                 || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */
822 #endif
823                 )
824             {
825                 h->io_pending = CS_WANT_READ;
826                 break;
827             }
828             else if (yaz_errno() == 0)
829                 continue;
830             else
831                 return -1;
832 #endif
833         }
834         else if (!res)
835             return hasread;
836         hasread += res;
837         if (hasread > h->max_recv_bytes)
838         {
839             h->cerrno = CSBUFSIZE;
840             return -1;
841         }
842     }
843     TRC (fprintf (stderr, "  Out of read loop with hasread=%d, berlen=%d\n",
844                   hasread, berlen));
845     /* move surplus buffer (or everything if we didn't get a BER rec.) */
846     if (hasread > berlen)
847     {
848         tomove = req = hasread - berlen;
849         rest = tomove % CS_TCPIP_BUFCHUNK;
850         if (rest)
851             req += CS_TCPIP_BUFCHUNK - rest;
852         if (!sp->altbuf)
853         {
854             if (!(sp->altbuf = (char *)xmalloc(sp->altsize = req)))
855                 return -1;
856         } else if (sp->altsize < req)
857             if (!(sp->altbuf =(char *)xrealloc(sp->altbuf, sp->altsize = req)))
858                 return -1;
859         TRC(fprintf(stderr, "  Moving %d bytes to altbuf(0x%x)\n", tomove,
860             (unsigned) sp->altbuf));
861         memcpy(sp->altbuf, *buf + berlen, sp->altlen = tomove);
862     }
863     if (berlen < CS_TCPIP_BUFCHUNK - 1)
864         *(*buf + berlen) = '\0';
865     return berlen ? berlen : 1;
866 }
867
868
869 #if HAVE_OPENSSL_SSL_H
870 /*
871  * Return: -1 error, >1 good, len of buffer, ==1 incomplete buffer,
872  * 0=connection closed.
873  */
874 int ssl_get(COMSTACK h, char **buf, int *bufsize)
875 {
876     tcpip_state *sp = (tcpip_state *)h->cprivate;
877     char *tmpc;
878     int tmpi, berlen, rest, req, tomove;
879     int hasread = 0, res;
880
881     TRC(fprintf(stderr, "ssl_get: bufsize=%d\n", *bufsize));
882     if (sp->altlen) /* switch buffers */
883     {
884         TRC(fprintf(stderr, "  %d bytes in altbuf (0x%x)\n", sp->altlen,
885             (unsigned) sp->altbuf));
886         tmpc = *buf;
887         tmpi = *bufsize;
888         *buf = sp->altbuf;
889         *bufsize = sp->altsize;
890         hasread = sp->altlen;
891         sp->altlen = 0;
892         sp->altbuf = tmpc;
893         sp->altsize = tmpi;
894     }
895     h->io_pending = 0;
896     while (!(berlen = (*sp->complete)((unsigned char *)*buf, hasread)))
897     {
898         if (!*bufsize)
899         {
900             if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK)))
901                 return -1;
902         }
903         else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK)
904             if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2)))
905                 return -1;
906         res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK);
907         TRC(fprintf(stderr, "  SSL_read res=%d, hasread=%d\n", res, hasread));
908         if (res <= 0)
909         {
910             int ssl_err = SSL_get_error(sp->ssl, res);
911             if (ssl_err == SSL_ERROR_WANT_READ)
912             {
913                 h->io_pending = CS_WANT_READ;
914                 break;
915             }
916             if (ssl_err == SSL_ERROR_WANT_WRITE)
917             {
918                 h->io_pending = CS_WANT_WRITE;
919                 break;
920             }
921             if (res == 0)
922                 return 0;
923             h->cerrno = CSERRORSSL;
924             return -1;
925         }
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 #endif
953
954 /*
955  * Returns 1, 0 or -1
956  * In nonblocking mode, you must call again with same buffer while
957  * return value is 1.
958  */
959 int tcpip_put(COMSTACK h, char *buf, int size)
960 {
961     int res;
962     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
963
964     TRC(fprintf(stderr, "tcpip_put: size=%d\n", size));
965     h->io_pending = 0;
966     h->event = CS_DATA;
967     if (state->towrite < 0)
968     {
969         state->towrite = size;
970         state->written = 0;
971     }
972     else if (state->towrite != size)
973     {
974         h->cerrno = CSWRONGBUF;
975         return -1;
976     }
977     while (state->towrite > state->written)
978     {
979         if ((res =
980              send(h->iofile, buf + state->written, size -
981                   state->written, 
982 #ifdef MSG_NOSIGNAL
983                   MSG_NOSIGNAL
984 #else
985                   0
986 #endif
987                  )) < 0)
988         {
989             if (
990 #ifdef WIN32
991                 WSAGetLastError() == WSAEWOULDBLOCK
992 #else
993                 yaz_errno() == EWOULDBLOCK 
994 #ifdef EAGAIN
995 #if EAGAIN != EWOULDBLOCK
996              || yaz_errno() == EAGAIN
997 #endif
998 #endif
999 #ifdef __sun__
1000                 || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */
1001 #endif
1002                 || yaz_errno() == EINPROGRESS
1003 #endif
1004                 )
1005             {
1006                 TRC(fprintf(stderr, "  Flow control stop\n"));
1007                 h->io_pending = CS_WANT_WRITE;
1008                 return 1;
1009             }
1010             h->cerrno = CSYSERR;
1011             return -1;
1012         }
1013         state->written += res;
1014         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
1015                     res, state->written, size));
1016     }
1017     state->towrite = state->written = -1;
1018     TRC(fprintf(stderr, "  Ok\n"));
1019     return 0;
1020 }
1021
1022
1023 #if HAVE_OPENSSL_SSL_H
1024 /*
1025  * Returns 1, 0 or -1
1026  * In nonblocking mode, you must call again with same buffer while
1027  * return value is 1.
1028  */
1029 int ssl_put(COMSTACK h, char *buf, int size)
1030 {
1031     int res;
1032     struct tcpip_state *state = (struct tcpip_state *)h->cprivate;
1033
1034     TRC(fprintf(stderr, "ssl_put: size=%d\n", size));
1035     h->io_pending = 0;
1036     h->event = CS_DATA;
1037     if (state->towrite < 0)
1038     {
1039         state->towrite = size;
1040         state->written = 0;
1041     }
1042     else if (state->towrite != size)
1043     {
1044         h->cerrno = CSWRONGBUF;
1045         return -1;
1046     }
1047     while (state->towrite > state->written)
1048     {
1049         res = SSL_write (state->ssl, buf + state->written,
1050                          size - state->written);
1051         if (res <= 0)
1052         {
1053             int ssl_err = SSL_get_error(state->ssl, res);
1054             if (ssl_err == SSL_ERROR_WANT_READ)
1055             {
1056                 h->io_pending = CS_WANT_READ;
1057                 return 1;
1058             }
1059             if (ssl_err == SSL_ERROR_WANT_WRITE)
1060             {
1061                 h->io_pending = CS_WANT_WRITE;
1062                 return 1;
1063             }
1064             h->cerrno = CSERRORSSL;
1065             return -1;
1066         }
1067         state->written += res;
1068         TRC(fprintf(stderr, "  Wrote %d, written=%d, nbytes=%d\n",
1069                     res, state->written, size));
1070     }
1071     state->towrite = state->written = -1;
1072     TRC(fprintf(stderr, "  Ok\n"));
1073     return 0;
1074 }
1075 #endif
1076
1077 int tcpip_close(COMSTACK h)
1078 {
1079     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1080
1081     TRC(fprintf(stderr, "tcpip_close\n"));
1082     if (h->iofile != -1)
1083     {
1084 #if HAVE_OPENSSL_SSL_H
1085         if (sp->ssl)
1086         {
1087             SSL_shutdown (sp->ssl);
1088         }
1089 #endif
1090 #ifdef WIN32
1091         closesocket(h->iofile);
1092 #else
1093         close(h->iofile);
1094 #endif
1095     }
1096     if (sp->altbuf)
1097         xfree(sp->altbuf);
1098 #if HAVE_OPENSSL_SSL_H
1099     if (sp->ssl)
1100     {
1101         TRC (fprintf(stderr, "SSL_free\n"));
1102         SSL_free (sp->ssl);
1103     }
1104     sp->ssl = 0;
1105     if (sp->ctx_alloc)
1106         SSL_CTX_free (sp->ctx_alloc);
1107 #endif
1108     xfree(sp);
1109     xfree(h);
1110     return 0;
1111 }
1112
1113 char *tcpip_addrstr(COMSTACK h)
1114 {
1115     struct sockaddr_in addr;
1116     tcpip_state *sp = (struct tcpip_state *)h->cprivate;
1117     char *r = 0, *buf = sp->buf;
1118     YAZ_SOCKLEN_T len;
1119     struct hostent *host;
1120     
1121     len = sizeof(addr);
1122     if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0)
1123     {
1124         h->cerrno = CSYSERR;
1125         return 0;
1126     }
1127     if (!(h->blocking&2)) {
1128         if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr),
1129                               AF_INET)))
1130             r = (char*) host->h_name;
1131     }
1132     if (!r)
1133         r = inet_ntoa(addr.sin_addr);
1134     if (h->protocol == PROTO_HTTP)
1135         sprintf(buf, "http:%s", r);
1136     else
1137         sprintf(buf, "tcp:%s", r);
1138 #if HAVE_OPENSSL_SSL_H
1139     if (sp->ctx)
1140     {
1141         if (h->protocol == PROTO_HTTP)
1142             sprintf(buf, "https:%s", r);
1143         else
1144             sprintf(buf, "ssl:%s", r);
1145     }
1146 #endif
1147     return buf;
1148 }
1149
1150 int static tcpip_set_blocking(COMSTACK p, int blocking)
1151 {
1152     unsigned long flag;
1153     
1154     if (p->blocking == blocking)
1155         return 1;
1156 #ifdef WIN32
1157     flag = 1;
1158     if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0)
1159         return 0;
1160 #else
1161     flag = fcntl(p->iofile, F_GETFL, 0);
1162     if(!(blocking&1))
1163         flag = flag & ~O_NONBLOCK;
1164     else
1165         flag = flag | O_NONBLOCK;
1166     if (fcntl(p->iofile, F_SETFL, flag) < 0)
1167         return 0;
1168 #endif
1169     p->blocking = blocking;
1170     return 1;
1171 }
1172
1173 #if HAVE_OPENSSL_SSL_H
1174 int cs_set_ssl_ctx(COMSTACK cs, void *ctx)
1175 {
1176     struct tcpip_state *sp;
1177     if (!cs || cs->type != ssl_type)
1178         return 0;
1179     sp = (struct tcpip_state *) cs->cprivate;
1180     if (sp->ctx_alloc)
1181         return 0;
1182     sp->ctx = (SSL_CTX *) ctx;
1183     return 1;
1184 }
1185
1186 void *cs_get_ssl(COMSTACK cs)
1187 {
1188     struct tcpip_state *sp;
1189     if (!cs || cs->type != ssl_type)
1190         return 0;
1191     sp = (struct tcpip_state *) cs->cprivate;
1192     return sp->ssl;  
1193 }
1194
1195 int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname)
1196 {
1197     struct tcpip_state *sp;
1198     if (!cs || cs->type != ssl_type)
1199         return 0;
1200     sp = (struct tcpip_state *) cs->cprivate;
1201     strncpy(sp->cert_fname, fname, sizeof(sp->cert_fname)-1);
1202     sp->cert_fname[sizeof(sp->cert_fname)-1] = '\0';
1203     return 1;
1204 }
1205
1206 int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len)
1207 {
1208     SSL *ssl = (SSL *) cs_get_ssl(cs);
1209     if (ssl)
1210     {
1211         X509 *server_cert = SSL_get_peer_certificate (ssl);
1212         if (server_cert)
1213         {
1214             BIO *bio = BIO_new(BIO_s_mem());
1215             char *pem_buf;
1216             /* get PEM buffer in memory */
1217             PEM_write_bio_X509(bio, server_cert);
1218             *len = BIO_get_mem_data(bio, &pem_buf);
1219             *buf = (char *) xmalloc(*len);
1220             memcpy(*buf, pem_buf, *len);
1221             BIO_free(bio);
1222             return 1;
1223         }
1224     }
1225     return 0;
1226 }
1227 #else
1228 int cs_set_ssl_ctx(COMSTACK cs, void *ctx)
1229 {
1230     return 0;
1231 }
1232
1233 void *cs_get_ssl(COMSTACK cs)
1234 {
1235     return 0;
1236 }
1237
1238 int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len)
1239 {
1240     return 0;
1241 }
1242
1243 int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname)
1244 {
1245     return 0;
1246 }
1247 #endif
1248
1249 /*
1250  * Local variables:
1251  * c-basic-offset: 4
1252  * indent-tabs-mode: nil
1253  * End:
1254  * vim: shiftwidth=4 tabstop=8 expandtab
1255  */
1256