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.

795 lines
26 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 <array.h>
  11. #include <opt.h>
  12. #include <optl.h>
  13. #include <optclass.h>
  14. #include <bitmask.h>
  15. #include <range.h>
  16. #include <reserve.h>
  17. #include <dhcp.h>
  18. #include <winnls.h>
  19. #include "server\uniqid.h"
  20. #include "subnet.h"
  21. // the following are the flags bits used for subnet object.
  22. #define DEFAULT_SCOPE 0x01
  23. #define IS_DEFAULT_SCOPE( _subnet ) ((_subnet)->Flags & DEFAULT_SCOPE == DEFAULT_SCOPE )
  24. #define SET_DEFAULT_SCOPE( _subnet ) ((_subnet)->Flags |= DEFAULT_SCOPE )
  25. #define RESET_DEFAULT_SCOPE( _subnet ) ((_subnet)->Flags &= ~DEFAULT_SCOPE)
  26. //BeginExport(function)
  27. DWORD
  28. MemSubnetInit(
  29. OUT PM_SUBNET *pSubnet,
  30. IN DWORD Address,
  31. IN DWORD Mask,
  32. IN DWORD State,
  33. IN DWORD SuperScopeId,
  34. IN LPWSTR Name,
  35. IN LPWSTR Description
  36. ) //EndExport(function)
  37. {
  38. DWORD Error;
  39. DWORD Size;
  40. PM_SUBNET Subnet;
  41. AssertRet(pSubnet, ERROR_INVALID_PARAMETER);
  42. AssertRet( !(CLASSD_HOST_ADDR(Address)||CLASSE_HOST_ADDR(Address)),
  43. ERROR_INVALID_PARAMETER );
  44. Require((Address&Mask));
  45. *pSubnet = NULL;
  46. Size = ROUND_UP_COUNT(sizeof(*Subnet), ALIGN_WORST);
  47. Size += sizeof(WCHAR) * (Name?(1+wcslen(Name)):0);
  48. Size += sizeof(WCHAR) * (Description?(1+wcslen(Description)):0);
  49. Subnet = MemAlloc(Size);
  50. if( NULL == Subnet) return ERROR_NOT_ENOUGH_MEMORY;
  51. Size = ROUND_UP_COUNT(sizeof(*Subnet), ALIGN_WORST);
  52. Subnet->Name = Subnet->Description = NULL;
  53. if( Name ) {
  54. Subnet->Name = (LPWSTR)(Size + (LPBYTE)Subnet);
  55. wcscpy(Subnet->Name, Name);
  56. Size += sizeof(WCHAR) * ( 1 + wcslen(Name));
  57. }
  58. if( Description ) {
  59. Subnet->Description = (LPWSTR)( Size + (LPBYTE)Subnet );
  60. wcscpy(Subnet->Description, Description);
  61. }
  62. Subnet->ServerPtr = NULL;
  63. Subnet->Address = Address;
  64. Subnet->Mask = Mask;
  65. Subnet->State = State;
  66. Subnet->SuperScopeId = SuperScopeId;
  67. Subnet->fSubnet = TRUE;
  68. Subnet->Policy = AddressPolicyNone;
  69. Subnet->UniqId = INVALID_UNIQ_ID;
  70. Error = MemOptClassInit(&Subnet->Options);
  71. if( ERROR_SUCCESS != Error ) { MemFree(Subnet); return Error; }
  72. Error = MemArrayInit(&Subnet->Ranges);
  73. if( ERROR_SUCCESS != Error ) { MemFree(Subnet); return Error; }
  74. Error = MemArrayInit(&Subnet->Exclusions);
  75. if( ERROR_SUCCESS != Error ) { MemFree(Subnet); return Error; }
  76. Error = MemArrayInit(&Subnet->Servers);
  77. if( ERROR_SUCCESS != Error ) { MemFree(Subnet); return Error; }
  78. Error = MemReserveInit(&Subnet->Reservations);
  79. if( ERROR_SUCCESS != Error ) { MemFree(Subnet); return Error; }
  80. *pSubnet = Subnet;
  81. return ERROR_SUCCESS;
  82. }
  83. VOID
  84. GetLangTag(
  85. WCHAR LangTag[]
  86. )
  87. {
  88. WCHAR b1[8], b2[8];
  89. b1[0] = b2[0] = L'\0';
  90. GetLocaleInfoW(
  91. LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME,
  92. b1, sizeof(b1)/sizeof(b1[0])
  93. );
  94. GetLocaleInfoW(
  95. LOCALE_SYSTEM_DEFAULT, LOCALE_SISO3166CTRYNAME,
  96. b2, sizeof(b2)/sizeof(b2[0])
  97. );
  98. if (_wcsicmp(b1, b2))
  99. wsprintf(LangTag, L"%s-%s", b1, b2);
  100. else
  101. wcscpy(LangTag, b1);
  102. }
  103. //BeginExport(function)
  104. DWORD
  105. MemMScopeInit(
  106. OUT PM_SUBNET *pMScope,
  107. IN DWORD MScopeId,
  108. IN DWORD State,
  109. IN DWORD AddressPolicy,
  110. IN BYTE TTL,
  111. IN LPWSTR Name,
  112. IN LPWSTR Description,
  113. IN LPWSTR LangTag,
  114. IN DATE_TIME ExpiryTime
  115. ) //EndExport(function)
  116. {
  117. DWORD Error;
  118. DWORD Size;
  119. PM_SUBNET MScope;
  120. WCHAR DummyLangTag[100];
  121. AssertRet(pMScope, ERROR_INVALID_PARAMETER);
  122. //AssertRet(MScopeId, ERROR_INVALID_PARAMETER);
  123. Require(LangTag);
  124. if( NULL == LangTag ) {
  125. LangTag = DummyLangTag;
  126. GetLangTag(DummyLangTag);
  127. }
  128. *pMScope = NULL;
  129. Size = ROUND_UP_COUNT(sizeof(*MScope), ALIGN_WORST);
  130. Size += sizeof(WCHAR) * (Name?(1+wcslen(Name)):0);
  131. Size += sizeof(WCHAR) * (Description?(1+wcslen(Description)):0);
  132. Size += sizeof(WCHAR) * (1+wcslen(LangTag));
  133. MScope = MemAlloc(Size);
  134. if( NULL == MScope) return ERROR_NOT_ENOUGH_MEMORY;
  135. Size = ROUND_UP_COUNT(sizeof(*MScope), ALIGN_WORST);
  136. MScope->Name = MScope->Description = MScope->LangTag = NULL;
  137. if( Name ) {
  138. MScope->Name = (LPWSTR)(Size + (LPBYTE)MScope);
  139. wcscpy(MScope->Name, Name);
  140. Size += sizeof(WCHAR) * ( 1 + wcslen(Name));
  141. }
  142. if( Description ) {
  143. MScope->Description = (LPWSTR)( Size + (LPBYTE)MScope );
  144. wcscpy(MScope->Description, Description);
  145. Size += sizeof(WCHAR) * ( 1 + wcslen(Description));
  146. }
  147. MScope->LangTag = (LPWSTR)( Size + (LPBYTE)MScope );
  148. wcscpy(MScope->LangTag, LangTag);
  149. MScope->ServerPtr = NULL;
  150. MScope->MScopeId = MScopeId;
  151. MScope->State = State;
  152. MScope->TTL = TTL;
  153. MScope->fSubnet = FALSE;
  154. MScope->Policy = AddressPolicy;
  155. MScope->ExpiryTime = ExpiryTime;
  156. Error = MemOptClassInit(&MScope->Options);
  157. if( ERROR_SUCCESS != Error ) { MemFree(MScope); return Error; }
  158. Error = MemArrayInit(&MScope->Ranges);
  159. if( ERROR_SUCCESS != Error ) { MemFree(MScope); return Error; }
  160. Error = MemArrayInit(&MScope->Exclusions);
  161. if( ERROR_SUCCESS != Error ) { MemFree(MScope); return Error; }
  162. Error = MemArrayInit(&MScope->Servers);
  163. if( ERROR_SUCCESS != Error ) { MemFree(MScope); return Error; }
  164. Error = MemReserveInit(&MScope->Reservations);
  165. if( ERROR_SUCCESS != Error ) { MemFree(MScope); return Error; }
  166. *pMScope = MScope;
  167. return ERROR_SUCCESS;
  168. }
  169. //BeginExport(function)
  170. DWORD // SUCCESS if either of Excl or Range get filled, else FILE_NOT_FOUND
  171. MemSubnetGetAddressInfo(
  172. IN PM_SUBNET Subnet,
  173. IN DWORD Address,
  174. OUT PM_RANGE *Range, // OPTIONAL -- filled if a range could be found -- even if excluded
  175. OUT PM_EXCL *Excl, // OPTIONAL -- filled if an exclusion could be found
  176. OUT PM_RESERVATION *Reservation // OPTIONAL -- filled with a matching reservation, if found
  177. ) //EndExport(function)
  178. {
  179. ARRAY_LOCATION Location;
  180. DWORD Error;
  181. DWORD RetError;
  182. PM_RANGE ThisRange;
  183. PM_EXCL ThisExcl;
  184. AssertRet(Subnet && (Range || Excl || Reservation), ERROR_INVALID_PARAMETER );
  185. if( Subnet->fSubnet && (Address & Subnet->Mask) != Subnet->Address )
  186. return ERROR_FILE_NOT_FOUND; // it is ok for MSCOPE objects, as Address refers to ScopeId
  187. RetError = ERROR_FILE_NOT_FOUND;
  188. if( Range ) {
  189. *Range = NULL;
  190. Error = MemArrayInitLoc(&Subnet->Ranges, &Location);
  191. while( ERROR_FILE_NOT_FOUND != Error ) {
  192. Require(ERROR_SUCCESS == Error);
  193. Error = MemArrayGetElement(&Subnet->Ranges, &Location, (LPVOID *)&ThisRange);
  194. Require(ERROR_SUCCESS == Error && ThisRange);
  195. if( ThisRange->Start <= Address && Address <= ThisRange->End ) {
  196. *Range = ThisRange;
  197. RetError = ERROR_SUCCESS;
  198. break;
  199. }
  200. Error = MemArrayNextLoc(&Subnet->Ranges, &Location);
  201. }
  202. }
  203. if( Excl ) {
  204. *Excl = NULL;
  205. Error = MemArrayInitLoc(&Subnet->Exclusions, &Location);
  206. while( ERROR_FILE_NOT_FOUND != Error ) {
  207. Require(ERROR_SUCCESS == Error);
  208. Error = MemArrayGetElement(&Subnet->Exclusions, &Location, (LPVOID *)&ThisExcl);
  209. Require(ERROR_SUCCESS == Error && ThisExcl);
  210. if( ThisExcl->Start <= Address && Address <= ThisExcl->End ) {
  211. *Excl = ThisExcl;
  212. RetError = ERROR_SUCCESS;
  213. break;
  214. }
  215. Error = MemArrayNextLoc(&Subnet->Exclusions, &Location);
  216. }
  217. }
  218. if( Reservation ) {
  219. *Reservation = NULL;
  220. Error = MemReserveFindByAddress(&Subnet->Reservations, Address, Reservation);
  221. if( ERROR_SUCCESS == Error ) RetError = ERROR_SUCCESS;
  222. }
  223. return RetError;
  224. }
  225. //BeginExport(function)
  226. DWORD // ERROR_SUCCESS on finding a collition, else ERROR_FILE_NOT_FOUND
  227. MemSubnetFindCollision(
  228. IN OUT PM_SUBNET Subnet,
  229. IN DWORD Start,
  230. IN DWORD End,
  231. OUT PM_RANGE *Range, // OPTIONAL
  232. OUT PM_EXCL *Excl // OPTIONAL
  233. ) //EndExport(function)
  234. {
  235. ARRAY_LOCATION Location;
  236. DWORD Error;
  237. DWORD RetError;
  238. DWORD Cond;
  239. PM_RANGE ThisRange;
  240. PM_EXCL ThisExcl;
  241. Require(Subnet && (Range || Excl));
  242. if( Subnet->fSubnet ) { // checks ommitted for MCAST scopes.
  243. if( (Start & Subnet->Mask) != (End & Subnet->Mask) )
  244. return ERROR_INVALID_PARAMETER;
  245. if( (Start & Subnet->Mask) != (Subnet->Address & Subnet->Mask) )
  246. return ERROR_INVALID_PARAMETER;
  247. }
  248. RetError = ERROR_FILE_NOT_FOUND;
  249. if(Range) {
  250. *Range = NULL;
  251. Error = MemArrayInitLoc(&Subnet->Ranges, &Location);
  252. while( ERROR_FILE_NOT_FOUND != Error ) {
  253. Require(ERROR_SUCCESS == Error);
  254. Error = MemArrayGetElement(&Subnet->Ranges, &Location, (LPVOID *)&ThisRange);
  255. Require(ERROR_SUCCESS == Error && ThisRange);
  256. Cond = MemRangeCompare(Start,End, ThisRange->Start, ThisRange->End);
  257. if( Cond != X_LESSTHAN_Y && Cond != Y_LESSTHAN_X ) {
  258. // Collision has occured
  259. *Range = ThisRange;
  260. RetError = ERROR_SUCCESS;
  261. break;
  262. }
  263. Error = MemArrayNextLoc(&Subnet->Ranges, &Location);
  264. }
  265. }
  266. if( Excl ) {
  267. *Excl = NULL;
  268. Error = MemArrayInitLoc(&Subnet->Exclusions, &Location);
  269. while( ERROR_FILE_NOT_FOUND != Error ) {
  270. Require(ERROR_SUCCESS == Error);
  271. Error = MemArrayGetElement(&Subnet->Exclusions, &Location, (LPVOID *)&ThisExcl);
  272. Require(ERROR_SUCCESS == Error && ThisExcl);
  273. Cond = MemRangeCompare(Start,End, ThisExcl->Start, ThisExcl->End);
  274. if( Cond != X_LESSTHAN_Y && Cond != Y_LESSTHAN_X ) {
  275. *Excl = ThisExcl;
  276. RetError = ERROR_SUCCESS;
  277. break;
  278. }
  279. Error = MemArrayNextLoc(&Subnet->Exclusions, &Location);
  280. }
  281. }
  282. return RetError;
  283. }
  284. //BeginExport(function)
  285. DWORD // ERROR_OBJECT_ALREADY_EXISTS on collision
  286. MemSubnetAddRange( // check if the range is valid, and only then add it
  287. IN OUT PM_SUBNET Subnet,
  288. IN DWORD Start,
  289. IN DWORD End,
  290. IN DWORD State,
  291. IN ULONG BootpAllocated,
  292. IN ULONG MaxBootpAllowed,
  293. OUT PM_RANGE *OverlappingRange,
  294. IN ULONG UniqId
  295. ) //EndExport(function)
  296. {
  297. DWORD Error;
  298. DWORD LocalError;
  299. PM_RANGE NewRange;
  300. AssertRet(Subnet && OverlappingRange, ERROR_INVALID_PARAMETER);
  301. if( Subnet->fSubnet ) {
  302. if( (Subnet->Address & Subnet->Mask) != (Start & Subnet->Mask) ||
  303. (Start & Subnet->Mask) != (End & Subnet->Mask) )
  304. return ERROR_INVALID_PARAMETER;
  305. } else {
  306. if (!CLASSD_HOST_ADDR(Start) || !CLASSD_HOST_ADDR(End)) {
  307. return ERROR_INVALID_PARAMETER;
  308. }
  309. }
  310. if( Start > End ) return ERROR_INVALID_PARAMETER;
  311. *OverlappingRange = NULL;
  312. Error = MemSubnetFindCollision(
  313. Subnet,
  314. Start,
  315. End,
  316. OverlappingRange,
  317. NULL
  318. );
  319. if(ERROR_FILE_NOT_FOUND != Error ) { // collision with a range?
  320. Require(ERROR_SUCCESS == Error);
  321. return ERROR_OBJECT_ALREADY_EXISTS;
  322. }
  323. NewRange = MemAlloc(sizeof(*NewRange));
  324. if( NULL == NewRange ) return ERROR_NOT_ENOUGH_MEMORY;
  325. Error = MemRangeInit(
  326. NewRange, Start, End, Subnet->fSubnet ? Subnet->Mask : 0, State,
  327. BootpAllocated, MaxBootpAllowed );
  328. if( ERROR_SUCCESS != Error ) {
  329. MemFree(NewRange);
  330. return Error;
  331. }
  332. NewRange->UniqId = UniqId;
  333. Error = MemArrayAddElement(
  334. &Subnet->Ranges,
  335. NewRange
  336. );
  337. if( ERROR_SUCCESS != Error ) {
  338. LocalError = MemRangeCleanup(NewRange);
  339. Require(LocalError == ERROR_SUCCESS);
  340. MemFree(NewRange);
  341. }
  342. return Error;
  343. } // MemSubnetAddRange()
  344. //BeginExport(function)
  345. DWORD
  346. MemSubnetAddRangeExpandOrContract(
  347. IN PM_SUBNET Subnet,
  348. IN DWORD StartAddress,
  349. IN DWORD EndAddress,
  350. OUT DWORD *OldStartAddress,
  351. OUT DWORD *OldEndAddress
  352. ) //EndExport(function)
  353. {
  354. DWORD Error;
  355. DWORD LocalError;
  356. DWORD Cond;
  357. DWORD nAddresses;
  358. BOOL fExtend;
  359. PM_RANGE OldRange;
  360. PM_RANGE ThisRange;
  361. PARRAY Ranges;
  362. ARRAY_LOCATION Loc;
  363. Ranges = &Subnet->Ranges;
  364. *OldStartAddress = *OldEndAddress = 0;
  365. OldRange = NULL;
  366. Error = MemArrayInitLoc(Ranges, &Loc);
  367. while( ERROR_FILE_NOT_FOUND != Error ) {
  368. Require(ERROR_SUCCESS == Error);
  369. Error = MemArrayGetElement(Ranges, &Loc, (LPVOID *)&ThisRange);
  370. Require(ERROR_SUCCESS == Error && ThisRange);
  371. Cond = MemRangeCompare(StartAddress, EndAddress, ThisRange->Start, ThisRange->End);
  372. if( Cond != X_LESSTHAN_Y && Cond != Y_LESSTHAN_X ) {
  373. if( OldRange ) return ERROR_OBJECT_ALREADY_EXISTS;
  374. if( X_IN_Y != Cond && Y_IN_X != Cond )
  375. return ERROR_OBJECT_ALREADY_EXISTS;
  376. OldRange = ThisRange;
  377. }
  378. Error = MemArrayNextLoc(Ranges, &Loc);
  379. } // while
  380. if( NULL == OldRange ) return ERROR_FILE_NOT_FOUND;
  381. *OldStartAddress = OldRange->Start;
  382. *OldEndAddress = OldRange->End;
  383. if( OldRange->Start < StartAddress ) {
  384. fExtend = FALSE;
  385. nAddresses = StartAddress - OldRange->Start;
  386. } else {
  387. fExtend = TRUE;
  388. nAddresses = OldRange->Start - StartAddress;
  389. }
  390. Error = ERROR_SUCCESS;
  391. if( nAddresses ) Error = MemRangeExtendOrContract(
  392. OldRange,
  393. nAddresses,
  394. fExtend,
  395. FALSE
  396. );
  397. if( ERROR_SUCCESS != Error ) return Error;
  398. if( OldRange->End < EndAddress ) {
  399. fExtend = TRUE;
  400. nAddresses = EndAddress - OldRange->End;
  401. } else {
  402. fExtend = FALSE;
  403. nAddresses = OldRange->End - EndAddress;
  404. }
  405. if( nAddresses ) Error = MemRangeExtendOrContract(
  406. OldRange,
  407. nAddresses,
  408. fExtend,
  409. TRUE
  410. );
  411. if ( ERROR_SUCCESS == Error ) {
  412. // range changed, update the database
  413. Error = DeleteRecord( OldRange->UniqId );
  414. if ( ERROR_SUCCESS != Error ) {
  415. return Error;
  416. }
  417. // mark it so that a new record is created.
  418. OldRange->UniqId = INVALID_UNIQ_ID;
  419. } // if
  420. return Error;
  421. } // MemSubnetAddRangeExpandOrContract()
  422. //BeginExport(function)
  423. DWORD
  424. MemSubnetAddExcl(
  425. IN OUT PM_SUBNET Subnet,
  426. IN DWORD Start,
  427. IN DWORD End,
  428. OUT PM_EXCL *OverlappingExcl,
  429. IN ULONG UniqId
  430. ) //EndExport(function)
  431. {
  432. DWORD Error;
  433. DWORD LocalError;
  434. PM_EXCL NewExcl;
  435. AssertRet(Subnet && OverlappingExcl, ERROR_INVALID_PARAMETER);
  436. if( Subnet->fSubnet ) {
  437. if( (Subnet->Address & Subnet->Mask) != (Start & Subnet->Mask) ||
  438. (Start & Subnet->Mask) != (End & Subnet->Mask) )
  439. return ERROR_INVALID_PARAMETER;
  440. }
  441. if( Start > End ) return ERROR_INVALID_PARAMETER;
  442. *OverlappingExcl = NULL;
  443. Error = MemSubnetFindCollision(
  444. Subnet,
  445. Start,
  446. End,
  447. NULL,
  448. OverlappingExcl
  449. );
  450. if(ERROR_FILE_NOT_FOUND != Error ) { // collision with a range?
  451. Require(ERROR_SUCCESS == Error);
  452. return ERROR_OBJECT_ALREADY_EXISTS;
  453. }
  454. NewExcl = MemAlloc(sizeof(*NewExcl));
  455. if( NULL == NewExcl ) return ERROR_NOT_ENOUGH_MEMORY;
  456. NewExcl->Start = Start;
  457. NewExcl->End = End;
  458. NewExcl->UniqId = UniqId;
  459. Error = MemArrayAddElement(
  460. &Subnet->Exclusions,
  461. NewExcl
  462. );
  463. if( ERROR_SUCCESS != Error ) {
  464. MemFree(NewExcl);
  465. }
  466. return Error;
  467. } // MemSubnetAddExcl()
  468. //BeginExport(function)
  469. DWORD
  470. MemSubnetDelRange(
  471. IN OUT PM_SUBNET Subnet,
  472. IN DWORD Start
  473. ) //EndExport(function)
  474. {
  475. DWORD Error;
  476. PM_RANGE ThisRange;
  477. ARRAY_LOCATION Location;
  478. Error = MemArrayInitLoc(&Subnet->Ranges, &Location);
  479. while( ERROR_FILE_NOT_FOUND != Error ) {
  480. Require(ERROR_SUCCESS == Error);
  481. Error = MemArrayGetElement(&Subnet->Ranges, &Location, (LPVOID *)&ThisRange);
  482. Require(ERROR_SUCCESS == Error && ThisRange);
  483. if( ThisRange->Start == Start ) { // Collision has occured
  484. Error = DeleteRecord( ThisRange->UniqId );
  485. if ( ERROR_SUCCESS != Error ) {
  486. return Error;
  487. }
  488. Error = MemRangeCleanup(ThisRange);
  489. Require(ERROR_SUCCESS == Error);
  490. MemFree(ThisRange);
  491. Error = MemArrayDelElement(&Subnet->Ranges, &Location, (LPVOID *)&ThisRange);
  492. return ERROR_SUCCESS;
  493. }
  494. Error = MemArrayNextLoc(&Subnet->Ranges, &Location);
  495. } // while
  496. return ERROR_FILE_NOT_FOUND;
  497. } // MemSubnetDelRange()
  498. //BeginExport(function)
  499. DWORD
  500. MemSubnetDelExcl(
  501. IN OUT PM_SUBNET Subnet,
  502. IN DWORD Start
  503. ) //EndExport(function)
  504. {
  505. DWORD Error;
  506. PM_EXCL ThisExcl;
  507. ARRAY_LOCATION Location;
  508. Error = MemArrayInitLoc(&Subnet->Exclusions, &Location);
  509. while( ERROR_FILE_NOT_FOUND != Error ) {
  510. Require(ERROR_SUCCESS == Error);
  511. Error = MemArrayGetElement(&Subnet->Exclusions, &Location, (LPVOID *)&ThisExcl);
  512. Require(ERROR_SUCCESS == Error && ThisExcl);
  513. if( ThisExcl->Start == Start ) {
  514. Error = DeleteRecord( ThisExcl->UniqId );
  515. if ( ERROR_SUCCESS != Error ) {
  516. return Error;
  517. }
  518. Error = MemArrayDelElement(&Subnet->Exclusions, &Location, (LPVOID *)&ThisExcl);
  519. MemFree(ThisExcl);
  520. return ERROR_SUCCESS;
  521. }
  522. Error = MemArrayNextLoc(&Subnet->Exclusions, &Location);
  523. } // while
  524. return ERROR_FILE_NOT_FOUND;
  525. } // MemSubnetDelExcl()
  526. //BeginExport(function)
  527. DWORD
  528. MemSubnetExtendOrContractRange(
  529. IN OUT PM_SUBNET Subnet,
  530. IN OUT PM_RANGE Range,
  531. IN DWORD nAddresses, // how many addresses to extend by
  532. IN BOOL fExtend, // is this an EXTEND? or a CONTRACT?
  533. IN BOOL fEnd // is this operation to be done to END of range or START?
  534. ) //EndExport(function)
  535. {
  536. DWORD Error;
  537. PM_RANGE CollidedRange;
  538. AssertRet(Subnet && Range, ERROR_INVALID_PARAMETER);
  539. if( Subnet->fSubnet ) { // for real subnets (non-multicast-scopes) do sanity check
  540. if( fExtend ) {
  541. if( fEnd ) {
  542. if( ((Range->End + nAddresses) & Subnet->Mask) != (Range->Start & Subnet->Mask) )
  543. return ERROR_INVALID_PARAMETER;
  544. Error = MemSubnetFindCollision(
  545. Subnet,
  546. Range->End +1,
  547. Range->End +nAddresses,
  548. &CollidedRange,
  549. NULL
  550. );
  551. if( ERROR_SUCCESS == Error && NULL != CollidedRange)
  552. return ERROR_OBJECT_ALREADY_EXISTS;
  553. } else {
  554. if( ((Range->Start - nAddresses) & Subnet->Mask) != (Range->End & Subnet->Mask) )
  555. return ERROR_INVALID_PARAMETER;
  556. Error = MemSubnetFindCollision(
  557. Subnet,
  558. Range->Start - nAddresses,
  559. Range->Start - 1,
  560. &CollidedRange,
  561. NULL
  562. );
  563. if( ERROR_SUCCESS == Error && NULL != CollidedRange)
  564. return ERROR_OBJECT_ALREADY_EXISTS;
  565. } // else
  566. } // if
  567. } // if
  568. if( !fExtend && nAddresses > Range->End - Range->Start )
  569. return ERROR_INVALID_PARAMETER;
  570. Error = MemRangeExtendOrContract(
  571. Range,
  572. nAddresses,
  573. fExtend,
  574. fEnd
  575. );
  576. if ( ERROR_SUCCESS == Error ) {
  577. // record modified
  578. Error = DeleteRecord( Range->UniqId );
  579. if ( ERROR_SUCCESS != Error ) {
  580. return Error;
  581. }
  582. // mark for new rec creation
  583. Range->UniqId = INVALID_UNIQ_ID;
  584. } // if
  585. return Error;
  586. } // MemSubnetExtendOrContractRange()
  587. //BeginExport(function)
  588. DWORD
  589. MemSubnetExtendOrContractExcl(
  590. IN OUT PM_SUBNET Subnet,
  591. IN OUT PM_EXCL Excl,
  592. IN DWORD nAddresses, // how many addresses to extend by
  593. IN BOOL fExtend, // is this an EXTEND? or a CONTRACT?
  594. IN BOOL fEnd // is this operation to be done to END of range or START?
  595. ) //EndExport(function)
  596. {
  597. DWORD Error;
  598. PM_EXCL CollidedExcl;
  599. AssertRet(Subnet && Excl, ERROR_INVALID_PARAMETER);
  600. if( Subnet->fSubnet ) { // for real subnets (non-multicast-scopes) do sanity check
  601. if( fExtend ) {
  602. if( fEnd ) {
  603. if( ((Excl->End + nAddresses) & Subnet->Mask) != (Excl->Start & Subnet->Mask) )
  604. return ERROR_INVALID_PARAMETER;
  605. Error = MemSubnetFindCollision(
  606. Subnet,
  607. Excl->End +1,
  608. Excl->End +nAddresses,
  609. NULL,
  610. &CollidedExcl
  611. );
  612. if( ERROR_SUCCESS == Error && NULL != CollidedExcl)
  613. return ERROR_OBJECT_ALREADY_EXISTS;
  614. } else {
  615. if( ((Excl->Start - nAddresses) & Subnet->Mask) != (Excl->End & Subnet->Mask) )
  616. return ERROR_INVALID_PARAMETER;
  617. Error = MemSubnetFindCollision(
  618. Subnet,
  619. Excl->Start - nAddresses,
  620. Excl->Start - 1,
  621. NULL,
  622. &CollidedExcl
  623. );
  624. if( ERROR_SUCCESS == Error && NULL != CollidedExcl)
  625. return ERROR_OBJECT_ALREADY_EXISTS;
  626. }
  627. } // if
  628. } // if
  629. if( !fExtend && nAddresses > Excl->End - Excl->Start )
  630. return ERROR_INVALID_PARAMETER;
  631. if( fExtend )
  632. if( fEnd )
  633. Excl->End += nAddresses;
  634. else
  635. Excl->Start -= nAddresses;
  636. else
  637. if( fEnd )
  638. Excl->End -= nAddresses;
  639. else
  640. Excl->Start += nAddresses;
  641. Error = DeleteRecord( Excl->UniqId );
  642. if ( ERROR_SUCCESS != Error ) {
  643. return Error;
  644. }
  645. Excl->UniqId = INVALID_UNIQ_ID;
  646. return NO_ERROR;
  647. } // MemSubnetExtendOrContractExcl()
  648. //================================================================================
  649. // Multicast Scopes implementation
  650. //================================================================================
  651. //================================================================================
  652. // end of file
  653. //================================================================================