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.

792 lines
18 KiB

  1. /*++
  2. Copyright (c) 1999, Microsoft Corporation
  3. Module Name:
  4. qosminfo.c
  5. Abstract:
  6. The file contains global and interface
  7. config functions for QOS Mgr protocol.
  8. Revision History:
  9. --*/
  10. #include "pchqosm.h"
  11. #pragma hdrstop
  12. DWORD
  13. WINAPI
  14. QosmGetGlobalInfo (
  15. IN PVOID GlobalInfo,
  16. IN OUT PULONG BufferSize,
  17. OUT PULONG InfoSize
  18. )
  19. /*++
  20. Routine Description:
  21. Returns the global config info for this protocol.
  22. Arguments:
  23. See corr header file.
  24. Return Value:
  25. Status of the operation
  26. --*/
  27. {
  28. PIPQOS_GLOBAL_CONFIG GlobalConfig;
  29. DWORD Status;
  30. //
  31. // Validate all input params before reading the global info
  32. //
  33. if (BufferSize == NULL)
  34. {
  35. return ERROR_INVALID_PARAMETER;
  36. }
  37. ACQUIRE_GLOBALS_READ_LOCK();
  38. do
  39. {
  40. *InfoSize = Globals.ConfigSize;
  41. if ((*BufferSize < *InfoSize) ||
  42. (GlobalInfo == NULL))
  43. {
  44. //
  45. // Either the size was too small or there was no storage
  46. //
  47. Trace1(CONFIG,
  48. "GetGlobalInfo: Buffer size too small: %u",
  49. *BufferSize);
  50. *BufferSize = *InfoSize;
  51. Status = ERROR_INSUFFICIENT_BUFFER;
  52. break;
  53. }
  54. *BufferSize = *InfoSize;
  55. GlobalConfig = (PIPQOS_GLOBAL_CONFIG) GlobalInfo;
  56. CopyMemory(GlobalConfig,
  57. Globals.GlobalConfig,
  58. *InfoSize);
  59. Status = NO_ERROR;
  60. }
  61. while (FALSE);
  62. RELEASE_GLOBALS_READ_LOCK();
  63. return Status;
  64. }
  65. DWORD
  66. WINAPI
  67. QosmSetGlobalInfo (
  68. IN PVOID GlobalInfo,
  69. IN ULONG InfoSize
  70. )
  71. /*++
  72. Routine Description:
  73. Sets the global config info for this protocol.
  74. Arguments:
  75. See corr header file.
  76. Return Value:
  77. Status of the operation
  78. --*/
  79. {
  80. PIPQOS_GLOBAL_CONFIG GlobalConfig;
  81. DWORD Status;
  82. //
  83. // Update the global config information.
  84. //
  85. ACQUIRE_GLOBALS_WRITE_LOCK();
  86. do
  87. {
  88. GlobalConfig = AllocMemory(InfoSize);
  89. if (GlobalConfig == NULL)
  90. {
  91. Status = ERROR_NOT_ENOUGH_MEMORY;
  92. break;
  93. }
  94. //
  95. // Copy the new config information
  96. //
  97. CopyMemory(GlobalConfig, GlobalInfo, InfoSize);
  98. Globals.ConfigSize = InfoSize;
  99. //
  100. // Set up rest of the global state
  101. //
  102. if (GlobalConfig->LoggingLevel <= IPQOS_LOGGING_INFO)
  103. {
  104. Globals.LoggingLevel = GlobalConfig->LoggingLevel;
  105. }
  106. //
  107. // Cleanup old global information
  108. //
  109. if (Globals.GlobalConfig)
  110. {
  111. FreeMemory(Globals.GlobalConfig);
  112. }
  113. Globals.GlobalConfig = GlobalConfig;
  114. Status = NO_ERROR;
  115. }
  116. while (FALSE);
  117. RELEASE_GLOBALS_WRITE_LOCK();
  118. return Status;
  119. }
  120. DWORD
  121. WINAPI
  122. QosmGetInterfaceInfo (
  123. IN QOSMGR_INTERFACE_ENTRY *Interface,
  124. IN PVOID InterfaceInfo,
  125. IN OUT PULONG BufferSize,
  126. OUT PULONG InfoSize
  127. )
  128. /*++
  129. Routine Description:
  130. Gets the inteface config info for this protocol
  131. for this interface.
  132. Arguments:
  133. See corr header file.
  134. Return Value:
  135. Status of the operation
  136. --*/
  137. {
  138. PIPQOS_IF_CONFIG InterfaceConfig;
  139. DWORD Status;
  140. //
  141. // Validate all input params before reading interface info
  142. //
  143. if (BufferSize == NULL)
  144. {
  145. return ERROR_INVALID_PARAMETER;
  146. }
  147. ACQUIRE_INTERFACE_READ_LOCK(Interface);
  148. do
  149. {
  150. *InfoSize = Interface->ConfigSize;
  151. if ((*BufferSize < *InfoSize) ||
  152. (InterfaceInfo == NULL))
  153. {
  154. //
  155. // Either the size was too small or there was no storage
  156. //
  157. Trace1(CONFIG,
  158. "GetInterfaceInfo: Buffer size too small: %u",
  159. *BufferSize);
  160. *BufferSize = *InfoSize;
  161. Status = ERROR_INSUFFICIENT_BUFFER;
  162. break;
  163. }
  164. *BufferSize = *InfoSize;
  165. InterfaceConfig = (PIPQOS_IF_CONFIG) InterfaceInfo;
  166. CopyMemory(InterfaceConfig,
  167. Interface->InterfaceConfig,
  168. *InfoSize);
  169. Status = NO_ERROR;
  170. }
  171. while (FALSE);
  172. RELEASE_INTERFACE_READ_LOCK(Interface);
  173. return Status;
  174. }
  175. DWORD
  176. WINAPI
  177. QosmSetInterfaceInfo (
  178. IN QOSMGR_INTERFACE_ENTRY *Interface,
  179. IN PVOID InterfaceInfo,
  180. IN ULONG InfoSize
  181. )
  182. /*++
  183. Routine Description:
  184. Sets the interface config info for this protocol
  185. on this interface.
  186. Arguments:
  187. See corr header file.
  188. Return Value:
  189. Status of the operation
  190. --*/
  191. {
  192. PIPQOS_IF_CONFIG InterfaceConfig;
  193. PIPQOS_IF_FLOW FlowConfig;
  194. PQOSMGR_FLOW_ENTRY Flow;
  195. UINT i;
  196. PLIST_ENTRY p, q;
  197. PTC_GEN_FLOW FlowInfo;
  198. ULONG FlowSize;
  199. HANDLE FlowHandle;
  200. DWORD Status;
  201. //
  202. // Update the interface config information.
  203. //
  204. ACQUIRE_INTERFACE_WRITE_LOCK(Interface);
  205. do
  206. {
  207. //
  208. // Allocate memory to store new config
  209. //
  210. InterfaceConfig = AllocMemory(InfoSize);
  211. if (InterfaceConfig == NULL)
  212. {
  213. Status = ERROR_NOT_ENOUGH_MEMORY;
  214. break;
  215. }
  216. //
  217. // Copy the new config information
  218. //
  219. CopyMemory(InterfaceConfig, InterfaceInfo, InfoSize);
  220. Interface->ConfigSize = InfoSize;
  221. //
  222. // Set up rest of interface state
  223. //
  224. if (Interface->State != InterfaceConfig->QosState)
  225. {
  226. if (InterfaceConfig->QosState == IPQOS_STATE_DISABLED)
  227. {
  228. //
  229. // Disable all flows on this interface
  230. //
  231. ;
  232. }
  233. else
  234. {
  235. //
  236. // Renable all flows on this interface
  237. //
  238. ;
  239. }
  240. Interface->State = InterfaceConfig->QosState;
  241. }
  242. //
  243. // Update the flow information on if
  244. //
  245. //
  246. // First mark all flows as needing refresh
  247. //
  248. for (p = Interface->FlowList.Flink;
  249. p != &Interface->FlowList;
  250. p = p->Flink)
  251. {
  252. Flow = CONTAINING_RECORD(p, QOSMGR_FLOW_ENTRY, OnInterfaceLE);
  253. ASSERT(!(Flow->Flags & FLOW_FLAG_DELETE));
  254. Flow->Flags |= FLOW_FLAG_DELETE;
  255. }
  256. //
  257. // If we do not have an TC interface handle,
  258. // we delete all flows as they are obsolete
  259. //
  260. if (Interface->TciIfHandle)
  261. {
  262. //
  263. // Set each flow if it has changed from before
  264. //
  265. FlowConfig = IPQOS_GET_FIRST_FLOW_ON_IF(InterfaceConfig);
  266. for (i = 0; i < InterfaceConfig->NumFlows; i++)
  267. {
  268. //
  269. // Search for a flow with the same name
  270. //
  271. for (p = Interface->FlowList.Flink;
  272. p != &Interface->FlowList;
  273. p = p->Flink)
  274. {
  275. Flow =
  276. CONTAINING_RECORD(p, QOSMGR_FLOW_ENTRY, OnInterfaceLE);
  277. if (!_wcsicmp(Flow->FlowName, FlowConfig->FlowName))
  278. {
  279. break;
  280. }
  281. }
  282. if (p == &Interface->FlowList)
  283. {
  284. //
  285. // No flow by this name - add new one
  286. //
  287. Flow = NULL;
  288. }
  289. //
  290. // Get a flow info from description
  291. //
  292. Status = GetFlowFromDescription(&FlowConfig->FlowDesc,
  293. &FlowInfo,
  294. &FlowSize);
  295. if (Status == NO_ERROR)
  296. {
  297. do
  298. {
  299. if ((Flow) &&
  300. (FlowSize == Flow->FlowSize) &&
  301. (EqualMemory(FlowInfo, Flow->FlowInfo, FlowSize)))
  302. {
  303. //
  304. // No change in the flow info yet,
  305. // this flow still remains valid
  306. //
  307. Flow->Flags &= ~FLOW_FLAG_DELETE;
  308. Status = ERROR_ALREADY_EXISTS;
  309. break;
  310. }
  311. if (Flow)
  312. {
  313. //
  314. // Flow info changed - modify flow
  315. //
  316. Status = TcModifyFlow(Flow->TciFlowHandle,
  317. FlowInfo);
  318. if (Status != NO_ERROR)
  319. {
  320. break;
  321. }
  322. Flow->Flags &= ~FLOW_FLAG_DELETE;
  323. //
  324. // Update cached flow info
  325. //
  326. FreeMemory(Flow->FlowInfo);
  327. Flow->FlowInfo = FlowInfo;
  328. Flow->FlowSize = FlowSize;
  329. }
  330. else
  331. {
  332. //
  333. // Add the new flow using the TC API
  334. //
  335. Status = TcAddFlow(Interface->TciIfHandle,
  336. NULL,
  337. 0,
  338. FlowInfo,
  339. &FlowHandle);
  340. if (Status != NO_ERROR)
  341. {
  342. break;
  343. }
  344. //
  345. // Addition of a new flow in TC
  346. //
  347. Flow = AllocMemory(sizeof(QOSMGR_FLOW_ENTRY));
  348. if (Flow == NULL)
  349. {
  350. Status = TcDeleteFlow(FlowHandle);
  351. ASSERT(Status);
  352. Status = ERROR_NOT_ENOUGH_MEMORY;
  353. break;
  354. }
  355. //
  356. // Initialize flow and insert in list
  357. //
  358. Flow->TciFlowHandle = FlowHandle;
  359. Flow->Flags = 0;
  360. Flow->FlowInfo = FlowInfo;
  361. Flow->FlowSize = FlowSize;
  362. wcscpy(Flow->FlowName, FlowConfig->FlowName);
  363. InsertTailList(p, &Flow->OnInterfaceLE);
  364. }
  365. }
  366. while (FALSE);
  367. if (Status != NO_ERROR)
  368. {
  369. FreeMemory(FlowInfo);
  370. }
  371. }
  372. //
  373. // Move to the next flow in config
  374. //
  375. FlowConfig = IPQOS_GET_NEXT_FLOW_ON_IF(FlowConfig);
  376. }
  377. }
  378. //
  379. // Cleanup all flows that are obsolete
  380. //
  381. for (p = Interface->FlowList.Flink;
  382. p != &Interface->FlowList;
  383. p = q)
  384. {
  385. Flow = CONTAINING_RECORD(p, QOSMGR_FLOW_ENTRY, OnInterfaceLE);
  386. q = p->Flink;
  387. if (Flow->Flags & FLOW_FLAG_DELETE)
  388. {
  389. //
  390. // Delete the flow from the TC API
  391. //
  392. Status = TcDeleteFlow(Flow->TciFlowHandle);
  393. if (Status != NO_ERROR)
  394. {
  395. Flow->Flags &= ~FLOW_FLAG_DELETE;
  396. continue;
  397. }
  398. //
  399. // Remove flow from this flow list
  400. //
  401. RemoveEntryList(p);
  402. //
  403. // Free the flow and its resources
  404. //
  405. if (Flow->FlowInfo)
  406. {
  407. FreeMemory(Flow->FlowInfo);
  408. }
  409. FreeMemory(Flow);
  410. }
  411. }
  412. //
  413. // Cleanup old interface information
  414. //
  415. if (Interface->InterfaceConfig)
  416. {
  417. FreeMemory(Interface->InterfaceConfig);
  418. }
  419. Interface->InterfaceConfig = InterfaceConfig;
  420. Status = NO_ERROR;
  421. }
  422. while (FALSE);
  423. RELEASE_INTERFACE_WRITE_LOCK(Interface);
  424. return Status;
  425. }
  426. DWORD
  427. GetFlowFromDescription(
  428. IN PIPQOS_NAMED_FLOW FlowDesc,
  429. OUT PTC_GEN_FLOW *FlowInfo,
  430. OUT ULONG *FlowSize
  431. )
  432. {
  433. FLOWSPEC *CurrFlowspec;
  434. FLOWSPEC SendFlowspec;
  435. FLOWSPEC RecvFlowspec;
  436. FLOWSPEC *Flowspec;
  437. PTC_GEN_FLOW Flow;
  438. QOS_OBJECT_HDR *QosObject;
  439. PWCHAR FlowspecName;
  440. PWCHAR QosObjectName;
  441. PUCHAR CopyAtPtr;
  442. ULONG ObjectsLength;
  443. ULONG i;
  444. #if 1
  445. //
  446. // Check for the existence of sending flowspec
  447. //
  448. if (FlowDesc->SendingFlowspecName[0] == L'\0')
  449. {
  450. return ERROR_INVALID_DATA;
  451. }
  452. #endif
  453. //
  454. // Get the sending and receiving flowspecs
  455. //
  456. for (i = 0; i < 2; i++)
  457. {
  458. if (i)
  459. {
  460. FlowspecName = FlowDesc->RecvingFlowspecName;
  461. CurrFlowspec = &RecvFlowspec;
  462. }
  463. else
  464. {
  465. FlowspecName = FlowDesc->SendingFlowspecName;
  466. CurrFlowspec = &SendFlowspec;
  467. }
  468. FillMemory(CurrFlowspec, sizeof(FLOWSPEC), QOS_NOT_SPECIFIED);
  469. if (FlowspecName[0] != L'\0')
  470. {
  471. Flowspec = GetFlowspecFromGlobalConfig(FlowspecName);
  472. if (Flowspec == NULL)
  473. {
  474. return ERROR_INVALID_DATA;
  475. }
  476. *CurrFlowspec = *Flowspec;
  477. }
  478. }
  479. //
  480. // Calculate the size of the TC_GEN_FLOW block
  481. //
  482. QosObjectName = IPQOS_GET_FIRST_OBJECT_NAME_ON_NAMED_FLOW(FlowDesc);
  483. ObjectsLength = 0;
  484. for (i = 0; i < FlowDesc->NumTcObjects; i++)
  485. {
  486. //
  487. // Get object's description in global info
  488. //
  489. QosObject = GetQosObjectFromGlobalConfig(QosObjectName);
  490. if (QosObject == NULL)
  491. {
  492. //
  493. // Incomplete description
  494. //
  495. return ERROR_INVALID_DATA;
  496. }
  497. ObjectsLength += QosObject->ObjectLength;
  498. QosObjectName= IPQOS_GET_NEXT_OBJECT_NAME_ON_NAMED_FLOW(QosObjectName);
  499. }
  500. *FlowSize = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + ObjectsLength;
  501. *FlowInfo = Flow = AllocMemory(*FlowSize);
  502. if (Flow == NULL)
  503. {
  504. return ERROR_NOT_ENOUGH_MEMORY;
  505. }
  506. //
  507. // Fill in the flow information now
  508. //
  509. Flow->ReceivingFlowspec = RecvFlowspec;
  510. Flow->SendingFlowspec = SendFlowspec;
  511. Flow->TcObjectsLength = ObjectsLength;
  512. //
  513. // Repeat the loop above filling info
  514. //
  515. QosObjectName = IPQOS_GET_FIRST_OBJECT_NAME_ON_NAMED_FLOW(FlowDesc);
  516. CopyAtPtr = (PUCHAR) &Flow->TcObjects[0];
  517. for (i = 0; i < FlowDesc->NumTcObjects; i++)
  518. {
  519. //
  520. // Get object's description in global info
  521. //
  522. QosObject = GetQosObjectFromGlobalConfig(QosObjectName);
  523. // We just checked above for its existence
  524. ASSERT(QosObject != NULL);
  525. CopyMemory(CopyAtPtr,
  526. QosObject,
  527. QosObject->ObjectLength);
  528. CopyAtPtr += QosObject->ObjectLength;
  529. QosObjectName= IPQOS_GET_NEXT_OBJECT_NAME_ON_NAMED_FLOW(QosObjectName);
  530. }
  531. return NO_ERROR;
  532. }
  533. FLOWSPEC *
  534. GetFlowspecFromGlobalConfig(
  535. IN PWCHAR FlowspecName
  536. )
  537. {
  538. IPQOS_NAMED_FLOWSPEC *Flowspec;
  539. UINT i;
  540. Flowspec = IPQOS_GET_FIRST_FLOWSPEC_IN_CONFIG(Globals.GlobalConfig);
  541. for (i = 0; i < Globals.GlobalConfig->NumFlowspecs; i++)
  542. {
  543. if (!_wcsicmp(Flowspec->FlowspecName, FlowspecName))
  544. {
  545. break;
  546. }
  547. Flowspec = IPQOS_GET_NEXT_FLOWSPEC_IN_CONFIG(Flowspec);
  548. }
  549. if (i < Globals.GlobalConfig->NumFlowspecs)
  550. {
  551. return &Flowspec->FlowspecDesc;
  552. }
  553. return NULL;
  554. }
  555. QOS_OBJECT_HDR *
  556. GetQosObjectFromGlobalConfig(
  557. IN PWCHAR QosObjectName
  558. )
  559. {
  560. IPQOS_NAMED_QOSOBJECT *QosObject;
  561. UINT i;
  562. QosObject = IPQOS_GET_FIRST_QOSOBJECT_IN_CONFIG(Globals.GlobalConfig);
  563. for (i = 0; i < Globals.GlobalConfig->NumQosObjects; i++)
  564. {
  565. if (!_wcsicmp(QosObject->QosObjectName, QosObjectName))
  566. {
  567. break;
  568. }
  569. QosObject = IPQOS_GET_NEXT_QOSOBJECT_IN_CONFIG(QosObject);
  570. }
  571. if (i < Globals.GlobalConfig->NumFlowspecs)
  572. {
  573. return &QosObject->QosObjectHdr;
  574. }
  575. return NULL;
  576. }