//##-------------------------------------------------------------- // // 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