2 * LIBPING socket library
4 * Copyright (C) 2000, 2001, 2002 by
5 * Jeffrey Fulmer - <jdfulmer@armstrong.com>
6 * This file is distributed as part of libping
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #endif/*HAVE_CONFIG_H*/
30 #ifdef HAVE_ARPA_INET_H
31 # include <arpa/inet.h>
32 #endif/*HAVE_ARPA_INET_H*/
34 #ifdef HAVE_SYS_SOCKET_H
35 # include <sys/socket.h>
36 #endif/*HAVE_SYS_SOCKET_H*/
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif/*HAVE_NETINET_IN_H*/
44 #endif/*HAVE_NETDB_H*/
47 # include <openssl/rand.h>
57 int mknblock( int socket, int nonblock );
58 ssize_t socket_write( int sock, const void *vbuf, size_t len );
59 ssize_t ssl_socket_write( CONN *C, const void *vbuf, size_t len );
63 * returns int, socket handle
66 JOEsocket( CONN *C, const char *hn )
69 struct timeval timeout;
75 struct sockaddr_in cli;
94 if( C->prot == HTTPS ){
96 SSL_load_error_strings();
97 SSLeay_add_ssl_algorithms();
98 C->ctx = SSL_CTX_new( SSLv3_client_method());
99 if( C->ctx == NULL ){ perror( "SSL: ctx is NULL" ); }
100 /* http://www.openssl.org/support/faq.html#USER1
101 * Perhaps someday I'll learn to read the FAQ
102 * first and then code second, but probably not.
103 * Not all OSes have /dev/urandom, we must seed
106 memset( buf, 0, sizeof( buf ));
107 RAND_seed( buf, sizeof( buf ));
108 C->ssl = SSL_new( C->ctx );
109 SSL_set_connect_state( C->ssl );
112 #endif /* HAVE_SSL */
115 /* create a socket, return -1 on failure */
116 if(( C->sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ){
120 #if defined(__GLIBC__)
121 /* for systems using GNU libc */
122 if(( gethostbyname_r( hn, &hent, hbf, sizeof(hbf), &hp, &herrno ) < 0 )){
127 hp = gethostbyname_r( hn, &hent, hbf, sizeof(hbf), &herrno );
129 aixbuf = (char*)xmalloc( 9000 );
130 rc = gethostbyname_r(hn, (struct hostent *)aixbuf,
131 (struct hostent_data *)(aixbuf + sizeof(struct hostent)));
132 hp = (struct hostent*)aixbuf;
133 #elif ( defined(hpux) || defined(__osf__) )
134 hp = gethostbyname( hn );
137 /* simply hoping that gethostbyname is thread-safe */
138 hp = gethostbyname( hn );
140 #endif/*OS SPECIFICS*/
142 if( hp == NULL ) return -1;
143 bzero( &cli, sizeof( cli ));
144 bcopy( (char*)hp->h_addr, (char*)&cli.sin_addr, hp->h_length );
145 cli.sin_family = AF_INET;
146 cli.sin_port = htons( C->port );
150 if( setsockopt( C->sock, SOL_SOCKET, SO_LINGER, &ling, sizeof( ling )) < 0 ){
155 * connect to the host
156 * evaluate the server response and check for
157 * readability/writeability of the socket....
159 conn = connect( C->sock, (struct sockaddr *)&cli, sizeof(struct sockaddr_in));
164 else if( conn == 0 ){
165 goto FINISH; /* immediate connection */
169 * we have a connection, set the
170 * socket to non-blocking and test
173 if(( mknblock( C->sock, TRUE )) < 0 ){
178 FD_SET( C->sock, &C->rset );
179 FD_SET( C->sock, &C->wset );
180 memset((void *)&timeout, '\0', sizeof( struct timeval ));
182 * the default timeout is set in init.c, it's
183 * value can be changed by the user in .siegerc,
184 * but we'll still use a ternary condition since
185 * you can't be too safe....
187 timeout.tv_sec = (C->timeout > 0)?C->timeout:60;
190 if(( res = select( C->sock+1, &C->rset, &C->wset, NULL, &timeout )) < 1 ){
191 perror( "JOEsocket: connection timed out." );
195 if( FD_ISSET( C->sock, &C->rset) || FD_ISSET( C->sock, &C->wset )){
197 if( getsockopt( C->sock, SOL_SOCKET, SO_ERROR, &error, &len ) < 0 )
200 } /* end of connect conditional */
204 * make the socket blocking again.
206 if(( mknblock( C->sock, FALSE )) < 0 ){
207 perror( "JOEsocket: unable to set socket to non-blocking." );
211 /* if requested, encrypt the transaction */
212 if( C->prot == HTTPS ){
214 /* currently a fatal error, should it be? */
215 if(( SSL_set_fd( C->ssl, C->sock )) < 0 ){
216 perror( "unable to create secure socket!" );
219 if(( serr = SSL_connect( C->ssl )) < 0 ){
220 int problem = SSL_get_error( C->ssl, serr );
221 fprintf( stderr, "SSL_connect: want to %s more...\n",
222 ( problem == SSL_ERROR_WANT_READ) ? "read" : "write");
225 SSL_get_cipher( C->ssl );
228 #endif /* HAVE_SSL */
231 return((C->sock>0)?C->sock:-1);
235 * makes the socket non-blocking,
236 * calls select with timeout and
237 * returns the socket to blocking.
240 JOEsocket_check( CONN *C, SDSET test )
243 struct timeval timeout;
247 FD_SET( C->sock, &C->rset );
248 FD_SET( C->sock, &C->wset );
249 memset((void *)&timeout, '\0', sizeof( struct timeval ));
251 if(( mknblock( C->sock, TRUE )) < 0 ){
252 perror( "SIMBOTsocket: unable to set socket to non-blocking." );
256 timeout.tv_sec = ( C->timeout > 0)?C->timeout:60;
261 if(( res = select( C->sock+1, &C->rset, NULL, NULL, &timeout )) < 1 ){
267 if(( res = select( C->sock+1, NULL, &C->wset, NULL, &timeout )) < 1 ){
273 if(( res = select( C->sock+1, &C->rset, &C->wset, NULL, &timeout )) < 1 ){
280 if(( mknblock( C->sock, FALSE )) < 0 ){
281 perror( "SIMBOTsocket: unable to set socket to non-blocking." );
284 FD_CLR( C->sock, &C->rset );
291 * set socket to non-blocking
294 mknblock( int sock, int nonblock )
300 flags = fcntl( sock, F_GETFL, 0 );
311 retval = fcntl( sock, F_SETFL, flags);
317 #elif defined( FIONBIO )
321 return ioctl( sd, FIONBIO, &status );
330 * writes vbuf to sock
333 socket_write( int sock, const void *vbuf, size_t len )
342 if(( w = write( sock, buf, n )) <= 0 ){
357 * writes vbuf to sock
360 ssl_socket_write( CONN *C, const void *vbuf, size_t len )
370 if(( w = SSL_write( C->ssl, buf, n )) <= 0 ){
381 perror( "protocol not supported" );
387 JOEreadline( CONN *C, char *ptr, size_t len )
392 n = read( C->sock, ptr, 1 );
393 } while( n > 0 && *ptr++ != '\n' );
400 JOEsocket_read( CONN *C, void *vbuf, size_t len )
409 if( C->prot == HTTPS ){
412 if(( r = SSL_read( C->ssl, buf, n )) < 0 ){
418 else if( r == 0 ) break;
426 if(( r = read( C->sock, buf, n )) < 0 ){
432 else if( r == 0 ) break;
443 * socket_write wrapper function.
446 JOEsocket_write( CONN *C, const void *buf, size_t len )
450 if( C->prot == HTTPS ){
451 /* handle HTTPS protocol */
453 if(( bytes = ssl_socket_write( C, buf, len )) != len ){
454 perror( "JOEssl_socket_write: ERROR" );
458 perror( "JOEssl_socket_write: protocol NOT supported" );
464 if(( bytes = socket_write( C->sock, buf, len )) != len ){
465 perror( "JOEsocket_write: ERROR" );
475 * frees ssl resources if using ssl and
476 * closes the connection and the socket.
482 if( C->prot == HTTPS ){
483 SSL_shutdown( C->ssl );
486 SSL_CTX_free( C->ctx );