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.

499 lines
14 KiB

  1. // MDHCP COM wrapper
  2. // Copyright (c) 1998-1999 Microsoft Corporation
  3. //
  4. // Module: local.cpp
  5. //
  6. // Author: Zoltan Szilagyi
  7. //
  8. // This file contains my implementation of local address allocation, plus a
  9. // function to see if we are doing local address allocation (based on the
  10. // registry). Prototypes are in local.cpp.
  11. //
  12. // These functions are called within CMDhcp, and just delegate calls to the
  13. // corresponding C API calls for MDHCP if the registry indicates that we
  14. // are using MDHCP. Otherwise they try to mimic the MDHCP behavior using
  15. // local allocation.
  16. #include "stdafx.h"
  17. #include "resource.h"
  18. #include "local.h"
  19. #include <string.h>
  20. #include <time.h>
  21. #include <winsock2.h>
  22. DWORD
  23. LocalEnumerateScopes(
  24. IN OUT PMCAST_SCOPE_ENTRY pScopeList,
  25. IN OUT PDWORD pScopeLen,
  26. OUT PDWORD pScopeCount,
  27. IN OUT BOOL * pfLocal
  28. )
  29. /*++
  30. Routine Description:
  31. This routine enumerates the multicast scopes available on the network.
  32. Arguments:
  33. pScopeList - pointer to the buffer where the scopelist is to be retrieved.
  34. This parameter can be NULL if only the length of the buffer is
  35. being retrieved.
  36. When this buffer is NULL, the API will force the re-query of the
  37. scope list from the MDHCP servers.
  38. pScopeLen - Pointer to a variable that specifies the size, in bytes, of the
  39. buffer pointed to by the pScopeList parameter. When the function returns,
  40. this variable contains the size of the data copied to pScopeList;
  41. The pScopeLen parameter can not be NULL.
  42. If the buffer specified by pScopeList parameter is not large enough
  43. to hold the data, the function returns the value ERROR_MORE_DATA, and
  44. stores the required buffer size, in bytes, into the variable pointed
  45. to by pScopeLen.
  46. If pScopeList is NULL, and pScopeLen is non-NULL, the function returns
  47. ERROR_SUCCESS, and stores the size of the data, in bytes, in the variable
  48. pointed to by pScopeLen. This lets an application determine the best
  49. way to allocate a buffer for the scope list.
  50. pScopeCount - Pointer to a variable that will store total number of scopes returned
  51. in the pScopeList buffer.
  52. pfLocal - points to a BOOL value that on exit is set to true if this
  53. is a locally-generated scope. If set to true on entry, then
  54. we go straight to local alloc (this usually means that this
  55. is the second call and the previous call returned local
  56. alloc)
  57. Return Value:
  58. The status of the operation.
  59. --*/
  60. {
  61. _ASSERTE( pfLocal );
  62. if ( *pfLocal == FALSE )
  63. {
  64. DWORD dwResult = McastEnumerateScopes(
  65. AF_INET, // this means IPv4
  66. pScopeList == NULL, // requery if asking for num scopes
  67. pScopeList,
  68. pScopeLen,
  69. pScopeCount);
  70. if ( dwResult == ERROR_SUCCESS )
  71. {
  72. *pfLocal = FALSE;
  73. return dwResult;
  74. }
  75. }
  76. _ASSERTE(pScopeLen);
  77. _ASSERTE(pScopeCount);
  78. *pfLocal = TRUE;
  79. //
  80. // First set up the string for the name of the scope.
  81. //
  82. const int ciAllocSize = 2048;
  83. static BOOL fFirstCall = TRUE;
  84. static WCHAR wszScopeDesc[ciAllocSize] = L"";
  85. static DWORD dwScopeDescLen = 0;
  86. if ( fFirstCall )
  87. {
  88. //
  89. // Get the string from the string table.
  90. //
  91. int iReturn = LoadString( _Module.GetModuleInstance(),
  92. IDS_LocalScopeName,
  93. wszScopeDesc,
  94. ciAllocSize - 1 );
  95. if ( iReturn == 0 )
  96. {
  97. return ERROR_NOT_ENOUGH_MEMORY;
  98. }
  99. dwScopeDescLen = sizeof(WCHAR) * (lstrlenW(wszScopeDesc) + 1);
  100. fFirstCall = FALSE;
  101. }
  102. //
  103. // When doing local allocation, there is only one scope. Return info about it.
  104. //
  105. *pScopeCount = 1;
  106. *pScopeLen = sizeof(MCAST_SCOPE_ENTRY) + dwScopeDescLen;
  107. if (pScopeList != NULL)
  108. {
  109. // wszDest points to the place in pScopeList right after the contents
  110. // of the MCAST_SCOPE_ENTRY structure.
  111. WCHAR * wszDest = (WCHAR *) (((BYTE *) pScopeList) + sizeof(MCAST_SCOPE_ENTRY));
  112. CopyMemory(wszDest, wszScopeDesc, dwScopeDescLen);
  113. pScopeList[0].ScopeCtx.ScopeID.IpAddrV4 = 0x01000000; // 1 -- net byte order
  114. pScopeList[0].ScopeCtx.ServerID.IpAddrV4 = 0x0100007f; // 127.0.0.1 localhost -- net byte order
  115. pScopeList[0].ScopeCtx.Interface.IpAddrV4 = 0x0100007f; // 127.0.0.1 loopback if -- net byte order
  116. pScopeList[0].ScopeDesc.Length = (USHORT) dwScopeDescLen;
  117. pScopeList[0].ScopeDesc.MaximumLength = (USHORT) dwScopeDescLen;
  118. pScopeList[0].ScopeDesc.Buffer = wszDest;
  119. pScopeList[0].TTL = 15;
  120. }
  121. return ERROR_SUCCESS;
  122. }
  123. //////////////////////////////////////////////////////////////////////////////
  124. //////////////////////////////////////////////////////////////////////////////
  125. //////////////////////////////////////////////////////////////////////////////
  126. //
  127. // ConvertLeaseInfoToRequest
  128. //
  129. // Given pRequestInfo, which points to a valid, contiguously stored
  130. // MCAST_LEASE_INFO (aka MCAST_LEASE_RESPONSE) structure for a request, fill
  131. // out the MCAST_LEASE_REQUEST structure pointed to by pRealRequest. The
  132. // pRealRequest structure points to the same addresses array as the
  133. // pRequestInfo structure, which makes it convenient to allocate on the stack.
  134. //
  135. void
  136. ConvertLeaseInfoToRequest(
  137. IN PMCAST_LEASE_INFO pRequestInfo,
  138. OUT PMCAST_LEASE_REQUEST pRealRequest
  139. )
  140. {
  141. DWORD dwDuration = (DWORD)(pRequestInfo->LeaseEndTime - pRequestInfo->LeaseStartTime);
  142. pRealRequest->LeaseStartTime = pRequestInfo->LeaseStartTime;
  143. pRealRequest->MaxLeaseStartTime = pRequestInfo->LeaseStartTime;
  144. pRealRequest->LeaseDuration = dwDuration;
  145. pRealRequest->MinLeaseDuration = dwDuration;
  146. pRealRequest->ServerAddress = pRequestInfo->ServerAddress;
  147. pRealRequest->MinAddrCount = pRequestInfo->AddrCount;
  148. pRealRequest->AddrCount = pRequestInfo->AddrCount;
  149. pRealRequest->pAddrBuf = pRequestInfo->pAddrBuf; // see above
  150. }
  151. //////////////////////////////////////////////////////////////////////////////
  152. //////////////////////////////////////////////////////////////////////////////
  153. //////////////////////////////////////////////////////////////////////////////
  154. DWORD
  155. LocalRequestAddress(
  156. IN BOOL fLocal,
  157. IN LPMCAST_CLIENT_UID pRequestID,
  158. IN PMCAST_SCOPE_CTX pScopeCtx,
  159. IN PMCAST_LEASE_INFO pAddrRequest,
  160. IN OUT PMCAST_LEASE_INFO pAddrResponse
  161. )
  162. /*++
  163. Routine Description:
  164. This routine request multicast address(es) from the MDHCP server.
  165. Arguments:
  166. fLocal - if true, do not go to server
  167. pRequestID - Unique identifier for this request. Client is responsible for
  168. generating unique identifier for every request. One recommendation
  169. is to use application specific context hashed by time.
  170. pRequestIDLen - Length of the pRequestID buffer.
  171. pScopeCtx - Pointer to the context of the scope from which the address is to
  172. be allocated. Scope context has to be retrieved via MDhcpEnumerateScopes
  173. call before calling this.
  174. pAddrRequest - Pointer to the block containing all the parameters pertaining
  175. to multicast address request.
  176. pAddrResponse - Pointer to the block which contains the response paramters for
  177. the multicast address request.
  178. Return Value:
  179. The status of the operation.
  180. --*/
  181. {
  182. if ( ! fLocal )
  183. {
  184. MCAST_LEASE_REQUEST RealRequest;
  185. ConvertLeaseInfoToRequest(
  186. pAddrRequest,
  187. & RealRequest
  188. );
  189. //
  190. // Tell the C API where to stick the returned addresses and how many
  191. // we have space for.
  192. //
  193. pAddrResponse->pAddrBuf =
  194. ( (PBYTE) pAddrResponse ) + sizeof( MCAST_LEASE_INFO );
  195. pAddrResponse->AddrCount = RealRequest.AddrCount;
  196. return McastRequestAddress(AF_INET, // this means IPv4
  197. pRequestID,
  198. pScopeCtx,
  199. & RealRequest,
  200. pAddrResponse);
  201. }
  202. //
  203. // Local allocation case...
  204. //
  205. DWORD dwAddrCount = pAddrRequest->AddrCount;
  206. if (dwAddrCount == 0)
  207. {
  208. return ERROR_INVALID_DATA;
  209. }
  210. //
  211. // Seed the random number generator the first time we are called.
  212. //
  213. static bool fFirstCall = true;
  214. if ( fFirstCall )
  215. {
  216. srand( (unsigned)time( NULL ) );
  217. fFirstCall = false;
  218. }
  219. //
  220. // We always grant whatever request the user wants. Start by copying the
  221. // relevant fields. This gives us valid start time, end time, and
  222. // address count. Still need to fill out serveraddress and array of
  223. // returned addresses.
  224. //
  225. CopyMemory(pAddrResponse,
  226. pAddrRequest,
  227. sizeof(MCAST_LEASE_INFO));
  228. //
  229. // The array of returned addresses will be contiguous in the strucutre.
  230. //
  231. pAddrResponse->pAddrBuf =
  232. ( (PBYTE) pAddrResponse ) + sizeof( MCAST_LEASE_INFO );
  233. //
  234. // The server address is the local host: 127.0.0.1 in net byte order
  235. //
  236. pAddrResponse->ServerAddress.IpAddrV4 = 0x0100007f;
  237. //
  238. // Allocate the random addresses (Based on Rajeev's code)
  239. // note: we do not support ipv6 (ipv4 assumed throughout)
  240. //
  241. // get mask
  242. DWORD dwNetworkMask = 0xffff8000; // 255.255.128.0
  243. // if the desired number of addresses are more than the range allows
  244. if ( dwAddrCount > ~ dwNetworkMask )
  245. {
  246. return ERROR_INVALID_DATA;
  247. }
  248. // get base address
  249. DWORD dwBaseAddress = 0xe0028000; // 224.2.128.0
  250. // transform base address (AND base address with mask)
  251. dwBaseAddress &= dwNetworkMask;
  252. //
  253. // choose unmasked bits of generated number and OR with transformed
  254. // base address
  255. // ZoltanS: added - 1 so that we can give out odd addresses too
  256. //
  257. DWORD * pdwAddresses = (DWORD *) pAddrResponse->pAddrBuf;
  258. pdwAddresses[0] = htonl(
  259. dwBaseAddress | ( rand() & ( ~ dwNetworkMask - (dwAddrCount - 1) )) );
  260. //
  261. // Set the rest of the addresses.
  262. //
  263. DWORD dwCurrAddr = ntohl(pdwAddresses[0]);
  264. for (DWORD i = 1; i < dwAddrCount; i++)
  265. {
  266. pdwAddresses[i] = htonl( ++dwCurrAddr );
  267. }
  268. return ERROR_SUCCESS;
  269. }
  270. DWORD
  271. LocalRenewAddress(
  272. IN BOOL fLocal,
  273. IN LPMCAST_CLIENT_UID pRequestID,
  274. IN PMCAST_LEASE_INFO pRenewRequest,
  275. IN OUT PMCAST_LEASE_INFO pRenewResponse
  276. )
  277. /*++
  278. Routine Description:
  279. This routine renews multicast address(es) from the MDHCP server.
  280. Arguments:
  281. fLocal - if true, do not go to server
  282. pRequestID - Unique identifier that was used when the address(es) were
  283. obtained initially.
  284. RequestIDLen - Length of the pRequestID buffer.
  285. pRenewRequest - Pointer to the block containing all the parameters pertaining
  286. to the renew request.
  287. pRenewResponse - Pointer to the block which contains the response paramters for
  288. the renew request.
  289. Return Value:
  290. The status of the operation.
  291. --*/
  292. {
  293. if ( ! fLocal )
  294. {
  295. MCAST_LEASE_REQUEST RealRequest;
  296. ConvertLeaseInfoToRequest(
  297. pRenewRequest,
  298. & RealRequest
  299. );
  300. //
  301. // Tell the C API where to stick the returned addresses and how many
  302. // we have space for.
  303. //
  304. pRenewResponse->pAddrBuf =
  305. ( (PBYTE) pRenewResponse ) + sizeof( MCAST_LEASE_INFO );
  306. pRenewResponse->AddrCount = RealRequest.AddrCount;
  307. return McastRenewAddress(AF_INET, // this means IPv4
  308. pRequestID,
  309. & RealRequest,
  310. pRenewResponse);
  311. }
  312. //
  313. // Local renewal...
  314. //
  315. //
  316. // We always grant whatever renewal the user wants. Just copy the
  317. // structure from the request to the response, keeping in mind
  318. // that the pAddrBuf member has to change to avoid referencing
  319. // the old structure.
  320. //
  321. // Note that we ASSUME that the response strucutre is big enough
  322. // to hold the response including all the addresses, allocated
  323. // CONTIGUOUSLY.
  324. // note: assumes IPv4
  325. //
  326. CopyMemory( pRenewResponse,
  327. pRenewRequest,
  328. sizeof(MCAST_LEASE_INFO) +
  329. sizeof(DWORD) * pRenewRequest->AddrCount
  330. );
  331. //
  332. // The pAddrbuf member has to change to avoid referencing the old
  333. // structure. Make it point to the end of this one.
  334. //
  335. pRenewResponse->pAddrBuf =
  336. ( (PBYTE) pRenewResponse ) + sizeof( MCAST_LEASE_INFO );
  337. return ERROR_SUCCESS;
  338. }
  339. DWORD
  340. LocalReleaseAddress(
  341. IN BOOL fLocal,
  342. IN LPMCAST_CLIENT_UID pRequestID,
  343. IN PMCAST_LEASE_INFO pReleaseRequest
  344. )
  345. /*++
  346. Routine Description:
  347. This routine releases multicast address(es) from the MDHCP server.
  348. Arguments:
  349. pRequestID - Unique identifier that was used when the address(es) were
  350. obtained initially.
  351. RequestIDLen - Length of the pRequestID buffer.
  352. pReleaseRequest - Pointer to the block containing all the parameters pertaining
  353. to the release request.
  354. Return Value:
  355. The status of the operation.
  356. --*/
  357. {
  358. if ( ! fLocal )
  359. {
  360. MCAST_LEASE_REQUEST RealRequest;
  361. ConvertLeaseInfoToRequest(
  362. pReleaseRequest,
  363. & RealRequest
  364. );
  365. return McastReleaseAddress(AF_INET, // this means IPv4
  366. pRequestID,
  367. & RealRequest);
  368. }
  369. // locally, we don't care about releases.
  370. return ERROR_SUCCESS;
  371. }
  372. // eof