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.

374 lines
12 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV
  4. // Description: implements the basic structures for managing (multicast) scopes
  5. // ThreadSafe: no
  6. // Locks: none
  7. // Please read stdinfo.txt for programming style.
  8. //================================================================================
  9. #include <mm.h>
  10. #include <winbase.h>
  11. #include <array.h>
  12. #include <opt.h>
  13. #include <optl.h>
  14. #include <optclass.h>
  15. #include <bitmask.h>
  16. #include <range.h>
  17. #include <reserve.h>
  18. #include <subnet.h>
  19. #include <optdefl.h>
  20. #include <classdefl.h>
  21. #include <oclassdl.h>
  22. #include <sscope.h>
  23. #include <server.h>
  24. #include <dhcpapi.h>
  25. #include <address.h>
  26. //================================================================================
  27. // subnet only address api's
  28. //================================================================================
  29. BOOL
  30. MemSubnetGetThisAddress(
  31. IN PM_SUBNET Subnet,
  32. IN DWORD Address,
  33. IN BOOL fAcquire, // if available, also acquire?
  34. IN BOOL fBootp
  35. )
  36. {
  37. DWORD Error;
  38. DWORD Offset;
  39. DWORD OldState;
  40. PM_RANGE Range;
  41. Error = MemSubnetGetAddressInfo(
  42. Subnet,
  43. Address,
  44. &Range,
  45. NULL,
  46. NULL
  47. );
  48. if( ERROR_SUCCESS != Error ) return FALSE;
  49. Require(Range);
  50. if( fBootp ) {
  51. if( 0 == (Range->State & MM_FLAG_ALLOW_BOOTP))
  52. return FALSE;
  53. if( fAcquire &&
  54. Range->BootpAllocated >= Range->MaxBootpAllowed ) {
  55. return FALSE;
  56. }
  57. } else {
  58. if( 0 == (Range->State & MM_FLAG_ALLOW_DHCP) )
  59. return FALSE;
  60. }
  61. Offset = Address - Range->Start;
  62. if( !fAcquire ) return MemBitIsSet(Range->BitMask, Offset);
  63. Error = MemBitSetOrClear(
  64. Range->BitMask,
  65. Offset,
  66. TRUE /* Acquire */,
  67. &OldState
  68. );
  69. if( ERROR_SUCCESS != Error ) { Require(FALSE); return FALSE; }
  70. if( FALSE == OldState ) {
  71. InterlockedIncrement(&Range->DirtyOps);
  72. if( fBootp ) InterlockedIncrement( &Range->BootpAllocated );
  73. }
  74. return !OldState;
  75. }
  76. BOOL
  77. MemSubnetGetAnAddress(
  78. IN PM_SUBNET Subnet,
  79. OUT LPDWORD AltAddress,
  80. IN DWORD fAcquire,
  81. IN BOOL fBootp
  82. ) {
  83. DWORD Error;
  84. DWORD Offset;
  85. DWORD Policy;
  86. ARRAY_LOCATION Loc;
  87. PM_RANGE Range;
  88. if( IS_DISABLED(Subnet->State)) return FALSE;
  89. Policy = Subnet->Policy;
  90. if( AddressPolicyNone == Policy )
  91. Policy = ((PM_SERVER)(Subnet->ServerPtr))->Policy;
  92. if( AddressPolicyRoundRobin == Policy ) {
  93. Error = MemArrayRotateCyclical(&Subnet->Ranges);
  94. Require(ERROR_SUCCESS == Error);
  95. }
  96. for ( Error = MemArrayInitLoc(&Subnet->Ranges, &Loc);
  97. ERROR_FILE_NOT_FOUND != Error ;
  98. Error = MemArrayNextLoc(&Subnet->Ranges, &Loc) ) {
  99. Require(ERROR_SUCCESS == Error);
  100. Error = MemArrayGetElement(&Subnet->Ranges, &Loc, (LPVOID *)&Range);
  101. Require(ERROR_SUCCESS == Error && Range);
  102. if( fBootp ) {
  103. if( 0 == (Range->State & MM_FLAG_ALLOW_BOOTP) ) {
  104. continue;
  105. }
  106. if( fAcquire &&
  107. Range->BootpAllocated >= Range->MaxBootpAllowed ) {
  108. continue;
  109. }
  110. } else {
  111. if( 0 == (Range->State & MM_FLAG_ALLOW_DHCP ) ) {
  112. continue;
  113. }
  114. }
  115. Error = MemBitGetSomeClearedBit(
  116. Range->BitMask,
  117. &Offset,
  118. fAcquire,
  119. Range->Start,
  120. &Subnet->Exclusions
  121. );
  122. if( ERROR_SUCCESS == Error ) {
  123. *AltAddress = Range->Start + Offset;
  124. InterlockedIncrement(&Range->DirtyOps);
  125. if( fBootp && fAcquire ) {
  126. InterlockedIncrement(&Range->BootpAllocated);
  127. }
  128. return TRUE;
  129. }
  130. }
  131. return FALSE;
  132. }
  133. //================================================================================
  134. // per-server scans
  135. //================================================================================
  136. BOOL
  137. MemServerGetAddress( // acquire address or check for availability
  138. IN OUT PM_SERVER Server,
  139. IN PM_SUBNET Subnet, // search all subnets in superscope with this, except for this subnet alone
  140. IN BOOL fAcquire, // is this just a lookup or a full blown request?
  141. IN BOOL fBootp, // is this a DHCP address or BOOTP address?
  142. OUT DWORD *AltAddress, // the address that looks available
  143. OUT PM_SUBNET *AltSubnet // got it from this subnet
  144. ) {
  145. DWORD Error;
  146. DWORD SScopeId;
  147. DWORD Size;
  148. DWORD Policy;
  149. BOOL Obtained;
  150. PM_SUBNET NextSubnet;
  151. PM_SSCOPE SScope;
  152. AssertRet(Server && Subnet && AltAddress && AltSubnet, ERROR_INVALID_PARAMETER );
  153. AssertRet(NULL == AltAddress || NULL != AltSubnet, ERROR_INVALID_PARAMETER);
  154. AssertRet(Subnet->fSubnet, FALSE );
  155. SScopeId = Subnet->SuperScopeId;
  156. if( 0 == SScopeId ) {
  157. if( AltSubnet ) *AltSubnet = Subnet;
  158. return MemSubnetGetAnAddress(Subnet,AltAddress, fAcquire, fBootp);
  159. }
  160. Error = MemServerFindSScope(Server, SScopeId, NULL, &SScope);
  161. if( ERROR_FILE_NOT_FOUND == Error ) { // the superscope quietly died ?
  162. Subnet->SuperScopeId = 0; // no superscope at all
  163. if( AltSubnet ) *AltSubnet = Subnet;
  164. return MemSubnetGetAnAddress(Subnet, AltAddress, fAcquire, fBootp);
  165. }
  166. Require(ERROR_SUCCESS == Error);
  167. Policy = SScope->Policy;
  168. if( AddressPolicyNone == Policy )
  169. Policy = Server->Policy;
  170. if( AddressPolicyRoundRobin != Policy )
  171. Error = MemArrayInitLoc(&Server->Subnets, &Server->Loc);
  172. else Error = MemArrayNextLoc(&Server->Subnets, &Server->Loc);
  173. Size = MemArraySize(&Server->Subnets);
  174. while( Size -- ) {
  175. if(ERROR_FILE_NOT_FOUND == Error) { // wraparound
  176. Error = MemArrayInitLoc(&Server->Subnets, &Server->Loc);
  177. }
  178. Require(ERROR_SUCCESS == Error);
  179. Error = MemArrayGetElement(&Server->Subnets, &Server->Loc, &NextSubnet);
  180. Require(ERROR_SUCCESS == Error && NextSubnet);
  181. if( NextSubnet->SuperScopeId == SScopeId ) {
  182. Obtained = MemSubnetGetAnAddress(NextSubnet,AltAddress,fAcquire, fBootp);
  183. if( Obtained ) {
  184. *AltSubnet = NextSubnet;
  185. return TRUE;
  186. }
  187. }
  188. Error = MemArrayNextLoc(&Server->Subnets, &Server->Loc);
  189. }
  190. return FALSE;
  191. }
  192. //BeginExport(function)
  193. BOOL
  194. MemSubnetRequestAddress(
  195. IN OUT PM_SUBNET Subnet, // the subnet to start the search in
  196. IN DWORD Address, // init. addr: 0 => search in SuperScope, SubnetAddr = try subnet first
  197. IN BOOL fAcquire, // also acquire the address? or just test for availability?
  198. IN BOOL fBootp, // acquire BOOTP address?
  199. OUT DWORD *RetAddress, // OPTIONAL if Address is not 0 or SubnetAddr -- address obtained
  200. OUT PM_SUBNET *RetSubnet // OPTIONAL if Address is not 0 - which subnet is the address from
  201. ) //EndExport(function)
  202. {
  203. BOOL Obtained;
  204. AssertRet( Subnet , ERROR_INVALID_PARAMETER);
  205. if( 0 == Address ) AssertRet(RetAddress && RetSubnet, ERROR_INVALID_PARAMETER);
  206. if( Subnet->fSubnet && Subnet->Address == Address ) AssertRet(RetAddress, ERROR_INVALID_PARAMETER);
  207. if( (!Subnet->fSubnet || Subnet->Address != Address ) && 0 != Address ) {
  208. Obtained = MemSubnetGetThisAddress( // for the specific address requested
  209. Subnet,
  210. Address,
  211. fAcquire,
  212. fBootp
  213. );
  214. if( Obtained ) {
  215. if( RetAddress ) *RetAddress = Address;
  216. if( RetSubnet ) *RetSubnet = Subnet;
  217. return TRUE;
  218. }
  219. }
  220. if( !RetAddress ) return FALSE;
  221. if (0) {
  222. if( 0 == Address && Subnet->fSubnet ) Obtained = FALSE; // this case, dont try subnet first.. go thru sscope list instead
  223. else
  224. Obtained = MemSubnetGetAnAddress( // try for some address in this subnet?
  225. Subnet,
  226. RetAddress,
  227. fAcquire,
  228. fBootp
  229. );
  230. }
  231. Obtained = MemSubnetGetAnAddress( // try for some address in this subnet?
  232. Subnet,
  233. RetAddress,
  234. fAcquire,
  235. fBootp
  236. );
  237. if( Obtained && RetSubnet ) *RetSubnet = Subnet;
  238. if( Obtained ) return TRUE;
  239. // if the address was requested from a particular subnet OR
  240. // multicast address requested then return FALSE now.
  241. if( !Subnet->fSubnet || Subnet->Address == Address ) return FALSE;
  242. return MemServerGetAddress(
  243. Subnet->ServerPtr,
  244. Subnet,
  245. fAcquire,
  246. fBootp,
  247. RetAddress,
  248. RetSubnet
  249. );
  250. }
  251. //BeginExport(function)
  252. DWORD
  253. MemServerReleaseAddress(
  254. IN OUT PM_SERVER Server,
  255. IN DWORD Address,
  256. IN BOOL fBootp
  257. ) //EndExport(function)
  258. {
  259. DWORD Error;
  260. PM_SUBNET Subnet;
  261. AssertRet(Server, ERROR_INVALID_PARAMETER);
  262. Error = MemServerGetAddressInfo(
  263. Server,
  264. Address,
  265. &Subnet,
  266. NULL,
  267. NULL,
  268. NULL
  269. );
  270. if( ERROR_SUCCESS != Error ) return Error;
  271. Require(Subnet);
  272. if( Subnet->fSubnet ) {
  273. Require((Subnet->Mask & Address) == Subnet->Address);
  274. }
  275. return MemSubnetReleaseAddress(Subnet, Address, fBootp);
  276. }
  277. //BeginExport(function)
  278. BOOL // TRUE ==> allowed, FALSE ==> not allowed
  279. MemSubnetCheckBootpDhcp(
  280. IN PM_SUBNET Subnet,
  281. IN BOOL fBootp,
  282. IN BOOL fCheckSuperScope
  283. ) //EndExport(function)
  284. {
  285. ARRAY_LOCATION Loc;
  286. ULONG Error;
  287. PM_RANGE Range;
  288. PM_SUBNET ThisSubnet;
  289. PARRAY Array;
  290. if( Subnet->fSubnet && !IS_DISABLED( Subnet->State ) ) {
  291. for( Error = MemArrayInitLoc( &Subnet->Ranges, &Loc );
  292. ERROR_SUCCESS == Error ;
  293. Error = MemArrayNextLoc( &Subnet->Ranges, &Loc ) ) {
  294. Error = MemArrayGetElement( &Subnet->Ranges, &Loc , &Range );
  295. Require( ERROR_SUCCESS == Error );
  296. if( 0 == (Range->State & (fBootp? MM_FLAG_ALLOW_BOOTP : MM_FLAG_ALLOW_DHCP) ) ) {
  297. continue;
  298. }
  299. return TRUE;
  300. }
  301. }
  302. if( FALSE == fCheckSuperScope || 0 == Subnet->SuperScopeId ) {
  303. return FALSE;
  304. }
  305. Array = &((PM_SERVER) (Subnet->ServerPtr))->Subnets;
  306. for( Error = MemArrayInitLoc( Array, &Loc );
  307. ERROR_SUCCESS == Error ;
  308. Error = MemArrayNextLoc( Array, &Loc ) ) {
  309. Error = MemArrayGetElement( Array, &Loc, &ThisSubnet );
  310. Require( ERROR_SUCCESS == Error );
  311. if( ThisSubnet == Subnet ) continue;
  312. if( ThisSubnet->SuperScopeId != Subnet->SuperScopeId ) continue;
  313. if( FALSE == MemSubnetCheckBootpDhcp( ThisSubnet, fBootp, FALSE ) )
  314. continue;
  315. return TRUE;
  316. }
  317. return FALSE;
  318. }
  319. //================================================================================
  320. // end of file
  321. //================================================================================