332 lines
8.5 KiB
C++
332 lines
8.5 KiB
C++
|
//##--------------------------------------------------------------
|
||
|
//
|
||
|
// File: ports.cpp
|
||
|
//
|
||
|
// Synopsis: Implementation of CPorts class responsible
|
||
|
// for setting up the ports on which the RADIUS
|
||
|
// server will accept authentication & accounting
|
||
|
// requests
|
||
|
//
|
||
|
// History: 10/22/98 MKarki Created
|
||
|
//
|
||
|
// Copyright (C) 1997-98 Microsoft Corporation
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
#include "radcommon.h"
|
||
|
#include "ports.h"
|
||
|
#include "portscoll.h"
|
||
|
#include "portparser.h"
|
||
|
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ~CPorts
|
||
|
//
|
||
|
// Synopsis: This is CPortParser class public destructionr which
|
||
|
// cleans up the sockets created
|
||
|
//
|
||
|
// Arguments: VARIANT*
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// History: MKarki Created 10/22/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
CPorts::~CPorts ()
|
||
|
{
|
||
|
Clear ();
|
||
|
|
||
|
} // end of CPorts class destructor
|
||
|
|
||
|
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: Resolve
|
||
|
//
|
||
|
// Synopsis: This is CPortParser class public method which
|
||
|
// is called to setting up the ports collection
|
||
|
//
|
||
|
// Arguments: [in] VARIANT*
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// History: MKarki Created 10/22/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT CPorts::Resolve (
|
||
|
/*[in]*/ VARIANT *pvtIn
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
_ASSERT ((pvtIn) && (VT_BSTR == V_VT (pvtIn)));
|
||
|
|
||
|
do
|
||
|
{
|
||
|
//
|
||
|
// clear any previous information
|
||
|
//
|
||
|
Clear ();
|
||
|
|
||
|
CPortsCollection portCollection;
|
||
|
//
|
||
|
// get the port info into the ports collection
|
||
|
//
|
||
|
CollectPortInfo (portCollection,V_BSTR (pvtIn));
|
||
|
|
||
|
//
|
||
|
// set the socketset now
|
||
|
//
|
||
|
SetPorts (portCollection,m_PortSet);
|
||
|
}
|
||
|
while (FALSE);
|
||
|
|
||
|
return (hr);
|
||
|
|
||
|
} // end of CPorts::Resolve method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CollectPortInfo
|
||
|
//
|
||
|
// Synopsis: This is CPortParser class private method which
|
||
|
// is called to setting up the port info from the
|
||
|
// BSTR provided
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [in] PWSTR - port info string
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// History: MKarki Created 10/22/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT CPorts::CollectPortInfo (
|
||
|
/*[in]*/ CPortsCollection& portCollection,
|
||
|
/*[in]*/ PWSTR pwszPortInfo
|
||
|
)
|
||
|
{
|
||
|
_ASSERT (pwszPortInfo);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
CPortParser parser (pwszPortInfo);
|
||
|
do
|
||
|
{
|
||
|
//
|
||
|
// get the IP address
|
||
|
//
|
||
|
DWORD dwIPAddress = 0;
|
||
|
hr = parser.GetIPAddress(&dwIPAddress);
|
||
|
if (S_FALSE == hr)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
else if (S_OK == hr)
|
||
|
{
|
||
|
//
|
||
|
// get the ports associated with this IP address
|
||
|
//
|
||
|
do
|
||
|
{
|
||
|
WORD wPort = 0;
|
||
|
hr = parser.GetNextPort (&wPort);
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
//
|
||
|
// put the info in the collection
|
||
|
//
|
||
|
portCollection.Insert (wPort, dwIPAddress);
|
||
|
}
|
||
|
}
|
||
|
while (S_OK == hr);
|
||
|
}
|
||
|
}
|
||
|
while (SUCCEEDED (hr));
|
||
|
|
||
|
return (hr);
|
||
|
|
||
|
} // end of CPorts::CollectPortInfo method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SetPorts
|
||
|
//
|
||
|
// Synopsis: This is CPortParser class private method which
|
||
|
// is responsible for getting the ports and IP address
|
||
|
// out of the collection and putting them in the FD_SET
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [in] CPortCollection&
|
||
|
// [in] PWSTR - port info string
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// History: MKarki Created 10/22/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT CPorts::SetPorts (
|
||
|
CPortsCollection& portsCollection,
|
||
|
const fd_set& SocketSet
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
WORD wPort = 0;
|
||
|
DWORD dwIPAddress = 0;
|
||
|
SOCKET sock = INVALID_SOCKET;
|
||
|
|
||
|
|
||
|
FD_ZERO (&SocketSet);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
//
|
||
|
// get port info from the collection
|
||
|
//
|
||
|
hr = portsCollection.GetNext (&wPort, &dwIPAddress);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get a socket and add the port to the socket
|
||
|
//
|
||
|
sock = ::socket (AF_INET, SOCK_DGRAM, 0);
|
||
|
if (INVALID_SOCKET == sock)
|
||
|
{
|
||
|
//
|
||
|
// we failed to get a socket
|
||
|
//
|
||
|
DWORD dwError = ::WSAGetLastError ();
|
||
|
IASTracePrintf (
|
||
|
"Unable to create socket during interface resolution "
|
||
|
"due to error:%d",
|
||
|
dwError
|
||
|
);
|
||
|
hr = HRESULT_FROM_WIN32 (dwError);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Bind the socket for exclusive access to keep other apps from
|
||
|
// snooping. We don't care if this fails.
|
||
|
int optval = 1;
|
||
|
setsockopt(
|
||
|
sock,
|
||
|
SOL_SOCKET,
|
||
|
SO_EXCLUSIVEADDRUSE,
|
||
|
(const char*)&optval,
|
||
|
sizeof(optval)
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// we successfully got the socket
|
||
|
// now go ahead and bind it to a port if so requested
|
||
|
//
|
||
|
SOCKADDR_IN sin;
|
||
|
ZeroMemory (&sin, sizeof (sin));
|
||
|
|
||
|
//
|
||
|
// put address information into SOCKADDR_IN struct
|
||
|
//
|
||
|
sin.sin_family = AF_INET;
|
||
|
sin.sin_port = htons (wPort);
|
||
|
sin.sin_addr.s_addr = dwIPAddress;
|
||
|
|
||
|
//
|
||
|
// make call to bind API
|
||
|
//
|
||
|
int iStatus = ::bind (
|
||
|
sock,
|
||
|
(LPSOCKADDR)&sin,
|
||
|
(INT) sizeof (SOCKADDR_IN)
|
||
|
);
|
||
|
if (SOCKET_ERROR == iStatus)
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to bind socket to IP address:%s due to error:%d",
|
||
|
inet_ntoa (sin.sin_addr),
|
||
|
::WSAGetLastError ()
|
||
|
);
|
||
|
::closesocket (sock);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Radius Component will accept requests on IP address:%s, port:%d",
|
||
|
inet_ntoa (sin.sin_addr),
|
||
|
wPort
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// add this socket to the socket set
|
||
|
//
|
||
|
m_PortArray.push_back (sock);
|
||
|
FD_SET (sock, &SocketSet);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (SUCCEEDED (hr));
|
||
|
|
||
|
return (hr);
|
||
|
|
||
|
} // end of CPorts::SetPorts method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetSocketSet
|
||
|
//
|
||
|
// Synopsis: This is CPortParser class public method which
|
||
|
// is returns the socket set to the
|
||
|
// caller, if there are any sockets in the set
|
||
|
//
|
||
|
// Arguments: [in] fd_set* - Socket Set
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// History: MKarki Created 10/22/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT CPorts::GetSocketSet(
|
||
|
/*[in]*/ fd_set *pSocketSet
|
||
|
)
|
||
|
{
|
||
|
_ASSERT (pSocketSet);
|
||
|
|
||
|
*pSocketSet = m_PortSet;
|
||
|
|
||
|
return (S_OK);
|
||
|
|
||
|
} // end of CPorts::GetSocketSet method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: Clear
|
||
|
//
|
||
|
// Synopsis: This is CPortParser class public method which
|
||
|
// clear up all the authentication and accounting sockets
|
||
|
//
|
||
|
// Arguments: VARIANT*
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// History: MKarki Created 10/22/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT CPorts::Clear ()
|
||
|
{
|
||
|
DWORD dwPortCount = m_PortArray.size ();
|
||
|
for (DWORD dwCount = 0; dwCount < dwPortCount; dwCount++)
|
||
|
{
|
||
|
if (INVALID_SOCKET != m_PortArray[dwCount])
|
||
|
{
|
||
|
::closesocket (m_PortArray[dwCount]);
|
||
|
}
|
||
|
}
|
||
|
m_PortArray.erase (m_PortArray.begin(), m_PortArray.end ());
|
||
|
return (S_OK);
|
||
|
|
||
|
} // end of CPorts::Clear method
|