00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <ctype.h>
00034 #include <sys/types.h>
00035 #include <sys/socket.h>
00036 #include <netinet/in.h>
00037 #include <arpa/inet.h>
00038 #include <netdb.h>
00039 #include <fcntl.h>
00040 #include <netinet/tcp.h>
00041
00042 #ifdef HAVE_LIBWRAP
00043 extern "C" {
00044 #include "tcpd.h"
00045 int allow_severity;
00046 int deny_severity;
00047 }
00048 #endif
00049
00050 #include <cstring>
00051 #include <cerrno>
00052
00053 #include <iostream>
00054 #include <sstream>
00055
00056 using std::cerr ;
00057 using std::endl ;
00058 using std::istringstream ;
00059
00060 #include "TcpSocket.h"
00061 #include "SocketConfig.h"
00062 #include "TheBESKeys.h"
00063 #include "BESDebug.h"
00064 #include "BESInternalError.h"
00065 #include "BESInternalFatalError.h"
00066
00067 void
00068 TcpSocket::connect()
00069 {
00070 if( _listening )
00071 {
00072 string err( "Socket is already listening" ) ;
00073 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00074 }
00075
00076 if( _connected )
00077 {
00078 string err( "Socket is already connected" ) ;
00079 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00080 }
00081
00082 if( _host == "" )
00083 _host = "localhost" ;
00084
00085 struct protoent *pProtoEnt ;
00086 struct sockaddr_in sin ;
00087 struct hostent *ph ;
00088 long address ;
00089 if( isdigit( _host[0] ) )
00090 {
00091 if( ( address = inet_addr( _host.c_str() ) ) == -1 )
00092 {
00093 string err( "Invalid host ip address " ) ;
00094 err += _host ;
00095 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00096 }
00097 sin.sin_addr.s_addr = address ;
00098 sin.sin_family = AF_INET ;
00099 }
00100 else
00101 {
00102 if( ( ph = gethostbyname( _host.c_str() ) ) == NULL )
00103 {
00104 switch( h_errno )
00105 {
00106 case HOST_NOT_FOUND:
00107 {
00108 string err( "No such host " ) ;
00109 err += _host ;
00110 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00111 }
00112 case TRY_AGAIN:
00113 {
00114 string err( "Host " ) ;
00115 err += _host + " is busy, try again later" ;
00116 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00117 }
00118 case NO_RECOVERY:
00119 {
00120 string err( "DNS error for host " ) ;
00121 err += _host ;
00122 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00123 }
00124 case NO_ADDRESS:
00125 {
00126 string err( "No IP address for host " ) ;
00127 err += _host ;
00128 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00129 }
00130 default:
00131 {
00132 throw BESInternalError( "unknown error", __FILE__, __LINE__ ) ;
00133 }
00134 }
00135 }
00136 else
00137 {
00138 sin.sin_family = ph->h_addrtype ;
00139 for( char **p =ph->h_addr_list; *p != NULL; p++ )
00140 {
00141 struct in_addr in ;
00142 (void)memcpy( &in.s_addr, *p, sizeof( in.s_addr ) ) ;
00143 memcpy( (char*)&sin.sin_addr, (char*)&in, sizeof( in ) ) ;
00144 }
00145 }
00146 }
00147
00148 sin.sin_port = htons( _portVal ) ;
00149 pProtoEnt = getprotobyname( "tcp" ) ;
00150 if( !pProtoEnt )
00151 {
00152 string err( "Error retreiving tcp protocol information" ) ;
00153 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00154 }
00155
00156 _connected = false;
00157 int descript = socket( AF_INET, SOCK_STREAM, pProtoEnt->p_proto ) ;
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 if( descript == -1 )
00168 {
00169 string err("getting socket descriptor: ");
00170 const char* error_info = strerror(errno);
00171 if(error_info)
00172 err += (string)error_info;
00173 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00174 } else {
00175 long holder;
00176 _socket = descript;
00177
00178
00179 holder = fcntl(_socket, F_GETFL, NULL);
00180 holder = holder | O_NONBLOCK;
00181 fcntl(_socket, F_SETFL, holder);
00182
00183
00184 setTcpRecvBufferSize( ) ;
00185 setTcpSendBufferSize( ) ;
00186
00187 int res = ::connect( descript, (struct sockaddr*)&sin, sizeof( sin ) );
00188
00189
00190 if( res == -1 )
00191 {
00192 if(errno == EINPROGRESS) {
00193
00194 fd_set write_fd ;
00195 struct timeval timeout ;
00196 int maxfd = _socket;
00197
00198 timeout.tv_sec = 5;
00199 timeout.tv_usec = 0;
00200
00201 FD_ZERO( &write_fd);
00202 FD_SET( _socket, &write_fd );
00203
00204 if( select( maxfd+1, NULL, &write_fd, NULL, &timeout) < 0 ) {
00205
00206
00207 holder = fcntl(_socket, F_GETFL, NULL);
00208 holder = holder & (~O_NONBLOCK);
00209 fcntl(_socket, F_SETFL, holder);
00210
00211
00212 string err( "selecting sockets: " ) ;
00213 const char *error_info = strerror( errno ) ;
00214 if( error_info )
00215 err += (string)error_info ;
00216 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00217
00218 }
00219 else
00220 {
00221
00222
00223 socklen_t lon;
00224 int valopt;
00225 lon = sizeof(int);
00226 getsockopt(_socket, SOL_SOCKET, SO_ERROR, (void*) &valopt, &lon);
00227
00228 if(valopt)
00229 {
00230
00231
00232 holder = fcntl(_socket, F_GETFL, NULL);
00233 holder = holder & (~O_NONBLOCK);
00234 fcntl(_socket, F_SETFL, holder);
00235
00236
00237 string err("Did not successfully connect to server\n");
00238 err += "Server may be down or you may be trying on the wrong port";
00239 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00240
00241 }
00242 else
00243 {
00244
00245 holder = fcntl(_socket, F_GETFL, NULL);
00246 holder = holder & (~O_NONBLOCK);
00247 fcntl(_socket, F_SETFL, holder);
00248
00249
00250 _connected = true;
00251 }
00252 }
00253 }
00254 else
00255 {
00256
00257
00258 holder = fcntl(_socket, F_GETFL, NULL);
00259 holder = holder & (~O_NONBLOCK);
00260 fcntl(_socket, F_SETFL, holder);
00261
00262
00263 string err("socket connect: ");
00264 const char* error_info = strerror(errno);
00265 if(error_info)
00266 err += (string)error_info;
00267 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00268 }
00269 }
00270 else
00271 {
00272
00273
00274
00275
00276 holder = fcntl(_socket, F_GETFL, NULL);
00277 holder = holder & (~O_NONBLOCK);
00278 fcntl(_socket, F_SETFL, holder);
00279 _connected = true;
00280 }
00281 }
00282 }
00283
00284 void
00285 TcpSocket::listen()
00286 {
00287 if( _connected )
00288 {
00289 string err( "Socket is already connected" ) ;
00290 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00291 }
00292
00293 if( _listening )
00294 {
00295 string err( "Socket is already listening" ) ;
00296 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00297 }
00298
00299 int on = 1 ;
00300 struct sockaddr_in server ;
00301 server.sin_family = AF_INET ;
00302 server.sin_addr.s_addr = INADDR_ANY ;
00303 struct servent *sir = 0 ;
00304 sir = getservbyport( _portVal, "tcp" ) ;
00305 if( sir )
00306 {
00307 string error = sir->s_name + (string)" is using my socket" ;
00308 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00309 }
00310 server.sin_port = htons( _portVal ) ;
00311 _socket = socket( AF_INET, SOCK_STREAM, 0 ) ;
00312 if( _socket != -1 )
00313 {
00314 if( setsockopt( _socket, SOL_SOCKET, SO_REUSEADDR,
00315 (char*)&on, sizeof( on ) ) )
00316 {
00317 string error( "could not set SO_REUSEADDR on TCP socket" ) ;
00318 const char* error_info = strerror( errno ) ;
00319 if( error_info )
00320 error += " " + (string)error_info ;
00321 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00322 }
00323
00324 if( bind( _socket, (struct sockaddr*)&server, sizeof server) != -1 )
00325 {
00326 int length = sizeof( server ) ;
00327 #ifdef _GETSOCKNAME_USES_SOCKLEN_T
00328 if( getsockname( _socket, (struct sockaddr *)&server,
00329 (socklen_t *)&length ) == -1 )
00330 #else
00331 if( getsockname( _socket, (struct sockaddr *)&server,
00332 &length ) == -1 )
00333 #endif
00334 {
00335 string error( "getting socket name" ) ;
00336 const char* error_info = strerror( errno ) ;
00337 if( error_info )
00338 error += " " + (string)error_info ;
00339 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00340 }
00341
00342
00343
00344 setTcpRecvBufferSize( ) ;
00345 setTcpSendBufferSize( ) ;
00346
00347 if( ::listen( _socket, 5 ) == 0 )
00348 {
00349 _listening = true ;
00350 }
00351 else
00352 {
00353 string error( "could not listen TCP socket" ) ;
00354 const char* error_info = strerror( errno ) ;
00355 if( error_info )
00356 error += " " + (string)error_info ;
00357 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00358 }
00359 }
00360 else
00361 {
00362 string error( "could not bind TCP socket" ) ;
00363 const char* error_info = strerror( errno ) ;
00364 if( error_info )
00365 error += " " + (string)error_info ;
00366 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00367 }
00368 }
00369 else
00370 {
00371 string error( "could not create socket" ) ;
00372 const char *error_info = strerror( errno ) ;
00373 if( error_info )
00374 error += " " + (string)error_info ;
00375 throw BESInternalError( error, __FILE__, __LINE__ ) ;
00376 }
00377 }
00378
00397 void
00398 TcpSocket::setTcpRecvBufferSize()
00399 {
00400 if( !_haveRecvBufferSize )
00401 {
00402 bool found = false ;
00403 string setit ;
00404 try
00405 {
00406 TheBESKeys::TheKeys()->get_value( "BES.SetSockRecvSize",
00407 setit, found);
00408 }
00409 catch( ... )
00410 {
00411
00412
00413 setit = "No" ;
00414 }
00415 if( setit == "Yes" || setit == "yes" || setit == "Yes" )
00416 {
00417 found = false ;
00418 string sizestr ;
00419 TheBESKeys::TheKeys()->get_value( "BES.SockRecvSize",
00420 sizestr, found ) ;
00421 istringstream sizestrm( sizestr ) ;
00422 unsigned int sizenum = 0 ;
00423 sizestrm >> sizenum ;
00424 if( !sizenum )
00425 {
00426 string err = "Socket Recv Size malformed: " + sizestr ;
00427 throw BESInternalFatalError( err, __FILE__, __LINE__ ) ;
00428 }
00429
00430
00431 int err = setsockopt( _socket, SOL_SOCKET, SO_RCVBUF,
00432 (char *)&sizenum, (socklen_t)sizeof(sizenum) ) ;
00433 int myerrno = errno ;
00434 if( err == -1 )
00435 {
00436 char *serr = strerror( myerrno ) ;
00437 string err = "Failed to set the socket receive buffer size: " ;
00438 if( serr )
00439 err += serr ;
00440 else
00441 err += "unknow error occurred" ;
00442 throw BESInternalFatalError( err, __FILE__, __LINE__ ) ;
00443 }
00444
00445 BESDEBUG( "ppt", "Tcp receive buffer size set to "
00446 << (unsigned long)sizenum << endl ) ;
00447 }
00448 }
00449 }
00450
00469 void
00470 TcpSocket::setTcpSendBufferSize()
00471 {
00472 bool found = false ;
00473 vector<string> vals ;
00474 string setit ;
00475 try
00476 {
00477 TheBESKeys::TheKeys()->get_value( "BES.SetSockSendSize", setit, found );
00478 }
00479 catch( ... )
00480 {
00481
00482
00483 setit = "No" ;
00484 }
00485 if( setit == "Yes" || setit == "yes" || setit == "Yes" )
00486 {
00487 found = false ;
00488 string sizestr ;
00489 try
00490 {
00491 TheBESKeys::TheKeys()->get_value( "BES.SockSendSize", sizestr, found ) ;
00492 }
00493 catch( BESError &e )
00494 {
00495 throw BESInternalFatalError( e.get_message(), e.get_file(),
00496 e.get_line() ) ;
00497 }
00498 istringstream sizestrm( sizestr ) ;
00499 unsigned int sizenum = 0 ;
00500 sizestrm >> sizenum ;
00501 if( !sizenum )
00502 {
00503 string err = "Socket Send Size malformed: " + sizestr ;
00504 throw BESInternalFatalError( err, __FILE__, __LINE__ ) ;
00505 }
00506
00507
00508 int err = setsockopt( _socket, SOL_SOCKET, SO_SNDBUF,
00509 (char *)&sizenum, (socklen_t)sizeof(sizenum) ) ;
00510 int myerrno = errno ;
00511 if( err == -1 )
00512 {
00513 char *serr = strerror( myerrno ) ;
00514 string err = "Failed to set the socket send buffer size: " ;
00515 if( serr )
00516 err += serr ;
00517 else
00518 err += "unknow error occurred" ;
00519 throw BESInternalFatalError( err, __FILE__, __LINE__ ) ;
00520 }
00521
00522 BESDEBUG( "ppt", "Tcp send buffer size set to "
00523 << (unsigned long)sizenum << endl ) ;
00524 }
00525 }
00526
00535 unsigned int
00536 TcpSocket::getRecvBufferSize()
00537 {
00538 if( !_haveRecvBufferSize )
00539 {
00540
00541 unsigned int sizenum = 0 ;
00542 socklen_t sizelen = sizeof(sizenum) ;
00543 int err = getsockopt( _socket, SOL_SOCKET, SO_RCVBUF,
00544 (char *)&sizenum, (socklen_t *)&sizelen ) ;
00545 int myerrno = errno ;
00546 if( err == -1 )
00547 {
00548 char *serr = strerror( myerrno ) ;
00549 string err = "Failed to get the socket receive buffer size: " ;
00550 if( serr )
00551 err += serr ;
00552 else
00553 err += "unknow error occurred" ;
00554 throw BESInternalFatalError( err, __FILE__, __LINE__ ) ;
00555 }
00556
00557 BESDEBUG( "ppt", "Tcp receive buffer size is "
00558 << (unsigned long)sizenum << endl ) ;
00559
00560 _haveRecvBufferSize = true ;
00561 _recvBufferSize = sizenum ;
00562 }
00563 return _recvBufferSize ;
00564 }
00565
00574 unsigned int
00575 TcpSocket::getSendBufferSize()
00576 {
00577 if( !_haveSendBufferSize )
00578 {
00579
00580 unsigned int sizenum = 0 ;
00581 socklen_t sizelen = sizeof(sizenum) ;
00582 int err = getsockopt( _socket, SOL_SOCKET, SO_SNDBUF,
00583 (char *)&sizenum, (socklen_t *)&sizelen ) ;
00584 int myerrno = errno ;
00585 if( err == -1 )
00586 {
00587 char *serr = strerror( myerrno ) ;
00588 string err = "Failed to get the socket send buffer size: " ;
00589 if( serr )
00590 err += serr ;
00591 else
00592 err += "unknow error occurred" ;
00593 throw BESInternalFatalError( err, __FILE__, __LINE__ ) ;
00594 }
00595
00596 BESDEBUG( "ppt", "Tcp send buffer size is "
00597 << (unsigned long)sizenum << endl ) ;
00598
00599 _haveSendBufferSize = true ;
00600 _sendBufferSize = sizenum ;
00601 }
00602 return _sendBufferSize ;
00603 }
00604
00608 bool
00609 TcpSocket::allowConnection()
00610 {
00611 bool retval = true ;
00612
00613 #ifdef HAVE_LIBWRAP
00614 struct request_info req ;
00615 request_init( &req, RQ_DAEMON, "besdaemon", RQ_FILE,
00616 getSocketDescriptor(), 0 ) ;
00617 fromhost() ;
00618
00619 if( STR_EQ( eval_hostname(), paranoid ) && hosts_access() )
00620 {
00621 retval = false ;
00622 }
00623 #endif
00624
00625 return retval ;
00626 }
00627
00634 void
00635 TcpSocket::dump( ostream &strm ) const
00636 {
00637 strm << BESIndent::LMarg << "TcpSocket::dump - ("
00638 << (void *)this << ")" << endl ;
00639 BESIndent::Indent() ;
00640 strm << BESIndent::LMarg << "host: " << _host << endl ;
00641 strm << BESIndent::LMarg << "port: " << _portVal << endl ;
00642 strm << BESIndent::LMarg << "have recv buffer size: " << _haveRecvBufferSize
00643 << endl ;
00644 strm << BESIndent::LMarg << "recv buffer size: " << _recvBufferSize
00645 << endl ;
00646 strm << BESIndent::LMarg << "have send buffer size: " << _haveSendBufferSize
00647 << endl ;
00648 strm << BESIndent::LMarg << "send buffer size: " << _sendBufferSize
00649 << endl ;
00650 Socket::dump( strm ) ;
00651 BESIndent::UnIndent() ;
00652 }
00653