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.

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