Leaked source code of windows server 2003
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.

238 lines
5.5 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // SYNOPSIS
  6. //
  7. // Defines the class CPorts.
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "radcommon.h"
  11. #include "ports.h"
  12. #include "portparser.h"
  13. #include <new>
  14. #include <ws2tcpip.h>
  15. CPorts::CPorts() throw ()
  16. : ports(0),
  17. numPorts(0)
  18. {
  19. FD_ZERO(&fdSet);
  20. }
  21. CPorts::~CPorts() throw ()
  22. {
  23. Clear();
  24. }
  25. HRESULT CPorts::SetConfig(const wchar_t* config) throw ()
  26. {
  27. // We can only be configured once.
  28. if (ports != 0)
  29. {
  30. return E_UNEXPECTED;
  31. }
  32. size_t maxPorts = CPortParser::CountPorts(config);
  33. if (maxPorts == 0)
  34. {
  35. return E_INVALIDARG;
  36. }
  37. ports = new (std::nothrow) Port[maxPorts];
  38. if (ports == 0)
  39. {
  40. return E_OUTOFMEMORY;
  41. }
  42. CPortParser parser(config);
  43. DWORD ipAddress;
  44. while (parser.GetIPAddress(&ipAddress) == S_OK)
  45. {
  46. WORD ipPort;
  47. while (parser.GetNextPort(&ipPort) == S_OK)
  48. {
  49. InsertPort(ipAddress, ipPort);
  50. }
  51. }
  52. return S_OK;
  53. }
  54. HRESULT CPorts::OpenSockets() throw ()
  55. {
  56. HRESULT result = S_OK;
  57. for (size_t i = 0; i < numPorts; ++i)
  58. {
  59. if (ports[i].socket != INVALID_SOCKET)
  60. {
  61. continue;
  62. }
  63. SOCKADDR_IN sin;
  64. sin.sin_family = AF_INET;
  65. sin.sin_port = htons(ports[i].ipPort);
  66. sin.sin_addr.s_addr = ports[i].ipAddress;
  67. SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
  68. if (sock == INVALID_SOCKET)
  69. {
  70. int error = WSAGetLastError();
  71. IASTracePrintf(
  72. "Create socket failed for %s:%hu; error = %lu",
  73. inet_ntoa(sin.sin_addr),
  74. ports[i].ipPort,
  75. error
  76. );
  77. result = HRESULT_FROM_WIN32(error);
  78. break;
  79. }
  80. else
  81. {
  82. // Bind the socket for exclusive access to keep other apps from
  83. // snooping.
  84. int optval = 1;
  85. if (setsockopt(
  86. sock,
  87. SOL_SOCKET,
  88. SO_EXCLUSIVEADDRUSE,
  89. reinterpret_cast<const char*>(&optval),
  90. sizeof(optval)
  91. ) == SOCKET_ERROR)
  92. {
  93. int error = WSAGetLastError();
  94. IASTracePrintf(
  95. "Set socket option SO_EXCLUSIVEADDRUSE failed for %s:%hu; error = %lu",
  96. inet_ntoa(sin.sin_addr),
  97. ports[i].ipPort,
  98. error
  99. );
  100. result = HRESULT_FROM_WIN32(error);
  101. closesocket(sock);
  102. break;
  103. }
  104. // Block receiving broadcast traffic (for security)
  105. optval = 0; // FALSE
  106. if (setsockopt(
  107. sock,
  108. IPPROTO_IP,
  109. IP_RECEIVE_BROADCAST,
  110. reinterpret_cast<const char*>(&optval),
  111. sizeof(optval)
  112. ) == SOCKET_ERROR)
  113. {
  114. int error = WSAGetLastError();
  115. IASTracePrintf(
  116. "Set IP option IP_RECEIVE_BROADCAST failed for %s:%hu; error = %lu",
  117. inet_ntoa(sin.sin_addr),
  118. ports[i].ipPort,
  119. error
  120. );
  121. result = HRESULT_FROM_WIN32(error);
  122. closesocket(sock);
  123. break;
  124. }
  125. int bindResult = bind(
  126. sock,
  127. reinterpret_cast<const SOCKADDR*>(&sin),
  128. sizeof(SOCKADDR_IN)
  129. );
  130. if (bindResult == SOCKET_ERROR)
  131. {
  132. int error = WSAGetLastError();
  133. IASTracePrintf(
  134. "Bind failed for %s:%hu; error = %lu",
  135. inet_ntoa(sin.sin_addr),
  136. ports[i].ipPort,
  137. error
  138. );
  139. result = HRESULT_FROM_WIN32(error);
  140. closesocket (sock);
  141. }
  142. else
  143. {
  144. IASTracePrintf(
  145. "RADIUS Server starting to listen on %s:%hu",
  146. inet_ntoa(sin.sin_addr),
  147. ports[i].ipPort
  148. );
  149. ports[i].socket = sock;
  150. FD_SET(sock, &fdSet);
  151. }
  152. }
  153. }
  154. return result;
  155. }
  156. void CPorts::CloseSockets() throw ()
  157. {
  158. for (size_t i = 0; i < numPorts; ++i)
  159. {
  160. if (ports[i].socket != INVALID_SOCKET)
  161. {
  162. closesocket(ports[i].socket);
  163. ports[i].socket = INVALID_SOCKET;
  164. }
  165. }
  166. FD_ZERO(&fdSet);
  167. }
  168. void CPorts::Clear() throw ()
  169. {
  170. CloseSockets();
  171. delete[] ports;
  172. ports = 0;
  173. numPorts = 0;
  174. }
  175. void CPorts::InsertPort(DWORD ipAddress, WORD ipPort) throw ()
  176. {
  177. for (size_t i = 0; i < numPorts; )
  178. {
  179. if (ipPort == ports[i].ipPort)
  180. {
  181. if (ipAddress == INADDR_ANY)
  182. {
  183. // Remove the existing entry.
  184. --numPorts;
  185. ports[i] = ports[numPorts];
  186. // Don't increment the loop variable because we just put a new port
  187. // into this array element.
  188. continue;
  189. }
  190. else if ((ipAddress == ports[i].ipAddress) ||
  191. (ports[i].ipAddress == INADDR_ANY))
  192. {
  193. // The new port is already covered by an existing entry.
  194. return;
  195. }
  196. }
  197. ++i;
  198. }
  199. // Add the port to the array.
  200. ports[numPorts].ipAddress = ipAddress;
  201. ports[numPorts].ipPort = ipPort;
  202. ports[numPorts].socket = INVALID_SOCKET;
  203. ++numPorts;
  204. }