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.

638 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. rtmregn.c
  5. Abstract:
  6. Contains routines for managing registration
  7. of protocol & management entities with RTM.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 20-Aug-1998
  10. Revision History:
  11. --*/
  12. #include "pchrtm.h"
  13. #pragma hdrstop
  14. DWORD
  15. WINAPI
  16. RtmRegisterEntity (
  17. IN PRTM_ENTITY_INFO RtmEntityInfo,
  18. IN PRTM_ENTITY_EXPORT_METHODS ExportMethods OPTIONAL,
  19. IN RTM_EVENT_CALLBACK EventCallback,
  20. IN BOOL ReserveOpaquePtr,
  21. OUT PRTM_REGN_PROFILE RtmRegProfile,
  22. OUT PRTM_ENTITY_HANDLE RtmRegHandle
  23. )
  24. /*++
  25. Routine Description:
  26. Registers an entity with an RTM instance for a specific address
  27. family.
  28. A registration handle, and a profile of the RTM instance with
  29. with supported views, number of equal cost NHops / route etc.
  30. is returned.
  31. If registration is with a new instance and/or address family,
  32. then this instance/address family is created in this process.
  33. Arguments:
  34. RtmEntityInfo - Information (RtmInstance, Protocol ID etc.)
  35. for the entity that is registering here,
  36. ExportMethods - List of methods exported by this entity,
  37. EventCallback - Callback invoked to inform of certain events
  38. like entity registrations, de-registrations,
  39. ReserveOpaquePtr - Reserve a ptr in each destination or not,
  40. RtmRegProfile - RTM parameters that the entity will use in
  41. RTM API calls [eg: No. of equal cost NHOPs],
  42. RtmRegHandle - Identification handle for this entity used
  43. in all API calls until its de-registration.
  44. Return Value:
  45. Status of the operation
  46. --*/
  47. {
  48. PINSTANCE_INFO Instance;
  49. PADDRFAM_INFO AddrFamilyInfo;
  50. PENTITY_INFO Entity;
  51. DWORD Status;
  52. CHECK_FOR_RTM_API_INITIALIZED();
  53. TraceEnter("RtmRegisterEntity");
  54. ACQUIRE_INSTANCES_WRITE_LOCK();
  55. do
  56. {
  57. //
  58. // Search (or create) for an instance with the input RtmInstanceId
  59. //
  60. Status = GetInstance(RtmEntityInfo->RtmInstanceId,
  61. TRUE,
  62. &Instance);
  63. if (Status != NO_ERROR)
  64. {
  65. break;
  66. }
  67. //
  68. // Search (or create) for an address family info with input family
  69. //
  70. Status = GetAddressFamily(Instance,
  71. RtmEntityInfo->AddressFamily,
  72. TRUE,
  73. &AddrFamilyInfo);
  74. if (Status != NO_ERROR)
  75. {
  76. break;
  77. }
  78. //
  79. // Search (or create) for an entity with input protocol id, instance
  80. //
  81. Status = GetEntity(AddrFamilyInfo,
  82. RtmEntityInfo->EntityId.EntityId,
  83. TRUE,
  84. RtmEntityInfo,
  85. ReserveOpaquePtr,
  86. ExportMethods,
  87. EventCallback,
  88. &Entity);
  89. if (Status != NO_ERROR)
  90. {
  91. break;
  92. }
  93. //
  94. // Collect all relevant information and build registration profile
  95. //
  96. RtmRegProfile->MaxNextHopsInRoute = AddrFamilyInfo->MaxNextHopsInRoute;
  97. RtmRegProfile->MaxHandlesInEnum = AddrFamilyInfo->MaxHandlesInEnum;
  98. RtmRegProfile->ViewsSupported = AddrFamilyInfo->ViewsSupported;
  99. RtmRegProfile->NumberOfViews = AddrFamilyInfo->NumberOfViews;
  100. //
  101. // Return a handle to this entity registration block
  102. //
  103. *RtmRegHandle = MAKE_HANDLE_FROM_POINTER(Entity);
  104. }
  105. while (FALSE);
  106. RELEASE_INSTANCES_WRITE_LOCK();
  107. TraceLeave("RtmRegisterEntity");
  108. return Status;
  109. }
  110. DWORD
  111. WINAPI
  112. RtmDeregisterEntity (
  113. IN RTM_ENTITY_HANDLE RtmRegHandle
  114. )
  115. /*++
  116. Routine Description:
  117. Deregisters an entity with its RTM instance and addr family.
  118. We assume that the entity is responsible for making sure
  119. that once this call is made, no other RTM calls will be
  120. made using this entity registration handle. In case such
  121. a thing happens, it might result in crashing the process.
  122. We make this assumption for performance reasons - else we
  123. we have to make sure that the entity handle passed in is
  124. valid in a try-except block (same with other handles) and
  125. this will lead to degradation in performance.
  126. Arguments:
  127. RtmRegHandle - RTM registration handle for the entity
  128. Return Value:
  129. Status of the operation
  130. --*/
  131. {
  132. PADDRFAM_INFO AddrFamInfo;
  133. PENTITY_INFO Entity;
  134. HANDLE Event;
  135. DWORD Status;
  136. TraceEnter("RtmDeregisterEntity");
  137. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  138. //
  139. // Release all handles opened by entity
  140. //
  141. CleanupAfterDeregister(Entity);
  142. //
  143. // Mark the entity info as de-registered
  144. //
  145. Entity->State = ENTITY_STATE_DEREGISTERED;
  146. //
  147. // Make sure no more methods are invoked
  148. //
  149. ACQUIRE_ENTITY_METHODS_WRITE_LOCK(Entity);
  150. // At this time all entity methods are
  151. // done - no more methods will be called
  152. // as we set the state to DEREGISTERED
  153. RELEASE_ENTITY_METHODS_WRITE_LOCK(Entity);
  154. //
  155. // Remove from entity table and inform others
  156. //
  157. AddrFamInfo = Entity->OwningAddrFamily;
  158. ACQUIRE_INSTANCES_WRITE_LOCK();
  159. //
  160. // Remove entity from the list of entities
  161. // even before ref counts on this entity
  162. // go to zero - this enables the entity to
  163. // re-register meanwhile as a new entity.
  164. //
  165. RemoveEntryList(&Entity->EntityTableLE);
  166. //
  167. // Insert in the list of entities to be
  168. // destroyed on the address family info.
  169. //
  170. InsertTailList(&AddrFamInfo->DeregdEntities,
  171. &Entity->EntityTableLE);
  172. InformEntitiesOfEvent(AddrFamInfo->EntityTable,
  173. RTM_ENTITY_DEREGISTERED,
  174. Entity);
  175. RELEASE_INSTANCES_WRITE_LOCK();
  176. DBG_UNREFERENCED_LOCAL_VARIABLE(Event);
  177. #if DBG_REF
  178. //
  179. // Create an event on which to block on - this
  180. // event gets signalled when entity ref is 0.
  181. //
  182. Event = CreateEvent(NULL, FALSE, FALSE, NULL);
  183. ASSERT(Event != NULL);
  184. Entity->BlockingEvent = Event;
  185. #endif
  186. //
  187. // Remove the creation reference on the entity
  188. //
  189. DEREFERENCE_ENTITY(Entity, CREATION_REF);
  190. DBG_UNREFERENCED_LOCAL_VARIABLE(Status);
  191. #if DBG_REF
  192. //
  193. // Block until the reference count goes to zero
  194. //
  195. Status = WaitForSingleObject(Event, INFINITE);
  196. ASSERT(Status == WAIT_OBJECT_0);
  197. CloseHandle(Event);
  198. #endif
  199. TraceLeave("RtmDeregisterEntity");
  200. return NO_ERROR;
  201. }
  202. DWORD
  203. WINAPI
  204. RtmGetRegisteredEntities (
  205. IN RTM_ENTITY_HANDLE RtmRegHandle,
  206. IN OUT PUINT NumEntities,
  207. OUT PRTM_ENTITY_HANDLE EntityHandles,
  208. OUT PRTM_ENTITY_INFO EntityInfos OPTIONAL
  209. )
  210. /*++
  211. Routine Description:
  212. Retrieves information about all entities registered with an
  213. RTM instance.
  214. Arguments:
  215. RtmRegHandle - RTM registration handle for calling entity,
  216. NumEntities - Number of entities that can be filled
  217. is passed in, and number of entities
  218. that exist in this address family is retd,
  219. RegdEntityHandles - Array to return the entity handles in,
  220. RegdEntityInfos - Array to return the entity infos in
  221. Return Value:
  222. Status of the operation
  223. --*/
  224. {
  225. PENTITY_INFO Entity;
  226. PADDRFAM_INFO AddrFamilyInfo;
  227. USHORT RtmInstanceId;
  228. USHORT AddressFamily;
  229. UINT EntitiesCopied;
  230. UINT i;
  231. PLIST_ENTRY Entities;
  232. PLIST_ENTRY p;
  233. DWORD Status;
  234. TraceEnter("RtmGetRegisteredEntities");
  235. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  236. AddrFamilyInfo = Entity->OwningAddrFamily;
  237. //
  238. // Just cache the instance and address family
  239. // as it is identical for all entities infos.
  240. //
  241. #if WRN
  242. RtmInstanceId = AddressFamily = 0;
  243. #endif
  244. if (ARGUMENT_PRESENT(EntityInfos))
  245. {
  246. RtmInstanceId = AddrFamilyInfo->Instance->RtmInstanceId;
  247. AddressFamily = AddrFamilyInfo->AddressFamily;
  248. }
  249. //
  250. // Go over the entity table and copy out handles
  251. // If the OPTIONAL argument 'EntityInfos' is
  252. // given, copy out entity information as well.
  253. //
  254. EntitiesCopied = 0;
  255. ACQUIRE_INSTANCES_READ_LOCK();
  256. for (i = 0; (i < ENTITY_TABLE_SIZE) && (EntitiesCopied < *NumEntities);i++)
  257. {
  258. Entities = &AddrFamilyInfo->EntityTable[i];
  259. //
  260. // Process the next bucket in the entities table
  261. //
  262. for (p = Entities->Flink; p != Entities; p = p->Flink)
  263. {
  264. Entity = CONTAINING_RECORD(p, ENTITY_INFO, EntityTableLE);
  265. //
  266. // Copy the next entity handle and info to output buffer
  267. //
  268. if (Entity->State != ENTITY_STATE_DEREGISTERED)
  269. {
  270. EntityHandles[EntitiesCopied]=MAKE_HANDLE_FROM_POINTER(Entity);
  271. REFERENCE_ENTITY(Entity, HANDLE_REF);
  272. if (ARGUMENT_PRESENT(EntityInfos))
  273. {
  274. EntityInfos[EntitiesCopied].RtmInstanceId = RtmInstanceId;
  275. EntityInfos[EntitiesCopied].AddressFamily = AddressFamily;
  276. EntityInfos[EntitiesCopied].EntityId = Entity->EntityId;
  277. }
  278. if (++EntitiesCopied == *NumEntities)
  279. {
  280. break;
  281. }
  282. }
  283. }
  284. }
  285. //
  286. // Set output to total entities present,
  287. // and also the appropriate return value
  288. //
  289. if (*NumEntities >= AddrFamilyInfo->NumEntities)
  290. {
  291. Status = NO_ERROR;
  292. }
  293. else
  294. {
  295. Status = ERROR_INSUFFICIENT_BUFFER;
  296. }
  297. *NumEntities = AddrFamilyInfo->NumEntities;
  298. RELEASE_INSTANCES_READ_LOCK();
  299. TraceLeave("RtmGetRegisteredEntities");
  300. return Status;
  301. }
  302. DWORD
  303. WINAPI
  304. RtmReleaseEntities (
  305. IN RTM_ENTITY_HANDLE RtmRegHandle,
  306. IN UINT NumEntities,
  307. IN PRTM_ENTITY_HANDLE EntityHandles
  308. )
  309. /*++
  310. Routine Description:
  311. Release (also called de-reference) handles to entities
  312. obtained in other RTM calls.
  313. Arguments:
  314. RtmRegHandle - RTM registration handle for calling entity,
  315. NumEntities - Number of handles that are being released,
  316. EntityHandles - An array of handles that are being released.
  317. Return Value:
  318. Status of the operation
  319. --*/
  320. {
  321. PENTITY_INFO Entity;
  322. UINT i;
  323. DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  324. //
  325. // Dereference each entity handle in array
  326. //
  327. for (i = 0; i < NumEntities; i++)
  328. {
  329. Entity = ENTITY_FROM_HANDLE(EntityHandles[i]);
  330. DEREFERENCE_ENTITY(Entity, HANDLE_REF);
  331. }
  332. return NO_ERROR;
  333. }
  334. DWORD
  335. WINAPI
  336. RtmLockDestination(
  337. IN RTM_ENTITY_HANDLE RtmRegHandle,
  338. IN RTM_DEST_HANDLE DestHandle,
  339. IN BOOL Exclusive,
  340. IN BOOL LockDest
  341. )
  342. /*++
  343. Routine Description:
  344. Locks/unlocks a destination in the route table. This function
  345. is used to guard the dest while opaque ptrs are being changed.
  346. Arguments:
  347. RtmRegHandle - RTM registration handle for calling entity,
  348. DestHandle - Handle to the destination to be locked,
  349. Exclusive - TRUE to lock in write mode, else read mode,
  350. LockDest - Flag that tells whether to lock or unlock.
  351. Return Value:
  352. Status of the operation
  353. --*/
  354. {
  355. PENTITY_INFO Entity;
  356. PDEST_INFO Dest;
  357. DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  358. VALIDATE_DEST_HANDLE(DestHandle, &Dest);
  359. // Lock or unlock the dest as the case may be
  360. if (LockDest)
  361. {
  362. if (Exclusive)
  363. {
  364. ACQUIRE_DEST_WRITE_LOCK(Dest);
  365. }
  366. else
  367. {
  368. ACQUIRE_DEST_READ_LOCK(Dest);
  369. }
  370. }
  371. else
  372. {
  373. if (Exclusive)
  374. {
  375. RELEASE_DEST_WRITE_LOCK(Dest);
  376. }
  377. else
  378. {
  379. RELEASE_DEST_READ_LOCK(Dest);
  380. }
  381. }
  382. return NO_ERROR;
  383. }
  384. DWORD
  385. WINAPI
  386. RtmGetOpaqueInformationPointer (
  387. IN RTM_ENTITY_HANDLE RtmRegHandle,
  388. IN RTM_DEST_HANDLE DestHandle,
  389. OUT PVOID *OpaqueInfoPtr
  390. )
  391. /*++
  392. Routine Description:
  393. Retrieves a pointer to the opaque info pointer field in a dest
  394. for this entity, or NULL if entity has not reserved such a ptr
  395. during registration.
  396. Arguments:
  397. RtmRegHandle - RTM registration handle for calling entity,
  398. DestHandle - Handle to dest whose opaque info ptr we want,
  399. OpaqueInfoPtr - Pointer to opaque info ptr is returned here
  400. Return Value:
  401. Status of the operation
  402. --*/
  403. {
  404. PENTITY_INFO Entity;
  405. PDEST_INFO Dest;
  406. DWORD Status;
  407. TraceEnter("RtmGetOpaqueInformationPointer");
  408. *OpaqueInfoPtr = NULL;
  409. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  410. Status = ERROR_NOT_FOUND;
  411. //
  412. // If dest is valid and we have an opaque slot
  413. // reserved, do ptr arithmetic to get the addr
  414. //
  415. if (Entity->OpaquePtrOffset != (-1))
  416. {
  417. //
  418. // We do not check if the dest in deleted
  419. // as the entity will need to access its
  420. // opaque info even after dest is deleted.
  421. //
  422. Dest = DEST_FROM_HANDLE(DestHandle);
  423. if (Dest)
  424. {
  425. *OpaqueInfoPtr = &Dest->OpaqueInfoPtrs[Entity->OpaquePtrOffset];
  426. Status = NO_ERROR;
  427. }
  428. else
  429. {
  430. Status = ERROR_INVALID_HANDLE;
  431. }
  432. }
  433. TraceLeave("RtmGetOpaqueInformationPointer");
  434. return Status;
  435. }