DSNetworkUtilities.cpp [plain text]
#include <string.h>
#include <ctype.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <errno.h>
#include <netinet/in.h>
#include <net/if.h> // interface struture ifreq, ifconf
#include <net/if_dl.h> // datalink structs
#include <net/if_types.h>
#include <arpa/inet.h> // for inet_*
#include <arpa/nameser.h>
#include <resolv.h>
#include <string.h>
#include <stdlib.h>
#include "DSNetworkUtilities.h"
#ifdef DSSERVERTCP
#include "CLog.h"
#endif
#define IFR_NEXT(ifr) \
((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
MAX(0, (int) (ifr)->ifr_addr.sa_len - (int) sizeof((ifr)->ifr_addr))))
Boolean DSNetworkUtilities::sNetworkInitialized = false;
Boolean DSNetworkUtilities::sAppleTalkAvailable = false;
Boolean DSNetworkUtilities::sTCPAvailable = false;
short DSNetworkUtilities::sIPAddrCount = 0; short DSNetworkUtilities::sAliasCount = 0;
InetDomainName DSNetworkUtilities::sLocalNodeName = "\0";
InetDomainName DSNetworkUtilities::sLocalHostName = "\0";
InetHost DSNetworkUtilities::sLocalHostIPAddr = 0;
MultiHomeIPInfo DSNetworkUtilities::sIPInfo[ kMaxIPAddrs ];
IPAddressInfo DSNetworkUtilities::sAddrList[ kMaxIPAddrs ];
InetDomainName DSNetworkUtilities::sAliasList[ kMaxIPAddrs ];
DSMutexSemaphore *DSNetworkUtilities::sNetSemaphore = NULL;
OSStatus DSNetworkUtilities::Initialize ( void )
{
register int rc = 0;
struct utsname myname;
if (sNetworkInitialized == true)
{
return eDSNoErr;
}
sNetSemaphore = new DSMutexSemaphore();
::memset( &sLocalHostName, 0, sizeof( sLocalHostName ) );
::memset( &sIPInfo, 0, sizeof(sIPInfo) );
::memset( &sAddrList, 0, sizeof(sAddrList) );
::memset( &sAliasList, 0, sizeof(sAliasList) );
if ( ::uname(&myname) == 0 )
{
::strncpy( sLocalNodeName, myname.nodename, sizeof( sLocalNodeName ) );
}
else
{
::strcpy( sLocalNodeName, "localhost" );
}
try
{
#ifdef DSSERVERTCP
SRVRLOG( kLogApplication, "Initializing TCP ..." );
#endif
rc = InitializeTCP();
if ( rc != 0 )
{
#ifdef DSSERVERTCP
ERRORLOG1( kLogApplication, "*** Warning*** TCP is not available. Error: %d", rc );
DBGLOG( kLogTCPEndpoint, "DSNetworkUtilities::Initialize(): TCP not available." );
#else
LOG1( kStdErr, "*** Warning*** DSNetworkUtilities::Initialize(): TCP is not available. Error: %d", rc );
#endif
throw( (sInt32)rc );
}
}
catch( sInt32 err )
{
sNetworkInitialized = false;
#ifdef DSSERVERTCP
DBGLOG1( kLogTCPEndpoint, "DSNetworkUtilities::Initialize failed. Error: %d", err );
#else
LOG1( kStdErr, "DSNetworkUtilities::Initialize failed. Error: %d", err );
#endif
return err;
}
sNetworkInitialized = true;
#ifdef DSSERVERTCP
DBGLOG( kLogTCPEndpoint, "DSNetworkUtilities::Initialized." );
#endif
return( eDSNoErr );
}
OSStatus DSNetworkUtilities::ResolveToIPAddress ( const InetDomainName inDomainName, InetHost* outInetHost )
{
register struct hostent *hp = NULL;
DSNetworkUtilities::Wait();
try
{
if ( inDomainName[0] != '\0' && outInetHost != NULL)
{
hp = ::gethostbyname( inDomainName );
if ( hp == NULL )
{
throw( (sInt32)h_errno );
}
*outInetHost = ntohl( ((struct in_addr *)(hp->h_addr_list[0]))->s_addr );
DSNetworkUtilities::Signal();
return( eDSNoErr );
}
}
catch( sInt32 err )
{
#ifdef DSSERVERTCP
ERRORLOG1( kLogTCPEndpoint, "Unable to resolve the IP address for %s.", inDomainName );
#else
LOG1( kStdErr, "Unable to resolve the IP address for %s.", inDomainName );
#endif
DSNetworkUtilities::Signal();
return( err );
}
return( eDSNoErr );
}
InetHost DSNetworkUtilities::GetOurIPAddress ( short inIndex )
{
if ( sNetworkInitialized == false )
{
if ( Initialize() != eDSNoErr )
{
return 0;
}
}
if (inIndex < sIPAddrCount && inIndex < kMaxIPAddrs)
{
return( sIPInfo[ inIndex ].IPAddress );
}
return 0;
}
const char *
DSNetworkUtilities::GetOurIPAddressString (short inIndex)
{
if (inIndex < sIPAddrCount && inIndex < kMaxIPAddrs)
return( sIPInfo[ inIndex ].IPAddressString );
return NULL;
}
void DSNetworkUtilities::GetOurIPAddressString2 ( short inIndex, char *ioBuffer, int inBufferSize )
{
if ( ioBuffer != NULL && inIndex < sIPAddrCount && inIndex < kMaxIPAddrs )
{
::strncpy(ioBuffer, sIPInfo[inIndex].IPAddressString, inBufferSize);
}
}
Boolean DSNetworkUtilities::DoesIPAddrMatch ( InetHost inIPAddr )
{
if ((inIPAddr != 0x00000000) && (inIPAddr != 0xFFFFFFFF) )
{
for ( int i=0; i < sIPAddrCount && i < kMaxIPAddrs; i++ )
{
if (inIPAddr == sIPInfo[i].IPAddress)
return true;
}
}
return false;
}
Boolean
DSNetworkUtilities::IsValidAddressString (const char *inString, InetHost *outInetHost)
{
register const char *cp;
struct in_addr hostaddr;
if (inString == NULL)
return false;
for (cp = inString; *cp; ++cp) {
if ((isdigit(*cp) !=0) && *cp != '.') {
return false;
}
}
if (*--cp != '.') {
if (::inet_aton(inString, &hostaddr) == 1) {
*outInetHost = ntohl(hostaddr.s_addr);
return true;
}
}
return false;
}
InetHost
DSNetworkUtilities::GetIPAddressByName(const char *inName)
{
register struct hostent *hp = NULL;
register InetHost IPAddr = 0;
DSNetworkUtilities::Wait();
try {
hp = ::gethostbyname(inName);
if (hp == NULL) {
throw((sInt32)h_errno);
}
IPAddr = ntohl(((struct in_addr *)hp->h_addr)->s_addr);
DSNetworkUtilities::Signal();
return IPAddr;
}
catch( sInt32 err )
{
#ifdef DSSERVERTCP
ERRORLOG2( kLogTCPEndpoint, "GetIPAddressByName for %s failed: %d.", inName, err );
#else
LOG2( kStdErr, "GetIPAddressByName for %s failed: %d.", inName, err );
#endif
DSNetworkUtilities::Signal();
return IPAddr;
}
}
int
DSNetworkUtilities::IPAddrToString(const InetHost inAddr, char *ioNameBuffer, const int inBufferSize)
{
char *result;
struct in_addr InetAddr;
DSNetworkUtilities::Wait();
InetAddr.s_addr = htonl(inAddr);
result = ::inet_ntoa(InetAddr);
if ( result != NULL )
::strncpy(ioNameBuffer, result, inBufferSize);
else {
#ifdef DSSERVERTCP
ERRORLOG1( kLogTCPEndpoint, "IPAddrToString for %u failed.", inAddr );
#else
LOG1( kStdErr, "IPAddrToString for %u failed.", inAddr );
#endif
ioNameBuffer[0] = '\0';
DSNetworkUtilities::Signal();
return -1;
}
DSNetworkUtilities::Signal();
return 0;
}
int
DSNetworkUtilities::StringToIPAddr(const char *inAddrStr, InetHost *ioIPAddr)
{
struct in_addr InetAddr;
int rc;
if ( inAddrStr && ioIPAddr ) {
DSNetworkUtilities::Wait();
rc = ::inet_aton(inAddrStr, &InetAddr);
if ( rc == 1 ) {
*ioIPAddr = ntohl(InetAddr.s_addr);
DSNetworkUtilities::Signal();
return 0;
}
#ifdef DSSERVERTCP
ERRORLOG1( kLogTCPEndpoint, "StringToIPAddr() failed for %s", inAddrStr );
#else
LOG1( kStdErr, "StringToIPAddr() failed for %s", inAddrStr );
#endif
DSNetworkUtilities::Signal();
}
return -1;
}
int DSNetworkUtilities::InitializeTCP ( void )
{
struct ifconf ifc;
struct ifreq ifrbuf[30];
register struct ifreq *ifrptr;
register struct sockaddr_in *sain;
register int sock = 0;
register int i = 0;
register int ipcount = 0;
int rc = 0;
int err = 0;
sTCPAvailable = false;
DSNetworkUtilities::Wait();
try {
sock = socket(AF_INET, SOCK_DGRAM, 0);
if ( sock == -1 )
{
err = errno;
#ifdef DSSERVERTCP
ERRORLOG1( kLogTCPEndpoint, "SOCKET: %d.", err );
#else
LOG1( kStdErr, "SOCKET: %d.", err );
#endif
throw((sInt32)err);
}
ifc.ifc_buf = (caddr_t)ifrbuf;
ifc.ifc_len = sizeof(ifrbuf);
rc = ::ioctl(sock, SIOCGIFCONF, &ifc);
if ( rc == -1 )
{
err = errno;
#ifdef DSSERVERTCP
ERRORLOG1( kLogTCPEndpoint, "ioctl:SIOCGIFCONF: %d.", err );
#else
LOG1( kStdErr, "ioctl:SIOCGIFCONF: %d.", err );
#endif
throw((sInt32)err);
}
ipcount = 0;
for ( ifrptr = (struct ifreq *)ifc.ifc_buf, i=0;
(char *) ifrptr < &ifc.ifc_buf[ifc.ifc_len] && i < kMaxIPAddrs;
ifrptr = IFR_NEXT(ifrptr), i++ )
{
if ( (*ifrptr->ifr_name != '\0') && (ifrptr->ifr_addr.sa_family == AF_INET) )
{
if ( *ifrptr->ifr_name == 'e' )
{
sain = (struct sockaddr_in *)&(ifrptr->ifr_addr);
sIPInfo[ipcount].IPAddress = ntohl(sain->sin_addr.s_addr);
IPAddrToString(sIPInfo[ipcount].IPAddress, sIPInfo[ipcount].IPAddressString, MAXIPADDRSTRLEN);
ipcount ++;
}
else if (*ifrptr->ifr_name == 'l')
{
sain = (struct sockaddr_in *)&(ifrptr->ifr_addr);
sLocalHostIPAddr = ntohl(sain->sin_addr.s_addr);
::strcpy(sLocalHostName, "localhost");
}
}
}
close(sock);
sIPAddrCount = ipcount;
sTCPAvailable = true;
DSNetworkUtilities::Signal();
}
catch( sInt32 someError )
{
DSNetworkUtilities::Signal();
#ifdef DSSERVERTCP
ERRORLOG( kLogTCPEndpoint, "DSNetworkUtilities::InitializeTCP failed." );
#else
LOG( kStdErr, "DSNetworkUtilities::InitializeTCP failed." );
#endif
sTCPAvailable = false;
return someError;
}
return eDSNoErr;
}
void DSNetworkUtilities::Signal ( void )
{
if ( sNetSemaphore != nil )
{
sNetSemaphore->Signal();
}
else
{
#ifdef DSSERVERTCP
DBGLOG( kLogApplication,"DSNetworkUtilities::Signal -- sNetSemaphore is NULL" );
#else
LOG( kStdErr,"DSNetworkUtilities::Signal -- sNetSemaphore is NULL" );
#endif
}
}
long DSNetworkUtilities::Wait ( sInt32 milliSecs )
{
if ( sNetSemaphore != nil )
{
return sNetSemaphore->Wait(milliSecs);
}
else
{
#ifdef DSSERVERTCP
DBGLOG( kLogApplication,"DSNetworkUtilities::Wait -- sNetSemaphore is NULL" );
#else
LOG( kStdErr,"DSNetworkUtilities::Wait -- sNetSemaphore is NULL" );
#endif
return (long)DSSemaphore::semOtherErr;
}
}