X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ftcpip.c;h=66dbd09bf4502cc424b30176f273dc86d9e3b779;hb=b335dcd534287a207ef75b35e486df21293feddb;hp=689b0d561add3a302696e790ae1dde20db7dc800;hpb=7d8ce865edf7af1329b506590717fc846c9becb6;p=yaz-moved-to-github.git diff --git a/src/tcpip.c b/src/tcpip.c index 689b0d5..66dbd09 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -1,22 +1,49 @@ /* - * Copyright (c) 1995-2004, Index Data + * Copyright (C) 1995-2006, Index Data ApS * See the file LICENSE for details. * - * $Id: tcpip.c,v 1.9 2004-05-10 11:40:51 adam Exp $ + * $Id: tcpip.c,v 1.23 2006-08-30 18:58:59 adam Exp $ + */ +/** + * \file tcpip.c + * \brief Implements TCP/IP + SSL COMSTACK. */ #include #include #include +#include +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif #ifdef WIN32 +#include #else -#include +#include +#include +#include +#include +#endif + +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include #endif -#include -#include -#include #if HAVE_OPENSSL_SSL_H #include #include @@ -24,14 +51,8 @@ #include #include -#include #include -#ifdef WIN32 -#else -#include -#endif - static int tcpip_close(COMSTACK h); static int tcpip_put(COMSTACK h, char *buf, int size); static int tcpip_get(COMSTACK h, char **buf, int *bufsize); @@ -40,8 +61,8 @@ static int tcpip_more(COMSTACK h); static int tcpip_rcvconnect(COMSTACK h); static int tcpip_bind(COMSTACK h, void *address, int mode); static int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, - int (*check_ip)(void *cd, const char *a, int len, int type), - void *cd); + int (*check_ip)(void *cd, const char *a, int len, int type), + void *cd); static int tcpip_set_blocking(COMSTACK p, int blocking); #if HAVE_OPENSSL_SSL_H @@ -73,7 +94,11 @@ typedef struct tcpip_state int written; /* -1 if we aren't writing */ int towrite; /* to verify against user input */ int (*complete)(const unsigned char *buf, int len); /* length/comple. */ +#if HAVE_GETADDRINFO + struct addrinfo *res; +#else struct sockaddr_in addr; /* returned by cs_straddr */ +#endif char buf[128]; /* returned by cs_addrstr */ #if HAVE_OPENSSL_SSL_H SSL_CTX *ctx; /* current CTX. */ @@ -123,17 +148,17 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) return 0; if (s < 0) { - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) - return 0; - new_socket = 1; + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return 0; + new_socket = 1; } else - new_socket = 0; + new_socket = 0; if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack)))) - return 0; + return 0; if (!(sp = (struct tcpip_state *)(p->cprivate = xmalloc(sizeof(tcpip_state))))) - return 0; + return 0; if (!((p->blocking = blocking)&1)) { @@ -166,11 +191,13 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) p->f_addrstr = tcpip_addrstr; p->f_straddr = tcpip_straddr; p->f_set_blocking = tcpip_set_blocking; + p->max_recv_bytes = 5000000; p->state = new_socket ? CS_ST_UNBND : CS_ST_IDLE; /* state of line */ p->event = CS_NONE; p->cerrno = 0; p->stackerr = 0; + p->user = 0; #if HAVE_OPENSSL_SSL_H sp->ctx = sp->ctx_alloc = 0; @@ -178,13 +205,16 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) strcpy(sp->cert_fname, "yaz.pem"); #endif +#if HAVE_GETADDRINFO + sp->res = 0; +#endif sp->altbuf = 0; sp->altsize = sp->altlen = 0; sp->towrite = sp->written = -1; if (protocol == PROTO_WAIS) - sp->complete = completeWAIS; + sp->complete = completeWAIS; else - sp->complete = cs_complete_auto; + sp->complete = cs_complete_auto; p->timeout = COMSTACK_DEFAULT_TIMEOUT; TRC(fprintf(stderr, "Created new TCPIP comstack\n")); @@ -201,7 +231,7 @@ COMSTACK ssl_type(int s, int blocking, int protocol, void *vp) p = tcpip_type (s, blocking, protocol, 0); if (!p) - return 0; + return 0; p->f_get = ssl_get; p->f_put = ssl_put; p->type = ssl_type; @@ -214,20 +244,64 @@ COMSTACK ssl_type(int s, int blocking, int protocol, void *vp) } #endif +#if HAVE_GETADDRINFO +/* resolve using getaddrinfo */ +struct addrinfo *tcpip_getaddrinfo(const char *str, const char *port) +{ + struct addrinfo hints, *res; + int error; + char host[512], *p; + + hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + strncpy(host, str, sizeof(host)-1); + host[sizeof(host)-1] = 0; + if ((p = strchr(host, '/'))) + *p = 0; + if ((p = strchr(host, ':'))) + { + *p = '\0'; + port = p+1; + } + + if (!strcmp("@", host)) + { + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(0, port, &hints, &res); + } + else + { + error = getaddrinfo(host, port, &hints, &res); + } + if (error) + return 0; + return res; +} + +#endif +/* gethostbyname .. old systems */ int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add, int default_port) { struct hostent *hp; char *p, buf[512]; short int port = default_port; - unsigned tmpadd; - - if (!tcpip_init ()) - return 0; +#ifdef WIN32 + unsigned long tmpadd; +#else + in_addr_t tmpadd; +#endif TRC(fprintf(stderr, "tcpip_strtoaddress: %s\n", str ? str : "NULL")); add->sin_family = AF_INET; - strncpy(buf, str, 511); - buf[511] = 0; + strncpy(buf, str, sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; if ((p = strchr(buf, '/'))) *p = 0; if ((p = strchr(buf, ':'))) @@ -237,45 +311,61 @@ int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add, } add->sin_port = htons(port); if (!strcmp("@", buf)) + { add->sin_addr.s_addr = INADDR_ANY; + } + else if ((tmpadd = inet_addr(buf)) != -1) + { + memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr)); + } else if ((hp = gethostbyname(buf))) + { memcpy(&add->sin_addr.s_addr, *hp->h_addr_list, - sizeof(struct in_addr)); - else if ((tmpadd = (unsigned) inet_addr(buf)) != 0) - memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr)); + sizeof(struct in_addr)); + } else return 0; return 1; } + +#if HAVE_GETADDRINFO void *tcpip_straddr(COMSTACK h, const char *str) { tcpip_state *sp = (tcpip_state *)h->cprivate; - int port = 210; + const char *port = "210"; + if (h->protocol == PROTO_HTTP) + port = "80"; + if (!tcpip_init ()) + return 0; + if (sp->res) + freeaddrinfo(sp->res); + sp->res = tcpip_getaddrinfo(str, port); + return sp->res; +} +#else +void *tcpip_straddr(COMSTACK h, const char *str) +{ + tcpip_state *sp = (tcpip_state *)h->cprivate; + int port = 210; if (h->protocol == PROTO_HTTP) port = 80; + if (!tcpip_init ()) + return 0; if (!tcpip_strtoaddr_ex (str, &sp->addr, port)) - return 0; + return 0; return &sp->addr; } - -struct sockaddr_in *tcpip_strtoaddr(const char *str) -{ - static struct sockaddr_in add; - - if (!tcpip_strtoaddr_ex (str, &add, 210)) - return 0; - return &add; -} +#endif int tcpip_more(COMSTACK h) { tcpip_state *sp = (tcpip_state *)h->cprivate; return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf, - sp->altlen); + sp->altlen); } /* @@ -285,7 +375,11 @@ int tcpip_more(COMSTACK h) */ int tcpip_connect(COMSTACK h, void *address) { - struct sockaddr_in *add = (struct sockaddr_in *)address; +#if HAVE_GETADDRINFO + struct addrinfo *ai = (struct addrinfo *) address; +#else + struct sockaddr_in *add = (struct sockaddr_in *) address; +#endif int r; #ifdef __sun__ int recbuflen; @@ -296,7 +390,7 @@ int tcpip_connect(COMSTACK h, void *address) if (h->state != CS_ST_UNBND) { h->cerrno = CSOUTSTATE; - return -1; + return -1; } #ifdef __sun__ /* On Suns, you must set a bigger Receive Buffer BEFORE a call to connect @@ -309,7 +403,7 @@ int tcpip_connect(COMSTACK h, void *address) return -1; } TRC(fprintf( stderr, "Current Size of TCP Receive Buffer= %d\n", - recbuflen )); + recbuflen )); recbuflen *= 10; /* lets be optimistic */ if ( setsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, rbufsize ) < 0 ) { @@ -322,9 +416,14 @@ int tcpip_connect(COMSTACK h, void *address) return -1; } TRC(fprintf( stderr, "New Size of TCP Receive Buffer = %d\n", - recbuflen )); + recbuflen )); #endif + +#if HAVE_GETADDRINFO + r = connect(h->iofile, ai->ai_addr, ai->ai_addrlen); +#else r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add)); +#endif if (r < 0) { #ifdef WIN32 @@ -368,47 +467,47 @@ int tcpip_rcvconnect(COMSTACK h) if (h->state != CS_ST_CONNECTING) { h->cerrno = CSOUTSTATE; - return -1; + return -1; } #if HAVE_OPENSSL_SSL_H if (h->type == ssl_type && !sp->ctx) { - SSL_load_error_strings(); - SSLeay_add_all_algorithms(); - - sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method()); - if (!sp->ctx) - { - h->cerrno = CSERRORSSL; - return -1; - } + SSL_load_error_strings(); + SSLeay_add_all_algorithms(); + + sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method()); + if (!sp->ctx) + { + h->cerrno = CSERRORSSL; + return -1; + } } if (sp->ctx) { - int res; - - if (!sp->ssl) - { - sp->ssl = SSL_new (sp->ctx); - SSL_set_fd (sp->ssl, h->iofile); - } - res = SSL_connect (sp->ssl); - if (res <= 0) - { - int err = SSL_get_error(sp->ssl, res); - if (err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - return 1; - } - if (err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - return 1; - } - h->cerrno = CSERRORSSL; - return -1; - } + int res; + + if (!sp->ssl) + { + sp->ssl = SSL_new (sp->ctx); + SSL_set_fd (sp->ssl, h->iofile); + } + res = SSL_connect (sp->ssl); + if (res <= 0) + { + int err = SSL_get_error(sp->ssl, res); + if (err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + return 1; + } + if (err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + return 1; + } + h->cerrno = CSERRORSSL; + return -1; + } } #endif h->event = CS_DATA; @@ -442,7 +541,12 @@ static void tcpip_setsockopt (int fd) static int tcpip_bind(COMSTACK h, void *address, int mode) { + int r; +#if HAVE_GETADDRINFO + struct addrinfo *ai = (struct addrinfo *)address; +#else struct sockaddr *addr = (struct sockaddr *)address; +#endif #ifdef WIN32 BOOL one = 1; #else @@ -453,66 +557,71 @@ static int tcpip_bind(COMSTACK h, void *address, int mode) tcpip_state *sp = (tcpip_state *)h->cprivate; if (h->type == ssl_type && !sp->ctx) { - SSL_load_error_strings(); - SSLeay_add_all_algorithms(); - - sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method()); - if (!sp->ctx) - { - h->cerrno = CSERRORSSL; - return -1; - } + SSL_load_error_strings(); + SSLeay_add_all_algorithms(); + + sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method()); + if (!sp->ctx) + { + h->cerrno = CSERRORSSL; + return -1; + } } if (sp->ctx) { - if (sp->ctx_alloc) - { - int res; - res = SSL_CTX_use_certificate_file (sp->ctx, sp->cert_fname, - SSL_FILETYPE_PEM); - if (res <= 0) - { - ERR_print_errors_fp(stderr); - exit (2); - } - res = SSL_CTX_use_PrivateKey_file (sp->ctx, sp->cert_fname, - SSL_FILETYPE_PEM); - if (res <= 0) - { - ERR_print_errors_fp(stderr); - exit (3); - } - res = SSL_CTX_check_private_key (sp->ctx); - if (res <= 0) - { - ERR_print_errors_fp(stderr); - exit(5); - } - } - TRC (fprintf (stderr, "ssl_bind\n")); + if (sp->ctx_alloc) + { + int res; + res = SSL_CTX_use_certificate_chain_file(sp->ctx, sp->cert_fname); + if (res <= 0) + { + ERR_print_errors_fp(stderr); + exit (2); + } + res = SSL_CTX_use_PrivateKey_file (sp->ctx, sp->cert_fname, + SSL_FILETYPE_PEM); + if (res <= 0) + { + ERR_print_errors_fp(stderr); + exit (3); + } + res = SSL_CTX_check_private_key (sp->ctx); + if (res <= 0) + { + ERR_print_errors_fp(stderr); + exit(5); + } + } + TRC (fprintf (stderr, "ssl_bind\n")); } else { - TRC (fprintf (stderr, "tcpip_bind\n")); + TRC (fprintf (stderr, "tcpip_bind\n")); } #else TRC (fprintf (stderr, "tcpip_bind\n")); #endif #ifndef WIN32 if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) - &one, sizeof(one)) < 0) + &one, sizeof(one)) < 0) { h->cerrno = CSYSERR; return -1; } #endif tcpip_setsockopt(h->iofile); - if (bind(h->iofile, addr, sizeof(struct sockaddr_in))) +#if HAVE_GETADDRINFO + r = bind(h->iofile, ai->ai_addr, ai->ai_addrlen); +#else + r = bind(h->iofile, addr, sizeof(struct sockaddr_in)); +#endif + if (r) { h->cerrno = CSYSERR; return -1; } - if (mode == CS_SERVER && listen(h->iofile, 3) < 0) + /* Allow a maximum-sized backlog of waiting-to-connect clients */ + if (mode == CS_SERVER && listen(h->iofile, SOMAXCONN) < 0) { h->cerrno = CSYSERR; return -1; @@ -523,8 +632,8 @@ static int tcpip_bind(COMSTACK h, void *address, int mode) } int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, - int (*check_ip)(void *cd, const char *a, int len, int t), - void *cd) + int (*check_ip)(void *cd, const char *a, int len, int t), + void *cd) { struct sockaddr_in addr; YAZ_SOCKLEN_T len = sizeof(addr); @@ -538,21 +647,21 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len); if (h->newfd < 0) { - if ( + if ( #ifdef WIN32 - WSAGetLastError() == WSAEWOULDBLOCK + WSAGetLastError() == WSAEWOULDBLOCK #else - yaz_errno() == EWOULDBLOCK + yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN #endif #endif #endif - ) - h->cerrno = CSNODATA; - else - h->cerrno = CSYSERR; + ) + h->cerrno = CSNODATA; + else + h->cerrno = CSYSERR; return -1; } if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in)) @@ -562,14 +671,14 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, if (check_ip && (*check_ip)(cd, (const char *) &addr, sizeof(addr), AF_INET)) { - h->cerrno = CSDENY; + h->cerrno = CSDENY; #ifdef WIN32 closesocket(h->newfd); #else close(h->newfd); #endif - h->newfd = -1; - return -1; + h->newfd = -1; + return -1; } h->state = CS_ST_INCON; tcpip_setsockopt (h->newfd); @@ -587,102 +696,102 @@ COMSTACK tcpip_accept(COMSTACK h) TRC(fprintf(stderr, "tcpip_accept\n")); if (h->state == CS_ST_INCON) { - if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew)))) - { - h->cerrno = CSYSERR; + if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew)))) + { + h->cerrno = CSYSERR; #ifdef WIN32 - closesocket(h->newfd); + closesocket(h->newfd); #else - close(h->newfd); -#endif - h->newfd = -1; - return 0; - } - memcpy(cnew, h, sizeof(*h)); - cnew->iofile = h->newfd; - cnew->io_pending = 0; - if (!(state = (tcpip_state *) - (cnew->cprivate = xmalloc(sizeof(tcpip_state))))) - { - h->cerrno = CSYSERR; - if (h->newfd != -1) - { + close(h->newfd); +#endif + h->newfd = -1; + return 0; + } + memcpy(cnew, h, sizeof(*h)); + cnew->iofile = h->newfd; + cnew->io_pending = 0; + if (!(state = (tcpip_state *) + (cnew->cprivate = xmalloc(sizeof(tcpip_state))))) + { + h->cerrno = CSYSERR; + if (h->newfd != -1) + { #ifdef WIN32 - closesocket(h->newfd); + closesocket(h->newfd); #else - close(h->newfd); + close(h->newfd); #endif - h->newfd = -1; - } - return 0; - } - if (!(cnew->blocking&1) && + h->newfd = -1; + } + return 0; + } + if (!(cnew->blocking&1) && #ifdef WIN32 - (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0) + (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0) #else - (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0) + (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0) #endif - ) - { - h->cerrno = CSYSERR; - if (h->newfd != -1) - { + ) + { + h->cerrno = CSYSERR; + if (h->newfd != -1) + { #ifdef WIN32 - closesocket(h->newfd); + closesocket(h->newfd); #else - close(h->newfd); -#endif - h->newfd = -1; - } - xfree (cnew); - xfree (state); - return 0; - } - h->newfd = -1; - state->altbuf = 0; - state->altsize = state->altlen = 0; - state->towrite = state->written = -1; - state->complete = st->complete; - cnew->state = CS_ST_ACCEPT; - h->state = CS_ST_IDLE; - + close(h->newfd); +#endif + h->newfd = -1; + } + xfree (cnew); + xfree (state); + return 0; + } + h->newfd = -1; + state->altbuf = 0; + state->altsize = state->altlen = 0; + state->towrite = state->written = -1; + state->complete = st->complete; + cnew->state = CS_ST_ACCEPT; + h->state = CS_ST_IDLE; + #if HAVE_OPENSSL_SSL_H - state->ctx = st->ctx; - state->ctx_alloc = 0; - state->ssl = st->ssl; - if (state->ctx) - { - state->ssl = SSL_new (state->ctx); - SSL_set_fd (state->ssl, cnew->iofile); - } -#endif - h = cnew; + state->ctx = st->ctx; + state->ctx_alloc = 0; + state->ssl = st->ssl; + if (state->ctx) + { + state->ssl = SSL_new (state->ctx); + SSL_set_fd (state->ssl, cnew->iofile); + } +#endif + h = cnew; } if (h->state == CS_ST_ACCEPT) { #if HAVE_OPENSSL_SSL_H - tcpip_state *state = (tcpip_state *)h->cprivate; - if (state->ctx) - { - int res = SSL_accept (state->ssl); - TRC(fprintf(stderr, "SSL_accept\n")); - if (res <= 0) - { - int err = SSL_get_error(state->ssl, res); - if (err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - return h; - } - if (err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - return h; - } - cs_close (h); - return 0; - } - } + tcpip_state *state = (tcpip_state *)h->cprivate; + if (state->ctx) + { + int res = SSL_accept (state->ssl); + TRC(fprintf(stderr, "SSL_accept\n")); + if (res <= 0) + { + int err = SSL_get_error(state->ssl, res); + if (err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + return h; + } + if (err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + return h; + } + cs_close (h); + return 0; + } + } #endif } else @@ -729,58 +838,69 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize) if (!*bufsize) { if (!(*buf = (char *)xmalloc(*bufsize = CS_TCPIP_BUFCHUNK))) + { + h->cerrno = CSYSERR; return -1; + } } else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK) if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2))) + { + h->cerrno = CSYSERR; return -1; + } #ifdef __sun__ - yaz_set_errno( 0 ); - /* unfortunatly, sun sometimes forgets to set errno in recv - when EWOULDBLOCK etc. would be required (res = -1) */ -#endif - res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0); - TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread)); - if (res < 0) - { - TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(), - strerror(yaz_errno()))); + yaz_set_errno( 0 ); + /* unfortunatly, sun sometimes forgets to set errno in recv + when EWOULDBLOCK etc. would be required (res = -1) */ +#endif + res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0); + TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread)); + if (res < 0) + { + TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(), + strerror(yaz_errno()))); #ifdef WIN32 - if (WSAGetLastError() == WSAEWOULDBLOCK) - { - h->io_pending = CS_WANT_READ; - break; - } - else - return -1; + if (WSAGetLastError() == WSAEWOULDBLOCK) + { + h->io_pending = CS_WANT_READ; + break; + } + else + return -1; #else - if (yaz_errno() == EWOULDBLOCK + if (yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN #endif #endif - || yaz_errno() == EINPROGRESS + || yaz_errno() == EINPROGRESS #ifdef __sun__ - || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */ -#endif - ) - { - h->io_pending = CS_WANT_READ; - break; - } - else if (yaz_errno() == 0) - continue; - else - return -1; -#endif - } - else if (!res) - return 0; + || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */ +#endif + ) + { + h->io_pending = CS_WANT_READ; + break; + } + else if (yaz_errno() == 0) + continue; + else + return -1; +#endif + } + else if (!res) + return hasread; hasread += res; + if (hasread > h->max_recv_bytes) + { + h->cerrno = CSBUFSIZE; + return -1; + } } TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n", - hasread, berlen)); + hasread, berlen)); /* move surplus buffer (or everything if we didn't get a BER rec.) */ if (hasread > berlen) { @@ -842,27 +962,27 @@ int ssl_get(COMSTACK h, char **buf, int *bufsize) else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK) if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2))) return -1; - res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK); - TRC(fprintf(stderr, " SSL_read res=%d, hasread=%d\n", res, hasread)); - if (res <= 0) - { - int ssl_err = SSL_get_error(sp->ssl, res); - if (ssl_err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - break; - } - if (ssl_err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - break; - } - if (res == 0) - return 0; - h->cerrno = CSERRORSSL; - return -1; - } - hasread += res; + res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK); + TRC(fprintf(stderr, " SSL_read res=%d, hasread=%d\n", res, hasread)); + if (res <= 0) + { + int ssl_err = SSL_get_error(sp->ssl, res); + if (ssl_err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + break; + } + if (ssl_err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + break; + } + if (res == 0) + return 0; + h->cerrno = CSERRORSSL; + return -1; + } + hasread += res; } TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n", hasread, berlen)); @@ -915,21 +1035,21 @@ int tcpip_put(COMSTACK h, char *buf, int size) } while (state->towrite > state->written) { - if ((res = - send(h->iofile, buf + state->written, size - - state->written, + if ((res = + send(h->iofile, buf + state->written, size - + state->written, #ifdef MSG_NOSIGNAL - MSG_NOSIGNAL + MSG_NOSIGNAL #else - 0 + 0 #endif - )) < 0) - { - if ( + )) < 0) + { + if ( #ifdef WIN32 - WSAGetLastError() == WSAEWOULDBLOCK + WSAGetLastError() == WSAEWOULDBLOCK #else - yaz_errno() == EWOULDBLOCK + yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN @@ -938,20 +1058,20 @@ int tcpip_put(COMSTACK h, char *buf, int size) #ifdef __sun__ || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */ #endif - || yaz_errno() == EINPROGRESS -#endif - ) - { - TRC(fprintf(stderr, " Flow control stop\n")); - h->io_pending = CS_WANT_WRITE; - return 1; - } - h->cerrno = CSYSERR; - return -1; - } - state->written += res; - TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", - res, state->written, size)); + || yaz_errno() == EINPROGRESS +#endif + ) + { + TRC(fprintf(stderr, " Flow control stop\n")); + h->io_pending = CS_WANT_WRITE; + return 1; + } + h->cerrno = CSYSERR; + return -1; + } + state->written += res; + TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", + res, state->written, size)); } state->towrite = state->written = -1; TRC(fprintf(stderr, " Ok\n")); @@ -985,27 +1105,27 @@ int ssl_put(COMSTACK h, char *buf, int size) } while (state->towrite > state->written) { - res = SSL_write (state->ssl, buf + state->written, - size - state->written); - if (res <= 0) - { - int ssl_err = SSL_get_error(state->ssl, res); - if (ssl_err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - return 1; - } - if (ssl_err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - return 1; - } - h->cerrno = CSERRORSSL; - return -1; - } - state->written += res; - TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", - res, state->written, size)); + res = SSL_write (state->ssl, buf + state->written, + size - state->written); + if (res <= 0) + { + int ssl_err = SSL_get_error(state->ssl, res); + if (ssl_err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + return 1; + } + if (ssl_err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + return 1; + } + h->cerrno = CSERRORSSL; + return -1; + } + state->written += res; + TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", + res, state->written, size)); } state->towrite = state->written = -1; TRC(fprintf(stderr, " Ok\n")); @@ -1021,10 +1141,10 @@ int tcpip_close(COMSTACK h) if (h->iofile != -1) { #if HAVE_OPENSSL_SSL_H - if (sp->ssl) - { - SSL_shutdown (sp->ssl); - } + if (sp->ssl) + { + SSL_shutdown (sp->ssl); + } #endif #ifdef WIN32 closesocket(h->iofile); @@ -1037,12 +1157,16 @@ int tcpip_close(COMSTACK h) #if HAVE_OPENSSL_SSL_H if (sp->ssl) { - TRC (fprintf(stderr, "SSL_free\n")); - SSL_free (sp->ssl); + TRC (fprintf(stderr, "SSL_free\n")); + SSL_free (sp->ssl); } sp->ssl = 0; if (sp->ctx_alloc) - SSL_CTX_free (sp->ctx_alloc); + SSL_CTX_free (sp->ctx_alloc); +#endif +#if HAVE_GETADDRINFO + if (sp->res) + freeaddrinfo(sp->res); #endif xfree(sp); xfree(h); @@ -1060,16 +1184,16 @@ char *tcpip_addrstr(COMSTACK h) len = sizeof(addr); if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0) { - h->cerrno = CSYSERR; - return 0; + h->cerrno = CSYSERR; + return 0; } if (!(h->blocking&2)) { if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), - AF_INET))) - r = (char*) host->h_name; + AF_INET))) + r = (char*) host->h_name; } if (!r) - r = inet_ntoa(addr.sin_addr); + r = inet_ntoa(addr.sin_addr); if (h->protocol == PROTO_HTTP) sprintf(buf, "http:%s", r); else @@ -1091,19 +1215,19 @@ int static tcpip_set_blocking(COMSTACK p, int blocking) unsigned long flag; if (p->blocking == blocking) - return 1; + return 1; #ifdef WIN32 flag = 1; if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0) - return 0; + return 0; #else flag = fcntl(p->iofile, F_GETFL, 0); if(!(blocking&1)) - flag = flag & ~O_NONBLOCK; + flag = flag & ~O_NONBLOCK; else flag = flag | O_NONBLOCK; if (fcntl(p->iofile, F_SETFL, flag) < 0) - return 0; + return 0; #endif p->blocking = blocking; return 1; @@ -1117,7 +1241,7 @@ int cs_set_ssl_ctx(COMSTACK cs, void *ctx) return 0; sp = (struct tcpip_state *) cs->cprivate; if (sp->ctx_alloc) - return 0; + return 0; sp->ctx = (SSL_CTX *) ctx; return 1; } @@ -1135,7 +1259,7 @@ int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname) { struct tcpip_state *sp; if (!cs || cs->type != ssl_type) - return 0; + return 0; sp = (struct tcpip_state *) cs->cprivate; strncpy(sp->cert_fname, fname, sizeof(sp->cert_fname)-1); sp->cert_fname[sizeof(sp->cert_fname)-1] = '\0'; @@ -1147,19 +1271,19 @@ int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len) SSL *ssl = (SSL *) cs_get_ssl(cs); if (ssl) { - X509 *server_cert = SSL_get_peer_certificate (ssl); - if (server_cert) - { - BIO *bio = BIO_new(BIO_s_mem()); - char *pem_buf; - /* get PEM buffer in memory */ - PEM_write_bio_X509(bio, server_cert); - *len = BIO_get_mem_data(bio, &pem_buf); - *buf = (char *) xmalloc(*len); - memcpy(*buf, pem_buf, *len); - BIO_free(bio); - return 1; - } + X509 *server_cert = SSL_get_peer_certificate (ssl); + if (server_cert) + { + BIO *bio = BIO_new(BIO_s_mem()); + char *pem_buf; + /* get PEM buffer in memory */ + PEM_write_bio_X509(bio, server_cert); + *len = BIO_get_mem_data(bio, &pem_buf); + *buf = (char *) xmalloc(*len); + memcpy(*buf, pem_buf, *len); + BIO_free(bio); + return 1; + } } return 0; } @@ -1185,3 +1309,11 @@ int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname) } #endif +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +