Ejemplo n.º 1
0
  int DNS::connect( const std::string& host, unsigned short port, const LogSink& logInstance )
  {
    int fd = getSocket();
    if( fd < 0 )
      return fd;

    struct hostent* h;
    if( ( h = gethostbyname( host.c_str() ) ) == 0 )
    {
      cleanup();
      return -ConnDnsError;
    }

    struct sockaddr_in target;
    target.sin_family = AF_INET;
    target.sin_port = htons( port );

    if( h->h_length != sizeof( struct in_addr ) )
    {
      cleanup();
      return -ConnDnsError;
    }
    else
    {
      memcpy( &target.sin_addr, h->h_addr, sizeof( struct in_addr ) );
    }

#ifndef _WIN32_WCE
    std::ostringstream oss;
#endif

    memset( target.sin_zero, '\0', 8 );
    if( ::connect( fd, (struct sockaddr *)&target, sizeof( struct sockaddr ) ) == 0 )
    {
#ifndef _WIN32_WCE
      oss << "connecting to " << host.c_str()
          << " (" << inet_ntoa( target.sin_addr ) << ":" << port << ")";
      logInstance.dbg( LogAreaClassDns, oss.str() );
#endif
      return fd;
    }

#ifndef _WIN32_WCE
    oss << "connection to " << host.c_str()
         << " (" << inet_ntoa( target.sin_addr ) << ":" << port << ") failed";
    logInstance.dbg( LogAreaClassDns, oss.str() );
#endif

    closeSocket( fd );
    return -ConnConnectionRefused;
  }
Ejemplo n.º 2
0
  int DNS::connect( const std::string& host, int port, const LogSink& logInstance )
  {
    struct addrinfo hints, *servinfo, *p;
    int rv = 0;
    int fd = 0;

    memset( &hints, 0, sizeof( hints ) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if( ( rv = getaddrinfo( host.c_str(), util::int2string( port ).c_str(), &hints, &servinfo ) ) != 0 )
    {
      logInstance.dbg( LogAreaClassDns, "getaddrinfo() failed for " + host + "." );
      return -ConnDnsError;
    }

    for( p = servinfo; p != 0; p = p->ai_next )
    {
      if( ( fd = getSocket( p->ai_family, p->ai_socktype, p->ai_protocol, logInstance ) ) == -1 )
      {
        continue;
      }

      if( ::connect( fd, p->ai_addr, p->ai_addrlen ) == -1 )
      {
        closeSocket( fd, logInstance );
        continue;
      }

      break;
    }

    if( p == 0 )
    {
      freeaddrinfo( servinfo );
      std::string message = "Connection to " + host + ":" + util::int2string( port ) + " failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
      "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
      "errno: " + util::int2string( errno ) + ": " + strerror( errno );
#endif
      logInstance.dbg( LogAreaClassDns, message );
      return -ConnConnectionRefused;
    }

    freeaddrinfo( servinfo );
    return fd;
  }
Ejemplo n.º 3
0
  int DNS::getSocket( int af, int socktype, int proto, const LogSink& logInstance )
  {
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
    SOCKET fd;
#else
    int fd;
#endif
    if( ( fd = socket( af, socktype, proto ) ) == INVALID_SOCKET )
    {
      std::string message = "getSocket( "
          + util::int2string( af ) + ", "
          + util::int2string( socktype ) + ", "
          + util::int2string( proto )
          + " ) failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
          "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
          "errno: " + util::int2string( errno ) + ": " + strerror( errno );
#endif
      logInstance.dbg( LogAreaClassDns, message );

      cleanup( logInstance );
      return -ConnConnectionRefused;
    }

#ifdef HAVE_SETSOCKOPT
    int timeout = 5000;
    int reuseaddr = 1;
    setsockopt( fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof( timeout ) );
    setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof( reuseaddr ) );
#endif

    return (int)fd;
  }
Ejemplo n.º 4
0
  int DNS::connect( struct addrinfo* res, const LogSink& logInstance )
  {
    if( !res )
      return -1;

    int fd = getSocket( res->ai_family, res->ai_socktype, res->ai_protocol, logInstance );
    if( fd < 0 )
      return fd;

    if( ::connect( fd, res->ai_addr, res->ai_addrlen ) == 0 )
    {
      char ip[NI_MAXHOST];
      char port[NI_MAXSERV];

      if( getnameinfo( res->ai_addr, res->ai_addrlen,
                       ip, sizeof( ip ),
                       port, sizeof( port ),
                       NI_NUMERICHOST | NI_NUMERICSERV ) )
      {
        //FIXME do we need to handle this? How? Can it actually happen at all?
//         printf( "could not get numeric hostname");
      }

      if( res->ai_canonname )
        logInstance.dbg( LogAreaClassDns, std::string( "Connecting to " ).append( res->ai_canonname ).append( " (" ).append( ip ).append( "), port  " ).append( port ) );
      else
        logInstance.dbg( LogAreaClassDns, std::string( "Connecting to " ).append( ip ).append( ":" ).append( port ) );

      return fd;
    }

    std::string message = "connect() failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
        "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
        "errno: " + util::int2string( errno ) + ": " + strerror( errno );
#endif
    logInstance.dbg( LogAreaClassDns, message );

    closeSocket( fd, logInstance );
    return -ConnConnectionRefused;
  }
