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.

328 lines
8.5 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // counters.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the classes SharedMemory and ProxyCounters.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/16/2000 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <proxypch.h>
  19. #include <counters.h>
  20. //////////
  21. // Helper function that creates a named mutex which only admins can access.
  22. //////////
  23. HANDLE CreateAdminMutex(PCWSTR name) throw ()
  24. {
  25. // Create the SID for local Administrators.
  26. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  27. PSID adminSid = (PSID)_alloca(GetSidLengthRequired(2));
  28. InitializeSid(
  29. adminSid,
  30. &sia,
  31. 2
  32. );
  33. *GetSidSubAuthority(adminSid, 0) = SECURITY_BUILTIN_DOMAIN_RID;
  34. *GetSidSubAuthority(adminSid, 1) = DOMAIN_ALIAS_RID_ADMINS;
  35. // Create an ACL giving Administrators all access.
  36. ULONG cbAcl = sizeof(ACL) +
  37. (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) +
  38. GetLengthSid(adminSid);
  39. PACL acl = (PACL)_alloca(cbAcl);
  40. InitializeAcl(
  41. acl,
  42. cbAcl,
  43. ACL_REVISION
  44. );
  45. AddAccessAllowedAce(
  46. acl,
  47. ACL_REVISION,
  48. MUTEX_ALL_ACCESS,
  49. adminSid
  50. );
  51. // Create a security descriptor with the above ACL.
  52. PSECURITY_DESCRIPTOR pSD;
  53. BYTE buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  54. pSD = (PSECURITY_DESCRIPTOR)buffer;
  55. InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
  56. SetSecurityDescriptorDacl(pSD, TRUE, acl, FALSE);
  57. // Fill in the SECURITY_ATTRIBUTES struct.
  58. SECURITY_ATTRIBUTES sa;
  59. sa.nLength = sizeof(sa);
  60. sa.lpSecurityDescriptor = pSD;
  61. sa.bInheritHandle = TRUE;
  62. // Create the mutex.
  63. return CreateMutex(&sa, FALSE, name);
  64. }
  65. SharedMemory::SharedMemory() throw ()
  66. : fileMap(NULL),
  67. view(NULL),
  68. reserved(0),
  69. committed(0)
  70. {
  71. // Determine the page size for this platform.
  72. SYSTEM_INFO si;
  73. GetSystemInfo(&si);
  74. pageSize = si.dwPageSize;
  75. }
  76. bool SharedMemory::open(PCWSTR name, DWORD size) throw ()
  77. {
  78. close();
  79. // Determine the number of pages to reserve.
  80. reserved = (size + pageSize - 1)/pageSize;
  81. // Create the mapping in the pagefile ...
  82. fileMap = CreateFileMappingW(
  83. INVALID_HANDLE_VALUE,
  84. NULL,
  85. PAGE_READWRITE | SEC_RESERVE,
  86. 0,
  87. reserved * pageSize,
  88. name
  89. );
  90. if (fileMap)
  91. {
  92. // ... and map it into our process.
  93. view = MapViewOfFile(
  94. fileMap,
  95. FILE_MAP_WRITE,
  96. 0,
  97. 0,
  98. 0
  99. );
  100. if (!view)
  101. {
  102. CloseHandle(fileMap);
  103. fileMap = NULL;
  104. }
  105. }
  106. return view != NULL;
  107. }
  108. void SharedMemory::close() throw ()
  109. {
  110. if (view)
  111. {
  112. UnmapViewOfFile(view);
  113. view = NULL;
  114. }
  115. if (fileMap)
  116. {
  117. CloseHandle(fileMap);
  118. fileMap = NULL;
  119. }
  120. reserved = 0;
  121. committed = 0;
  122. }
  123. bool SharedMemory::commit(DWORD nbyte) throw ()
  124. {
  125. // How many pages will we need ?
  126. DWORD pagesNeeded = (nbyte + pageSize - 1)/pageSize;
  127. // Do we have to commit more memory?
  128. if (pagesNeeded > committed)
  129. {
  130. // If we've hit the max or we can't commit anymore, we're done.
  131. if (pagesNeeded > reserved ||
  132. !VirtualAlloc(
  133. view,
  134. pageSize * pagesNeeded,
  135. MEM_COMMIT,
  136. PAGE_READWRITE
  137. ))
  138. {
  139. return false;
  140. }
  141. committed = pagesNeeded;
  142. }
  143. return true;
  144. }
  145. HRESULT ProxyCounters::FinalConstruct() throw ()
  146. {
  147. mutex = CreateAdminMutex(RadiusStatisticsMutex);
  148. if (mutex)
  149. {
  150. lock();
  151. // Opend the shared memory.
  152. if (data.open(RadiusProxyStatisticsName, 0x40000))
  153. {
  154. // Commit enough space for the Proxy entry.
  155. nbyte = sizeof(RadiusProxyStatistics) -
  156. sizeof(RadiusRemoteServerEntry);
  157. if (data.commit(nbyte))
  158. {
  159. // Zero out the stats.
  160. stats = (RadiusProxyStatistics*)data.base();
  161. memset(stats, 0, nbyte);
  162. }
  163. }
  164. unlock();
  165. }
  166. if (!stats)
  167. {
  168. DWORD error = GetLastError();
  169. return HRESULT_FROM_WIN32(error);
  170. }
  171. return S_OK;
  172. }
  173. RadiusRemoteServerEntry* ProxyCounters::getRemoteServerEntry(
  174. ULONG address
  175. ) throw ()
  176. {
  177. address = ntohl(address);
  178. // Try once without the lock.
  179. RadiusRemoteServerEntry* entry = findRemoteServer(address);
  180. if (!entry)
  181. {
  182. lock();
  183. // Now try again with the lock just to be sure.
  184. entry = findRemoteServer(address);
  185. if (!entry)
  186. {
  187. // Make sure we have space.
  188. if (data.commit(nbyte + sizeof(RadiusRemoteServerEntry)))
  189. {
  190. // Zero out the new entry.
  191. entry = stats->rseRemoteServers + stats->dwNumRemoteServers;
  192. memset(entry, 0, sizeof(*entry));
  193. // Set the address.
  194. entry->dwAddress = address;
  195. // Update the number of servers ...
  196. ++(stats->dwNumRemoteServers);
  197. // ... and the number of bytes.
  198. nbyte += sizeof(RadiusRemoteServerEntry);
  199. }
  200. }
  201. unlock();
  202. }
  203. return entry;
  204. }
  205. //////////
  206. // Array that maps a (RadiusMIB, RadiusEvent) pair to a RemoteServer counter
  207. // offset.
  208. //////////
  209. LONG counterOffset[][2] =
  210. {
  211. // eventNone
  212. { -1, -1 },
  213. // eventInvalidAddress
  214. { radiusAuthClientInvalidAddresses, radiusAccClientInvalidAddresses },
  215. // eventAccessRequest
  216. { radiusAuthClientAccessRequests, -1 },
  217. // eventAccessAccept
  218. { radiusAuthClientAccessAccepts, -1 },
  219. // eventAccessReject
  220. { radiusAuthClientAccessRejects, -1 },
  221. // eventAccessChallenge
  222. { radiusAuthClientAccessChallenges, -1 },
  223. // eventAccountingRequest
  224. { -1, radiusAccClientRequests },
  225. // eventAccountingResponse
  226. { -1, radiusAccClientResponses },
  227. // eventMalformedPacket
  228. { radiusAuthClientMalformedAccessResponses, radiusAccClientResponses },
  229. // eventBadAuthenticator
  230. { radiusAuthClientBadAuthenticators, radiusAccClientBadAuthenticators },
  231. // eventBadSignature
  232. { radiusAuthClientBadAuthenticators, radiusAccClientBadAuthenticators },
  233. // eventMissingSignature
  234. { radiusAuthClientBadAuthenticators, radiusAccClientBadAuthenticators },
  235. // eventTimeout
  236. { radiusAuthClientTimeouts, radiusAccClientTimeouts },
  237. // eventUnknownType
  238. { radiusAuthClientUnknownTypes, radiusAccClientUnknownTypes },
  239. // eventUnexpectedResponse
  240. { radiusAuthClientPacketsDropped, radiusAccClientPacketsDropped },
  241. // eventLateResponse
  242. { radiusAuthClientPacketsDropped, radiusAccClientPacketsDropped },
  243. // eventRoundTrip
  244. { radiusAuthClientRoundTripTime, radiusAccClientRoundTripTime },
  245. // eventSendError
  246. { -1, -1 },
  247. // eventReceiveError
  248. { -1, -1 },
  249. // eventServerAvailable
  250. { -1, -1 },
  251. // eventServerUnavailable
  252. { -1, -1 }
  253. };
  254. void ProxyCounters::updateCounters(
  255. RadiusPortType port,
  256. RadiusEventType event,
  257. RadiusRemoteServerEntry* server,
  258. ULONG data
  259. ) throw ()
  260. {
  261. // Get the counter offset. If it's negative, then this event doesn't effect
  262. // any counters.
  263. LONG offset = counterOffset[event][port];
  264. if (offset < 0) { return; }
  265. if (event == eventInvalidAddress)
  266. {
  267. InterlockedIncrement((PLONG)stats->peProxy.dwCounters + offset);
  268. }
  269. else if (server)
  270. {
  271. if (event == eventRoundTrip)
  272. {
  273. server->dwCounters[offset] = data;
  274. }
  275. else
  276. {
  277. InterlockedIncrement((PLONG)server->dwCounters + offset);
  278. }
  279. }
  280. }
  281. RadiusRemoteServerEntry* ProxyCounters::findRemoteServer(
  282. ULONG address
  283. ) throw ()
  284. {
  285. for (DWORD i = 0; i < stats->dwNumRemoteServers; ++i)
  286. {
  287. if (stats->rseRemoteServers[i].dwAddress == address)
  288. {
  289. return stats->rseRemoteServers + i;
  290. }
  291. }
  292. return NULL;
  293. }