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.

4181 lines
117 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ip\rtrmgr\iprtrmgr.c
  5. Abstract:
  6. The interface to DIM/DDM
  7. Revision History:
  8. Gurdeep Singh Pall 6/8/95 Created
  9. --*/
  10. #include "allinc.h"
  11. #include "exdeclar.h"
  12. BOOL
  13. InitIPRtrMgrDLL(
  14. HANDLE hInst,
  15. DWORD dwCallReason,
  16. PVOID pReserved
  17. )
  18. {
  19. switch (dwCallReason)
  20. {
  21. case DLL_PROCESS_ATTACH:
  22. {
  23. //
  24. // Init the state
  25. //
  26. InitializeCriticalSection(&RouterStateLock);
  27. InitializeCriticalSection(&g_csFwdState);
  28. RouterState.IRS_RefCount = 0;
  29. RouterState.IRS_State = RTR_STATE_STOPPED;
  30. //
  31. // We are not interested in THREAD_XXX reasons
  32. //
  33. DisableThreadLibraryCalls(hInst);
  34. //
  35. // Setup our info routines
  36. //
  37. g_rgicInfoCb[0].pfnGetInterfaceInfo = NULL;
  38. g_rgicInfoCb[0].pfnSetInterfaceInfo = SetRouteInfo;
  39. g_rgicInfoCb[0].pfnBindInterface = NULL;
  40. g_rgicInfoCb[0].pfnGetGlobalInfo = NULL;
  41. g_rgicInfoCb[0].pszInfoName = "Route";
  42. g_rgicInfoCb[1].pfnGetInterfaceInfo = NULL;
  43. g_rgicInfoCb[1].pfnSetInterfaceInfo = SetFilterInterfaceInfo;
  44. g_rgicInfoCb[1].pfnBindInterface = BindFilterInterface;
  45. g_rgicInfoCb[1].pfnGetGlobalInfo = NULL;
  46. g_rgicInfoCb[1].pszInfoName = "Filter";
  47. g_rgicInfoCb[2].pfnGetInterfaceInfo = NULL;
  48. g_rgicInfoCb[2].pfnSetInterfaceInfo = SetDemandDialFilters;
  49. g_rgicInfoCb[2].pfnBindInterface = NULL;
  50. g_rgicInfoCb[2].pfnGetGlobalInfo = NULL;
  51. g_rgicInfoCb[2].pszInfoName = "DemandFilter";
  52. #ifdef KSL_IPINIP
  53. g_rgicInfoCb[3].pfnGetInterfaceInfo = NULL;
  54. g_rgicInfoCb[3].pfnSetInterfaceInfo = SetIpInIpInfo;
  55. g_rgicInfoCb[3].pfnBindInterface = NULL;
  56. g_rgicInfoCb[3].pfnGetGlobalInfo = NULL;
  57. g_rgicInfoCb[3].pszInfoName = "IpIpInfo";
  58. g_rgicInfoCb[4].pfnGetInterfaceInfo = GetBoundaryInfo;
  59. g_rgicInfoCb[4].pfnSetInterfaceInfo = SetBoundaryInfo;
  60. g_rgicInfoCb[4].pfnBindInterface = BindBoundaryInterface;
  61. g_rgicInfoCb[4].pfnGetGlobalInfo = GetScopeInfo;
  62. g_rgicInfoCb[4].pszInfoName = "MulticastBoundary";
  63. g_rgicInfoCb[5].pfnGetInterfaceInfo = GetMcastLimitInfo;
  64. g_rgicInfoCb[5].pfnSetInterfaceInfo = SetMcastLimitInfo;
  65. g_rgicInfoCb[5].pfnBindInterface = NULL;
  66. g_rgicInfoCb[5].pfnGetGlobalInfo = NULL;
  67. g_rgicInfoCb[5].pszInfoName = "MulticastLimit";
  68. #endif //KSL_IPINIP
  69. g_rgicInfoCb[3].pfnGetInterfaceInfo = GetBoundaryInfo;
  70. g_rgicInfoCb[3].pfnSetInterfaceInfo = SetBoundaryInfo;
  71. g_rgicInfoCb[3].pfnBindInterface = BindBoundaryInterface;
  72. g_rgicInfoCb[3].pfnGetGlobalInfo = GetScopeInfo;
  73. g_rgicInfoCb[3].pszInfoName = "MulticastBoundary";
  74. g_rgicInfoCb[4].pfnGetInterfaceInfo = GetMcastLimitInfo;
  75. g_rgicInfoCb[4].pfnSetInterfaceInfo = SetMcastLimitInfo;
  76. g_rgicInfoCb[4].pfnBindInterface = NULL;
  77. g_rgicInfoCb[4].pfnGetGlobalInfo = NULL;
  78. g_rgicInfoCb[4].pszInfoName = "MulticastLimit";
  79. break ;
  80. }
  81. case DLL_PROCESS_DETACH:
  82. {
  83. DeleteCriticalSection(&RouterStateLock);
  84. DeleteCriticalSection(&g_csFwdState);
  85. break;
  86. }
  87. case DLL_THREAD_ATTACH:
  88. case DLL_THREAD_DETACH:
  89. {
  90. //
  91. // not of interest.
  92. //
  93. break;
  94. }
  95. }
  96. return TRUE;
  97. }
  98. const static WCHAR pszIpStackService[] = L"TcpIp";
  99. DWORD
  100. VerifyOrStartIpStack(
  101. VOID
  102. )
  103. /*++
  104. Routine Description
  105. Verifies that the ip stack is started and attempts to start the stack
  106. if not.
  107. Locks
  108. None - called at init time
  109. Arguments
  110. None
  111. Return Value
  112. NO_ERROR
  113. ERROR_CAN_NOT_COMPLETE
  114. --*/
  115. {
  116. SC_HANDLE hSC = NULL, hStack = NULL;
  117. SERVICE_STATUS Status;
  118. DWORD dwErr = NO_ERROR;
  119. TraceEnter("VerifyOrStartIpStack");
  120. __try
  121. {
  122. //
  123. // Get a handle to the service controller
  124. //
  125. if ((hSC = OpenSCManager (NULL, NULL, GENERIC_READ | GENERIC_EXECUTE)) == NULL)
  126. {
  127. dwErr = GetLastError();
  128. __leave;
  129. }
  130. //
  131. // Get a handle to the ipx stack service
  132. //
  133. hStack = OpenServiceW (hSC,
  134. pszIpStackService,
  135. SERVICE_START | SERVICE_QUERY_STATUS);
  136. if (!hStack)
  137. {
  138. dwErr = GetLastError();
  139. __leave;
  140. }
  141. //
  142. // Find out if the service is running
  143. //
  144. if (QueryServiceStatus (hStack, &Status) == 0)
  145. {
  146. dwErr = GetLastError();
  147. __leave;
  148. }
  149. //
  150. // See if the service is running
  151. //
  152. if (Status.dwCurrentState != SERVICE_RUNNING)
  153. {
  154. //
  155. // If it's stopped, start it
  156. //
  157. if (Status.dwCurrentState == SERVICE_STOPPED)
  158. {
  159. if (StartService (hStack, 0, NULL) == 0)
  160. {
  161. dwErr = GetLastError();
  162. __leave;
  163. }
  164. //
  165. // Make sure that the service started. StartService is not supposed
  166. // to return until the driver is started.
  167. //
  168. if (QueryServiceStatus (hStack, &Status) == 0)
  169. {
  170. dwErr = GetLastError();
  171. __leave;
  172. }
  173. if (Status.dwCurrentState != SERVICE_RUNNING)
  174. {
  175. dwErr = ERROR_CAN_NOT_COMPLETE;
  176. __leave;
  177. }
  178. }
  179. else
  180. {
  181. //
  182. // If it's not stopped, don't worry about it.
  183. //
  184. dwErr = NO_ERROR;
  185. __leave;
  186. }
  187. }
  188. }
  189. __finally
  190. {
  191. if (hSC)
  192. {
  193. CloseServiceHandle (hSC);
  194. }
  195. if (hStack)
  196. {
  197. CloseServiceHandle (hStack);
  198. }
  199. }
  200. return dwErr;
  201. }
  202. DWORD
  203. StartRouter(
  204. IN OUT DIM_ROUTER_INTERFACE *pDimRouterIf,
  205. IN BOOL bLanOnlyMode,
  206. IN PVOID pvGlobalInfo
  207. )
  208. /*++
  209. Routine Description
  210. This function is called by DIM to at startup. WE initialize tracing
  211. and event logging.
  212. Call InitRouter() to do the main stuff and then pass pointers to
  213. the rest of our functions back to DIM
  214. Locks
  215. None - called at init time
  216. Arguments
  217. pDimRouterIf structure that holds all the function pointers
  218. bLanOnlyMode True if not a WAN router
  219. pvGlobalInfo Pointer to our global info
  220. Return Value
  221. None
  222. --*/
  223. {
  224. DWORD dwResult, i;
  225. WORD wVersion = MAKEWORD(2,0); //Winsock version 2.0 minimum
  226. WSADATA wsaData;
  227. OSVERSIONINFOEX VersionInfo;
  228. //
  229. // Initialize Trace and logging
  230. //
  231. TraceHandle = TraceRegister("IPRouterManager");
  232. g_hLogHandle = RouterLogRegister("IPRouterManager");
  233. TraceEnter("StartRouter") ;
  234. if(pvGlobalInfo is NULL)
  235. {
  236. //
  237. // Sometimes setup screws up
  238. //
  239. LogErr0(NO_GLOBAL_INFO,
  240. ERROR_NO_DATA);
  241. return ERROR_INVALID_PARAMETER;
  242. }
  243. //
  244. // We need to make sure that the stack is started before westart.
  245. //
  246. if ( VerifyOrStartIpStack() isnot NO_ERROR )
  247. {
  248. Trace0(ERR, "StartRouter: Unable to start ip stack." );
  249. return ERROR_SERVICE_DEPENDENCY_FAIL;
  250. }
  251. g_hOwnModule = LoadLibraryEx("IPRTRMGR.DLL",
  252. NULL,
  253. 0);
  254. if(g_hOwnModule is NULL)
  255. {
  256. dwResult = GetLastError();
  257. Trace1(ERR,
  258. "StartRouter: Unable to load itself. %d",
  259. dwResult);
  260. return dwResult;
  261. }
  262. RouterState.IRS_State = RTR_STATE_RUNNING ;
  263. g_bUninitServer = TRUE;
  264. g_dwNextICBSeqNumberCounter = INITIAL_SEQUENCE_NUMBER;
  265. if(WSAStartup(wVersion,&wsaData) isnot NO_ERROR)
  266. {
  267. Trace1(ERR,
  268. "StartRouter: WSAStartup failed. Error %d",
  269. WSAGetLastError());
  270. TraceDeregister(TraceHandle);
  271. return ERROR_CAN_NOT_COMPLETE;
  272. }
  273. //
  274. // Read only variable, no locks protect this
  275. //
  276. RouterRoleLanOnly = bLanOnlyMode ;
  277. //
  278. // Do we have forwarding enabled?
  279. //
  280. EnterCriticalSection(&g_csFwdState);
  281. g_bEnableFwdRequest = TRUE;
  282. g_bFwdEnabled = FALSE;
  283. g_bSetRoutesToStack = TRUE;
  284. g_bEnableNetbtBcastFrowarding = FALSE;
  285. //
  286. // Are we running workstation?
  287. //
  288. ZeroMemory(&VersionInfo,
  289. sizeof(VersionInfo));
  290. VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
  291. if(GetVersionEx((POSVERSIONINFO)&VersionInfo))
  292. {
  293. if(VersionInfo.wProductType is VER_NT_WORKSTATION)
  294. {
  295. g_bSetRoutesToStack = FALSE;
  296. }
  297. }
  298. else
  299. {
  300. Trace1(ERR,
  301. "StartRouter: GetVersionEx failed with %d\n",
  302. GetLastError());
  303. }
  304. Trace1(GLOBAL,
  305. "\n\nStartRouter: Machine will run as %s\n\n",
  306. g_bSetRoutesToStack?"router":"non-router");
  307. if(!RouterRoleLanOnly)
  308. {
  309. HKEY hkIpcpParam;
  310. dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  311. L"System\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\Ip",
  312. 0,
  313. KEY_READ | KEY_WRITE,
  314. &hkIpcpParam);
  315. if(dwResult is NO_ERROR)
  316. {
  317. DWORD dwEnable, dwSize;
  318. dwSize = sizeof(dwEnable);
  319. dwResult = RegQueryValueExW(hkIpcpParam,
  320. L"AllowNetworkAccess",
  321. NULL,
  322. NULL,
  323. (PBYTE)&dwEnable,
  324. &dwSize);
  325. if(dwResult is NO_ERROR)
  326. {
  327. if(dwEnable is 0)
  328. {
  329. g_bEnableFwdRequest = FALSE;
  330. }
  331. }
  332. //
  333. // NETBT broadcast forwarding was enabled as an option
  334. // to allow simple RAS server configurations to perform
  335. // name resolution in the absence of WINS/DNS server
  336. // configuration.
  337. // This in turn was necessiated by the removal of NBF from the
  338. // system (NT SERVER). When NBF was present this functionality
  339. // was performed by the RAS Netbios gateway.
  340. //
  341. // NETBT broadcast forwarding is enabled only if
  342. // 1. Router is not in LanOnly Mode
  343. // 2. NETBT bcast fwd'g has been explicity turned on.
  344. //
  345. dwResult = RegQueryValueExW(hkIpcpParam,
  346. L"EnableNetbtBcastFwd",
  347. NULL,
  348. NULL,
  349. (PBYTE)&dwEnable,
  350. &dwSize);
  351. if(dwResult isnot NO_ERROR)
  352. {
  353. //
  354. // It is possible the value is not present
  355. // esp. if this is the first time RRAS is being
  356. // run or if the key was manually deleted
  357. //
  358. // Assume a default value of 1 (enabled) and set
  359. // the value in the registry
  360. //
  361. dwEnable = 1;
  362. dwResult = RegSetValueExW(
  363. hkIpcpParam,
  364. L"EnableNetbtBcastFwd",
  365. 0,
  366. REG_DWORD,
  367. (PBYTE) &dwEnable,
  368. sizeof( DWORD )
  369. );
  370. if(dwResult isnot NO_ERROR)
  371. {
  372. Trace1(
  373. ERR,
  374. "error %d setting EnableNetbtBcastFwd value",
  375. dwResult
  376. );
  377. }
  378. }
  379. Trace1(
  380. INIT, "Netbt Enable mode is %d", dwEnable
  381. );
  382. if(dwEnable isnot 0)
  383. {
  384. g_bEnableNetbtBcastFrowarding = TRUE;
  385. }
  386. EnableNetbtBcastForwarding(dwEnable);
  387. RegCloseKey(hkIpcpParam);
  388. }
  389. }
  390. LeaveCriticalSection(&g_csFwdState);
  391. //
  392. // Keep the entry points in a global structure.
  393. // Saves the overhead of copying into a structure everytime a protocol
  394. // has to be loaded
  395. //
  396. g_sfnDimFunctions.DemandDialRequest = DemandDialRequest;
  397. g_sfnDimFunctions.SetInterfaceReceiveType = SetInterfaceReceiveType;
  398. g_sfnDimFunctions.ValidateRoute = ValidateRouteForProtocolEx;
  399. g_sfnDimFunctions.MIBEntryGet = RtrMgrMIBEntryGet;
  400. g_sfnDimFunctions.MIBEntryGetNext = RtrMgrMIBEntryGetNext;
  401. g_sfnDimFunctions.MIBEntryGetFirst = RtrMgrMIBEntryGetFirst;
  402. g_sfnDimFunctions.MIBEntrySet = RtrMgrMIBEntrySet;
  403. g_sfnDimFunctions.MIBEntryCreate = RtrMgrMIBEntryCreate;
  404. g_sfnDimFunctions.MIBEntryDelete = RtrMgrMIBEntryDelete;
  405. g_sfnDimFunctions.GetRouterId = GetRouterId;
  406. g_sfnDimFunctions.HasMulticastBoundary = RmHasBoundary;
  407. Trace1(GLOBAL,
  408. "StartRouter: LAN MODE = %d",
  409. RouterRoleLanOnly) ;
  410. //
  411. // Do all the necessary initializations for the router
  412. //
  413. if((dwResult = InitRouter(pvGlobalInfo)) isnot NO_ERROR)
  414. {
  415. Trace1(ERR,
  416. "StartRouter: InitRouter failed %d", dwResult) ;
  417. RouterManagerCleanup();
  418. RouterState.IRS_State = RTR_STATE_STOPPED;
  419. return dwResult ;
  420. }
  421. //
  422. // fill in information required by DIM
  423. //
  424. pDimRouterIf->dwProtocolId = PID_IP;
  425. //
  426. // Set IP Router Manager entrypoints
  427. //
  428. pDimRouterIf->StopRouter = StopRouter;
  429. pDimRouterIf->AddInterface = AddInterface;
  430. pDimRouterIf->DeleteInterface = DeleteInterface;
  431. pDimRouterIf->GetInterfaceInfo = GetInterfaceInfo;
  432. pDimRouterIf->SetInterfaceInfo = SetInterfaceInfo;
  433. pDimRouterIf->InterfaceNotReachable = InterfaceNotReachable;
  434. pDimRouterIf->InterfaceReachable = InterfaceReachable;
  435. pDimRouterIf->InterfaceConnected = InterfaceConnected;
  436. pDimRouterIf->UpdateRoutes = UpdateRoutes;
  437. pDimRouterIf->GetUpdateRoutesResult = GetUpdateRoutesResult;
  438. pDimRouterIf->SetGlobalInfo = SetGlobalInfo;
  439. pDimRouterIf->GetGlobalInfo = GetGlobalInfo;
  440. pDimRouterIf->MIBEntryCreate = RtrMgrMIBEntryCreate;
  441. pDimRouterIf->MIBEntryDelete = RtrMgrMIBEntryDelete;
  442. pDimRouterIf->MIBEntryGet = RtrMgrMIBEntryGet;
  443. pDimRouterIf->MIBEntryGetFirst = RtrMgrMIBEntryGetFirst;
  444. pDimRouterIf->MIBEntryGetNext = RtrMgrMIBEntryGetNext;
  445. pDimRouterIf->MIBEntrySet = RtrMgrMIBEntrySet;
  446. pDimRouterIf->SetRasAdvEnable = SetRasAdvEnable;
  447. pDimRouterIf->RouterBootComplete = RouterBootComplete;
  448. //
  449. // Get DIM entrypoints
  450. //
  451. ConnectInterface = pDimRouterIf->ConnectInterface ;
  452. DisconnectInterface = pDimRouterIf->DisconnectInterface ;
  453. SaveInterfaceInfo = pDimRouterIf->SaveInterfaceInfo ;
  454. RestoreInterfaceInfo = pDimRouterIf->RestoreInterfaceInfo ;
  455. RouterStopped = pDimRouterIf->RouterStopped ;
  456. SaveGlobalInfo = pDimRouterIf->SaveGlobalInfo;
  457. EnableInterfaceWithDIM = pDimRouterIf->InterfaceEnabled;
  458. LoadStringA(g_hOwnModule,
  459. LOOPBACK_STRID,
  460. g_rgcLoopbackString,
  461. sizeof(g_rgcLoopbackString));
  462. LoadStringA(g_hOwnModule,
  463. INTERNAL_STRID,
  464. g_rgcInternalString,
  465. sizeof(g_rgcInternalString));
  466. LoadStringA(g_hOwnModule,
  467. WAN_STRID,
  468. g_rgcWanString,
  469. sizeof(g_rgcWanString));
  470. #ifdef KSL_IPINIP
  471. LoadStringA(g_hOwnModule,
  472. IPIP_STRID,
  473. g_rgcIpIpString,
  474. sizeof(g_rgcIpIpString));
  475. #endif //KSL_IPINIP
  476. return NO_ERROR;
  477. }
  478. DWORD
  479. RouterBootComplete(
  480. VOID
  481. )
  482. /*++
  483. Routine Description
  484. This function is called by DIM after all the interfaces in the registry
  485. have been loaded with the router manager.
  486. Locks
  487. None - called at init time
  488. Arguments
  489. None.
  490. Return Value
  491. NO_ERROR
  492. --*/
  493. {
  494. DWORD dwErr, dwSize, dwInfoSize, dwLastIndex;
  495. PVOID pvBuffer;
  496. Trace0(ERR,
  497. "\n-----------------------------------------------------------\n\n");
  498. //
  499. // Call DIM to save the interface info
  500. //
  501. dwLastIndex = 0;
  502. dwInfoSize = 0;
  503. pvBuffer = NULL;
  504. ENTER_WRITER(ICB_LIST);
  505. // Tell all protocols that start is complete
  506. ENTER_READER(PROTOCOL_CB_LIST);
  507. {
  508. PLIST_ENTRY pleNode;
  509. PPROTO_CB pProtocolCb;
  510. for(pleNode = g_leProtoCbList.Flink;
  511. pleNode != &g_leProtoCbList;
  512. pleNode = pleNode->Flink)
  513. {
  514. pProtocolCb = CONTAINING_RECORD(pleNode,
  515. PROTO_CB,
  516. leList) ;
  517. if (pProtocolCb->pfnStartComplete)
  518. {
  519. dwErr = (pProtocolCb->pfnStartComplete)();
  520. }
  521. }
  522. }
  523. EXIT_LOCK(PROTOCOL_CB_LIST);
  524. if(IsListEmpty(&ICBList))
  525. {
  526. EXIT_LOCK(ICB_LIST);
  527. return NO_ERROR;
  528. }
  529. #if 0
  530. while(TRUE)
  531. {
  532. PICB pIcb;
  533. PLIST_ENTRY pleNode;
  534. HANDLE hDimHandle;
  535. //
  536. // Walk the list finding the first ICB that has an index larger than
  537. // the last index we processed
  538. //
  539. pIcb = NULL;
  540. for(pleNode = ICBList.Flink;
  541. pleNode != &ICBList;
  542. pleNode = pleNode->Flink)
  543. {
  544. PICB pTempIcb;
  545. pTempIcb = CONTAINING_RECORD(pleNode,
  546. ICB,
  547. leIfLink);
  548. if((pTempIcb->ritType is ROUTER_IF_TYPE_CLIENT) or
  549. (pTempIcb->ritType is ROUTER_IF_TYPE_DIALOUT) or
  550. (pTempIcb->dwAdminState isnot IF_ADMIN_STATUS_UP))
  551. {
  552. continue;
  553. }
  554. if(pTempIcb->dwIfIndex > dwLastIndex)
  555. {
  556. //
  557. // Found the next ICB to save
  558. //
  559. pIcb = pTempIcb;
  560. break;
  561. }
  562. }
  563. //
  564. // If none found, we are done
  565. //
  566. if(pIcb is NULL)
  567. {
  568. break;
  569. }
  570. dwLastIndex = pIcb->dwIfIndex;
  571. hDimHandle = pIcb->hDIMHandle;
  572. //
  573. // Get the info for this ICB
  574. //
  575. dwSize = GetSizeOfInterfaceConfig(pIcb);
  576. //
  577. // If this will fit in the current buffer, use it
  578. //
  579. if(dwSize > dwInfoSize)
  580. {
  581. //
  582. // otherwise, allocate a new one
  583. //
  584. dwInfoSize = dwSize * 2;
  585. if(pvBuffer)
  586. {
  587. //
  588. // Free the old buffer
  589. //
  590. HeapFree(IPRouterHeap,
  591. 0,
  592. pvBuffer);
  593. pvBuffer = NULL;
  594. }
  595. pvBuffer = HeapAlloc(IPRouterHeap,
  596. HEAP_ZERO_MEMORY,
  597. dwInfoSize);
  598. if(pvBuffer is NULL)
  599. {
  600. dwInfoSize = 0;
  601. //
  602. // Go to the while(TRUE)
  603. //
  604. continue;
  605. }
  606. }
  607. dwErr = GetInterfaceConfiguration(pIcb,
  608. pvBuffer,
  609. dwInfoSize);
  610. if(dwErr is NO_ERROR)
  611. {
  612. //
  613. // Need to leave the lock for this
  614. //
  615. EXIT_LOCK(ICB_LIST);
  616. SaveInterfaceInfo(hDimHandle,
  617. PID_IP,
  618. pvBuffer,
  619. dwSize);
  620. //
  621. // Reacquire it once we are done
  622. //
  623. ENTER_WRITER(ICB_LIST);
  624. }
  625. else
  626. {
  627. Trace1(ERR,
  628. "RouterBootComplete: Error getting info for %S\n",
  629. pIcb->pwszName);
  630. }
  631. }
  632. #endif
  633. EXIT_LOCK(ICB_LIST);
  634. //
  635. // Now go in and start forwarding if we are not in lanonly mode
  636. // and IPCP is so configured
  637. //
  638. EnterCriticalSection(&g_csFwdState);
  639. Trace1(GLOBAL,
  640. "RouterBootComplete: Signalling worker to %s forwarding",
  641. g_bEnableFwdRequest ? "enable" : "disable");
  642. SetEvent(g_hSetForwardingEvent);
  643. LeaveCriticalSection(&g_csFwdState);
  644. return NO_ERROR;
  645. }
  646. DWORD
  647. AddInterface(
  648. IN PWSTR pwsInterfaceName,
  649. IN PVOID pInterfaceInfo,
  650. IN ROUTER_INTERFACE_TYPE InterfaceType,
  651. IN HANDLE hDIMInterface,
  652. IN OUT HANDLE *phInterface
  653. )
  654. /*++
  655. Routine Description
  656. Called by DIM to add an interface. This could be one of our configured
  657. interfaces or a client dialling in
  658. Locks
  659. Takes the ICB_LIST lock as WRITER
  660. Arguments
  661. pwsInterfaceName
  662. pInterfaceInfo
  663. InterfaceType
  664. hDIMInterface
  665. phInterface
  666. Return Value
  667. NO_ERROR
  668. ERROR_INVALID_PARAMETER
  669. --*/
  670. {
  671. PICB pNewInterfaceCb;
  672. DWORD dwResult, dwAdminState;
  673. PRTR_TOC_ENTRY pTocEntry;
  674. PRTR_INFO_BLOCK_HEADER pInfoHdr;
  675. PINTERFACE_STATUS_INFO pInfo;
  676. BOOL bEnable;
  677. EnterRouterApi();
  678. TraceEnter("AddInterface");
  679. Trace1(IF,
  680. "AddInterface: Adding %S",
  681. pwsInterfaceName);
  682. pInfoHdr = (PRTR_INFO_BLOCK_HEADER)pInterfaceInfo;
  683. #ifdef KSL_IPINIP
  684. #if !defined( __IPINIP )
  685. //
  686. // In preparation for IPinIP interface removal
  687. //
  688. if(InterfaceType is ROUTER_IF_TYPE_TUNNEL1)
  689. {
  690. Trace1(ERR,
  691. "AddInterface: Interface type is TUNNEL (%d), which is no longer"
  692. "supported",
  693. InterfaceType);
  694. LogErr0(IF_TYPE_NOT_SUPPORTED, ERROR_INVALID_PARAMETER);
  695. TraceLeave("AddInterface");
  696. ExitRouterApi();
  697. return ERROR_INVALID_PARAMETER;
  698. }
  699. #endif
  700. #endif //KSL_IPINIP
  701. if(RouterRoleLanOnly and
  702. (InterfaceType isnot ROUTER_IF_TYPE_DEDICATED) and
  703. #ifdef KSL_IPINIP
  704. (InterfaceType isnot ROUTER_IF_TYPE_TUNNEL1) and
  705. #endif //KSL_IPINIP
  706. (InterfaceType isnot ROUTER_IF_TYPE_LOOPBACK))
  707. {
  708. //
  709. // If we are in LAN only mode, we should not see CLIENT, INTERNAL
  710. // HOME_ROUTER or FULL_ROUTER
  711. //
  712. Trace1(ERR,
  713. "AddInterface: Interface is %d, but Router is in LanOnly Mode",
  714. InterfaceType);
  715. TraceLeave("AddInterface");
  716. ExitRouterApi();
  717. return ERROR_INVALID_PARAMETER;
  718. }
  719. ENTER_WRITER(ICB_LIST);
  720. EXIT_LOCK(ICB_LIST);
  721. //
  722. // Figure out the admin state (if any)
  723. // If there is no status info, we assume state to be UP
  724. //
  725. dwAdminState = IF_ADMIN_STATUS_UP;
  726. pTocEntry = GetPointerToTocEntry(IP_INTERFACE_STATUS_INFO,
  727. pInfoHdr);
  728. if(pTocEntry and (pTocEntry->InfoSize > 0) and (pTocEntry->Count > 0))
  729. {
  730. pInfo = (PINTERFACE_STATUS_INFO)GetInfoFromTocEntry(pInfoHdr,
  731. pTocEntry);
  732. //
  733. // Set it only if it is a valid value. Ignore others
  734. //
  735. if((pInfo isnot NULL) and
  736. ((pInfo->dwAdminStatus is IF_ADMIN_STATUS_UP) or
  737. (pInfo->dwAdminStatus is IF_ADMIN_STATUS_DOWN)))
  738. {
  739. dwAdminState = pInfo->dwAdminStatus;
  740. }
  741. }
  742. //
  743. // Create an ICB
  744. //
  745. pNewInterfaceCb = CreateIcb(pwsInterfaceName,
  746. hDIMInterface,
  747. InterfaceType,
  748. dwAdminState,
  749. 0);
  750. if(pNewInterfaceCb is NULL)
  751. {
  752. ExitRouterApi();
  753. return ERROR_CAN_NOT_COMPLETE;
  754. }
  755. //
  756. // HEAP_ZERO_MEMORY so we dont need to set any of the rtrdisc fields to 0
  757. //
  758. InitializeRouterDiscoveryInfo(pNewInterfaceCb,
  759. pInfoHdr);
  760. // *** Exclusion Begin ***
  761. ENTER_WRITER(ICB_LIST);
  762. //
  763. // Insert pNewInterfaceCb in interface list and hash table
  764. // This increments the interface count and sets the seq number
  765. //
  766. InsertInterfaceInLists(pNewInterfaceCb);
  767. Trace2(IF, "ICB number for %S is %d\n\n",
  768. pwsInterfaceName, pNewInterfaceCb->dwSeqNumber);
  769. //
  770. // The interface have been added to wanarp, so now add the demand dial
  771. // filters
  772. //
  773. if((pNewInterfaceCb->ritType is ROUTER_IF_TYPE_FULL_ROUTER) or
  774. (pNewInterfaceCb->ritType is ROUTER_IF_TYPE_HOME_ROUTER))
  775. {
  776. dwResult = SetDemandDialFilters(pNewInterfaceCb,
  777. pInfoHdr);
  778. if(dwResult isnot NO_ERROR)
  779. {
  780. CHAR Name[MAX_INTERFACE_NAME_LEN + 1];
  781. PCHAR pszName;
  782. pszName = Name;
  783. WideCharToMultiByte(CP_ACP,
  784. 0,
  785. pwsInterfaceName,
  786. -1,
  787. pszName,
  788. MAX_INTERFACE_NAME_LEN,
  789. NULL,
  790. NULL);
  791. LogErr1(CANT_ADD_DD_FILTERS,
  792. pszName,
  793. dwResult);
  794. }
  795. }
  796. //
  797. // If this is the loopback interface, do that extra something to
  798. // initialize it
  799. //
  800. if(pNewInterfaceCb->ritType is ROUTER_IF_TYPE_LOOPBACK)
  801. {
  802. InitializeLoopbackInterface(pNewInterfaceCb);
  803. }
  804. #ifdef KSL_IPINIP
  805. //
  806. // If this is an IP in IP tunnel, add the info if present
  807. //
  808. if(pNewInterfaceCb->ritType is ROUTER_IF_TYPE_TUNNEL1)
  809. {
  810. dwResult = SetIpInIpInfo(pNewInterfaceCb,
  811. pInfoHdr);
  812. if(dwResult isnot NO_ERROR)
  813. {
  814. Trace2(ERR,
  815. "AddInterface: Error %d adding %S to ipinip",
  816. dwResult,
  817. pwsInterfaceName);
  818. }
  819. }
  820. #endif //KSL_IPINIP
  821. //
  822. // Add multicast scope boundary info if present
  823. //
  824. dwResult = SetMcastLimitInfo(pNewInterfaceCb,
  825. pInfoHdr);
  826. dwResult = SetBoundaryInfo(pNewInterfaceCb,
  827. pInfoHdr);
  828. if(dwResult isnot NO_ERROR)
  829. {
  830. Trace2(ERR,
  831. "AddInterface: Error %d adding boundary info for %S",
  832. dwResult,
  833. pwsInterfaceName);
  834. }
  835. //
  836. // Add Interfaces with the approp. routing protocols
  837. // FULL_ROUTER and HOME_ROUTER -> demand dial
  838. // DEDICATED, INTERNAL and CLIENT -> permanent
  839. //
  840. AddInterfaceToAllProtocols(pNewInterfaceCb,
  841. pInfoHdr);
  842. //
  843. // Add filters and NAT info. We dont add the contexts to IP stack
  844. // over here, because that will happen when we bring the interface up
  845. //
  846. if((pNewInterfaceCb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  847. (pNewInterfaceCb->ritType isnot ROUTER_IF_TYPE_LOOPBACK))
  848. {
  849. dwResult = SetFilterInterfaceInfo(pNewInterfaceCb,
  850. pInfoHdr);
  851. if(dwResult isnot NO_ERROR)
  852. {
  853. Trace1(ERR,
  854. "AddInterface: Couldnt set filters for %S",
  855. pNewInterfaceCb->pwszName);
  856. }
  857. }
  858. if(pNewInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP)
  859. {
  860. //
  861. // If the admin wants the interface up, well good for hir
  862. //
  863. switch(pNewInterfaceCb->ritType)
  864. {
  865. case ROUTER_IF_TYPE_HOME_ROUTER:
  866. case ROUTER_IF_TYPE_FULL_ROUTER:
  867. {
  868. dwResult = WanInterfaceDownToInactive(pNewInterfaceCb);
  869. if(dwResult isnot NO_ERROR)
  870. {
  871. Trace2(ERR,
  872. "AddInterface: Error %d down->inactive for %S",
  873. dwResult,
  874. pNewInterfaceCb->pwszName);
  875. }
  876. break;
  877. }
  878. case ROUTER_IF_TYPE_DEDICATED:
  879. #ifdef KSL_IPINIP
  880. case ROUTER_IF_TYPE_TUNNEL1:
  881. #endif //KSL_IPINIP
  882. {
  883. #ifdef KSL_IPINIP
  884. if((pNewInterfaceCb->ritType is ROUTER_IF_TYPE_TUNNEL1) and
  885. (pNewInterfaceCb->pIpIpInfo->dwLocalAddress is 0))
  886. {
  887. //
  888. // Means we added the interface, but dont have info to
  889. // add it to IP in IP
  890. //
  891. break;
  892. }
  893. #endif //KSL_IPINIP
  894. dwResult = LanEtcInterfaceDownToUp(pNewInterfaceCb,
  895. TRUE);
  896. if(dwResult isnot NO_ERROR)
  897. {
  898. Trace2(ERR,
  899. "AddInterface: Error %d down->up for %S",
  900. dwResult,
  901. pNewInterfaceCb->pwszName);
  902. }
  903. break;
  904. }
  905. }
  906. }
  907. else
  908. {
  909. //
  910. // The problem with LAN and IP in IP interfaces is that the stack
  911. // brings them up even before we start. So if the user wants the
  912. // interface DOWN to begin with, we need to tell the stack to bring
  913. // the i/f down
  914. //
  915. switch(pNewInterfaceCb->ritType)
  916. {
  917. case ROUTER_IF_TYPE_DEDICATED:
  918. #ifdef KSL_IPINIP
  919. case ROUTER_IF_TYPE_TUNNEL1:
  920. #endif //KSL_IPINIP
  921. {
  922. dwResult = LanEtcInterfaceInitToDown(pNewInterfaceCb);
  923. if(dwResult isnot NO_ERROR)
  924. {
  925. Trace2(ERR,
  926. "AddInterface: Interface %S could not be set to DOWN in the stack. Results are undefined. Error %d",
  927. pNewInterfaceCb->pwszName,
  928. dwResult);
  929. }
  930. break;
  931. }
  932. }
  933. }
  934. //
  935. // Add Static Routes
  936. //
  937. if(pNewInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP)
  938. {
  939. //
  940. // Only add routes if the i/f is up
  941. //
  942. //
  943. // Note that since init static routes is not being called for some
  944. // interfaces the stack routes will not be picked up. But that
  945. // may be OK since bringing the i/f down will delete the routes anyway
  946. //
  947. //
  948. // Can only be called when the pIcb has the correct
  949. // dwOperational State
  950. //
  951. InitializeStaticRoutes(pNewInterfaceCb,
  952. pInfoHdr);
  953. }
  954. //
  955. // The handle we return to DIM is a pointer to our ICB
  956. //
  957. *phInterface = ULongToHandle(pNewInterfaceCb->dwSeqNumber);
  958. //
  959. // Check if we want to enable with DIM. Do this check while we still have
  960. // the LOCK
  961. //
  962. bEnable = (pNewInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP);
  963. // *** Exclusion End ***
  964. EXIT_LOCK(ICB_LIST);
  965. //
  966. // We can not call upwards from a component while holding
  967. // a lock, so we first exit the lock and then call
  968. // enabled
  969. //
  970. if(bEnable)
  971. {
  972. EnableInterfaceWithAllProtocols(pNewInterfaceCb);
  973. EnableInterfaceWithDIM(hDIMInterface,
  974. PID_IP,
  975. TRUE);
  976. }
  977. Trace4(IF,
  978. "AddInterface: Added %S: Type- %d, Index- %d, ICB 0x%x",
  979. pwsInterfaceName,
  980. InterfaceType,
  981. pNewInterfaceCb->dwIfIndex,
  982. pNewInterfaceCb);
  983. TraceLeave("AddInterface");
  984. ExitRouterApi();
  985. return NO_ERROR;
  986. }
  987. DWORD
  988. DeleteInterface(
  989. IN HANDLE hInterface
  990. )
  991. /*++
  992. Routine Description
  993. Called by DIM to delete an interface (or when a CLIENT disconnects)
  994. The main work is done by DeleteSingleInterface()
  995. Locks
  996. None
  997. Arguments
  998. None
  999. Return Value
  1000. None
  1001. --*/
  1002. {
  1003. PICB pIcb;
  1004. EnterRouterApi();
  1005. TraceEnter("DeleteInterface");
  1006. // *** Exclusion Begin ***
  1007. ENTER_WRITER(ICB_LIST);
  1008. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  1009. IpRtAssert(pIcb);
  1010. if (pIcb isnot NULL)
  1011. {
  1012. Trace1(IF,
  1013. "DeleteInterface: Deleting %S,",
  1014. pIcb->pwszName);
  1015. RemoveInterfaceFromLists(pIcb);
  1016. DeleteSingleInterface(pIcb);
  1017. if(pIcb is g_pInternalInterfaceCb)
  1018. {
  1019. g_pInternalInterfaceCb = NULL;
  1020. }
  1021. //
  1022. // Free the memory
  1023. //
  1024. HeapFree(IPRouterHeap,
  1025. 0,
  1026. pIcb);
  1027. }
  1028. else
  1029. {
  1030. Trace1(
  1031. ANY,
  1032. "DeleteInterface: No interface for ICB number %d",
  1033. HandleToULong(hInterface)
  1034. );
  1035. }
  1036. // *** Exclusion End ***
  1037. EXIT_LOCK(ICB_LIST);
  1038. TraceLeave("DeleteInterface");
  1039. ExitRouterApi();
  1040. return NO_ERROR;
  1041. }
  1042. DWORD
  1043. StopRouter(
  1044. VOID
  1045. )
  1046. /*++
  1047. Routine Description
  1048. Called by DIM to shut us down. We set our state to STOPPING (which stops
  1049. other APIs from being serviced) and set the event to let the worker
  1050. thread clean up
  1051. Locks
  1052. None
  1053. Arguments
  1054. None
  1055. Return Value
  1056. None
  1057. --*/
  1058. {
  1059. TraceEnter("Stop Router") ;
  1060. EnterCriticalSection(&RouterStateLock);
  1061. RouterState.IRS_State = RTR_STATE_STOPPING;
  1062. LeaveCriticalSection(&RouterStateLock);
  1063. //
  1064. // Try and delete as many interfaces as you can. The ones that are
  1065. // connected will be handled in worker thread
  1066. //
  1067. DeleteAllInterfaces();
  1068. SetEvent(g_hStopRouterEvent) ;
  1069. TraceLeave("Stop Router");
  1070. return PENDING;
  1071. }
  1072. DWORD
  1073. GetInterfaceInfo(
  1074. IN HANDLE hInterface,
  1075. OUT PVOID pvInterfaceInfo,
  1076. IN OUT PDWORD pdwInterfaceInfoSize
  1077. )
  1078. /*++
  1079. Routine Description
  1080. Called by DIM to get interface info.
  1081. Locks
  1082. Acquires the ICB_LIST lock as READER
  1083. Arguments
  1084. hInterface Our handle to the i/f (pIcb)
  1085. pvInterfaceInfo Buffer to store info
  1086. pdwInterfaceInfoSize Size of Buffer. If the info is more than this, we
  1087. return the needed size
  1088. Return Value
  1089. NO_ERROR
  1090. ERROR_INSUFFICIENT_BUFFER
  1091. --*/
  1092. {
  1093. DWORD dwErr;
  1094. DWORD dwInfoSize = 0;
  1095. PICB pIcb;
  1096. EnterRouterApi();
  1097. TraceEnter("GetInterfaceInfo");
  1098. dwErr = NO_ERROR;
  1099. // *** Exclusion Begin ***
  1100. ENTER_READER(ICB_LIST);
  1101. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  1102. IpRtAssert(pIcb);
  1103. if (pIcb isnot NULL)
  1104. {
  1105. dwInfoSize = GetSizeOfInterfaceConfig(pIcb);
  1106. if(dwInfoSize > *pdwInterfaceInfoSize)
  1107. {
  1108. dwErr = ERROR_INSUFFICIENT_BUFFER;
  1109. }
  1110. else
  1111. {
  1112. dwErr = GetInterfaceConfiguration(pIcb,
  1113. pvInterfaceInfo,
  1114. *pdwInterfaceInfoSize);
  1115. if(dwErr isnot NO_ERROR)
  1116. {
  1117. Trace1(ERR,
  1118. "GetInterfaceInfo: Error %d getting interface configuration",
  1119. dwErr);
  1120. dwErr = ERROR_CAN_NOT_COMPLETE;
  1121. }
  1122. }
  1123. }
  1124. else
  1125. {
  1126. Trace1(
  1127. ANY,
  1128. "GetInterfaceInfo : No interface with ICB number %d",
  1129. HandleToULong(hInterface)
  1130. );
  1131. dwErr = ERROR_INVALID_INDEX;
  1132. }
  1133. // *** Exclusion End ***
  1134. EXIT_LOCK(ICB_LIST);
  1135. *pdwInterfaceInfoSize = dwInfoSize;
  1136. TraceLeave("GetInterfaceInfo");
  1137. ExitRouterApi();
  1138. return dwErr;
  1139. }
  1140. DWORD
  1141. SetInterfaceInfo(
  1142. IN HANDLE hInterface,
  1143. IN LPVOID pInterfaceInfo
  1144. )
  1145. /*++
  1146. Routine Description
  1147. Called by DIM when a users sets interface info. All our sets follow
  1148. OVERWRITE semantics, i.e. the new info overwrites the old info instead of
  1149. being appended to the old info.
  1150. Locks
  1151. ICB_LIST lock as WRITER
  1152. Arguments
  1153. None
  1154. Return Value
  1155. None
  1156. --*/
  1157. {
  1158. DWORD i, dwResult;
  1159. PVOID *pInfo ;
  1160. PPROTO_CB pIfProt;
  1161. PIF_PROTO pProto;
  1162. PICB pIcb;
  1163. PLIST_ENTRY pleProto,pleNode;
  1164. PADAPTER_INFO pBinding;
  1165. IP_ADAPTER_BINDING_INFO *pBindInfo ;
  1166. PRTR_INFO_BLOCK_HEADER pInfoHdr;
  1167. PRTR_TOC_ENTRY pToc;
  1168. PINTERFACE_STATUS_INFO pStatusInfo;
  1169. BOOL bStatusChanged, bUpdateDIM = FALSE, bEnable;
  1170. HANDLE hDimInterface;
  1171. EnterRouterApi();
  1172. TraceEnter("SetInterfaceInfo");
  1173. //
  1174. // The set info is the standard Header+TOC
  1175. //
  1176. pInfoHdr = (PRTR_INFO_BLOCK_HEADER)pInterfaceInfo;
  1177. // *** Exclusion Begin ***
  1178. ENTER_WRITER(ICB_LIST);
  1179. //
  1180. // If the current AdminState is DOWN and we are being asked to
  1181. // bring it up, we do so BEFORE setting any other info
  1182. //
  1183. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  1184. IpRtAssert(pIcb);
  1185. if (pIcb isnot NULL)
  1186. {
  1187. Trace1(IF,
  1188. "SetInterfaceInfo: Setting configuration for %S",
  1189. pIcb->pwszName);
  1190. bStatusChanged = FALSE;
  1191. hDimInterface = pIcb->hDIMHandle;
  1192. pToc = GetPointerToTocEntry(IP_INTERFACE_STATUS_INFO, pInfoHdr);
  1193. if((pToc isnot NULL) and (pToc->InfoSize isnot 0))
  1194. {
  1195. pStatusInfo = (PINTERFACE_STATUS_INFO)GetInfoFromTocEntry(pInfoHdr,
  1196. pToc);
  1197. if((pStatusInfo isnot NULL) and
  1198. (pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN) and
  1199. (pStatusInfo->dwAdminStatus is IF_ADMIN_STATUS_UP))
  1200. {
  1201. dwResult = SetInterfaceAdminStatus(pIcb,
  1202. pStatusInfo->dwAdminStatus,
  1203. &bUpdateDIM);
  1204. if(dwResult isnot NO_ERROR)
  1205. {
  1206. Trace2(ERR,
  1207. "SetInterfaceInfo: Error %d setting Admin Status on %S",
  1208. dwResult,
  1209. pIcb->pwszName);
  1210. EXIT_LOCK(ICB_LIST);
  1211. TraceLeave("SetInterfaceInfo");
  1212. ExitRouterApi();
  1213. return dwResult;
  1214. }
  1215. bStatusChanged = TRUE;
  1216. }
  1217. }
  1218. if(pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN)
  1219. {
  1220. //
  1221. // If we are still down, we dont allow any SETS
  1222. //
  1223. Trace1(ERR,
  1224. "SetInterfaceInfo: Can not set info for %S since the the admin state is DOWN",
  1225. pIcb->pwszName);
  1226. EXIT_LOCK(ICB_LIST);
  1227. TraceLeave("SetInterfaceInfo");
  1228. ExitRouterApi();
  1229. return ERROR_INVALID_PARAMETER;
  1230. }
  1231. //
  1232. // Set router discovery info
  1233. //
  1234. SetRouterDiscoveryInfo(pIcb,
  1235. pInfoHdr);
  1236. //
  1237. // Make a copy of the binding info
  1238. // This may be needed to be passed to the protocols
  1239. //
  1240. pBindInfo = NULL;
  1241. CheckBindingConsistency(pIcb);
  1242. if(pIcb->bBound)
  1243. {
  1244. pBindInfo = HeapAlloc(IPRouterHeap,
  1245. 0,
  1246. SIZEOF_IP_BINDING(pIcb->dwNumAddresses));
  1247. if(pBindInfo is NULL)
  1248. {
  1249. Trace1(ERR,
  1250. "SetInterfaceInfo: Error allocating %d bytes for binding",
  1251. SIZEOF_IP_BINDING(pIcb->dwNumAddresses));
  1252. EXIT_LOCK(ICB_LIST);
  1253. if (bUpdateDIM)
  1254. {
  1255. EnableInterfaceWithDIM(hDimInterface,PID_IP,TRUE);
  1256. }
  1257. TraceLeave("SetInterfaceInfo");
  1258. ExitRouterApi();
  1259. return ERROR_NOT_ENOUGH_MEMORY;
  1260. }
  1261. pBindInfo->AddressCount = pIcb->dwNumAddresses;
  1262. pBindInfo->RemoteAddress = pIcb->dwRemoteAddress;
  1263. pBindInfo->Mtu = pIcb->ulMtu;
  1264. pBindInfo->Speed = pIcb->ullSpeed;
  1265. for (i = 0; i < pIcb->dwNumAddresses; i++)
  1266. {
  1267. pBindInfo->Address[i].Address = pIcb->pibBindings[i].dwAddress;
  1268. pBindInfo->Address[i].Mask = pIcb->pibBindings[i].dwMask;
  1269. }
  1270. }
  1271. // *** Exclusion Begin ***
  1272. ENTER_READER(PROTOCOL_CB_LIST);
  1273. //
  1274. // Walk all the protocols and see if we have info for that protocol
  1275. // If we do, we see if the interface is already added to the protocol.
  1276. // If it is, we just call the SetInfo callback.
  1277. // Otherwise we add the interface and then bind it.
  1278. // If we dont, we see if the interface had been added to the protocol
  1279. // If it had, we delete the interface from the protocol
  1280. //
  1281. for(pleProto = g_leProtoCbList.Flink;
  1282. pleProto isnot &g_leProtoCbList;
  1283. pleProto = pleProto->Flink)
  1284. {
  1285. PPROTO_CB pProtoCb;
  1286. ULONG ulStructureVersion, ulStructureSize, ulStructureCount;
  1287. pProtoCb = CONTAINING_RECORD(pleProto,
  1288. PROTO_CB,
  1289. leList);
  1290. Trace1(IF,
  1291. "SetInterfaceInfo: Checking for info for %S",
  1292. pProtoCb->pwszDisplayName);
  1293. pToc = GetPointerToTocEntry(pProtoCb->dwProtocolId,
  1294. pInfoHdr);
  1295. if(pToc is NULL)
  1296. {
  1297. //
  1298. // Block absent means do not change anything
  1299. //
  1300. Trace1(IF,
  1301. "SetInterfaceInfo: No TOC for %S. No change",
  1302. pProtoCb->pwszDisplayName);
  1303. continue;
  1304. }
  1305. else
  1306. {
  1307. pInfo = GetInfoFromTocEntry(pInfoHdr,
  1308. pToc);
  1309. }
  1310. ulStructureVersion = 0x500;
  1311. ulStructureSize = pToc->InfoSize;
  1312. ulStructureCount = pToc->Count;
  1313. if((pToc->InfoSize isnot 0) and (pInfo isnot NULL))
  1314. {
  1315. BOOL bFound;
  1316. //
  1317. // So we have protocol info
  1318. //
  1319. Trace1(IF,
  1320. "SetInterfaceInfo: TOC Found for %S",
  1321. pProtoCb->pwszDisplayName);
  1322. //
  1323. // See if this protocol exists on the active protocol list
  1324. // for the interface
  1325. //
  1326. bFound = FALSE;
  1327. for(pleNode = pIcb->leProtocolList.Flink;
  1328. pleNode isnot &(pIcb->leProtocolList);
  1329. pleNode = pleNode->Flink)
  1330. {
  1331. pProto = CONTAINING_RECORD(pleNode,
  1332. IF_PROTO,
  1333. leIfProtoLink);
  1334. if(pProto->pActiveProto->dwProtocolId is
  1335. pProtoCb->dwProtocolId)
  1336. {
  1337. //
  1338. // The interface has already been added to the interface
  1339. // Just set info
  1340. //
  1341. bFound = TRUE;
  1342. Trace2(IF,
  1343. "SetInterfaceInfo: %S already on %S. Setting info",
  1344. pProtoCb->pwszDisplayName,
  1345. pIcb->pwszName);
  1346. dwResult = (pProto->pActiveProto->pfnSetInterfaceInfo)(
  1347. pIcb->dwIfIndex,
  1348. pInfo,
  1349. ulStructureVersion,
  1350. ulStructureSize,
  1351. ulStructureCount);
  1352. //
  1353. // Set the promiscuous mode to false since this time we
  1354. // actually have info
  1355. //
  1356. pProto->bPromiscuous = FALSE;
  1357. break;
  1358. }
  1359. }
  1360. if(!bFound)
  1361. {
  1362. //
  1363. // The interface is being added to the protocol for the
  1364. // first time
  1365. //
  1366. Trace2(IF,
  1367. "SetInterfaceInfo: %S not running %S. Adding interface",
  1368. pProtoCb->pwszDisplayName,
  1369. pIcb->pwszName);
  1370. dwResult = AddInterfaceToProtocol(pIcb,
  1371. pProtoCb,
  1372. pInfo,
  1373. ulStructureVersion,
  1374. ulStructureSize,
  1375. ulStructureCount);
  1376. if(dwResult isnot NO_ERROR)
  1377. {
  1378. Trace3(ERR,
  1379. "SetInterfaceInfo: Error %d adding %S to %S",
  1380. dwResult,
  1381. pIcb->pwszName,
  1382. pProtoCb->pwszDisplayName);
  1383. }
  1384. dwResult = (pProtoCb->pfnInterfaceStatus)(
  1385. pIcb->dwIfIndex,
  1386. (pIcb->dwOperationalState >= CONNECTED),
  1387. RIS_INTERFACE_ENABLED,
  1388. NULL
  1389. );
  1390. if(dwResult isnot NO_ERROR)
  1391. {
  1392. Trace3(ERR,
  1393. "SetInterfaceInfo: Error %d enabling %S with %S",
  1394. dwResult,
  1395. pIcb->pwszName,
  1396. pProtoCb->pwszDisplayName);
  1397. }
  1398. //
  1399. // If the binding information is available, pass it to the
  1400. // protocol
  1401. //
  1402. if(pBindInfo)
  1403. {
  1404. Trace2(IF,
  1405. "SetInterfaceInfo: Binding %S in %S",
  1406. pIcb->pwszName,
  1407. pProtoCb->pwszDllName);
  1408. dwResult = BindInterfaceInProtocol(pIcb,
  1409. pProtoCb,
  1410. pBindInfo);
  1411. if(dwResult isnot NO_ERROR)
  1412. {
  1413. Trace3(ERR,
  1414. "SetInterfaceInfo: Error %d binding %S to %S",
  1415. dwResult,
  1416. pIcb->pwszName,
  1417. pProtoCb->pwszDllName);
  1418. }
  1419. }
  1420. //
  1421. // If this is the internal interface, also call connect client
  1422. // for connected clients
  1423. //
  1424. if((pIcb is g_pInternalInterfaceCb) and
  1425. (pProtoCb->pfnConnectClient))
  1426. {
  1427. PLIST_ENTRY pleTempNode;
  1428. IP_LOCAL_BINDING clientAddr;
  1429. PICB pTempIf;
  1430. for(pleTempNode = &ICBList;
  1431. pleTempNode->Flink != &ICBList;
  1432. pleTempNode = pleTempNode->Flink)
  1433. {
  1434. pTempIf = CONTAINING_RECORD(pleTempNode->Flink,
  1435. ICB,
  1436. leIfLink);
  1437. if(pTempIf->ritType isnot ROUTER_IF_TYPE_CLIENT)
  1438. {
  1439. continue;
  1440. }
  1441. clientAddr.Address = pTempIf->pibBindings[0].dwAddress;
  1442. clientAddr.Mask = pTempIf->pibBindings[0].dwMask;
  1443. pProtoCb->pfnConnectClient(g_pInternalInterfaceCb->dwIfIndex,
  1444. &clientAddr);
  1445. }
  1446. }
  1447. }
  1448. }
  1449. else
  1450. {
  1451. //
  1452. // A zero size TOC was found for this particular protocol. If
  1453. // this protocol exists in the current ActiveProtocol list,
  1454. // remove the interface from the protocol
  1455. //
  1456. Trace2(IF,
  1457. "SetInterfaceInfo: A zero size TOC was found for %S on %S",
  1458. pProtoCb->pwszDllName,
  1459. pIcb->pwszName);
  1460. pleNode = pIcb->leProtocolList.Flink;
  1461. while(pleNode isnot &(pIcb->leProtocolList))
  1462. {
  1463. pProto = CONTAINING_RECORD(pleNode,
  1464. IF_PROTO,
  1465. leIfProtoLink);
  1466. pleNode = pleNode->Flink;
  1467. if(pProto->pActiveProto->dwProtocolId is pProtoCb->dwProtocolId)
  1468. {
  1469. IpRtAssert(pProto->pActiveProto is pProtoCb);
  1470. //
  1471. // Call the routing protocol's deleteinterface entrypoint
  1472. //
  1473. Trace2(IF,
  1474. "SetInterfaceInfo: Deleting %S from %S",
  1475. pProtoCb->pwszDllName,
  1476. pIcb->pwszName);
  1477. dwResult = (pProtoCb->pfnDeleteInterface)(pIcb->dwIfIndex);
  1478. if(dwResult isnot NO_ERROR)
  1479. {
  1480. Trace3(ERR,
  1481. "SetInterfaceInfo: Err %d deleting %S from %S",
  1482. dwResult,
  1483. pIcb->pwszName,
  1484. pProtoCb->pwszDllName);
  1485. }
  1486. else
  1487. {
  1488. //
  1489. // Delete this protocol from the list of protocols
  1490. // in the Interface
  1491. //
  1492. RemoveEntryList(&(pProto->leIfProtoLink));
  1493. HeapFree(IPRouterHeap,
  1494. 0,
  1495. pProto);
  1496. }
  1497. }
  1498. }
  1499. }
  1500. }
  1501. // *** Exclusion End ***
  1502. EXIT_LOCK(PROTOCOL_CB_LIST);
  1503. for(i = 0; i < NUM_INFO_CBS; i++)
  1504. {
  1505. dwResult = g_rgicInfoCb[i].pfnSetInterfaceInfo(pIcb,
  1506. pInfoHdr);
  1507. if(dwResult isnot NO_ERROR)
  1508. {
  1509. Trace3(ERR,
  1510. "SetInterfaceInfo: Error %d setting %s info for %S",
  1511. dwResult,
  1512. g_rgicInfoCb[i].pszInfoName,
  1513. pIcb->pwszName);
  1514. }
  1515. }
  1516. if(pBindInfo)
  1517. {
  1518. HeapFree(IPRouterHeap,
  1519. 0,
  1520. pBindInfo);
  1521. }
  1522. //
  1523. // If we have already changed the status dont do it again
  1524. //
  1525. if(!bStatusChanged)
  1526. {
  1527. dwResult = SetInterfaceStatusInfo(pIcb,
  1528. pInfoHdr,
  1529. &bUpdateDIM);
  1530. if(dwResult isnot NO_ERROR)
  1531. {
  1532. Trace2(ERR,
  1533. "SetInterfaceInfo: Error %d setting status info for %S",
  1534. dwResult,
  1535. pIcb->pwszName);
  1536. }
  1537. }
  1538. bEnable = (pIcb->dwAdminState == IF_ADMIN_STATUS_UP) ? TRUE : FALSE;
  1539. }
  1540. else
  1541. {
  1542. Trace1(
  1543. ANY,
  1544. "SetInterfaceInfo : No interface with ICB number %d",
  1545. HandleToULong(hInterface)
  1546. );
  1547. }
  1548. // *** Exclusion End ***
  1549. EXIT_LOCK(ICB_LIST);
  1550. if(bUpdateDIM)
  1551. {
  1552. EnableInterfaceWithDIM(
  1553. hDimInterface,
  1554. PID_IP,
  1555. bEnable
  1556. );
  1557. }
  1558. TraceLeave("SetInterfaceInfo");
  1559. ExitRouterApi();
  1560. return NO_ERROR;
  1561. }
  1562. DWORD
  1563. InterfaceNotReachable(
  1564. IN HANDLE hInterface,
  1565. IN UNREACHABILITY_REASON Reason
  1566. )
  1567. /*++
  1568. Routine Description
  1569. Called by DIM to tell us that an interface should be considered
  1570. UNREACHABLE till further notice
  1571. Locks
  1572. None
  1573. Arguments
  1574. None
  1575. Return Value
  1576. None
  1577. --*/
  1578. {
  1579. PICB pIcb;
  1580. PADAPTER_INFO pBinding;
  1581. DWORD dwErr;
  1582. EnterRouterApi();
  1583. TraceEnter("InterfaceNotReachable");
  1584. ENTER_WRITER(ICB_LIST);
  1585. //
  1586. // If it is a CLIENT interface all this means is that the connection
  1587. // failed
  1588. //
  1589. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  1590. IpRtAssert(pIcb);
  1591. if (pIcb isnot NULL)
  1592. {
  1593. if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
  1594. {
  1595. pIcb->dwOperationalState = UNREACHABLE;
  1596. EXIT_LOCK(ICB_LIST);
  1597. ExitRouterApi();
  1598. return NO_ERROR;
  1599. }
  1600. Trace2(IF,
  1601. "InterfaceNotReachable: %S is not reachable for reason %d",
  1602. pIcb->pwszName,
  1603. Reason) ;
  1604. if(pIcb->ritType is ROUTER_IF_TYPE_DEDICATED)
  1605. {
  1606. if(Reason == INTERFACE_NO_MEDIA_SENSE)
  1607. {
  1608. HandleMediaSenseEvent(pIcb,
  1609. FALSE);
  1610. }
  1611. else
  1612. {
  1613. dwErr = LanEtcInterfaceUpToDown(pIcb, FALSE);
  1614. if(dwErr isnot NO_ERROR)
  1615. {
  1616. Trace1(ERR,
  1617. "InterfaceNotReachable: Failed to status for %S to down",
  1618. dwErr);
  1619. }
  1620. }
  1621. EXIT_LOCK(ICB_LIST);
  1622. ExitRouterApi();
  1623. return NO_ERROR;
  1624. }
  1625. #if STATIC_RT_DBG
  1626. ENTER_WRITER(BINDING_LIST);
  1627. pBinding = GetInterfaceBinding(pIcb->dwIfIndex);
  1628. pBinding->bUnreach = TRUE;
  1629. EXIT_LOCK(BINDING_LIST);
  1630. #endif
  1631. //
  1632. // If we were trying to connect on this - then inform WANARP to
  1633. // drain its queued up packets
  1634. //
  1635. if(pIcb->dwOperationalState is CONNECTING)
  1636. {
  1637. NTSTATUS Status;
  1638. Status = NotifyWanarpOfFailure(pIcb);
  1639. if((Status isnot STATUS_PENDING) and
  1640. (Status isnot STATUS_SUCCESS))
  1641. {
  1642. Trace1(ERR,
  1643. "InterfaceNotReachable: IOCTL_WANARP_CONNECT_FAILED failed. Status %x",
  1644. Status);
  1645. }
  1646. //
  1647. // If it was connecting, then the stack has set the interface context
  1648. // to something other than 0xffffffff. Hence he wont dial out on that
  1649. // route. We need to change the context in the stack back to invalid
  1650. // so that new packets cause the demand dial
  1651. //
  1652. ChangeAdapterIndexForDodRoutes(pIcb->dwIfIndex);
  1653. //
  1654. // We are still in INACTIVE state so dont have to call any if the
  1655. // WanInterface*To*() functions. But since we are in CONNECTING
  1656. // WANARP must have called us with CONNECTION notification
  1657. // so we undo what we did there
  1658. //
  1659. DeAllocateBindings(pIcb);
  1660. ClearNotificationFlags(pIcb);
  1661. }
  1662. else
  1663. {
  1664. //
  1665. // A connected interface must first be disconnected
  1666. //
  1667. if(pIcb->dwOperationalState is CONNECTED)
  1668. {
  1669. Trace1(IF,
  1670. "InterfaceNotReachable: %S is already connected",
  1671. pIcb->pwszName);
  1672. EXIT_LOCK(ICB_LIST);
  1673. ExitRouterApi();
  1674. return ERROR_INVALID_HANDLE_STATE;
  1675. }
  1676. }
  1677. //
  1678. // This sets the state to UNREACHABLE
  1679. //
  1680. WanInterfaceInactiveToDown(pIcb,
  1681. FALSE);
  1682. }
  1683. else
  1684. {
  1685. Trace1(
  1686. ANY,
  1687. "InterfaceNotReachable : No interface with ICB number %d",
  1688. HandleToULong(hInterface)
  1689. );
  1690. }
  1691. EXIT_LOCK(ICB_LIST);
  1692. TraceLeave("InterfaceNotReachable");
  1693. ExitRouterApi();
  1694. return NO_ERROR;
  1695. }
  1696. DWORD
  1697. InterfaceReachable(
  1698. IN HANDLE hInterface
  1699. )
  1700. /*++
  1701. Routine Description
  1702. Notification by DIM that the interface is REACHABLE again
  1703. Locks
  1704. None
  1705. Arguments
  1706. None
  1707. Return Value
  1708. None
  1709. --*/
  1710. {
  1711. DWORD dwErr;
  1712. PICB pIcb;
  1713. EnterRouterApi();
  1714. TraceEnter("InterfaceReachable");
  1715. // *** Exclusion Begin ***
  1716. ENTER_WRITER(ICB_LIST);
  1717. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  1718. IpRtAssert(pIcb);
  1719. if (pIcb isnot NULL)
  1720. {
  1721. Trace1(IF, "InterfaceReachable: %S is now reachable",
  1722. pIcb->pwszName);
  1723. if((pIcb->dwOperationalState <= UNREACHABLE) and
  1724. (pIcb->dwAdminState is IF_ADMIN_STATUS_UP))
  1725. {
  1726. //
  1727. // only if it was unreachable before.
  1728. //
  1729. if(pIcb->ritType is ROUTER_IF_TYPE_DEDICATED)
  1730. {
  1731. dwErr = LanEtcInterfaceDownToUp(pIcb,
  1732. FALSE);
  1733. }
  1734. else
  1735. {
  1736. dwErr = WanInterfaceDownToInactive(pIcb);
  1737. }
  1738. if(dwErr isnot NO_ERROR)
  1739. {
  1740. Trace2(ERR,
  1741. "InterfaceReachable: Err %d bringing up %S",
  1742. dwErr,
  1743. pIcb->pwszName);
  1744. }
  1745. }
  1746. }
  1747. else
  1748. {
  1749. Trace1(
  1750. ANY,
  1751. "InterfaceReachable : No interface with ICB number %d",
  1752. HandleToULong(hInterface)
  1753. );
  1754. }
  1755. // *** Exclusion End ***
  1756. EXIT_LOCK(ICB_LIST);
  1757. TraceLeave("InterfaceNotReachable");
  1758. ExitRouterApi();
  1759. return NO_ERROR;
  1760. }
  1761. DWORD
  1762. InterfaceConnected(
  1763. IN HANDLE hInterface,
  1764. IN PVOID pFilter,
  1765. IN PVOID pPppProjectionResult
  1766. )
  1767. /*++
  1768. Routine Description
  1769. Notification by DIM that an interface has connected.
  1770. Locks
  1771. None
  1772. Arguments
  1773. None
  1774. Return Value
  1775. None
  1776. --*/
  1777. {
  1778. DWORD dwResult, i;
  1779. PICB pIcb;
  1780. INTERFACE_ROUTE_INFO rifRoute;
  1781. EnterRouterApi();
  1782. TraceEnter("InterfaceConnected");
  1783. ENTER_WRITER(ICB_LIST);
  1784. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  1785. IpRtAssert(pIcb);
  1786. if (pIcb != NULL)
  1787. {
  1788. Trace2(IF,
  1789. "InterfaceConnected: InterfaceConnected called for %S. State is %d",
  1790. pIcb->pwszName,
  1791. pIcb->dwOperationalState);
  1792. if((pIcb->ritType is ROUTER_IF_TYPE_CLIENT) and
  1793. (g_pInternalInterfaceCb is NULL))
  1794. {
  1795. EXIT_LOCK(ICB_LIST);
  1796. ExitRouterApi();
  1797. return ERROR_INVALID_HANDLE_STATE;
  1798. }
  1799. if((pIcb->ritType is ROUTER_IF_TYPE_CLIENT) and
  1800. g_bUninitServer)
  1801. {
  1802. TryUpdateInternalInterface();
  1803. }
  1804. if(pIcb->dwOperationalState is UNREACHABLE)
  1805. {
  1806. //
  1807. // going from unreachable to connecting. This can happen
  1808. //
  1809. WanInterfaceDownToInactive(pIcb);
  1810. }
  1811. if(pIcb->dwOperationalState isnot CONNECTING)
  1812. {
  1813. //
  1814. // Wanarp has not called us as yet, so set the state to connecting
  1815. //
  1816. pIcb->dwOperationalState = CONNECTING;
  1817. }
  1818. SetDDMNotification(pIcb);
  1819. if(HaveAllNotificationsBeenReceived(pIcb))
  1820. {
  1821. //
  1822. // Wanarp has also called us
  1823. //
  1824. pIcb->dwOperationalState = CONNECTED ;
  1825. if(pIcb->ritType isnot ROUTER_IF_TYPE_CLIENT)
  1826. {
  1827. WRITER_TO_READER(ICB_LIST);
  1828. WanInterfaceInactiveToUp(pIcb);
  1829. }
  1830. else
  1831. {
  1832. IP_LOCAL_BINDING clientAddr;
  1833. PLIST_ENTRY pleNode;
  1834. PPP_IPCP_RESULT *pProjInfo;
  1835. pProjInfo = &(((PPP_PROJECTION_RESULT *)pPppProjectionResult)->ip);
  1836. IpRtAssert(pIcb->pibBindings);
  1837. pIcb->dwNumAddresses = 1;
  1838. pIcb->bBound = TRUE;
  1839. pIcb->pibBindings[0].dwAddress = pProjInfo->dwRemoteAddress;
  1840. if(g_pInternalInterfaceCb->bBound)
  1841. {
  1842. pIcb->pibBindings[0].dwMask =
  1843. g_pInternalInterfaceCb->pibBindings[0].dwMask;
  1844. }
  1845. else
  1846. {
  1847. pIcb->pibBindings[0].dwMask =
  1848. GetClassMask(pProjInfo->dwRemoteAddress);
  1849. }
  1850. clientAddr.Address = pIcb->pibBindings[0].dwAddress;
  1851. clientAddr.Mask = pIcb->pibBindings[0].dwMask;
  1852. #if 0
  1853. //
  1854. // Add a non-stack host route to the client
  1855. //
  1856. rifRoute.dwRtInfoMask = HOST_ROUTE_MASK;
  1857. rifRoute.dwRtInfoNextHop = clientAddr.Address;
  1858. rifRoute.dwRtInfoDest = clientAddr.Address;
  1859. rifRoute.dwRtInfoIfIndex = g_pInternalInterfaceCb->dwIfIndex;
  1860. rifRoute.dwRtInfoMetric1 = 1;
  1861. rifRoute.dwRtInfoMetric2 = 0;
  1862. rifRoute.dwRtInfoMetric3 = 0;
  1863. rifRoute.dwRtInfoPreference=
  1864. ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  1865. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  1866. RTM_VIEW_MASK_MCAST; // XXX config
  1867. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1868. rifRoute.dwRtInfoProto = MIB_IPPROTO_NETMGMT;
  1869. rifRoute.dwRtInfoAge = INFINITE;
  1870. rifRoute.dwRtInfoNextHopAS = 0;
  1871. rifRoute.dwRtInfoPolicy = 0;
  1872. dwResult = AddSingleRoute(g_pInternalInterfaceCb->dwIfIndex,
  1873. &rifRoute,
  1874. clientAddr.Mask,
  1875. 0, // RTM_ROUTE_INFO::Flags
  1876. TRUE,
  1877. FALSE,
  1878. FALSE,
  1879. NULL);
  1880. #endif
  1881. ENTER_READER(PROTOCOL_CB_LIST);
  1882. //
  1883. // Call ConnectClient for all the protocols configured
  1884. // over the ServerInterface
  1885. //
  1886. for(pleNode = g_pInternalInterfaceCb->leProtocolList.Flink;
  1887. pleNode isnot &(g_pInternalInterfaceCb->leProtocolList);
  1888. pleNode = pleNode->Flink)
  1889. {
  1890. PIF_PROTO pIfProto;
  1891. pIfProto = CONTAINING_RECORD(pleNode,
  1892. IF_PROTO,
  1893. leIfProtoLink);
  1894. if(pIfProto->pActiveProto->pfnConnectClient)
  1895. {
  1896. pIfProto->pActiveProto->pfnConnectClient(
  1897. g_pInternalInterfaceCb->dwIfIndex,
  1898. &clientAddr
  1899. );
  1900. }
  1901. }
  1902. EXIT_LOCK(PROTOCOL_CB_LIST);
  1903. for (i=0; i<NUM_INFO_CBS; i++)
  1904. {
  1905. if (!g_rgicInfoCb[i].pfnBindInterface)
  1906. {
  1907. continue;
  1908. }
  1909. dwResult = g_rgicInfoCb[i].pfnBindInterface(pIcb);
  1910. if(dwResult isnot NO_ERROR)
  1911. {
  1912. Trace3(IF,
  1913. "InterfaceConnected: Error %d binding %S for %s info",
  1914. dwResult,
  1915. pIcb->pwszName,
  1916. g_rgicInfoCb[i].pszInfoName);
  1917. }
  1918. }
  1919. AddAllClientRoutes(pIcb,
  1920. g_pInternalInterfaceCb->dwIfIndex);
  1921. }
  1922. }
  1923. }
  1924. else
  1925. {
  1926. Trace1(
  1927. ANY,
  1928. "InterfaceConnected : No interface with ICB number %d",
  1929. HandleToULong(hInterface)
  1930. );
  1931. }
  1932. EXIT_LOCK(ICB_LIST);
  1933. TraceLeave("InterfaceConnected");
  1934. ExitRouterApi();
  1935. return NO_ERROR;
  1936. }
  1937. DWORD
  1938. SetGlobalInfo(
  1939. IN LPVOID pGlobalInfo
  1940. )
  1941. {
  1942. DWORD dwSize, dwResult, i, j;
  1943. PPROTO_CB pProtocolCb;
  1944. PLIST_ENTRY pleNode ;
  1945. BOOL bFoundProto, bFoundInfo;
  1946. PRTR_INFO_BLOCK_HEADER pInfoHdr;
  1947. MPR_PROTOCOL_0 *pmpProtocolInfo;
  1948. DWORD dwNumProtoEntries;
  1949. PVOID pvInfo;
  1950. PRTR_TOC_ENTRY pToc;
  1951. PGLOBAL_INFO pRtrGlobalInfo;
  1952. EnterRouterApi();
  1953. TraceEnter("SetGlobalInfo");
  1954. if(pGlobalInfo is NULL)
  1955. {
  1956. TraceLeave("SetGlobalInfo");
  1957. ExitRouterApi();
  1958. return NO_ERROR;
  1959. }
  1960. pInfoHdr = (PRTR_INFO_BLOCK_HEADER)pGlobalInfo;
  1961. //
  1962. // Set Routing Protocol Priority info. Priority information is in its
  1963. // own DLL so no locks need to be taken
  1964. //
  1965. SetPriorityInfo(pInfoHdr);
  1966. //
  1967. // Set Multicast Scope info (no locks needed)
  1968. //
  1969. SetScopeInfo(pInfoHdr);
  1970. //
  1971. // Enforce the discipline of taking ICBListLock before Routing lock
  1972. //
  1973. ENTER_WRITER(ICB_LIST);
  1974. ENTER_WRITER(PROTOCOL_CB_LIST);
  1975. pToc = GetPointerToTocEntry(IP_GLOBAL_INFO,
  1976. pInfoHdr);
  1977. if(pToc is NULL)
  1978. {
  1979. Trace0(GLOBAL,
  1980. "SetGlobalInfo: No TOC found for Global Info");
  1981. }
  1982. else
  1983. {
  1984. if(pToc->InfoSize is 0)
  1985. {
  1986. g_dwLoggingLevel = IPRTR_LOGGING_NONE;
  1987. }
  1988. else
  1989. {
  1990. pRtrGlobalInfo = (PGLOBAL_INFO)GetInfoFromTocEntry(pInfoHdr,
  1991. pToc);
  1992. g_dwLoggingLevel = (pRtrGlobalInfo isnot NULL) ?
  1993. pRtrGlobalInfo->dwLoggingLevel :
  1994. IPRTR_LOGGING_NONE;
  1995. }
  1996. }
  1997. dwResult = MprSetupProtocolEnum(PID_IP,
  1998. (PBYTE *)(&pmpProtocolInfo),
  1999. &dwNumProtoEntries);
  2000. if(dwResult isnot NO_ERROR)
  2001. {
  2002. Trace1(ERR,
  2003. "SetGlobalInfo: Error %d loading protocol info from registry",
  2004. dwResult);
  2005. EXIT_LOCK(PROTOCOL_CB_LIST);
  2006. EXIT_LOCK(ICB_LIST);
  2007. TraceLeave("SetGlobalInfo");
  2008. ExitRouterApi();
  2009. return ERROR_REGISTRY_CORRUPT;
  2010. }
  2011. //
  2012. // Now go looking for protocols TOCs
  2013. //
  2014. for(i = 0; i < pInfoHdr->TocEntriesCount; i++)
  2015. {
  2016. ULONG ulStructureVersion, ulStructureSize, ulStructureCount;
  2017. DWORD dwType;
  2018. dwType = TYPE_FROM_PROTO_ID(pInfoHdr->TocEntry[i].InfoType);
  2019. if(dwType == PROTO_TYPE_MS1)
  2020. {
  2021. continue;
  2022. }
  2023. //
  2024. // Go through the loaded routing protocols and see if the protocol is
  2025. // in the list
  2026. // If it is, we just call SetGlobalInfo callback.
  2027. // If not we load the protocol
  2028. //
  2029. pProtocolCb = NULL;
  2030. bFoundProto = FALSE;
  2031. for(pleNode = g_leProtoCbList.Flink;
  2032. pleNode != &g_leProtoCbList;
  2033. pleNode = pleNode->Flink)
  2034. {
  2035. pProtocolCb = CONTAINING_RECORD(pleNode,
  2036. PROTO_CB,
  2037. leList) ;
  2038. if(pProtocolCb->dwProtocolId is pInfoHdr->TocEntry[i].InfoType)
  2039. {
  2040. bFoundProto = TRUE;
  2041. break;
  2042. }
  2043. }
  2044. if(bFoundProto)
  2045. {
  2046. //
  2047. // Ok, so this protocol was already loaded.
  2048. //
  2049. if(pInfoHdr->TocEntry[i].InfoSize is 0)
  2050. {
  2051. //
  2052. // 0 TOC size means delete
  2053. //
  2054. if(pProtocolCb->posOpState is RTR_STATE_RUNNING)
  2055. {
  2056. //
  2057. // If its stopped or stopping, we dont tell it again
  2058. //
  2059. Trace1(GLOBAL,
  2060. "SetGlobalInfo: Removing %S since the TOC size was 0",
  2061. pProtocolCb->pwszDisplayName);
  2062. dwResult = StopRoutingProtocol(pProtocolCb);
  2063. if(dwResult is NO_ERROR)
  2064. {
  2065. //
  2066. // The routing protocol stopped synchronously and
  2067. // all references to it in the interfaces have
  2068. // been removed
  2069. //
  2070. //
  2071. // At this point we need to hold the PROTOCOL_CB_LIST
  2072. // lock exclusively
  2073. //
  2074. //
  2075. // relenquish CPU to enable DLL threads to
  2076. // finish
  2077. //
  2078. Sleep(0);
  2079. FreeLibrary(pProtocolCb->hiHInstance);
  2080. RemoveEntryList(&(pProtocolCb->leList));
  2081. HeapFree(IPRouterHeap,
  2082. 0,
  2083. pProtocolCb);
  2084. TotalRoutingProtocols--;
  2085. }
  2086. else
  2087. {
  2088. if(dwResult isnot ERROR_PROTOCOL_STOP_PENDING)
  2089. {
  2090. Trace2(ERR,
  2091. "SetGlobalInfo: Error %d stopping %S. Not removing from list",
  2092. dwResult,
  2093. pProtocolCb->pwszDisplayName);
  2094. }
  2095. }
  2096. }
  2097. }
  2098. else
  2099. {
  2100. //
  2101. // So we do have info with this protocol
  2102. //
  2103. pvInfo = GetInfoFromTocEntry(pInfoHdr,
  2104. &(pInfoHdr->TocEntry[i]));
  2105. //ulStructureVersion = pInfoHdr->TocEntry[i].InfoVersion;
  2106. ulStructureVersion = 0x500;
  2107. ulStructureSize = pInfoHdr->TocEntry[i].InfoSize;
  2108. ulStructureCount = pInfoHdr->TocEntry[i].Count;
  2109. dwResult = (pProtocolCb->pfnSetGlobalInfo)(pvInfo,
  2110. ulStructureVersion,
  2111. ulStructureSize,
  2112. ulStructureCount);
  2113. if(dwResult isnot NO_ERROR)
  2114. {
  2115. Trace2(ERR,
  2116. "SetGlobalInfo: Error %d setting info for %S",
  2117. dwResult,
  2118. pProtocolCb->pwszDisplayName);
  2119. }
  2120. }
  2121. }
  2122. else
  2123. {
  2124. //
  2125. // Well the protocol was not found so, lets load it up
  2126. //
  2127. //
  2128. // Bad case when size == 0
  2129. //
  2130. if(pInfoHdr->TocEntry[i].InfoSize is 0)
  2131. {
  2132. continue;
  2133. }
  2134. bFoundInfo = FALSE;
  2135. for(j = 0; j < dwNumProtoEntries; j ++)
  2136. {
  2137. if(pmpProtocolInfo[j].dwProtocolId is pInfoHdr->TocEntry[i].InfoType)
  2138. {
  2139. bFoundInfo = TRUE;
  2140. break;
  2141. }
  2142. }
  2143. if(!bFoundInfo)
  2144. {
  2145. Trace1(ERR,
  2146. "SetGlobalInfo: Couldnt find config information for %d",
  2147. pInfoHdr->TocEntry[i].InfoType);
  2148. continue;
  2149. }
  2150. //
  2151. // Load the library and make a cb for this protocol
  2152. //
  2153. dwSize =
  2154. (wcslen(pmpProtocolInfo[j].wszProtocol) + wcslen(pmpProtocolInfo[j].wszDLLName) + 2) * sizeof(WCHAR) +
  2155. sizeof(PROTO_CB);
  2156. pProtocolCb = HeapAlloc(IPRouterHeap,
  2157. HEAP_ZERO_MEMORY,
  2158. dwSize);
  2159. if(pProtocolCb is NULL)
  2160. {
  2161. Trace2(ERR,
  2162. "SetGlobalInfo: Error allocating %d bytes for %S",
  2163. dwSize,
  2164. pmpProtocolInfo[j].wszProtocol);
  2165. continue ;
  2166. }
  2167. pvInfo = GetInfoFromTocEntry(pInfoHdr,
  2168. &(pInfoHdr->TocEntry[i]));
  2169. //ulStructureVersion = pInfoHdr->TocEntry[i].InfoVersion;
  2170. ulStructureVersion = 0x500;
  2171. ulStructureSize = pInfoHdr->TocEntry[i].InfoSize;
  2172. ulStructureCount = pInfoHdr->TocEntry[i].Count;
  2173. dwResult = LoadProtocol(&(pmpProtocolInfo[j]),
  2174. pProtocolCb,
  2175. pvInfo,
  2176. ulStructureVersion,
  2177. ulStructureSize,
  2178. ulStructureCount);
  2179. if(dwResult isnot NO_ERROR)
  2180. {
  2181. Trace2(ERR,
  2182. "SetGlobalInfo: %S failed to load: %d",
  2183. pmpProtocolInfo[j].wszProtocol,
  2184. dwResult);
  2185. HeapFree (IPRouterHeap,
  2186. 0,
  2187. pProtocolCb) ;
  2188. }
  2189. else
  2190. {
  2191. pProtocolCb->posOpState = RTR_STATE_RUNNING ;
  2192. //
  2193. // Insert this routing protocol in the list of routing
  2194. // protocols
  2195. //
  2196. InsertTailList (&g_leProtoCbList, &pProtocolCb->leList);
  2197. Trace1(GLOBAL,
  2198. "SetGlobalInfo: %S successfully initialized",
  2199. pmpProtocolInfo[j].wszProtocol) ;
  2200. TotalRoutingProtocols++;
  2201. //
  2202. // Lets see if it wants to be in promiscuous add mode.
  2203. // If so, add all the current interfaces
  2204. //
  2205. if(pProtocolCb->fSupportedFunctionality & RF_ADD_ALL_INTERFACES)
  2206. {
  2207. //
  2208. // First lets add the internal interface
  2209. //
  2210. if(g_pInternalInterfaceCb)
  2211. {
  2212. dwResult = AddInterfaceToProtocol(g_pInternalInterfaceCb,
  2213. pProtocolCb,
  2214. NULL,
  2215. 0,
  2216. 0,
  2217. 0);
  2218. if(dwResult isnot NO_ERROR)
  2219. {
  2220. Trace3(ERR,
  2221. "SetGlobalInfo: Error %d adding %S to %S promously",
  2222. dwResult,
  2223. g_pInternalInterfaceCb->pwszName,
  2224. pProtocolCb->pwszDisplayName);
  2225. }
  2226. if(g_pInternalInterfaceCb->dwAdminState is IF_ADMIN_STATUS_UP)
  2227. {
  2228. EnableInterfaceWithAllProtocols(g_pInternalInterfaceCb);
  2229. }
  2230. if(g_pInternalInterfaceCb->bBound)
  2231. {
  2232. BindInterfaceInAllProtocols(g_pInternalInterfaceCb);
  2233. }
  2234. }
  2235. for(pleNode = &ICBList;
  2236. pleNode->Flink != &ICBList;
  2237. pleNode = pleNode->Flink)
  2238. {
  2239. PICB pIcb;
  2240. pIcb = CONTAINING_RECORD(pleNode->Flink,
  2241. ICB,
  2242. leIfLink);
  2243. if(pIcb is g_pInternalInterfaceCb)
  2244. {
  2245. //
  2246. // Already added, continue;
  2247. //
  2248. continue;
  2249. }
  2250. if(pIcb->ritType is ROUTER_IF_TYPE_DIALOUT)
  2251. {
  2252. //
  2253. // Skip dial out interfaces
  2254. //
  2255. continue;
  2256. }
  2257. if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
  2258. {
  2259. IP_LOCAL_BINDING clientAddr;
  2260. //
  2261. // Just call connect client for these
  2262. // We have to have internal interface
  2263. //
  2264. clientAddr.Address = pIcb->pibBindings[0].dwAddress;
  2265. clientAddr.Mask = pIcb->pibBindings[0].dwMask;
  2266. if(pProtocolCb->pfnConnectClient)
  2267. {
  2268. pProtocolCb->pfnConnectClient(g_pInternalInterfaceCb->dwIfIndex,
  2269. &clientAddr);
  2270. }
  2271. continue;
  2272. }
  2273. //
  2274. // The rest we add
  2275. //
  2276. dwResult = AddInterfaceToProtocol(pIcb,
  2277. pProtocolCb,
  2278. NULL,
  2279. 0,
  2280. 0,
  2281. 0);
  2282. if(dwResult isnot NO_ERROR)
  2283. {
  2284. Trace3(ERR,
  2285. "SetGlobalInfo: Error %d adding %S to %S promiscuously",
  2286. dwResult,
  2287. pIcb->pwszName,
  2288. pProtocolCb->pwszDisplayName);
  2289. continue;
  2290. }
  2291. if(pIcb->dwAdminState is IF_ADMIN_STATUS_UP)
  2292. {
  2293. EnableInterfaceWithAllProtocols(pIcb);
  2294. }
  2295. if(pIcb->bBound)
  2296. {
  2297. BindInterfaceInAllProtocols(pIcb);
  2298. }
  2299. }
  2300. }
  2301. }
  2302. }
  2303. }
  2304. MprSetupProtocolFree(pmpProtocolInfo);
  2305. EXIT_LOCK(PROTOCOL_CB_LIST);
  2306. EXIT_LOCK(ICB_LIST);
  2307. TraceLeave("SetGlobalInfo");
  2308. ExitRouterApi();
  2309. return NO_ERROR;
  2310. }
  2311. DWORD
  2312. GetGlobalInfo(
  2313. OUT LPVOID pGlobalInfo,
  2314. IN OUT LPDWORD lpdwGlobalInfoSize
  2315. )
  2316. /*++
  2317. Routine Description
  2318. This function
  2319. Locks
  2320. None
  2321. Arguments
  2322. None
  2323. Return Value
  2324. None
  2325. --*/
  2326. {
  2327. DWORD dwSize;
  2328. DWORD dwResult;
  2329. EnterRouterApi();
  2330. TraceEnter("GetGlobalInfo");
  2331. ENTER_READER(ICB_LIST);
  2332. ENTER_READER(PROTOCOL_CB_LIST);
  2333. dwSize = GetSizeOfGlobalInfo();
  2334. if(dwSize > *lpdwGlobalInfoSize)
  2335. {
  2336. *lpdwGlobalInfoSize = dwSize;
  2337. EXIT_LOCK(PROTOCOL_CB_LIST);
  2338. EXIT_LOCK(ICB_LIST);
  2339. TraceLeave("GetGlobalInfo");
  2340. ExitRouterApi();
  2341. return ERROR_INSUFFICIENT_BUFFER;
  2342. }
  2343. dwResult = GetGlobalConfiguration((PRTR_INFO_BLOCK_HEADER)pGlobalInfo,
  2344. *lpdwGlobalInfoSize);
  2345. if(dwResult isnot NO_ERROR)
  2346. {
  2347. Trace1(ERR,
  2348. "GetGlobalInfo: Error %d getting global config",
  2349. dwResult);
  2350. }
  2351. EXIT_LOCK(PROTOCOL_CB_LIST);
  2352. EXIT_LOCK(ICB_LIST);
  2353. TraceLeave("GetGlobalInfo");
  2354. ExitRouterApi();
  2355. return NO_ERROR;
  2356. }
  2357. DWORD
  2358. UpdateRoutes(
  2359. IN HANDLE hInterface,
  2360. IN HANDLE hEvent
  2361. )
  2362. {
  2363. DWORD i;
  2364. DWORD dwResult;
  2365. PIF_PROTO pProto;
  2366. PICB pIcb;
  2367. PLIST_ENTRY pleNode;
  2368. EnterRouterApi();
  2369. TraceEnter("UpdateRoutes");
  2370. // *** Exclusion Begin ***
  2371. ENTER_READER(ICB_LIST);
  2372. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  2373. IpRtAssert(pIcb);
  2374. if (pIcb != NULL)
  2375. {
  2376. Trace1(ROUTE,
  2377. "UpdateRoutes: Updating routes over %S", pIcb->pwszName) ;
  2378. if(pIcb->dwOperationalState < CONNECTED)
  2379. {
  2380. Trace1(ERR,
  2381. "UpdateRoutes: %S is not connected.",
  2382. pIcb->pwszName);
  2383. EXIT_LOCK(ICB_LIST);
  2384. TraceLeave("UpdateRoutes");
  2385. ExitRouterApi();
  2386. return ERROR_INVALID_PARAMETER;
  2387. }
  2388. //
  2389. // We first delete all the routes over this interface. If we
  2390. // fail the update routes, that means we have lost the autostatic
  2391. // routes. But that is OK, since if we fail for some reason - that
  2392. // is an error condition and we should be getting rid of the routes
  2393. // anyway. Sure, we can fail for non protocol related reasons
  2394. // (out of memory) but that is also an error. Earlier we used to
  2395. // let the routing protocol finish its update and then delete the
  2396. // route. However if RIP did not have "Overwrite routes" stuff
  2397. // set, it would not write its routes to RTM. So now we first delete
  2398. // the routes. This means that for some time (while the update is
  2399. // going on) we have loss of reachability.
  2400. //
  2401. dwResult = DeleteRtmRoutesOnInterface(g_hAutoStaticRoute,
  2402. pIcb->dwIfIndex);
  2403. if(//(dwResult isnot ERROR_NO_ROUTES) and
  2404. (dwResult isnot NO_ERROR))
  2405. {
  2406. Trace1(ERR,
  2407. "UpdateRoutes: Error %d block deleting routes",
  2408. dwResult);
  2409. EXIT_LOCK(ICB_LIST);
  2410. TraceLeave("UpdateRoutes");
  2411. ExitRouterApi();
  2412. return dwResult ;
  2413. }
  2414. if(pIcb->hDIMNotificationEvent isnot NULL)
  2415. {
  2416. //
  2417. // There is already an update routes for this interface in progress
  2418. //
  2419. dwResult = ERROR_UPDATE_IN_PROGRESS;
  2420. }
  2421. else
  2422. {
  2423. dwResult = ERROR_FILE_NOT_FOUND;
  2424. // *** Exclusion Begin ***
  2425. ENTER_READER(PROTOCOL_CB_LIST);
  2426. //
  2427. // Find a protocol that supports update route operation. we
  2428. // settle for the first one that does.
  2429. //
  2430. for(pleNode = pIcb->leProtocolList.Flink;
  2431. pleNode isnot &(pIcb->leProtocolList);
  2432. pleNode = pleNode->Flink)
  2433. {
  2434. pProto = CONTAINING_RECORD(pleNode,
  2435. IF_PROTO,
  2436. leIfProtoLink);
  2437. if(pProto->pActiveProto->pfnUpdateRoutes isnot NULL)
  2438. {
  2439. //
  2440. // found a routing protocol that supports updates
  2441. //
  2442. dwResult = (pProto->pActiveProto->pfnUpdateRoutes)(
  2443. pIcb->dwIfIndex
  2444. );
  2445. if((dwResult isnot NO_ERROR) and (dwResult isnot PENDING))
  2446. {
  2447. //
  2448. // The protocol can return NO_ERROR, or PENDING all
  2449. // else is an error
  2450. //
  2451. Trace2(ERR,
  2452. "UpdateRoutes: %S returned %d while trying to update routes. Trying other protocols",
  2453. pProto->pActiveProto->pwszDisplayName,
  2454. dwResult);
  2455. }
  2456. else
  2457. {
  2458. //
  2459. // Even if the protocol returned NO_ERROR, this is
  2460. // an inherently
  2461. // asynchronous call, so we return PENDING
  2462. //
  2463. dwResult = PENDING;
  2464. pIcb->hDIMNotificationEvent = hEvent;
  2465. break;
  2466. }
  2467. }
  2468. }
  2469. // *** Exclusion End ***
  2470. EXIT_LOCK(PROTOCOL_CB_LIST);
  2471. }
  2472. }
  2473. else
  2474. {
  2475. Trace1(
  2476. ANY,
  2477. "UpdateRoutes : No interface with ICB number %d",
  2478. HandleToULong(hInterface)
  2479. );
  2480. dwResult = ERROR_INVALID_INDEX;
  2481. }
  2482. // *** Exclusion End ***
  2483. EXIT_LOCK(ICB_LIST);
  2484. TraceLeave("UpdateRoutes");
  2485. ExitRouterApi();
  2486. return dwResult ;
  2487. }
  2488. DWORD
  2489. GetUpdateRoutesResult(
  2490. IN HANDLE hInterface,
  2491. OUT PDWORD pdwUpdateResult
  2492. )
  2493. {
  2494. DWORD dwResult ;
  2495. UpdateResultList *pResult ;
  2496. PLIST_ENTRY pleNode ;
  2497. PICB pIcb;
  2498. EnterRouterApi();
  2499. TraceEnter("GetUpdateRoutesResult") ;
  2500. // *** Exclusion Begin ***
  2501. ENTER_WRITER(ICB_LIST);
  2502. pIcb = InterfaceLookupByICBSeqNumber(HandleToULong(hInterface));
  2503. IpRtAssert(pIcb);
  2504. if (pIcb != NULL)
  2505. {
  2506. if (IsListEmpty (&pIcb->lePendingResultList))
  2507. {
  2508. dwResult = ERROR_CAN_NOT_COMPLETE ;
  2509. }
  2510. else
  2511. {
  2512. pleNode = RemoveHeadList (&pIcb->lePendingResultList) ;
  2513. pResult = CONTAINING_RECORD(pleNode,
  2514. UpdateResultList,
  2515. URL_List) ;
  2516. *pdwUpdateResult = pResult->URL_UpdateStatus;
  2517. HeapFree(IPRouterHeap,
  2518. 0,
  2519. pResult) ;
  2520. dwResult = NO_ERROR ;
  2521. }
  2522. }
  2523. else
  2524. {
  2525. Trace1(
  2526. ANY,
  2527. "GetInterfaceInfo : No interface with ICB number %d",
  2528. HandleToULong(hInterface)
  2529. );
  2530. dwResult = ERROR_INVALID_INDEX;
  2531. }
  2532. // *** Exclusion End ***
  2533. EXIT_LOCK(ICB_LIST);
  2534. TraceLeave("GetUpdateRoutesResult");
  2535. ExitRouterApi();
  2536. return dwResult;
  2537. }
  2538. DWORD
  2539. DemandDialRequest(
  2540. IN DWORD dwProtocolId,
  2541. IN DWORD dwInterfaceIndex
  2542. )
  2543. {
  2544. PICB pIcb;
  2545. DWORD dwResult;
  2546. HANDLE hDim;
  2547. EnterRouterApi();
  2548. TraceEnter("DemandDialRequest");
  2549. //
  2550. // This doesnt follow the normal locking rules of not taking locks
  2551. // when calling up
  2552. //
  2553. ENTER_READER(ICB_LIST);
  2554. pIcb = InterfaceLookupByIfIndex(dwInterfaceIndex);
  2555. if(pIcb is NULL)
  2556. {
  2557. EXIT_LOCK(ICB_LIST);
  2558. return ERROR_INVALID_INDEX;
  2559. }
  2560. hDim = pIcb->hDIMHandle;
  2561. EXIT_LOCK(ICB_LIST);
  2562. dwResult = (ConnectInterface)(hDim,
  2563. PID_IP);
  2564. TraceLeave("DemandDialRequest");
  2565. ExitRouterApi();
  2566. return dwResult;
  2567. }
  2568. DWORD
  2569. RtrMgrMIBEntryCreate(
  2570. IN DWORD dwRoutingPid,
  2571. IN DWORD dwEntrySize,
  2572. IN LPVOID lpEntry
  2573. )
  2574. {
  2575. PMIB_OPAQUE_QUERY pQuery;
  2576. PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpEntry;
  2577. DWORD dwInEntrySize,dwOutEntrySize, dwResult;
  2578. BOOL fCache;
  2579. PPROTO_CB pProtocolCb ;
  2580. PLIST_ENTRY pleNode ;
  2581. DWORD rgdwQuery[6];
  2582. EnterRouterApi();;
  2583. TraceEnter("RtrMgrMIBEntryCreate");
  2584. pQuery = (PMIB_OPAQUE_QUERY)rgdwQuery;
  2585. if(dwRoutingPid is IPRTRMGR_PID)
  2586. {
  2587. switch(pInfo->dwId)
  2588. {
  2589. case IP_FORWARDROW:
  2590. {
  2591. PMIB_IPFORWARDROW pRow = (PMIB_IPFORWARDROW)(pInfo->rgbyData);
  2592. pQuery->dwVarId = IP_FORWARDROW;
  2593. pQuery->rgdwVarIndex[0] = pRow->dwForwardDest;
  2594. pQuery->rgdwVarIndex[1] = pRow->dwForwardProto;
  2595. pQuery->rgdwVarIndex[2] = pRow->dwForwardPolicy;
  2596. pQuery->rgdwVarIndex[3] = pRow->dwForwardNextHop;
  2597. dwOutEntrySize = dwEntrySize;
  2598. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + 3 * sizeof(DWORD);
  2599. dwResult = AccessIpForwardRow(ACCESS_CREATE_ENTRY,
  2600. dwInEntrySize,
  2601. pQuery,
  2602. &dwOutEntrySize,
  2603. pInfo,
  2604. &fCache);
  2605. break;
  2606. }
  2607. case ROUTE_MATCHING:
  2608. {
  2609. dwOutEntrySize = dwEntrySize;
  2610. dwResult = AccessIpMatchingRoute(ACCESS_CREATE_ENTRY,
  2611. 0,
  2612. NULL,
  2613. &dwOutEntrySize,
  2614. pInfo,
  2615. &fCache);
  2616. break;
  2617. }
  2618. case IP_NETROW:
  2619. {
  2620. PMIB_IPNETROW pRow = (PMIB_IPNETROW)(pInfo->rgbyData);
  2621. pQuery->dwVarId = IP_NETROW;
  2622. pQuery->rgdwVarIndex[0] = pRow->dwIndex;
  2623. pQuery->rgdwVarIndex[1] = pRow->dwAddr;
  2624. dwOutEntrySize = dwEntrySize;
  2625. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD);
  2626. dwResult = AccessIpNetRow(ACCESS_CREATE_ENTRY,
  2627. dwInEntrySize,
  2628. pQuery,
  2629. &dwOutEntrySize,
  2630. pInfo,
  2631. &fCache);
  2632. break;
  2633. }
  2634. case PROXY_ARP:
  2635. {
  2636. PMIB_PROXYARP pRow = (PMIB_PROXYARP)(pInfo->rgbyData);
  2637. pQuery->dwVarId = IP_NETROW;
  2638. pQuery->rgdwVarIndex[0] = pRow->dwAddress;
  2639. pQuery->rgdwVarIndex[1] = pRow->dwMask;
  2640. pQuery->rgdwVarIndex[2] = pRow->dwIfIndex;
  2641. dwOutEntrySize = dwEntrySize;
  2642. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + (2 * sizeof(DWORD));
  2643. dwResult = AccessProxyArp(ACCESS_CREATE_ENTRY,
  2644. dwInEntrySize,
  2645. pQuery,
  2646. &dwOutEntrySize,
  2647. pInfo,
  2648. &fCache);
  2649. break;
  2650. }
  2651. default:
  2652. {
  2653. dwResult = ERROR_INVALID_PARAMETER;
  2654. break;
  2655. }
  2656. }
  2657. }
  2658. else
  2659. {
  2660. //
  2661. // Send over to other pids
  2662. //
  2663. // *** Exclusion Begin ***
  2664. ENTER_READER(PROTOCOL_CB_LIST);
  2665. dwResult = ERROR_CAN_NOT_COMPLETE;
  2666. for(pleNode = g_leProtoCbList.Flink;
  2667. pleNode != &g_leProtoCbList;
  2668. pleNode = pleNode->Flink)
  2669. {
  2670. pProtocolCb = CONTAINING_RECORD(pleNode,
  2671. PROTO_CB,
  2672. leList);
  2673. if (dwRoutingPid == pProtocolCb->dwProtocolId)
  2674. {
  2675. dwResult = (pProtocolCb->pfnMibCreateEntry)(dwEntrySize,
  2676. lpEntry) ;
  2677. break;
  2678. }
  2679. }
  2680. // *** Exclusion End ***
  2681. EXIT_LOCK(PROTOCOL_CB_LIST);
  2682. }
  2683. TraceLeave("RtrMgrMIBEntryCreate");
  2684. ExitRouterApi();
  2685. return dwResult;
  2686. }
  2687. DWORD
  2688. RtrMgrMIBEntryDelete(
  2689. IN DWORD dwRoutingPid,
  2690. IN DWORD dwEntrySize,
  2691. IN LPVOID lpEntry
  2692. )
  2693. {
  2694. DWORD dwOutEntrySize = 0;
  2695. PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY) lpEntry;
  2696. DWORD dwResult;
  2697. BOOL fCache;
  2698. PPROTO_CB pProtocolCb ;
  2699. PLIST_ENTRY pleNode ;
  2700. EnterRouterApi();
  2701. TraceEnter("RtrMgrMIBEntryDelete");
  2702. if(dwRoutingPid is IPRTRMGR_PID)
  2703. {
  2704. switch(pQuery->dwVarId)
  2705. {
  2706. case IP_FORWARDROW:
  2707. {
  2708. dwResult = AccessIpForwardRow(ACCESS_DELETE_ENTRY,
  2709. dwEntrySize,
  2710. pQuery,
  2711. &dwOutEntrySize,
  2712. NULL,
  2713. &fCache);
  2714. break;
  2715. }
  2716. case ROUTE_MATCHING:
  2717. {
  2718. dwResult = AccessIpMatchingRoute(ACCESS_DELETE_ENTRY,
  2719. dwEntrySize,
  2720. pQuery,
  2721. &dwOutEntrySize,
  2722. NULL,
  2723. &fCache);
  2724. break;
  2725. }
  2726. case IP_NETROW:
  2727. {
  2728. dwResult = AccessIpNetRow(ACCESS_DELETE_ENTRY,
  2729. dwEntrySize,
  2730. pQuery,
  2731. &dwOutEntrySize,
  2732. NULL,
  2733. &fCache);
  2734. break;
  2735. }
  2736. case PROXY_ARP:
  2737. {
  2738. dwResult = AccessProxyArp(ACCESS_DELETE_ENTRY,
  2739. dwEntrySize,
  2740. pQuery,
  2741. &dwOutEntrySize,
  2742. NULL,
  2743. &fCache);
  2744. break;
  2745. }
  2746. case IP_NETTABLE:
  2747. {
  2748. dwResult = AccessIpNetRow(ACCESS_DELETE_ENTRY,
  2749. dwEntrySize,
  2750. pQuery,
  2751. &dwOutEntrySize,
  2752. NULL,
  2753. &fCache);
  2754. break;
  2755. }
  2756. default:
  2757. {
  2758. dwResult = ERROR_INVALID_PARAMETER;
  2759. break;
  2760. }
  2761. }
  2762. }
  2763. else
  2764. {
  2765. // *** Exclusion Begin ***
  2766. ENTER_READER(PROTOCOL_CB_LIST);
  2767. dwResult = ERROR_CAN_NOT_COMPLETE;
  2768. for (pleNode = g_leProtoCbList.Flink;
  2769. pleNode != &g_leProtoCbList;
  2770. pleNode = pleNode->Flink)
  2771. {
  2772. pProtocolCb = CONTAINING_RECORD(pleNode,
  2773. PROTO_CB,
  2774. leList);
  2775. if(dwRoutingPid == pProtocolCb->dwProtocolId)
  2776. {
  2777. dwResult = (pProtocolCb->pfnMibDeleteEntry)(dwEntrySize,
  2778. lpEntry);
  2779. break ;
  2780. }
  2781. }
  2782. // *** Exclusion End ***
  2783. EXIT_LOCK(PROTOCOL_CB_LIST);
  2784. }
  2785. TraceLeave("RtrMgrMIBEntryDelete");
  2786. ExitRouterApi();
  2787. return dwResult;
  2788. }
  2789. DWORD
  2790. RtrMgrMIBEntrySet(
  2791. IN DWORD dwRoutingPid,
  2792. IN DWORD dwEntrySize,
  2793. IN LPVOID lpEntry
  2794. )
  2795. {
  2796. PMIB_OPAQUE_QUERY pQuery;
  2797. PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpEntry;
  2798. DWORD dwInEntrySize, dwOutEntrySize, dwResult=NO_ERROR;
  2799. BOOL fCache;
  2800. PPROTO_CB pProtocolCb ;
  2801. PLIST_ENTRY pleNode ;
  2802. DWORD rgdwQuery[6];
  2803. EnterRouterApi();;
  2804. TraceEnter("RtrMgrMIBEntrySet");
  2805. pQuery = (PMIB_OPAQUE_QUERY)rgdwQuery;
  2806. if(dwRoutingPid is IPRTRMGR_PID)
  2807. {
  2808. switch(pInfo->dwId)
  2809. {
  2810. case IF_ROW:
  2811. {
  2812. PMIB_IFROW pRow = (PMIB_IFROW)(pInfo->rgbyData);
  2813. pQuery->dwVarId = IF_ROW;
  2814. pQuery->rgdwVarIndex[0] = pRow->dwIndex;
  2815. dwOutEntrySize = dwEntrySize;
  2816. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY);
  2817. dwResult = AccessIfRow(ACCESS_SET,
  2818. dwInEntrySize,
  2819. pQuery,
  2820. &dwOutEntrySize,
  2821. pInfo,
  2822. &fCache);
  2823. break;
  2824. }
  2825. case TCP_ROW:
  2826. {
  2827. PMIB_TCPROW pRow = (PMIB_TCPROW)(pInfo->rgbyData);
  2828. pQuery->dwVarId = TCP_ROW;
  2829. pQuery->rgdwVarIndex[0] = pRow->dwLocalAddr;
  2830. pQuery->rgdwVarIndex[1] = pRow->dwLocalPort;
  2831. pQuery->rgdwVarIndex[2] = pRow->dwRemoteAddr;
  2832. pQuery->rgdwVarIndex[3] = pRow->dwRemotePort;
  2833. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + (3 * sizeof(DWORD));
  2834. dwOutEntrySize = dwEntrySize;
  2835. dwResult = AccessTcpRow(ACCESS_SET,
  2836. dwInEntrySize,
  2837. pQuery,
  2838. &dwOutEntrySize,
  2839. pInfo,
  2840. &fCache);
  2841. break;
  2842. }
  2843. case IP_STATS:
  2844. {
  2845. PMIB_IPSTATS pStats = (PMIB_IPSTATS)(pInfo->rgbyData);
  2846. pQuery->dwVarId = IP_STATS;
  2847. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) - sizeof(DWORD);
  2848. dwOutEntrySize = dwEntrySize;
  2849. dwResult = AccessIpStats(ACCESS_SET,
  2850. dwInEntrySize,
  2851. pQuery,
  2852. &dwOutEntrySize,
  2853. pInfo,
  2854. &fCache);
  2855. break;
  2856. }
  2857. case IP_FORWARDROW:
  2858. {
  2859. PMIB_IPFORWARDROW pRow = (PMIB_IPFORWARDROW)(pInfo->rgbyData);
  2860. pQuery->dwVarId = IP_FORWARDROW;
  2861. pQuery->rgdwVarIndex[0] = pRow->dwForwardDest;
  2862. pQuery->rgdwVarIndex[1] = pRow->dwForwardProto;
  2863. pQuery->rgdwVarIndex[2] = pRow->dwForwardPolicy;
  2864. pQuery->rgdwVarIndex[3] = pRow->dwForwardNextHop;
  2865. dwOutEntrySize = dwEntrySize;
  2866. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + 3 * sizeof(DWORD);
  2867. dwResult = AccessIpForwardRow(ACCESS_SET,
  2868. dwInEntrySize,
  2869. pQuery,
  2870. &dwOutEntrySize,
  2871. pInfo,
  2872. &fCache);
  2873. break;
  2874. }
  2875. case ROUTE_MATCHING:
  2876. {
  2877. dwOutEntrySize = dwEntrySize;
  2878. dwResult = AccessIpMatchingRoute(ACCESS_SET,
  2879. 0,
  2880. NULL,
  2881. &dwOutEntrySize,
  2882. pInfo,
  2883. &fCache);
  2884. break;
  2885. }
  2886. case IP_NETROW:
  2887. {
  2888. PMIB_IPNETROW pRow = (PMIB_IPNETROW)(pInfo->rgbyData);
  2889. pQuery->dwVarId = IP_NETROW;
  2890. pQuery->rgdwVarIndex[0] = pRow->dwIndex;
  2891. pQuery->rgdwVarIndex[1] = pRow->dwAddr;
  2892. dwOutEntrySize = dwEntrySize;
  2893. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD);
  2894. dwResult = AccessIpNetRow(ACCESS_SET,
  2895. dwInEntrySize,
  2896. pQuery,
  2897. &dwOutEntrySize,
  2898. pInfo,
  2899. &fCache);
  2900. break;
  2901. }
  2902. case MCAST_MFE:
  2903. {
  2904. dwResult = AccessMcastMfe(ACCESS_SET,
  2905. 0,
  2906. NULL,
  2907. &dwOutEntrySize,
  2908. pInfo,
  2909. &fCache);
  2910. break;
  2911. }
  2912. case MCAST_BOUNDARY:
  2913. {
  2914. dwResult = AccessMcastBoundary(ACCESS_SET,
  2915. 0,
  2916. NULL,
  2917. &dwOutEntrySize,
  2918. pInfo,
  2919. &fCache);
  2920. break;
  2921. }
  2922. case MCAST_SCOPE:
  2923. {
  2924. dwResult = AccessMcastScope(ACCESS_SET,
  2925. 0,
  2926. NULL,
  2927. &dwOutEntrySize,
  2928. pInfo,
  2929. &fCache);
  2930. break;
  2931. }
  2932. case PROXY_ARP:
  2933. {
  2934. PMIB_PROXYARP pRow = (PMIB_PROXYARP)(pInfo->rgbyData);
  2935. pQuery->dwVarId = IP_NETROW;
  2936. pQuery->rgdwVarIndex[0] = pRow->dwAddress;
  2937. pQuery->rgdwVarIndex[1] = pRow->dwMask;
  2938. pQuery->rgdwVarIndex[2] = pRow->dwIfIndex;
  2939. dwOutEntrySize = dwEntrySize;
  2940. dwInEntrySize = sizeof(MIB_OPAQUE_QUERY) + (2 * sizeof(DWORD));
  2941. dwResult = AccessProxyArp(ACCESS_CREATE_ENTRY,
  2942. dwInEntrySize,
  2943. pQuery,
  2944. &dwOutEntrySize,
  2945. pInfo,
  2946. &fCache);
  2947. break;
  2948. }
  2949. default:
  2950. {
  2951. dwResult = ERROR_INVALID_PARAMETER;
  2952. break;
  2953. }
  2954. }
  2955. }
  2956. else
  2957. {
  2958. // *** Exclusion Begin ***
  2959. ENTER_READER(PROTOCOL_CB_LIST);
  2960. dwResult = ERROR_CAN_NOT_COMPLETE;
  2961. for (pleNode = g_leProtoCbList.Flink;
  2962. pleNode != &g_leProtoCbList;
  2963. pleNode = pleNode->Flink)
  2964. {
  2965. pProtocolCb = CONTAINING_RECORD(pleNode,
  2966. PROTO_CB,
  2967. leList) ;
  2968. if (dwRoutingPid == pProtocolCb->dwProtocolId)
  2969. {
  2970. dwResult = (pProtocolCb->pfnMibSetEntry) (dwEntrySize, lpEntry) ;
  2971. break ;
  2972. }
  2973. }
  2974. // *** Exclusion End ***
  2975. EXIT_LOCK(PROTOCOL_CB_LIST);
  2976. }
  2977. TraceLeave("RtrMgrMIBEntrySet");
  2978. ExitRouterApi();
  2979. return dwResult;
  2980. }
  2981. DWORD
  2982. RtrMgrMIBEntryGet(
  2983. IN DWORD dwRoutingPid,
  2984. IN DWORD dwInEntrySize,
  2985. IN LPVOID lpInEntry,
  2986. IN OUT LPDWORD lpOutEntrySize,
  2987. OUT LPVOID lpOutEntry
  2988. )
  2989. {
  2990. PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY)lpInEntry;
  2991. PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpOutEntry;
  2992. BOOL fCache;
  2993. DWORD dwResult;
  2994. PPROTO_CB pProtocolCb ;
  2995. PLIST_ENTRY pleNode ;
  2996. EnterRouterApi();
  2997. TraceEnter("RtrMgrMIBEntryGet");
  2998. if(dwRoutingPid is IPRTRMGR_PID)
  2999. {
  3000. if(*lpOutEntrySize > 0)
  3001. {
  3002. ZeroMemory(lpOutEntry,
  3003. *lpOutEntrySize);
  3004. }
  3005. dwResult = (*g_AccessFunctionTable[pQuery->dwVarId])(ACCESS_GET,
  3006. dwInEntrySize,
  3007. pQuery,
  3008. lpOutEntrySize,
  3009. pInfo,
  3010. &fCache);
  3011. }
  3012. else
  3013. {
  3014. // *** Exclusion Begin ***
  3015. ENTER_READER(PROTOCOL_CB_LIST);
  3016. dwResult = ERROR_CAN_NOT_COMPLETE;
  3017. for (pleNode = g_leProtoCbList.Flink;
  3018. pleNode != &g_leProtoCbList;
  3019. pleNode = pleNode->Flink)
  3020. {
  3021. pProtocolCb = CONTAINING_RECORD(pleNode,
  3022. PROTO_CB,
  3023. leList);
  3024. if (dwRoutingPid == pProtocolCb->dwProtocolId)
  3025. {
  3026. dwResult = (pProtocolCb->pfnMibGetEntry) (dwInEntrySize,
  3027. lpInEntry,
  3028. lpOutEntrySize,
  3029. lpOutEntry) ;
  3030. break ;
  3031. }
  3032. }
  3033. // *** Exclusion End ***
  3034. EXIT_LOCK(PROTOCOL_CB_LIST);
  3035. }
  3036. TraceLeave("RtrMgrMIBEntryGet");
  3037. ExitRouterApi();
  3038. return dwResult;
  3039. }
  3040. DWORD
  3041. RtrMgrMIBEntryGetFirst(
  3042. IN DWORD dwRoutingPid,
  3043. IN DWORD dwInEntrySize,
  3044. IN LPVOID lpInEntry,
  3045. IN OUT LPDWORD lpOutEntrySize,
  3046. OUT LPVOID lpOutEntry
  3047. )
  3048. {
  3049. PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY)lpInEntry;
  3050. PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpOutEntry;
  3051. DWORD dwResult;
  3052. BOOL fCache;
  3053. PPROTO_CB pProtocolCb ;
  3054. PLIST_ENTRY pleNode ;
  3055. EnterRouterApi();
  3056. TraceEnter("RtrMgrMIBEntryGetFirst");
  3057. if(dwRoutingPid is IPRTRMGR_PID)
  3058. {
  3059. if(*lpOutEntrySize > 0)
  3060. {
  3061. ZeroMemory(lpOutEntry,
  3062. *lpOutEntrySize);
  3063. }
  3064. dwResult = (*g_AccessFunctionTable[pQuery->dwVarId])(ACCESS_GET_FIRST,
  3065. dwInEntrySize,
  3066. pQuery,
  3067. lpOutEntrySize,
  3068. pInfo,
  3069. &fCache);
  3070. }
  3071. else
  3072. {
  3073. // *** Exclusion Begin ***
  3074. ENTER_READER(PROTOCOL_CB_LIST);
  3075. dwResult = ERROR_CAN_NOT_COMPLETE;
  3076. for(pleNode = g_leProtoCbList.Flink;
  3077. pleNode != &g_leProtoCbList;
  3078. pleNode = pleNode->Flink)
  3079. {
  3080. pProtocolCb = CONTAINING_RECORD(pleNode,
  3081. PROTO_CB,
  3082. leList) ;
  3083. if (dwRoutingPid == pProtocolCb->dwProtocolId)
  3084. {
  3085. dwResult = (pProtocolCb->pfnMibGetFirstEntry)(dwInEntrySize,
  3086. lpInEntry,
  3087. lpOutEntrySize,
  3088. lpOutEntry);
  3089. break;
  3090. }
  3091. }
  3092. // *** Exclusion End ***
  3093. EXIT_LOCK(PROTOCOL_CB_LIST);
  3094. }
  3095. TraceLeave("RtrMgrMIBEntryGetFirst");
  3096. ExitRouterApi();
  3097. return dwResult;
  3098. }
  3099. DWORD
  3100. RtrMgrMIBEntryGetNext(
  3101. IN DWORD dwRoutingPid,
  3102. IN DWORD dwInEntrySize,
  3103. IN LPVOID lpInEntry,
  3104. IN OUT LPDWORD lpOutEntrySize,
  3105. OUT LPVOID lpOutEntry
  3106. )
  3107. {
  3108. PMIB_OPAQUE_QUERY pQuery = (PMIB_OPAQUE_QUERY)lpInEntry;
  3109. PMIB_OPAQUE_INFO pInfo = (PMIB_OPAQUE_INFO)lpOutEntry;
  3110. DWORD dwResult;
  3111. BOOL fCache;
  3112. PPROTO_CB pProtocolCb ;
  3113. PLIST_ENTRY pleNode ;
  3114. EnterRouterApi();
  3115. TraceEnter("RtrMgrMIBEntryGetNext");
  3116. if(dwRoutingPid is IPRTRMGR_PID)
  3117. {
  3118. if(*lpOutEntrySize > 0)
  3119. {
  3120. ZeroMemory(lpOutEntry,
  3121. *lpOutEntrySize);
  3122. }
  3123. dwResult = (*g_AccessFunctionTable[pQuery->dwVarId])(ACCESS_GET_NEXT,
  3124. dwInEntrySize,
  3125. pQuery,
  3126. lpOutEntrySize,
  3127. pInfo,
  3128. &fCache);
  3129. }
  3130. else
  3131. {
  3132. // *** Exclusion Begin ***
  3133. ENTER_READER(PROTOCOL_CB_LIST);
  3134. dwResult = ERROR_CAN_NOT_COMPLETE;
  3135. for(pleNode = g_leProtoCbList.Flink;
  3136. pleNode != &g_leProtoCbList;
  3137. pleNode = pleNode->Flink)
  3138. {
  3139. pProtocolCb = CONTAINING_RECORD(pleNode,
  3140. PROTO_CB,
  3141. leList) ;
  3142. if(dwRoutingPid == pProtocolCb->dwProtocolId)
  3143. {
  3144. dwResult = (pProtocolCb->pfnMibGetNextEntry)(dwInEntrySize,
  3145. lpInEntry,
  3146. lpOutEntrySize,
  3147. lpOutEntry);
  3148. break;
  3149. }
  3150. }
  3151. // *** Exclusion End ***
  3152. EXIT_LOCK(PROTOCOL_CB_LIST);
  3153. }
  3154. TraceLeave("RtrMgrMIBEntryGetNext");
  3155. ExitRouterApi();
  3156. return dwResult;
  3157. }