Ejemplo n.º 5
0
  void DNS::cleanup( const LogSink& logInstance )
  {
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
    if( WSACleanup() != 0 )
    {
      logInstance.dbg( LogAreaClassDns, "WSACleanup() failed. WSAGetLastError: "
          + util::int2string( ::WSAGetLastError() ) );
    }
#else
    (void)logInstance;
#endif
  }
Ejemplo n.º 6
0
  int DNS::getSocket( const LogSink& logInstance )
  {
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
    WSADATA wsaData;
    if( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) != 0 )
    {
      logInstance.dbg( LogAreaClassDns, "WSAStartup() failed. WSAGetLastError: "
                                        + util::int2string( ::WSAGetLastError() ) );
      return -ConnDnsError;
    }
#endif

    int protocol = IPPROTO_TCP;
#if !defined( __APPLE__ )  // Sandboxing on Apple doesn't like you to use getprotobyname
    struct protoent* prot;
    if( ( prot = getprotobyname( "tcp" ) ) != 0 )
    {
      protocol = prot->p_proto;
    }
    else
    {
      std::string message = "getprotobyname( \"tcp\" ) failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
          "WSAGetLastError: " + util::int2string( ::WSAGetLastError() )
#else
          "errno: " + util::int2string( errno ) + ": " + strerror( errno );
#endif
          + ". Falling back to IPPROTO_TCP: " + util::int2string( IPPROTO_TCP );
      logInstance.dbg( LogAreaClassDns, message );

      // Do not return an error. We'll fall back to IPPROTO_TCP.
    }
#endif // !defined( __APPLE__ )

    return getSocket( PF_INET, SOCK_STREAM, protocol, logInstance );
  }
Ejemplo n.º 7
0
  void DNS::closeSocket( int fd, const LogSink& logInstance )
  {
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
    int result = closesocket( fd );
#else
    int result = close( fd );
#endif

    if( result != 0 )
    {
      std::string message = "closeSocket() failed. "
#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
          "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
#else
          "errno: " + util::int2string( errno ) + ": " + strerror( errno );
#endif
      logInstance.dbg( LogAreaClassDns, message );
    }
  }
Ejemplo n.º 8
0
 void DNS::resolve( struct addrinfo** res, const std::string& service, const std::string& proto,
                    const std::string& domain, const LogSink& logInstance )
 {
   logInstance.dbg( LogAreaClassDns, "Resolving: _" +  service + "._" + proto + "." + domain );
   struct addrinfo hints;
   if( proto == "tcp" )
     hints.ai_socktype = SOCK_STREAM;
   else if( proto == "udp" )
     hints.ai_socktype = SOCK_DGRAM;
   else
   {
     logInstance.err( LogAreaClassDns, "Unknown/Invalid protocol: " + proto );
   }
   memset( &hints, '\0', sizeof( hints ) );
   hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
   hints.ai_socktype = SOCK_STREAM;
   int e = getaddrinfo( domain.c_str(), service.c_str(), &hints, res );
   if( e )
     logInstance.err( LogAreaClassDns, "getaddrinfo() failed" );
 }
Ejemplo n.º 9
0
  int DNS::connect( struct addrinfo* res, const LogSink& logInstance )
  {
    if( !res )
      return -1;

    int fd = getSocket( res->ai_family, res->ai_socktype, res->ai_protocol );
    if( fd < 0 )
      return fd;

    if( ::connect( fd, res->ai_addr, res->ai_addrlen ) == 0 )
    {
      char ip[NI_MAXHOST];
      char port[NI_MAXSERV];

      if( getnameinfo( res->ai_addr, sizeof( sockaddr ),
                       ip, sizeof( ip ),
                       port, sizeof( port ),
                       NI_NUMERICHOST | NI_NUMERICSERV ) )
      {
        //FIXME do we need to handle this? How? Can it actually happen at all?
//         printf( "could not get numeric hostname");
      }

      std::ostringstream oss;
      oss << "Connecting to ";
      if( res->ai_canonname )
      {
        oss << res->ai_canonname;
        oss << " (" << ip << "), port " << port;
      }
      else
      {
        oss << ip << ":" << port;
      }
      logInstance.dbg( LogAreaClassDns, oss.str() );
      return fd;
    }

    closeSocket( fd );
    return -ConnConnectionRefused;
  }