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.

1128 lines
27 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ip\rtrmgr\protodll.c
  5. Abstract:
  6. Routines for managing protocol DLLs
  7. Revision History:
  8. Gurdeep Singh Pall 6/8/95 Created
  9. --*/
  10. #include "allinc.h"
  11. DWORD
  12. LoadProtocol(
  13. IN MPR_PROTOCOL_0 *pmpProtocolInfo,
  14. IN PPROTO_CB pProtocolCb,
  15. IN PVOID pvInfo,
  16. IN ULONG ulStructureVersion,
  17. IN ULONG ulStructureSize,
  18. IN ULONG ulStructureCount
  19. )
  20. /*++
  21. Routine Description:
  22. Loads the DLL for a routing protocol. Initializes the entry points in
  23. the CB
  24. Locks:
  25. Arguments:
  26. pszDllName Name of DLL of the routing protocol
  27. pProtocolCb Pointer to CB to hold info for this protocol
  28. pGlobalInfo GlobalInfo (from which the info for this protocol is
  29. extracted)
  30. Return Value:
  31. NO_ERROR or some error code
  32. --*/
  33. {
  34. DWORD dwResult,dwNumStructs, dwSupport;
  35. PVOID pInfo;
  36. HINSTANCE hModule;
  37. PRTR_TOC_ENTRY pToc;
  38. PREGISTER_PROTOCOL pfnRegisterProtocol;
  39. MPR_ROUTING_CHARACTERISTICS mrcRouting;
  40. MPR_SERVICE_CHARACTERISTICS mscService;
  41. TraceEnter("LoadProtocol");
  42. Trace1(GLOBAL,
  43. "LoadProtocol: Loading %S",
  44. pmpProtocolInfo->wszProtocol);
  45. #if IA64
  46. if ( pmpProtocolInfo-> dwProtocolId == PROTO_IP_OSPF )
  47. {
  48. Trace1(
  49. ERR,
  50. "Protocol %S not supported on 64 bit",
  51. pmpProtocolInfo-> wszProtocol
  52. );
  53. return ERROR_NOT_SUPPORTED;
  54. }
  55. #endif
  56. //
  57. // Loading all entrypoints
  58. //
  59. hModule = LoadLibraryW(pmpProtocolInfo->wszDLLName);
  60. if(hModule is NULL)
  61. {
  62. dwResult = GetLastError();
  63. Trace2(ERR, "LoadProtocol: %S failed to load: %d\n",
  64. pmpProtocolInfo->wszDLLName,
  65. dwResult);
  66. return dwResult;
  67. }
  68. pProtocolCb->hiHInstance = hModule;
  69. pProtocolCb->dwProtocolId = pmpProtocolInfo->dwProtocolId;
  70. pfnRegisterProtocol = NULL;
  71. pfnRegisterProtocol =
  72. (PREGISTER_PROTOCOL)GetProcAddress(hModule,
  73. REGISTER_PROTOCOL_ENTRY_POINT_STRING);
  74. if(pfnRegisterProtocol is NULL)
  75. {
  76. //
  77. // Could not find the RegisterProtocol entry point
  78. // Nothing we can do - bail out
  79. //
  80. Sleep(0);
  81. FreeLibrary(hModule);
  82. Trace1(ERR, "LoadProtocol: Could not find RegisterProtocol for %S",
  83. pmpProtocolInfo->wszDLLName);
  84. return ERROR_INVALID_FUNCTION;
  85. }
  86. //
  87. // Give a chance for the protocol to register itself
  88. //
  89. //
  90. // Zero out the memory so that protocols with older versions
  91. // still work
  92. //
  93. ZeroMemory(&mrcRouting,
  94. sizeof(MPR_ROUTING_CHARACTERISTICS));
  95. mrcRouting.dwVersion = MS_ROUTER_VERSION;
  96. mrcRouting.dwProtocolId = pmpProtocolInfo->dwProtocolId;
  97. #define __CURRENT_FUNCTIONALITY \
  98. RF_ROUTING | \
  99. RF_DEMAND_UPDATE_ROUTES | \
  100. RF_ADD_ALL_INTERFACES | \
  101. RF_MULTICAST | \
  102. RF_POWER
  103. mrcRouting.fSupportedFunctionality = (__CURRENT_FUNCTIONALITY);
  104. //
  105. // We dont support any service related stuff
  106. //
  107. mscService.dwVersion = MS_ROUTER_VERSION;
  108. mscService.dwProtocolId = pmpProtocolInfo->dwProtocolId;
  109. mscService.fSupportedFunctionality = 0;
  110. dwResult = pfnRegisterProtocol(&mrcRouting,
  111. &mscService);
  112. if(dwResult isnot NO_ERROR)
  113. {
  114. Sleep(0);
  115. FreeLibrary(hModule);
  116. pProtocolCb->hiHInstance = NULL;
  117. Trace2(ERR, "LoadProtocol: %S returned error %d while registering",
  118. pmpProtocolInfo->wszDLLName,
  119. dwResult);
  120. return dwResult;
  121. }
  122. if(mrcRouting.dwVersion > MS_ROUTER_VERSION)
  123. {
  124. Trace3(ERR,
  125. "LoadProtocol: %S registered with version 0x%x. Our version is 0x%x\n",
  126. pmpProtocolInfo->wszProtocol,
  127. mrcRouting.dwVersion,
  128. MS_ROUTER_VERSION);
  129. //
  130. // relenquish CPU to enable DLL threads to finish
  131. //
  132. Sleep(0);
  133. FreeLibrary(hModule);
  134. return ERROR_CAN_NOT_COMPLETE;
  135. }
  136. if(mrcRouting.dwProtocolId isnot pmpProtocolInfo->dwProtocolId)
  137. {
  138. //
  139. // protocol tried to change IDs on us
  140. //
  141. Trace3(ERR,
  142. "LoadProtocol: %S returned ID of %x when it should be %x",
  143. pmpProtocolInfo->wszProtocol,
  144. mrcRouting.dwProtocolId,
  145. pmpProtocolInfo->dwProtocolId);
  146. Sleep(0);
  147. FreeLibrary(hModule);
  148. return ERROR_CAN_NOT_COMPLETE;
  149. }
  150. if(mrcRouting.fSupportedFunctionality & ~(__CURRENT_FUNCTIONALITY))
  151. {
  152. //
  153. // Hmm, some functionality that we dont understand
  154. //
  155. Trace3(ERR,
  156. "LoadProtocol: %S wanted functionalitf %x when we have %x",
  157. pmpProtocolInfo->wszProtocol,
  158. mrcRouting.fSupportedFunctionality,
  159. (__CURRENT_FUNCTIONALITY));
  160. Sleep(0);
  161. FreeLibrary(hModule);
  162. return ERROR_CAN_NOT_COMPLETE;
  163. }
  164. #undef __CURRENT_FUNCTIONALITY
  165. if(!(mrcRouting.fSupportedFunctionality & RF_ROUTING))
  166. {
  167. Trace1(ERR,
  168. "LoadProtocol: %S doesnt support routing",
  169. pmpProtocolInfo->wszProtocol);
  170. //
  171. // relenquish CPU to enable DLL threads to finish
  172. //
  173. Sleep(0);
  174. FreeLibrary(hModule);
  175. return ERROR_CAN_NOT_COMPLETE;
  176. }
  177. pProtocolCb->fSupportedFunctionality = mrcRouting.fSupportedFunctionality;
  178. pProtocolCb->pfnStartProtocol = mrcRouting.pfnStartProtocol;
  179. pProtocolCb->pfnStartComplete = mrcRouting.pfnStartComplete;
  180. pProtocolCb->pfnStopProtocol = mrcRouting.pfnStopProtocol;
  181. pProtocolCb->pfnGetGlobalInfo = mrcRouting.pfnGetGlobalInfo;
  182. pProtocolCb->pfnSetGlobalInfo = mrcRouting.pfnSetGlobalInfo;
  183. pProtocolCb->pfnQueryPower = mrcRouting.pfnQueryPower;
  184. pProtocolCb->pfnSetPower = mrcRouting.pfnSetPower;
  185. pProtocolCb->pfnAddInterface = mrcRouting.pfnAddInterface;
  186. pProtocolCb->pfnDeleteInterface = mrcRouting.pfnDeleteInterface;
  187. pProtocolCb->pfnInterfaceStatus = mrcRouting.pfnInterfaceStatus;
  188. pProtocolCb->pfnGetInterfaceInfo = mrcRouting.pfnGetInterfaceInfo;
  189. pProtocolCb->pfnSetInterfaceInfo = mrcRouting.pfnSetInterfaceInfo;
  190. pProtocolCb->pfnGetEventMessage = mrcRouting.pfnGetEventMessage;
  191. pProtocolCb->pfnUpdateRoutes = mrcRouting.pfnUpdateRoutes;
  192. pProtocolCb->pfnConnectClient = mrcRouting.pfnConnectClient;
  193. pProtocolCb->pfnDisconnectClient = mrcRouting.pfnDisconnectClient;
  194. pProtocolCb->pfnGetNeighbors = mrcRouting.pfnGetNeighbors;
  195. pProtocolCb->pfnGetMfeStatus = mrcRouting.pfnGetMfeStatus;
  196. pProtocolCb->pfnMibCreateEntry = mrcRouting.pfnMibCreateEntry;
  197. pProtocolCb->pfnMibDeleteEntry = mrcRouting.pfnMibDeleteEntry;
  198. pProtocolCb->pfnMibGetEntry = mrcRouting.pfnMibGetEntry;
  199. pProtocolCb->pfnMibSetEntry = mrcRouting.pfnMibSetEntry;
  200. pProtocolCb->pfnMibGetFirstEntry = mrcRouting.pfnMibGetFirstEntry;
  201. pProtocolCb->pfnMibGetNextEntry = mrcRouting.pfnMibGetNextEntry;
  202. if(!(pProtocolCb->pfnStartProtocol) or
  203. !(pProtocolCb->pfnStartComplete) or
  204. !(pProtocolCb->pfnStopProtocol) or
  205. !(pProtocolCb->pfnGetGlobalInfo) or
  206. !(pProtocolCb->pfnSetGlobalInfo) or
  207. // !(pProtocolCb->pfnQueryPower) or
  208. // !(pProtocolCb->pfnSetPower) or
  209. !(pProtocolCb->pfnAddInterface) or
  210. !(pProtocolCb->pfnDeleteInterface) or
  211. !(pProtocolCb->pfnInterfaceStatus) or
  212. !(pProtocolCb->pfnGetInterfaceInfo) or
  213. !(pProtocolCb->pfnSetInterfaceInfo) or
  214. !(pProtocolCb->pfnGetEventMessage) or
  215. // !(pProtocolCb->pfnConnectClient) or
  216. // !(pProtocolCb->pfnDisconnectClient) or
  217. // !(pProtocolCb->pfnGetNeighbors) or
  218. // !(pProtocolCb->pfnGetMfeStatus) or
  219. !(pProtocolCb->pfnMibCreateEntry) or
  220. !(pProtocolCb->pfnMibDeleteEntry) or
  221. !(pProtocolCb->pfnMibGetEntry) or
  222. !(pProtocolCb->pfnMibSetEntry) or
  223. !(pProtocolCb->pfnMibGetFirstEntry) or
  224. !(pProtocolCb->pfnMibGetNextEntry))
  225. {
  226. Trace1(ERR,
  227. "LoadProtocol: %S failed to provide atleast one entrypoint\n",
  228. pmpProtocolInfo->wszProtocol);
  229. //
  230. // relenquish CPU to enable DLL threads to finish
  231. //
  232. Sleep(0);
  233. FreeLibrary(hModule);
  234. pProtocolCb->hiHInstance = NULL;
  235. return ERROR_CAN_NOT_COMPLETE;
  236. }
  237. if(mrcRouting.fSupportedFunctionality & RF_DEMAND_UPDATE_ROUTES)
  238. {
  239. if(!pProtocolCb->pfnUpdateRoutes)
  240. {
  241. Trace1(ERR,
  242. "LoadProtocol: %S supports DEMAND but has no entry point",
  243. pmpProtocolInfo->wszProtocol);
  244. //
  245. // relenquish CPU to enable DLL threads to finish
  246. //
  247. Sleep(0);
  248. FreeLibrary(hModule);
  249. pProtocolCb->hiHInstance = NULL;
  250. return ERROR_CAN_NOT_COMPLETE;
  251. }
  252. }
  253. if(mrcRouting.fSupportedFunctionality & RF_MULTICAST)
  254. {
  255. DWORD dwType;
  256. //
  257. // Make sure it has a good ID
  258. //
  259. dwType = TYPE_FROM_PROTO_ID(mrcRouting.dwProtocolId);
  260. if(dwType isnot PROTO_TYPE_MCAST)
  261. {
  262. Trace2(ERR,
  263. "LoadProtocol: %S supports MCAST but has an id of %x",
  264. pmpProtocolInfo->wszProtocol,
  265. mrcRouting.dwProtocolId);
  266. //
  267. // relenquish CPU to enable DLL threads to finish
  268. //
  269. Sleep(0);
  270. FreeLibrary(hModule);
  271. pProtocolCb->hiHInstance = NULL;
  272. return ERROR_CAN_NOT_COMPLETE;
  273. }
  274. }
  275. pProtocolCb->pwszDllName = (PWCHAR)((PBYTE)pProtocolCb + sizeof(PROTO_CB));
  276. CopyMemory(pProtocolCb->pwszDllName,
  277. pmpProtocolInfo->wszDLLName,
  278. (wcslen(pmpProtocolInfo->wszDLLName) * sizeof(WCHAR))) ;
  279. pProtocolCb->pwszDllName[wcslen(pmpProtocolInfo->wszDLLName)] =
  280. UNICODE_NULL;
  281. //
  282. // The memory for display name starts after the DLL name storage
  283. //
  284. pProtocolCb->pwszDisplayName =
  285. &(pProtocolCb->pwszDllName[wcslen(pmpProtocolInfo->wszDLLName) + 1]);
  286. CopyMemory(pProtocolCb->pwszDisplayName,
  287. pmpProtocolInfo->wszProtocol,
  288. (wcslen(pmpProtocolInfo->wszProtocol) * sizeof(WCHAR))) ;
  289. pProtocolCb->pwszDisplayName[wcslen(pmpProtocolInfo->wszProtocol)] =
  290. UNICODE_NULL;
  291. dwResult = (pProtocolCb->pfnStartProtocol)(g_hRoutingProtocolEvent,
  292. &g_sfnDimFunctions,
  293. pvInfo,
  294. ulStructureVersion,
  295. ulStructureSize,
  296. ulStructureCount);
  297. if(dwResult isnot NO_ERROR)
  298. {
  299. Trace2(ERR,
  300. "LoadProtocol: %S failed to start: %d\n",
  301. pmpProtocolInfo->wszProtocol,
  302. dwResult);
  303. //
  304. // relenquish CPU to enable DLL threads to finish
  305. //
  306. Sleep(0);
  307. FreeLibrary(hModule);
  308. return dwResult;
  309. }
  310. Trace1(GLOBAL,
  311. "LoadProtocol: Loaded %S successfully",
  312. pmpProtocolInfo->wszProtocol);
  313. return NO_ERROR;
  314. }
  315. DWORD
  316. HandleRoutingProtocolNotification(
  317. VOID
  318. )
  319. /*++
  320. Routine Description:
  321. For all routing protocol initiated events - this routine calls the
  322. routing protocol to service the event.
  323. Locks:
  324. Arguments:
  325. None
  326. Return Value:
  327. NO_ERROR or some error code
  328. --*/
  329. {
  330. ROUTING_PROTOCOL_EVENTS routprotevent ;
  331. MESSAGE result ;
  332. PPROTO_CB protptr ;
  333. PLIST_ENTRY currentlist ;
  334. TraceEnter("HandleRoutingProtocolNotification");
  335. //
  336. // We take the ICBListLock because we want to enforce the discipline of
  337. // taking the ICB lock before the RoutingProtocol lock if both need to
  338. // be taken.
  339. // This is to avoid deadlocks.
  340. //
  341. //
  342. // TBD: Avoid calling out from our DLL while holding the locks exclusively
  343. //
  344. // *** Exclusion Begin ***
  345. ENTER_WRITER(ICB_LIST);
  346. // *** Exclusion Begin ***
  347. ENTER_WRITER(PROTOCOL_CB_LIST);
  348. currentlist = g_leProtoCbList.Flink;
  349. while(currentlist != &g_leProtoCbList)
  350. {
  351. protptr = CONTAINING_RECORD (currentlist, PROTO_CB, leList) ;
  352. //
  353. // drain all messages for this protocol
  354. //
  355. while ((protptr->pfnGetEventMessage) (&routprotevent, &result) == NO_ERROR)
  356. {
  357. switch (routprotevent)
  358. {
  359. case SAVE_GLOBAL_CONFIG_INFO:
  360. ProcessSaveGlobalConfigInfo() ;
  361. break ;
  362. case SAVE_INTERFACE_CONFIG_INFO:
  363. ProcessSaveInterfaceConfigInfo (result.InterfaceIndex) ;
  364. break ;
  365. case UPDATE_COMPLETE:
  366. ProcessUpdateComplete(protptr,
  367. &result.UpdateCompleteMessage) ;
  368. break ;
  369. case ROUTER_STOPPED:
  370. protptr->posOpState = RTR_STATE_STOPPED ;
  371. break ;
  372. default:
  373. // no event raised for this protocol.
  374. break;
  375. }
  376. }
  377. //
  378. // Move to the next item before freeing this one. The most common
  379. // error in the book
  380. //
  381. currentlist = currentlist->Flink;
  382. if(protptr->posOpState is RTR_STATE_STOPPED)
  383. {
  384. //
  385. // Something happened that caused the stopping of the protocol
  386. //
  387. RemoveProtocolFromAllInterfaces(protptr);
  388. //
  389. // relenquish CPU to enable DLL threads to finish
  390. //
  391. Sleep(0);
  392. FreeLibrary(protptr->hiHInstance);
  393. //
  394. // Move to the next entry before freeing this entry
  395. //
  396. RemoveEntryList(&(protptr->leList));
  397. HeapFree(IPRouterHeap,
  398. 0,
  399. protptr);
  400. TotalRoutingProtocols--;
  401. }
  402. }
  403. // *** Exclusion End ***
  404. EXIT_LOCK(PROTOCOL_CB_LIST);
  405. // *** Exclusion End ***
  406. EXIT_LOCK(ICB_LIST);
  407. return NO_ERROR;
  408. }
  409. VOID
  410. NotifyRoutingProtocolsToStop(
  411. VOID
  412. )
  413. /*++
  414. Routine Description:
  415. Notifies routing protocols to stop
  416. Locks:
  417. Must be called with the ICB_LIST lock held as READER and PROTOCOL_CB_LIST
  418. held as WRITER
  419. Arguments:
  420. None
  421. Return Value:
  422. None
  423. --*/
  424. {
  425. PLIST_ENTRY currentlist ;
  426. PPROTO_CB protptr ;
  427. DWORD dwResult;
  428. TraceEnter("NotifyRoutingProtocolsToStop");
  429. //
  430. // Go thru the routing protocol list and call stopprotocol() for each
  431. // of them
  432. //
  433. currentlist = g_leProtoCbList.Flink;
  434. while(currentlist isnot &g_leProtoCbList)
  435. {
  436. protptr = CONTAINING_RECORD (currentlist, PROTO_CB, leList) ;
  437. if((protptr->posOpState is RTR_STATE_STOPPING) or
  438. (protptr->posOpState is RTR_STATE_STOPPED))
  439. {
  440. //
  441. // If its stopped or stopping, we dont tell it again
  442. //
  443. continue;
  444. }
  445. dwResult = StopRoutingProtocol(protptr);
  446. currentlist = currentlist->Flink;
  447. if(dwResult is NO_ERROR)
  448. {
  449. //
  450. // The routing protocol stopped synchronously and all references
  451. // to it in the interfaces have been removed
  452. //
  453. //
  454. // relenquish CPU to enable DLL threads to finish
  455. //
  456. Sleep(0);
  457. FreeLibrary(protptr->hiHInstance);
  458. RemoveEntryList(&(protptr->leList));
  459. HeapFree(IPRouterHeap,
  460. 0,
  461. protptr);
  462. TotalRoutingProtocols--;
  463. }
  464. }
  465. }
  466. DWORD
  467. StopRoutingProtocol(
  468. PPROTO_CB pProtocolCB
  469. )
  470. /*++
  471. Routine Description:
  472. Stops a routing protocol
  473. Arguments:
  474. pProtocolCB The CB of the routing protocol to stop
  475. Locks:
  476. Return Value:
  477. NO_ERROR If the routing protocol stopped synchronously
  478. ERROR_PROTOCOL_STOP_PENDING If the protocol is stopping asynchronously
  479. other WIN32 code
  480. --*/
  481. {
  482. DWORD dwResult;
  483. TraceEnter("StopRoutingProtocol");
  484. Trace1(GLOBAL,
  485. "StopRoutingProtocol: Stopping %S",
  486. pProtocolCB->pwszDllName);
  487. RemoveProtocolFromAllInterfaces(pProtocolCB);
  488. dwResult = (pProtocolCB->pfnStopProtocol)();
  489. if(dwResult is ERROR_PROTOCOL_STOP_PENDING)
  490. {
  491. //
  492. // If the protocol stops asynchronously then we dont do any clean up
  493. // right now. We it signals us that it has stopped, we will do the
  494. // necessary clean up
  495. //
  496. Trace1(GLOBAL,
  497. "StopRoutingProtocol: %S will stop asynchronously",
  498. pProtocolCB->pwszDllName);
  499. pProtocolCB->posOpState = RTR_STATE_STOPPING;
  500. }
  501. else
  502. {
  503. if(dwResult is NO_ERROR)
  504. {
  505. //
  506. // Great. So it stopped synchronously.
  507. //
  508. Trace1(GLOBAL,
  509. "StopRoutingProtocol: %S stopped synchronously",
  510. pProtocolCB->pwszDllName);
  511. pProtocolCB->posOpState = RTR_STATE_STOPPED ;
  512. }
  513. else
  514. {
  515. //
  516. // This is not good. Routing Protocol couldnt stop
  517. //
  518. Trace2(ERR,
  519. "StopRoutingProtocol: %S returned error %d on calling StopProtocol().",
  520. pProtocolCB->pwszDllName,
  521. dwResult);
  522. }
  523. }
  524. return dwResult;
  525. }
  526. VOID
  527. RemoveProtocolFromAllInterfaces(
  528. PPROTO_CB pProtocolCB
  529. )
  530. /*++
  531. Routine Description:
  532. Each interface keeps a list of the protocols that are running on it.
  533. This removes the given protocol from all the interfaces list
  534. Locks:
  535. Arguments:
  536. pProtocolCB The CB of the routing protocol to remove
  537. Return Value:
  538. None
  539. --*/
  540. {
  541. PLIST_ENTRY pleIfNode,pleProtoNode;
  542. PICB pIcb;
  543. PIF_PROTO pProto;
  544. TraceEnter("RemoveProtocolFromAllInterfaces");
  545. Trace1(GLOBAL,
  546. "RemoveProtocolFromAllInterfaces: Removing %S from all interfaces",
  547. pProtocolCB->pwszDllName);
  548. //
  549. // For each interface, we go through the list of protocols it is active
  550. // over. If the interface had been active over this protocol, we remove the
  551. // entry from the i/f's list
  552. //
  553. for(pleIfNode = ICBList.Flink;
  554. pleIfNode isnot &ICBList;
  555. pleIfNode = pleIfNode->Flink)
  556. {
  557. pIcb = CONTAINING_RECORD(pleIfNode, ICB, leIfLink);
  558. pleProtoNode = pIcb->leProtocolList.Flink;
  559. while(pleProtoNode isnot &(pIcb->leProtocolList))
  560. {
  561. pProto = CONTAINING_RECORD(pleProtoNode,IF_PROTO,leIfProtoLink);
  562. pleProtoNode = pleProtoNode->Flink;
  563. if(pProto->pActiveProto is pProtocolCB)
  564. {
  565. Trace2(GLOBAL,
  566. "RemoveProtocolFromAllInterfaces: Removing %S from %S",
  567. pProtocolCB->pwszDllName,
  568. pIcb->pwszName);
  569. //
  570. // call the delete interface entry point
  571. //
  572. (pProto->pActiveProto->pfnDeleteInterface) (pIcb->dwIfIndex);
  573. RemoveEntryList(&(pProto->leIfProtoLink));
  574. break;
  575. }
  576. }
  577. }
  578. }
  579. BOOL
  580. AllRoutingProtocolsStopped(
  581. VOID
  582. )
  583. /*++
  584. Routine Description:
  585. Walks thru all routing protocols to see if all have operational state
  586. of STOPPED.
  587. Locks:
  588. Arguments:
  589. None
  590. Return Value:
  591. TRUE if all stopped, otherwise FALSE
  592. --*/
  593. {
  594. DWORD routprotevent ;
  595. PPROTO_CB protptr ;
  596. PLIST_ENTRY currentlist ;
  597. TraceEnter("AllRoutingProtocolsStopped");
  598. for (currentlist = g_leProtoCbList.Flink;
  599. currentlist != &g_leProtoCbList;
  600. currentlist = currentlist->Flink)
  601. {
  602. protptr = CONTAINING_RECORD (currentlist, PROTO_CB, leList) ;
  603. if (protptr->posOpState != RTR_STATE_STOPPED)
  604. {
  605. Trace1(GLOBAL,
  606. "AllRoutingProtocolsStopped: %S has not stopped as yet",
  607. protptr->pwszDllName);
  608. return FALSE;
  609. }
  610. }
  611. return TRUE ;
  612. }
  613. DWORD
  614. ProcessUpdateComplete (
  615. PPROTO_CB proutprot,
  616. UPDATE_COMPLETE_MESSAGE *updateresult
  617. )
  618. {
  619. PLIST_ENTRY currentlist ;
  620. LPHANDLE hDIMEventToSignal = NULL;
  621. PICB pIcb ;
  622. UpdateResultList *pupdateresultlist ;
  623. TraceEnter("ProcessUpdateComplete");
  624. //
  625. // If update is successful convert the protocol's routes to static routes.
  626. //
  627. if (updateresult->UpdateStatus == NO_ERROR)
  628. {
  629. ConvertRoutesToAutoStatic(proutprot->dwProtocolId,
  630. updateresult->InterfaceIndex);
  631. }
  632. //
  633. // Figure out which event to signal and where to queue the event
  634. //
  635. for (currentlist = ICBList.Flink;
  636. currentlist != &ICBList;
  637. currentlist = currentlist->Flink)
  638. {
  639. pIcb = CONTAINING_RECORD (currentlist, ICB, leIfLink);
  640. if (pIcb->dwIfIndex is updateresult->InterfaceIndex)
  641. {
  642. hDIMEventToSignal = pIcb->hDIMNotificationEvent;
  643. pIcb->hDIMNotificationEvent = NULL;
  644. if(hDIMEventToSignal is NULL)
  645. {
  646. Trace0(ERR, "ProcessUpdateComplete: No DIM event found in ICB - ERROR");
  647. return ERROR_CAN_NOT_COMPLETE;
  648. }
  649. //
  650. // Queue the update event
  651. //
  652. pupdateresultlist = HeapAlloc(IPRouterHeap,
  653. HEAP_ZERO_MEMORY,
  654. sizeof(UpdateResultList));
  655. if(pupdateresultlist is NULL)
  656. {
  657. Trace1(ERR,
  658. "ProcessUpdateComplete: Error allocating %d bytes",
  659. sizeof(UpdateResultList));
  660. SetEvent(hDIMEventToSignal);
  661. CloseHandle(hDIMEventToSignal);
  662. return ERROR_NOT_ENOUGH_MEMORY;
  663. }
  664. pupdateresultlist->URL_UpdateStatus = updateresult->UpdateStatus;
  665. InsertTailList(&pIcb->lePendingResultList,
  666. &pupdateresultlist->URL_List) ;
  667. //
  668. // Save the routes in the registry
  669. //
  670. ProcessSaveInterfaceConfigInfo(pIcb->dwIfIndex);
  671. Trace0(GLOBAL,
  672. "ProcessUpdateComplete: Notifying DIM of update route completion");
  673. if(!SetEvent(hDIMEventToSignal))
  674. {
  675. Trace2(ERR,
  676. "ProcessUpdateComplete: Error %d setting event for notifying completion of update routes for %S",
  677. proutprot->pwszDllName,
  678. GetLastError());
  679. CloseHandle(hDIMEventToSignal);
  680. return ERROR_CAN_NOT_COMPLETE;
  681. }
  682. CloseHandle(hDIMEventToSignal);
  683. return NO_ERROR;
  684. }
  685. }
  686. //
  687. // If you reach till here you didnt find the ICB
  688. //
  689. Trace1(ERR,
  690. "ProcessUpdateComplete: Couldnt find the ICB for interface %d",
  691. updateresult->InterfaceIndex);
  692. return ERROR_INVALID_PARAMETER;
  693. }
  694. DWORD
  695. ProcessSaveInterfaceConfigInfo(
  696. DWORD dwInterfaceindex
  697. )
  698. {
  699. PICB pIcb ;
  700. DWORD infosize;
  701. PVOID pinfobuffer ;
  702. PLIST_ENTRY currentlist ;
  703. BOOL bFound = FALSE;
  704. DWORD dwNumInFilters, dwNumOutFilters;
  705. TraceEnter("ProcessSaveInterfaceConfigInfo");
  706. //
  707. // find the if.
  708. //
  709. for (currentlist = ICBList.Flink;
  710. currentlist != &ICBList;
  711. currentlist = currentlist->Flink)
  712. {
  713. pIcb = CONTAINING_RECORD (currentlist, ICB, leIfLink);
  714. if (pIcb->dwIfIndex is dwInterfaceindex)
  715. {
  716. bFound = TRUE;
  717. break;
  718. }
  719. }
  720. if(!bFound)
  721. {
  722. Trace1(ERR,
  723. "ProcessSaveInterfaceConfigInfo: Couldnt find ICB for interface %d",
  724. dwInterfaceindex);
  725. return ERROR_INVALID_PARAMETER;
  726. }
  727. //
  728. // Interface info
  729. //
  730. infosize = GetSizeOfInterfaceConfig(pIcb);
  731. pinfobuffer = HeapAlloc(IPRouterHeap,
  732. HEAP_ZERO_MEMORY,
  733. infosize);
  734. if(pinfobuffer is NULL)
  735. {
  736. Trace0(
  737. ERR, "ProcessSaveInterfaceConfigInfo: failed to allocate buffer");
  738. return ERROR_NOT_ENOUGH_MEMORY;
  739. }
  740. GetInterfaceConfiguration(pIcb,
  741. pinfobuffer,
  742. infosize);
  743. EXIT_LOCK(PROTOCOL_CB_LIST);
  744. EXIT_LOCK(ICB_LIST);
  745. SaveInterfaceInfo(pIcb->hDIMHandle,
  746. PID_IP,
  747. pinfobuffer,
  748. infosize );
  749. ENTER_WRITER(ICB_LIST);
  750. ENTER_WRITER(PROTOCOL_CB_LIST);
  751. HeapFree (IPRouterHeap, 0, pinfobuffer) ;
  752. return NO_ERROR;
  753. }
  754. DWORD
  755. ProcessSaveGlobalConfigInfo(
  756. VOID
  757. )
  758. {
  759. PRTR_INFO_BLOCK_HEADER pInfoHdrAndBuffer;
  760. DWORD dwSize,dwResult;
  761. TraceEnter("ProcessSaveGlobalConfigInfo");
  762. dwSize = GetSizeOfGlobalInfo();
  763. pInfoHdrAndBuffer = HeapAlloc(IPRouterHeap,
  764. HEAP_ZERO_MEMORY,
  765. dwSize);
  766. if(pInfoHdrAndBuffer is NULL)
  767. {
  768. Trace1(ERR,
  769. "ProcessSaveGlobalConfigInfo: Error allocating %d bytes",
  770. dwSize);
  771. return ERROR_NOT_ENOUGH_MEMORY;
  772. }
  773. dwResult = GetGlobalConfiguration(pInfoHdrAndBuffer,
  774. dwSize);
  775. if(dwResult isnot NO_ERROR)
  776. {
  777. Trace1(ERR,
  778. "ProcessSaveGlobalConfigInfo: Error %d getting global configuration",
  779. dwResult);
  780. }
  781. else
  782. {
  783. EXIT_LOCK(PROTOCOL_CB_LIST);
  784. EXIT_LOCK(ICB_LIST);
  785. dwResult = SaveGlobalInfo(PID_IP,
  786. (PVOID)pInfoHdrAndBuffer,
  787. dwSize);
  788. ENTER_WRITER(ICB_LIST);
  789. ENTER_WRITER(PROTOCOL_CB_LIST);
  790. if(dwResult isnot NO_ERROR)
  791. {
  792. Trace1(ERR,
  793. "ProcessSaveGlobalConfigInfo: Error %d saving global information",
  794. dwResult);
  795. }
  796. }
  797. return dwResult;
  798. }