windows-nt/Source/XPSP1/NT/net/ias/protocol/radius/ports.cpp

332 lines
8.5 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//##--------------------------------------------------------------
//
// 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