Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
8.5 KiB

  1. //##--------------------------------------------------------------
  2. //
  3. // File: ports.cpp
  4. //
  5. // Synopsis: Implementation of CPorts class responsible
  6. // for setting up the ports on which the RADIUS
  7. // server will accept authentication & accounting
  8. // requests
  9. //
  10. // History: 10/22/98 MKarki Created
  11. //
  12. // Copyright (C) 1997-98 Microsoft Corporation
  13. // All rights reserved.
  14. //
  15. //----------------------------------------------------------------
  16. #include "radcommon.h"
  17. #include "ports.h"
  18. #include "portscoll.h"
  19. #include "portparser.h"
  20. //++--------------------------------------------------------------
  21. //
  22. // Function: ~CPorts
  23. //
  24. // Synopsis: This is CPortParser class public destructionr which
  25. // cleans up the sockets created
  26. //
  27. // Arguments: VARIANT*
  28. //
  29. // Returns: HRESULT
  30. //
  31. // History: MKarki Created 10/22/97
  32. //
  33. //----------------------------------------------------------------
  34. CPorts::~CPorts ()
  35. {
  36. Clear ();
  37. } // end of CPorts class destructor
  38. //++--------------------------------------------------------------
  39. //
  40. // Function: Resolve
  41. //
  42. // Synopsis: This is CPortParser class public method which
  43. // is called to setting up the ports collection
  44. //
  45. // Arguments: [in] VARIANT*
  46. //
  47. // Returns: HRESULT
  48. //
  49. // History: MKarki Created 10/22/97
  50. //
  51. //----------------------------------------------------------------
  52. HRESULT CPorts::Resolve (
  53. /*[in]*/ VARIANT *pvtIn
  54. )
  55. {
  56. HRESULT hr = S_OK;
  57. _ASSERT ((pvtIn) && (VT_BSTR == V_VT (pvtIn)));
  58. do
  59. {
  60. //
  61. // clear any previous information
  62. //
  63. Clear ();
  64. CPortsCollection portCollection;
  65. //
  66. // get the port info into the ports collection
  67. //
  68. CollectPortInfo (portCollection,V_BSTR (pvtIn));
  69. //
  70. // set the socketset now
  71. //
  72. SetPorts (portCollection,m_PortSet);
  73. }
  74. while (FALSE);
  75. return (hr);
  76. } // end of CPorts::Resolve method
  77. //++--------------------------------------------------------------
  78. //
  79. // Function: CollectPortInfo
  80. //
  81. // Synopsis: This is CPortParser class private method which
  82. // is called to setting up the port info from the
  83. // BSTR provided
  84. //
  85. // Arguments:
  86. // [in] PWSTR - port info string
  87. //
  88. // Returns: HRESULT
  89. //
  90. // History: MKarki Created 10/22/97
  91. //
  92. //----------------------------------------------------------------
  93. HRESULT CPorts::CollectPortInfo (
  94. /*[in]*/ CPortsCollection& portCollection,
  95. /*[in]*/ PWSTR pwszPortInfo
  96. )
  97. {
  98. _ASSERT (pwszPortInfo);
  99. HRESULT hr = S_OK;
  100. CPortParser parser (pwszPortInfo);
  101. do
  102. {
  103. //
  104. // get the IP address
  105. //
  106. DWORD dwIPAddress = 0;
  107. hr = parser.GetIPAddress(&dwIPAddress);
  108. if (S_FALSE == hr)
  109. {
  110. break;
  111. }
  112. else if (S_OK == hr)
  113. {
  114. //
  115. // get the ports associated with this IP address
  116. //
  117. do
  118. {
  119. WORD wPort = 0;
  120. hr = parser.GetNextPort (&wPort);
  121. if (S_OK == hr)
  122. {
  123. //
  124. // put the info in the collection
  125. //
  126. portCollection.Insert (wPort, dwIPAddress);
  127. }
  128. }
  129. while (S_OK == hr);
  130. }
  131. }
  132. while (SUCCEEDED (hr));
  133. return (hr);
  134. } // end of CPorts::CollectPortInfo method
  135. //++--------------------------------------------------------------
  136. //
  137. // Function: SetPorts
  138. //
  139. // Synopsis: This is CPortParser class private method which
  140. // is responsible for getting the ports and IP address
  141. // out of the collection and putting them in the FD_SET
  142. //
  143. // Arguments:
  144. // [in] CPortCollection&
  145. // [in] PWSTR - port info string
  146. //
  147. // Returns: HRESULT
  148. //
  149. // History: MKarki Created 10/22/97
  150. //
  151. //----------------------------------------------------------------
  152. HRESULT CPorts::SetPorts (
  153. CPortsCollection& portsCollection,
  154. const fd_set& SocketSet
  155. )
  156. {
  157. HRESULT hr = S_OK;
  158. WORD wPort = 0;
  159. DWORD dwIPAddress = 0;
  160. SOCKET sock = INVALID_SOCKET;
  161. FD_ZERO (&SocketSet);
  162. do
  163. {
  164. //
  165. // get port info from the collection
  166. //
  167. hr = portsCollection.GetNext (&wPort, &dwIPAddress);
  168. if (FAILED (hr))
  169. {
  170. hr = S_OK;
  171. break;
  172. }
  173. //
  174. // get a socket and add the port to the socket
  175. //
  176. sock = ::socket (AF_INET, SOCK_DGRAM, 0);
  177. if (INVALID_SOCKET == sock)
  178. {
  179. //
  180. // we failed to get a socket
  181. //
  182. DWORD dwError = ::WSAGetLastError ();
  183. IASTracePrintf (
  184. "Unable to create socket during interface resolution "
  185. "due to error:%d",
  186. dwError
  187. );
  188. hr = HRESULT_FROM_WIN32 (dwError);
  189. }
  190. else
  191. {
  192. // Bind the socket for exclusive access to keep other apps from
  193. // snooping. We don't care if this fails.
  194. int optval = 1;
  195. setsockopt(
  196. sock,
  197. SOL_SOCKET,
  198. SO_EXCLUSIVEADDRUSE,
  199. (const char*)&optval,
  200. sizeof(optval)
  201. );
  202. //
  203. // we successfully got the socket
  204. // now go ahead and bind it to a port if so requested
  205. //
  206. SOCKADDR_IN sin;
  207. ZeroMemory (&sin, sizeof (sin));
  208. //
  209. // put address information into SOCKADDR_IN struct
  210. //
  211. sin.sin_family = AF_INET;
  212. sin.sin_port = htons (wPort);
  213. sin.sin_addr.s_addr = dwIPAddress;
  214. //
  215. // make call to bind API
  216. //
  217. int iStatus = ::bind (
  218. sock,
  219. (LPSOCKADDR)&sin,
  220. (INT) sizeof (SOCKADDR_IN)
  221. );
  222. if (SOCKET_ERROR == iStatus)
  223. {
  224. IASTracePrintf (
  225. "Unable to bind socket to IP address:%s due to error:%d",
  226. inet_ntoa (sin.sin_addr),
  227. ::WSAGetLastError ()
  228. );
  229. ::closesocket (sock);
  230. }
  231. else
  232. {
  233. IASTracePrintf (
  234. "Radius Component will accept requests on IP address:%s, port:%d",
  235. inet_ntoa (sin.sin_addr),
  236. wPort
  237. );
  238. //
  239. // add this socket to the socket set
  240. //
  241. m_PortArray.push_back (sock);
  242. FD_SET (sock, &SocketSet);
  243. }
  244. }
  245. }
  246. while (SUCCEEDED (hr));
  247. return (hr);
  248. } // end of CPorts::SetPorts method
  249. //++--------------------------------------------------------------
  250. //
  251. // Function: GetSocketSet
  252. //
  253. // Synopsis: This is CPortParser class public method which
  254. // is returns the socket set to the
  255. // caller, if there are any sockets in the set
  256. //
  257. // Arguments: [in] fd_set* - Socket Set
  258. //
  259. // Returns: HRESULT
  260. //
  261. // History: MKarki Created 10/22/97
  262. //
  263. //----------------------------------------------------------------
  264. HRESULT CPorts::GetSocketSet(
  265. /*[in]*/ fd_set *pSocketSet
  266. )
  267. {
  268. _ASSERT (pSocketSet);
  269. *pSocketSet = m_PortSet;
  270. return (S_OK);
  271. } // end of CPorts::GetSocketSet method
  272. //++--------------------------------------------------------------
  273. //
  274. // Function: Clear
  275. //
  276. // Synopsis: This is CPortParser class public method which
  277. // clear up all the authentication and accounting sockets
  278. //
  279. // Arguments: VARIANT*
  280. //
  281. // Returns: HRESULT
  282. //
  283. // History: MKarki Created 10/22/97
  284. //
  285. //----------------------------------------------------------------
  286. HRESULT CPorts::Clear ()
  287. {
  288. DWORD dwPortCount = m_PortArray.size ();
  289. for (DWORD dwCount = 0; dwCount < dwPortCount; dwCount++)
  290. {
  291. if (INVALID_SOCKET != m_PortArray[dwCount])
  292. {
  293. ::closesocket (m_PortArray[dwCount]);
  294. }
  295. }
  296. m_PortArray.erase (m_PortArray.begin(), m_PortArray.end ());
  297. return (S_OK);
  298. } // end of CPorts::Clear method