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