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.

1852 lines
50 KiB

  1. #include "precomp.h"
  2. WCHAR g_wszRtrMgrDLL[] = L"%SystemRoot%\\system32\\IPRTRMGR.DLL";
  3. DWORD g_dwIfState = MIB_IF_ADMIN_STATUS_UP;
  4. BOOL g_bDiscEnable = FALSE;
  5. #define IP_KEY L"Ip"
  6. #undef EXTRA_DEBUG
  7. DWORD
  8. ValidateInterfaceInfo(
  9. IN LPCWSTR pwszIfName,
  10. OUT RTR_INFO_BLOCK_HEADER **ppInfo, OPTIONAL
  11. OUT PDWORD pdwIfType, OPTIONAL
  12. OUT INTERFACE_STORE **ppIfStore OPTIONAL
  13. )
  14. {
  15. PRTR_INFO_BLOCK_HEADER pOldInfo = NULL;
  16. DWORD dwErr, dwIfType, dwTmpSize;
  17. BOOL bFound = FALSE;
  18. LIST_ENTRY *ple;
  19. PINTERFACE_STORE pii;
  20. if(ppInfo)
  21. {
  22. *ppInfo = NULL;
  23. }
  24. if(ppIfStore)
  25. {
  26. *ppIfStore = NULL;
  27. }
  28. //
  29. // If the current mode is commit, get info from config/router
  30. //
  31. if(g_bCommit)
  32. {
  33. dwErr = GetInterfaceInfo(pwszIfName,
  34. ppInfo,
  35. NULL,
  36. pdwIfType);
  37. return dwErr;
  38. }
  39. //
  40. // Uncommit mode. Try to find the interface in the list
  41. //
  42. bFound = FALSE;
  43. for(ple = g_leIfListHead.Flink;
  44. ple != &g_leIfListHead;
  45. ple = ple->Flink)
  46. {
  47. pii = CONTAINING_RECORD(ple, INTERFACE_STORE, le);
  48. if (_wcsicmp(pii->pwszIfName, pwszIfName) == 0)
  49. {
  50. bFound = TRUE;
  51. break;
  52. }
  53. }
  54. if(!bFound ||
  55. !pii->bValid)
  56. {
  57. //
  58. // the required one was not found, or it was not valid
  59. // Need to get the info for both cases
  60. //
  61. dwErr = GetInterfaceInfo(pwszIfName,
  62. &pOldInfo,
  63. NULL,
  64. &dwIfType);
  65. if (dwErr isnot NO_ERROR)
  66. {
  67. return dwErr;
  68. }
  69. }
  70. if(bFound)
  71. {
  72. if(!pii->bValid)
  73. {
  74. //
  75. // Update
  76. //
  77. pii->pibhInfo = pOldInfo;
  78. pii->bValid = TRUE;
  79. pii->dwIfType = dwIfType;
  80. }
  81. }
  82. else
  83. {
  84. //
  85. // No entry for the interface in the list.
  86. //
  87. pii = HeapAlloc(GetProcessHeap(),
  88. 0,
  89. sizeof(INTERFACE_STORE));
  90. if(pii == NULL)
  91. {
  92. FREE_BUFFER(pOldInfo);
  93. DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  94. return ERROR_NOT_ENOUGH_MEMORY;
  95. }
  96. pii->pwszIfName =
  97. HeapAlloc(GetProcessHeap(),
  98. 0,
  99. (wcslen(pwszIfName) + 1) * sizeof(WCHAR));
  100. if(pii->pwszIfName == NULL)
  101. {
  102. FREE_BUFFER(pOldInfo);
  103. HeapFree(GetProcessHeap(),
  104. 0,
  105. pii);
  106. DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  107. return ERROR_NOT_ENOUGH_MEMORY;
  108. }
  109. InsertHeadList(&g_leIfListHead, &(pii->le));
  110. wcscpy(pii->pwszIfName, pwszIfName);
  111. pii->pibhInfo = pOldInfo;
  112. pii->bValid = TRUE;
  113. pii->dwIfType = dwIfType;
  114. }
  115. if(ppIfStore)
  116. {
  117. *ppIfStore = pii;
  118. }
  119. if(pdwIfType)
  120. {
  121. *pdwIfType = pii->dwIfType;
  122. }
  123. if(ppInfo)
  124. {
  125. *ppInfo = pii->pibhInfo;
  126. }
  127. return NO_ERROR;
  128. }
  129. DWORD
  130. ValidateGlobalInfo(
  131. OUT RTR_INFO_BLOCK_HEADER **ppInfo
  132. )
  133. {
  134. DWORD dwErr;
  135. //
  136. // If the current mode is commit, get info from config/router
  137. //
  138. if(g_bCommit)
  139. {
  140. dwErr = GetGlobalInfo(ppInfo);
  141. return dwErr;
  142. }
  143. //
  144. // Uncommit mode. Check if the info in g_tiTransport is valid
  145. //
  146. if(g_tiTransport.bValid)
  147. {
  148. *ppInfo = g_tiTransport.pibhInfo;
  149. }
  150. else
  151. {
  152. //
  153. // Get the info from config/router and store in g_tiTransport
  154. // Mark the info to be valid.
  155. //
  156. dwErr = GetGlobalInfo(ppInfo);
  157. if (dwErr isnot NO_ERROR)
  158. {
  159. return dwErr;
  160. }
  161. g_tiTransport.pibhInfo = *ppInfo;
  162. g_tiTransport.bValid = TRUE;
  163. }
  164. return NO_ERROR;
  165. }
  166. DWORD
  167. GetGlobalInfo(
  168. OUT PRTR_INFO_BLOCK_HEADER *ppibhInfo
  169. )
  170. /*++
  171. Routine Description:
  172. Gets global transport information from registry or router.
  173. Arguments:
  174. bMprConfig - Info from Registry or info from router
  175. ppibhInfo - ptr to header
  176. Return Value:
  177. NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_ROUTER_STOPPED
  178. --*/
  179. {
  180. HANDLE hTransport = (HANDLE) NULL;
  181. DWORD dwRes, dwSize;
  182. PRTR_INFO_BLOCK_HEADER pibhInfo = (PRTR_INFO_BLOCK_HEADER ) NULL;
  183. if(ppibhInfo == NULL)
  184. {
  185. return ERROR_INVALID_PARAMETER;
  186. }
  187. do
  188. {
  189. #ifdef READROUTERINFO
  190. if (IsRouterRunning())
  191. {
  192. //
  193. // Retrieve global protocol information from router
  194. //
  195. dwRes = MprAdminTransportGetInfo(g_hMprAdmin,
  196. PID_IP,
  197. (LPBYTE*) &pibhInfo,
  198. &dwSize,
  199. NULL,
  200. NULL);
  201. if ( dwRes != NO_ERROR )
  202. {
  203. break;
  204. }
  205. if ( pibhInfo == (PRTR_INFO_BLOCK_HEADER) NULL )
  206. {
  207. dwRes = ERROR_INVALID_PARAMETER;
  208. break;
  209. }
  210. //
  211. // unfortunately, the memory allocation mechanisms
  212. // are different between the apis that access the registry
  213. // and those that access that the running router. To make
  214. // the source of the info transparent to the caller, we
  215. // need to copy this info out.
  216. //
  217. *ppibhInfo = HeapAlloc(GetProcessHeap(),
  218. 0,
  219. dwSize);
  220. if ( *ppibhInfo == NULL)
  221. {
  222. dwRes = GetLastError();
  223. break;
  224. }
  225. CopyMemory(*ppibhInfo,
  226. pibhInfo,
  227. dwSize);
  228. MprAdminBufferFree(pibhInfo);
  229. }
  230. else
  231. #endif
  232. {
  233. #ifdef READROUTERINFO
  234. //
  235. // Router not running, get info from the registry
  236. //
  237. #else
  238. //
  239. // Always get the information from the registry.
  240. // Doesn't matter if the router is running or not.
  241. // When setting the global information,
  242. // write it to registry and to the router (if it is running).
  243. //
  244. #endif
  245. dwRes = MprConfigTransportGetHandle(g_hMprConfig,
  246. PID_IP,
  247. &hTransport);
  248. if ( dwRes != NO_ERROR )
  249. {
  250. break;
  251. }
  252. dwRes = MprConfigTransportGetInfo(g_hMprConfig,
  253. hTransport,
  254. (LPBYTE*) &pibhInfo,
  255. &dwSize,
  256. NULL,
  257. NULL,
  258. NULL);
  259. if ( dwRes != NO_ERROR )
  260. {
  261. break;
  262. }
  263. if(( pibhInfo == (PRTR_INFO_BLOCK_HEADER) NULL )
  264. or (dwSize < sizeof(RTR_INFO_BLOCK_HEADER)))
  265. {
  266. dwRes = ERROR_TRANSPORT_NOT_PRESENT;
  267. break;
  268. }
  269. //
  270. // HACKHACK: we know that MprConfigXxx apis allocate from
  271. // process heap, so we can return the same block
  272. //
  273. *ppibhInfo = pibhInfo;
  274. }
  275. } while(FALSE);
  276. return dwRes;
  277. }
  278. DWORD
  279. SetGlobalInfo(
  280. IN PRTR_INFO_BLOCK_HEADER pibhInfo
  281. )
  282. /*++
  283. Routine Description:
  284. Sets global transport information to both the registry and the router
  285. Arguments:
  286. pibhInfo - ptr to header
  287. Return Value:
  288. NO_ERROR, ERROR_ROUTER_STOPPED
  289. --*/
  290. {
  291. DWORD dwARes = NO_ERROR,
  292. dwCRes = NO_ERROR;
  293. HANDLE hTransport;
  294. UINT i;
  295. PRTR_INFO_BLOCK_HEADER pibhNewInfo, pibhOldInfo;
  296. //
  297. // Create a new info block with all 0-length blocks removed
  298. // since we don't want to write them to the registry,
  299. // we only need to send them to the router which we
  300. // will do with the original info block below.
  301. //
  302. pibhOldInfo = NULL;
  303. pibhNewInfo = pibhInfo;
  304. for (i=0; (dwCRes is NO_ERROR) && (i<pibhInfo->TocEntriesCount); i++)
  305. {
  306. if (pibhInfo->TocEntry[i].InfoSize is 0)
  307. {
  308. pibhOldInfo = pibhNewInfo;
  309. dwCRes = MprInfoBlockRemove(pibhOldInfo,
  310. pibhOldInfo->TocEntry[i].InfoType,
  311. &pibhNewInfo);
  312. if (pibhOldInfo isnot pibhInfo)
  313. {
  314. FREE_BUFFER(pibhOldInfo);
  315. }
  316. }
  317. }
  318. if (dwCRes is NO_ERROR)
  319. {
  320. dwCRes = MprConfigTransportGetHandle(g_hMprConfig,
  321. PID_IP,
  322. &hTransport);
  323. }
  324. if (dwCRes is NO_ERROR)
  325. {
  326. dwCRes = MprConfigTransportSetInfo(g_hMprConfig,
  327. hTransport,
  328. (LPBYTE) pibhNewInfo,
  329. pibhNewInfo->Size,
  330. NULL,
  331. 0,
  332. NULL);
  333. }
  334. if (pibhNewInfo isnot pibhInfo)
  335. {
  336. FREE_BUFFER(pibhNewInfo);
  337. }
  338. //
  339. // Even if we failed to write to the registry, we still want
  340. // to write to the router.
  341. //
  342. // We use the original format when writing to the router, since it
  343. // needs to see the 0-length blocks in order to delete config info.
  344. //
  345. if(IsRouterRunning())
  346. {
  347. dwARes = MprAdminTransportSetInfo(g_hMprAdmin,
  348. PID_IP,
  349. (LPBYTE) pibhInfo,
  350. pibhInfo->Size,
  351. NULL,
  352. 0);
  353. }
  354. return (dwARes isnot NO_ERROR)? dwARes : dwCRes;
  355. }
  356. DWORD
  357. GetInterfaceInfo(
  358. IN LPCWSTR pwszIfName,
  359. OUT RTR_INFO_BLOCK_HEADER **ppibhInfo, OPTIONAL
  360. OUT PMPR_INTERFACE_0 pMprIfInfo, OPTIONAL
  361. OUT PDWORD pdwIfType OPTIONAL
  362. )
  363. /*++
  364. Routine Description:
  365. Gets global transport information from registry or router.
  366. If one of the out information is not required, then the parameter
  367. can be NULL.
  368. Arguments:
  369. pwszIfName - Interface Name
  370. bMprConfig - Info from Registry or info from router
  371. ppibhInfo - ptr to header
  372. pMprIfInfo - ptr to interface info
  373. pdwIfType - Type of interface
  374. Return Value:
  375. NO_ERROR,
  376. ERROR_NO_SUCH_INTERFACE
  377. ERROR_TRANSPORT_NOT_PRESENT
  378. --*/
  379. {
  380. PMPR_INTERFACE_0 pMprIf = NULL;
  381. PRTR_INFO_BLOCK_HEADER pibh;
  382. HANDLE hInterface,hIfTransport;
  383. DWORD dwRes, dwSize;
  384. if(((ULONG_PTR)ppibhInfo | (ULONG_PTR)pMprIfInfo | (ULONG_PTR)pdwIfType) ==
  385. (ULONG_PTR)NULL)
  386. {
  387. return NO_ERROR;
  388. }
  389. do
  390. {
  391. #ifdef READROUTERINFO
  392. if(IsRouterRunning())
  393. {
  394. //
  395. // Get info from the router
  396. //
  397. dwRes = MprAdminInterfaceGetHandle(g_hMprAdmin,
  398. (LPWSTR)pwszIfName,
  399. &hInterface,
  400. FALSE);
  401. if( dwRes != NO_ERROR )
  402. {
  403. break;
  404. }
  405. if(pMprIfInfo || pdwIfType)
  406. {
  407. dwRes = MprAdminInterfaceGetInfo(g_hMprAdmin,
  408. hInterface,
  409. 0,
  410. (LPBYTE *) &pMprIf);
  411. if ( dwRes != NO_ERROR )
  412. {
  413. break;
  414. }
  415. if (pMprIf == NULL)
  416. {
  417. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  418. break;
  419. }
  420. if(pMprIfInfo)
  421. {
  422. //
  423. // structure copy
  424. //
  425. *pMprIfInfo= *pMprIf;
  426. }
  427. if(pdwIfType)
  428. {
  429. *pdwIfType = pMprIf->dwIfType;
  430. }
  431. MprAdminBufferFree(pMprIf);
  432. }
  433. if(ppibhInfo)
  434. {
  435. dwRes = MprAdminInterfaceTransportGetInfo(g_hMprAdmin,
  436. hInterface,
  437. PID_IP,
  438. (LPBYTE*) &pibh,
  439. &dwSize);
  440. if(dwRes != NO_ERROR)
  441. {
  442. break;
  443. }
  444. if(pibh == (PRTR_INFO_BLOCK_HEADER) NULL)
  445. {
  446. dwRes = ERROR_TRANSPORT_NOT_PRESENT;
  447. break;
  448. }
  449. //
  450. // The info returned to the user must be from
  451. // process heap. Admin calls use MIDL allocation, so
  452. // copy out info
  453. //
  454. *ppibhInfo = HeapAlloc(GetProcessHeap(),
  455. 0,
  456. dwSize);
  457. if(*ppibhInfo == NULL)
  458. {
  459. dwRes = GetLastError();
  460. break;
  461. }
  462. CopyMemory(*ppibhInfo,
  463. pibh,
  464. dwSize);
  465. MprAdminBufferFree(pibh);
  466. }
  467. }
  468. else
  469. #endif
  470. {
  471. #ifdef READROUTERINFO
  472. //
  473. // Router not running, get info from the registry
  474. //
  475. #else
  476. //
  477. // Always get the information from the registry.
  478. // Doesn't matter if the router is running or not.
  479. // When setting the interface information,
  480. // write it to registry and to the router (if it is running).
  481. //
  482. #endif
  483. dwRes = MprConfigInterfaceGetHandle(g_hMprConfig,
  484. (LPWSTR)pwszIfName,
  485. &hInterface);
  486. if(dwRes != NO_ERROR)
  487. {
  488. break;
  489. }
  490. if(pMprIfInfo || pdwIfType)
  491. {
  492. dwRes = MprConfigInterfaceGetInfo(g_hMprConfig,
  493. hInterface,
  494. 0,
  495. (LPBYTE *) &pMprIf,
  496. &dwSize);
  497. if(dwRes != NO_ERROR)
  498. {
  499. break;
  500. }
  501. if (pMprIf == NULL)
  502. {
  503. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  504. break;
  505. }
  506. if(pdwIfType)
  507. {
  508. *pdwIfType = pMprIf->dwIfType;
  509. }
  510. if(pMprIfInfo)
  511. {
  512. *pMprIfInfo = *pMprIf;
  513. }
  514. MprConfigBufferFree(pMprIf);
  515. }
  516. if (ppibhInfo)
  517. {
  518. dwRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
  519. hInterface,
  520. PID_IP,
  521. &hIfTransport);
  522. if(dwRes != NO_ERROR)
  523. {
  524. break;
  525. }
  526. dwRes = MprConfigInterfaceTransportGetInfo(g_hMprConfig,
  527. hInterface,
  528. hIfTransport,
  529. (LPBYTE*) &pibh,
  530. &dwSize);
  531. if(dwRes != NO_ERROR)
  532. {
  533. break;
  534. }
  535. if((pibh == (PRTR_INFO_BLOCK_HEADER) NULL)
  536. or (dwSize < sizeof(RTR_INFO_BLOCK_HEADER)))
  537. {
  538. dwRes = ERROR_TRANSPORT_NOT_PRESENT;
  539. break;
  540. }
  541. //
  542. // Again, since this is also allocated from process heap
  543. //
  544. *ppibhInfo = pibh;
  545. }
  546. }
  547. } while (FALSE);
  548. return dwRes;
  549. }
  550. DWORD
  551. MakeIPGlobalInfo( LPBYTE* ppBuff )
  552. {
  553. DWORD dwSize = 0,
  554. dwRes = (DWORD) -1;
  555. LPBYTE pbDataPtr = (LPBYTE) NULL;
  556. PRTR_TOC_ENTRY pTocEntry = (PRTR_TOC_ENTRY) NULL;
  557. PGLOBAL_INFO pGlbInfo = NULL;
  558. PPRIORITY_INFO pPriorInfo = NULL;
  559. PRTR_INFO_BLOCK_HEADER pIBH = (PRTR_INFO_BLOCK_HEADER) NULL;
  560. //
  561. // Alocate for minimal global Information
  562. //
  563. dwSize = sizeof( RTR_INFO_BLOCK_HEADER ) + sizeof(GLOBAL_INFO) +
  564. sizeof( RTR_TOC_ENTRY ) + SIZEOF_PRIORITY_INFO(7) +
  565. 2 * ALIGN_SIZE;
  566. pIBH = (PRTR_INFO_BLOCK_HEADER) HeapAlloc( GetProcessHeap(), 0, dwSize );
  567. if ( pIBH == (PRTR_INFO_BLOCK_HEADER) NULL )
  568. {
  569. DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  570. *ppBuff = (LPBYTE) NULL;
  571. return ERROR_NOT_ENOUGH_MEMORY;
  572. }
  573. //
  574. // init. infobase fields
  575. //
  576. *ppBuff = (LPBYTE) pIBH;
  577. pIBH-> Version = RTR_INFO_BLOCK_VERSION;
  578. pIBH-> TocEntriesCount = 2;
  579. pIBH-> Size = dwSize;
  580. pbDataPtr = (LPBYTE) &( pIBH-> TocEntry[ pIBH-> TocEntriesCount ] );
  581. ALIGN_POINTER( pbDataPtr );
  582. //
  583. // make IP rtr mgr global info.
  584. //
  585. pTocEntry = &(pIBH-> TocEntry[ 0 ]);
  586. pTocEntry-> InfoType = IP_GLOBAL_INFO;
  587. pTocEntry-> Count = 1;
  588. pTocEntry-> Offset = (ULONG)(pbDataPtr - (PBYTE) pIBH);
  589. pTocEntry-> InfoSize = sizeof(GLOBAL_INFO);
  590. pGlbInfo = (PGLOBAL_INFO) pbDataPtr;
  591. pGlbInfo-> bFilteringOn = TRUE;
  592. pGlbInfo-> dwLoggingLevel = IPRTR_LOGGING_ERROR;
  593. pbDataPtr += pTocEntry->Count * pTocEntry-> InfoSize;
  594. ALIGN_POINTER( pbDataPtr );
  595. //
  596. // make IP rtr priority. Info
  597. //
  598. pTocEntry = &(pIBH-> TocEntry[ 1 ]);
  599. pTocEntry-> InfoType = IP_PROT_PRIORITY_INFO;
  600. pTocEntry-> Count = 1;
  601. pTocEntry-> Offset = (DWORD)(pbDataPtr - (PBYTE) pIBH);
  602. pTocEntry-> InfoSize = SIZEOF_PRIORITY_INFO(7);
  603. pPriorInfo = (PPRIORITY_INFO) pbDataPtr;
  604. pPriorInfo-> dwNumProtocols = 7;
  605. pPriorInfo-> ppmProtocolMetric[ 0 ].dwProtocolId = PROTO_IP_LOCAL;
  606. pPriorInfo-> ppmProtocolMetric[ 0 ].dwMetric = 1;
  607. pPriorInfo-> ppmProtocolMetric[ 1 ].dwProtocolId = PROTO_IP_NT_STATIC;
  608. pPriorInfo-> ppmProtocolMetric[ 1 ].dwMetric = 3;
  609. pPriorInfo-> ppmProtocolMetric[ 2 ].dwProtocolId = PROTO_IP_NT_STATIC_NON_DOD;
  610. pPriorInfo-> ppmProtocolMetric[ 2 ].dwMetric = 5;
  611. pPriorInfo-> ppmProtocolMetric[ 3 ].dwProtocolId = PROTO_IP_NT_AUTOSTATIC;
  612. pPriorInfo-> ppmProtocolMetric[ 3 ].dwMetric = 7;
  613. pPriorInfo-> ppmProtocolMetric[ 4 ].dwProtocolId = PROTO_IP_NETMGMT;
  614. pPriorInfo-> ppmProtocolMetric[ 4 ].dwMetric = 10;
  615. pPriorInfo-> ppmProtocolMetric[ 5 ].dwProtocolId = PROTO_IP_OSPF;
  616. pPriorInfo-> ppmProtocolMetric[ 5 ].dwMetric = 110;
  617. pPriorInfo-> ppmProtocolMetric[ 6 ].dwProtocolId = PROTO_IP_RIP;
  618. pPriorInfo-> ppmProtocolMetric[ 6 ].dwMetric = 120;
  619. return NO_ERROR;
  620. }
  621. DWORD
  622. MakeIPInterfaceInfo(
  623. LPBYTE* ppBuff,
  624. DWORD dwIfType
  625. )
  626. {
  627. DWORD dwSize = (DWORD) -1;
  628. DWORD dwTocEntries = 2;
  629. LPBYTE pbDataPtr = (LPBYTE) NULL;
  630. PRTR_TOC_ENTRY pTocEntry = (PRTR_TOC_ENTRY) NULL;
  631. #if 0
  632. PRTR_DISC_INFO pRtrDisc = (PRTR_DISC_INFO) NULL;
  633. #endif
  634. PINTERFACE_STATUS_INFO pifStat = (PINTERFACE_STATUS_INFO) NULL;
  635. PRTR_INFO_BLOCK_HEADER pIBH = (PRTR_INFO_BLOCK_HEADER) NULL;
  636. #ifdef KSL_IPINIP
  637. PIPINIP_CONFIG_INFO pIpIpCfg;
  638. #endif //KSL_IPINIP
  639. //
  640. // Allocate for minimal interface Info.
  641. // a TOC entry is allocated for IP_ROUTE_INFO, but no route info
  642. // block is created, since initially there are no static routes.
  643. //
  644. dwSize = sizeof( RTR_INFO_BLOCK_HEADER ) +
  645. sizeof( RTR_TOC_ENTRY ) + sizeof( INTERFACE_STATUS_INFO ) +
  646. 2 * ALIGN_SIZE;
  647. #if 0
  648. if (dwIfType is ROUTER_IF_TYPE_DEDICATED)
  649. {
  650. dwSize += sizeof( RTR_TOC_ENTRY )
  651. + sizeof( RTR_DISC_INFO )
  652. + ALIGN_SIZE;
  653. dwTocEntries++;
  654. }
  655. #endif
  656. pIBH = (PRTR_INFO_BLOCK_HEADER) HeapAlloc( GetProcessHeap(), 0, dwSize );
  657. if ( pIBH == (PRTR_INFO_BLOCK_HEADER) NULL )
  658. {
  659. *ppBuff = (LPBYTE) NULL;
  660. DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY );
  661. return ERROR_NOT_ENOUGH_MEMORY;
  662. }
  663. *ppBuff = (LPBYTE) pIBH;
  664. pIBH-> Version = RTR_INFO_BLOCK_VERSION;
  665. pIBH-> TocEntriesCount = dwTocEntries;
  666. pIBH-> Size = dwSize;
  667. pbDataPtr = (LPBYTE) &( pIBH-> TocEntry[ pIBH-> TocEntriesCount ] );
  668. ALIGN_POINTER( pbDataPtr );
  669. //
  670. // Create empty route info block
  671. //
  672. pTocEntry = (PRTR_TOC_ENTRY) &( pIBH-> TocEntry[ 0 ] );
  673. pTocEntry-> InfoType = IP_ROUTE_INFO;
  674. pTocEntry-> InfoSize = sizeof( MIB_IPFORWARDROW );
  675. pTocEntry-> Count = 0;
  676. pTocEntry-> Offset = (ULONG) (pbDataPtr - (PBYTE) pIBH);
  677. pbDataPtr += pTocEntry-> Count * pTocEntry-> InfoSize;
  678. ALIGN_POINTER( pbDataPtr );
  679. //
  680. // Create interface status block.
  681. //
  682. pTocEntry = (PRTR_TOC_ENTRY) &( pIBH-> TocEntry[ 1 ] );
  683. pTocEntry-> InfoType = IP_INTERFACE_STATUS_INFO;
  684. pTocEntry-> InfoSize = sizeof( INTERFACE_STATUS_INFO );
  685. pTocEntry-> Count = 1;
  686. pTocEntry-> Offset = (ULONG) (pbDataPtr - (LPBYTE) pIBH);
  687. pifStat = (PINTERFACE_STATUS_INFO) pbDataPtr;
  688. pifStat-> dwAdminStatus = g_dwIfState;
  689. pbDataPtr += pTocEntry-> Count * pTocEntry-> InfoSize;
  690. ALIGN_POINTER( pbDataPtr );
  691. #if 0
  692. if (dwIfType is ROUTER_IF_TYPE_DEDICATED)
  693. {
  694. //
  695. // Create Router Disc. Info.
  696. //
  697. pTocEntry = (PRTR_TOC_ENTRY) &( pIBH-> TocEntry[ 2 ]);
  698. pTocEntry-> InfoType = IP_ROUTER_DISC_INFO;
  699. pTocEntry-> InfoSize = sizeof( RTR_DISC_INFO );
  700. pTocEntry-> Count = 1;
  701. pTocEntry-> Offset = (ULONG) (pbDataPtr - (LPBYTE) pIBH);
  702. pRtrDisc = (PRTR_DISC_INFO) pbDataPtr;
  703. pRtrDisc-> bAdvertise = TRUE;
  704. pRtrDisc-> wMaxAdvtInterval = g_wMaxAdvtInterval;
  705. pRtrDisc-> wMinAdvtInterval = g_wMinAdvtInterval;
  706. pRtrDisc-> wAdvtLifetime = g_wAdvtLifeTime;
  707. pRtrDisc-> lPrefLevel = g_lPrefLevel;
  708. pbDataPtr += pTocEntry-> Count * pTocEntry-> InfoSize;
  709. ALIGN_POINTER( pbDataPtr );
  710. }
  711. #endif
  712. return NO_ERROR;
  713. }
  714. DWORD
  715. AddInterfaceInfo(
  716. IN LPCWSTR pwszIfName
  717. )
  718. {
  719. DWORD dwRes = (DWORD) -1,
  720. dwIfType,
  721. dwSize = 0;
  722. BOOL bAddRtrMgr = FALSE;
  723. HANDLE hInterface = (HANDLE) NULL,
  724. hTransport = (HANDLE) NULL,
  725. hIfAdmin = (HANDLE) NULL,
  726. hIfTransport = (HANDLE) NULL;
  727. PRTR_INFO_BLOCK_HEADER pibhTmp = (PRTR_INFO_BLOCK_HEADER) NULL;
  728. #ifdef EXTRA_DEBUG
  729. PRINT(L"AddInterfaceInfo:");
  730. PRINT(pwszIfName);
  731. #endif
  732. do
  733. {
  734. PMPR_INTERFACE_0 pmiIfInfo;
  735. //
  736. // verify interface name.
  737. //
  738. dwRes = MprConfigInterfaceGetHandle( g_hMprConfig,
  739. (LPWSTR)pwszIfName,
  740. &hInterface );
  741. if ( dwRes != NO_ERROR )
  742. {
  743. DisplayMessage( g_hModule, MSG_NO_INTERFACE, pwszIfName );
  744. break;
  745. }
  746. // Make sure interface exists
  747. dwRes = MprConfigInterfaceGetInfo(g_hMprConfig,
  748. hInterface,
  749. 0,
  750. (BYTE **)&pmiIfInfo,
  751. &dwSize);
  752. if( dwRes != NO_ERROR )
  753. {
  754. DisplayError( NULL, dwRes );
  755. break;
  756. }
  757. dwIfType = pmiIfInfo->dwIfType;
  758. #ifdef KSL_IPINIP
  759. // Here's a hack due apparently due to the inability of
  760. // the current stack to do Foo-over-IP tunnels, so adding
  761. // an ipip tunnel both creates the tunnel and enables IP
  762. // on it.
  763. if(dwIfType is ROUTER_IF_TYPE_TUNNEL1)
  764. {
  765. MprConfigBufferFree(pmiIfInfo);
  766. dwRes = ERROR_INVALID_PARAMETER;
  767. DisplayMessage(g_hModule, MSG_IP_IF_IS_TUNNEL);
  768. break;
  769. }
  770. #endif //KSL_IPINIP
  771. MprConfigBufferFree(pmiIfInfo);
  772. //
  773. // Is IP RtrMgr present on this router.
  774. //
  775. // if specified IP router manager is absent,
  776. // we shall need to add global info for this
  777. // router manager "before" we add the interface
  778. // information
  779. //
  780. //
  781. // Try to get a handle to the rtr mgr.
  782. //
  783. dwRes = MprConfigTransportGetHandle(g_hMprConfig,
  784. PID_IP,
  785. &hTransport);
  786. if ( dwRes != NO_ERROR )
  787. {
  788. if ( dwRes == ERROR_UNKNOWN_PROTOCOL_ID )
  789. {
  790. bAddRtrMgr = TRUE;
  791. }
  792. else
  793. {
  794. DisplayError( NULL, dwRes );
  795. break;
  796. }
  797. }
  798. //
  799. // if handle is available, try to retrieve global info.
  800. // if not available we shall need to add the global info.
  801. //
  802. if ( !bAddRtrMgr )
  803. {
  804. dwRes = MprConfigTransportGetInfo(g_hMprConfig,
  805. hTransport,
  806. (LPBYTE*) &pibhTmp,
  807. &dwSize,
  808. NULL,
  809. NULL,
  810. NULL);
  811. if ( dwRes != NO_ERROR )
  812. {
  813. DisplayError( NULL, dwRes );
  814. break;
  815. }
  816. if ( pibhTmp == (PRTR_INFO_BLOCK_HEADER) NULL )
  817. {
  818. bAddRtrMgr = TRUE;
  819. }
  820. else
  821. {
  822. MprConfigBufferFree( pibhTmp );
  823. pibhTmp = NULL;
  824. }
  825. }
  826. //
  827. // If IP is already present on router, see if IP was already
  828. // added to the interface. If so, complain.
  829. //
  830. if ( !bAddRtrMgr )
  831. {
  832. dwRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
  833. hInterface,
  834. PID_IP,
  835. &hIfTransport);
  836. if ( dwRes == NO_ERROR )
  837. {
  838. dwRes = ERROR_INVALID_PARAMETER;
  839. // was SetInterfaceInRouterConfig(); to update
  840. break;
  841. }
  842. }
  843. //
  844. // If IP RtrMgr is not present, add global info.
  845. //
  846. if ( bAddRtrMgr )
  847. {
  848. dwRes = MakeIPGlobalInfo( (LPBYTE *)&pibhTmp );
  849. if ( dwRes != NO_ERROR )
  850. {
  851. break;
  852. }
  853. dwRes = MprConfigTransportCreate( g_hMprConfig,
  854. PID_IP,
  855. IP_KEY,
  856. (LPBYTE) pibhTmp,
  857. pibhTmp-> Size,
  858. NULL,
  859. 0,
  860. g_wszRtrMgrDLL,
  861. &hTransport );
  862. if ( dwRes != NO_ERROR )
  863. {
  864. DisplayError( NULL, dwRes );
  865. break;
  866. }
  867. HeapFree( GetProcessHeap(), 0, pibhTmp );
  868. }
  869. pibhTmp = (PRTR_INFO_BLOCK_HEADER) NULL;
  870. //
  871. // Add IP Rtr Mgr. information for the interface
  872. //
  873. dwRes = MakeIPInterfaceInfo( (LPBYTE*) &pibhTmp, dwIfType);
  874. if ( dwRes != NO_ERROR )
  875. {
  876. break;
  877. }
  878. dwRes = MprConfigInterfaceTransportAdd( g_hMprConfig,
  879. hInterface,
  880. PID_IP,
  881. IP_KEY,
  882. (LPBYTE) pibhTmp,
  883. pibhTmp-> Size,
  884. &hIfTransport );
  885. if ( dwRes != NO_ERROR )
  886. {
  887. DisplayError( NULL, dwRes );
  888. break;
  889. }
  890. if(IsRouterRunning())
  891. {
  892. dwRes = MprAdminInterfaceGetHandle(g_hMprAdmin,
  893. (LPWSTR)pwszIfName,
  894. &hIfAdmin,
  895. FALSE);
  896. if ( dwRes != NO_ERROR )
  897. {
  898. break;
  899. }
  900. dwRes = MprAdminInterfaceTransportAdd( g_hMprAdmin,
  901. hIfAdmin,
  902. PID_IP,
  903. (LPBYTE) pibhTmp,
  904. pibhTmp->Size );
  905. if ( dwRes != NO_ERROR )
  906. {
  907. DisplayMessage( g_hModule, ERROR_ADMIN, dwRes );
  908. break;
  909. }
  910. break;
  911. }
  912. } while( FALSE );
  913. //
  914. // Free all allocations
  915. //
  916. if ( pibhTmp ) { HeapFree( GetProcessHeap(), 0, pibhTmp ); }
  917. return dwRes;
  918. }
  919. DWORD
  920. DeleteInterfaceInfo(
  921. IN LPCWSTR pwszIfName
  922. )
  923. {
  924. DWORD dwRes, dwIfType = 0, dwErr;
  925. HANDLE hIfTransport, hInterface;
  926. do
  927. {
  928. dwRes = MprConfigInterfaceGetHandle(g_hMprConfig,
  929. (LPWSTR)pwszIfName,
  930. &hInterface);
  931. if ( dwRes != NO_ERROR )
  932. {
  933. break;
  934. }
  935. //
  936. // Get the type of the interface
  937. //
  938. dwErr = GetInterfaceInfo(pwszIfName,
  939. NULL,
  940. NULL,
  941. &dwIfType);
  942. if(dwErr != NO_ERROR)
  943. {
  944. break;
  945. }
  946. dwRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
  947. hInterface,
  948. PID_IP,
  949. &hIfTransport);
  950. if ( dwRes != NO_ERROR )
  951. {
  952. break;
  953. }
  954. dwRes = MprConfigInterfaceTransportRemove(g_hMprConfig,
  955. hInterface,
  956. hIfTransport);
  957. #ifdef KSL_IPINIP
  958. //
  959. // If its an ip in ip tunnel, clear out its name and delete from the
  960. // router
  961. //
  962. if(dwIfType == ROUTER_IF_TYPE_TUNNEL1)
  963. {
  964. dwRes = MprConfigInterfaceDelete(g_hMprConfig,
  965. hInterface);
  966. if(dwRes == NO_ERROR)
  967. {
  968. GUID Guid;
  969. dwRes = ConvertStringToGuid(pwszIfName,
  970. (USHORT)(wcslen(pwszIfName) * sizeof(WCHAR)),
  971. &Guid);
  972. if(dwRes != NO_ERROR)
  973. {
  974. break;
  975. }
  976. MprSetupIpInIpInterfaceFriendlyNameDelete(g_pwszRouter,
  977. &Guid);
  978. }
  979. }
  980. #endif //KSL_IPINIP
  981. if(IsRouterRunning())
  982. {
  983. dwRes = MprAdminInterfaceGetHandle(g_hMprAdmin,
  984. (LPWSTR)pwszIfName,
  985. &hInterface,
  986. FALSE);
  987. if ( dwRes != NO_ERROR )
  988. {
  989. break;
  990. }
  991. dwRes = MprAdminInterfaceTransportRemove(g_hMprAdmin,
  992. hInterface,
  993. PID_IP);
  994. #ifdef KSL_IPINIP
  995. if(dwIfType == ROUTER_IF_TYPE_TUNNEL1)
  996. {
  997. dwRes = MprAdminInterfaceDelete(g_hMprAdmin,
  998. hInterface);
  999. }
  1000. #endif //KSL_IPINIP
  1001. break;
  1002. }
  1003. } while (FALSE);
  1004. return dwRes;
  1005. }
  1006. DWORD
  1007. SetInterfaceInfo(
  1008. IN PRTR_INFO_BLOCK_HEADER pibhInfo,
  1009. IN LPCWSTR pwszIfName
  1010. )
  1011. /*++
  1012. Routine Description:
  1013. Sets interface transport information in registry or router.
  1014. Arguments:
  1015. pwszIfName - Interface Name
  1016. pibhInfo - ptr to header
  1017. Return Value:
  1018. NO_ERROR, ERROR_ROUTER_STOPPED
  1019. --*/
  1020. {
  1021. DWORD dwARes = NO_ERROR,
  1022. dwCRes = NO_ERROR;
  1023. HANDLE hIfTransport, hInterface;
  1024. UINT i;
  1025. PRTR_INFO_BLOCK_HEADER pibhNewInfo, pibhOldInfo;
  1026. //
  1027. // Create a new info block with all 0-length blocks removed
  1028. // since we don't want to write them to the registry,
  1029. // we only need to send them to the router which we
  1030. // will do with the original info block below.
  1031. //
  1032. pibhNewInfo = pibhInfo;
  1033. pibhOldInfo = NULL;
  1034. for (i=0; (dwCRes is NO_ERROR) && (i<pibhInfo->TocEntriesCount); i++)
  1035. {
  1036. if (pibhInfo->TocEntry[i].InfoSize is 0)
  1037. {
  1038. pibhOldInfo = pibhNewInfo;
  1039. dwCRes = MprInfoBlockRemove(pibhOldInfo,
  1040. pibhInfo->TocEntry[i].InfoType,
  1041. &pibhNewInfo);
  1042. if (pibhOldInfo isnot pibhInfo)
  1043. {
  1044. FREE_BUFFER(pibhOldInfo);
  1045. }
  1046. }
  1047. }
  1048. if (dwCRes is NO_ERROR)
  1049. {
  1050. dwCRes = MprConfigInterfaceGetHandle(g_hMprConfig,
  1051. (LPWSTR)pwszIfName,
  1052. &hInterface);
  1053. }
  1054. if (dwCRes is NO_ERROR)
  1055. {
  1056. dwCRes = MprConfigInterfaceTransportGetHandle(g_hMprConfig,
  1057. hInterface,
  1058. PID_IP,
  1059. &hIfTransport);
  1060. }
  1061. if (dwCRes is NO_ERROR)
  1062. {
  1063. dwCRes = MprConfigInterfaceTransportSetInfo(g_hMprConfig,
  1064. hInterface,
  1065. hIfTransport,
  1066. (LPBYTE) pibhNewInfo,
  1067. pibhNewInfo->Size);
  1068. }
  1069. if (pibhNewInfo isnot pibhInfo)
  1070. {
  1071. FREE_BUFFER(pibhNewInfo);
  1072. }
  1073. //
  1074. // Even if we failed to write to the registry, we still want
  1075. // to write to the router.
  1076. //
  1077. // We use the original format when writing to the router, since it
  1078. // needs to see the 0-length blocks in order to delete config info.
  1079. //
  1080. if(IsRouterRunning())
  1081. {
  1082. dwARes = MprAdminInterfaceGetHandle(g_hMprAdmin,
  1083. (LPWSTR)pwszIfName,
  1084. &hInterface,
  1085. FALSE);
  1086. if (dwARes is NO_ERROR)
  1087. {
  1088. dwARes = MprAdminInterfaceTransportSetInfo(g_hMprAdmin,
  1089. hInterface,
  1090. PID_IP,
  1091. (LPBYTE) pibhInfo,
  1092. pibhInfo->Size);
  1093. }
  1094. }
  1095. return (dwARes isnot NO_ERROR)? dwARes : dwCRes;
  1096. }
  1097. DWORD
  1098. WINAPI
  1099. IpCommit(
  1100. IN DWORD dwAction
  1101. )
  1102. {
  1103. PINTERFACE_STORE pii;
  1104. PLIST_ENTRY ple, pleTmp;
  1105. BOOL bCommit, bFlush = FALSE;
  1106. switch(dwAction)
  1107. {
  1108. case NETSH_COMMIT:
  1109. {
  1110. if (g_bCommit == TRUE)
  1111. {
  1112. return NO_ERROR;
  1113. }
  1114. g_bCommit = TRUE;
  1115. break;
  1116. }
  1117. case NETSH_UNCOMMIT:
  1118. {
  1119. g_bCommit = FALSE;
  1120. return NO_ERROR;
  1121. }
  1122. case NETSH_SAVE:
  1123. {
  1124. if (g_bCommit)
  1125. {
  1126. return NO_ERROR;
  1127. }
  1128. break;
  1129. }
  1130. case NETSH_FLUSH:
  1131. {
  1132. //
  1133. // Action is a flush. If current state is commit, then
  1134. // nothing to be done.
  1135. if (g_bCommit)
  1136. {
  1137. return NO_ERROR;
  1138. }
  1139. bFlush = TRUE;
  1140. break;
  1141. }
  1142. default:
  1143. {
  1144. return NO_ERROR;
  1145. }
  1146. }
  1147. //
  1148. // Switched to commit mode. So set all valid info in the
  1149. // strutures. Free memory and invalidate the info.
  1150. //
  1151. if((g_tiTransport.bValid && g_tiTransport.pibhInfo) &&
  1152. !bFlush)
  1153. {
  1154. SetGlobalInfo(g_tiTransport.pibhInfo);
  1155. }
  1156. g_tiTransport.bValid = FALSE;
  1157. if(g_tiTransport.pibhInfo)
  1158. {
  1159. FREE_BUFFER(g_tiTransport.pibhInfo);
  1160. g_tiTransport.pibhInfo = NULL;
  1161. }
  1162. //
  1163. // Set the interface info
  1164. //
  1165. while(!IsListEmpty(&g_leIfListHead))
  1166. {
  1167. ple = RemoveHeadList(&g_leIfListHead);
  1168. pii = CONTAINING_RECORD(ple,
  1169. INTERFACE_STORE,
  1170. le);
  1171. if ((pii->bValid && pii->pibhInfo) &&
  1172. !bFlush)
  1173. {
  1174. // Set the info in config
  1175. SetInterfaceInfo(pii->pibhInfo,
  1176. pii->pwszIfName);
  1177. }
  1178. pii->bValid = FALSE;
  1179. if(pii->pibhInfo)
  1180. {
  1181. FREE_BUFFER(pii->pibhInfo);
  1182. pii->pibhInfo = NULL;
  1183. }
  1184. if(pii->pwszIfName)
  1185. {
  1186. HeapFree(GetProcessHeap(),
  1187. 0,
  1188. pii->pwszIfName);
  1189. pii->pwszIfName = NULL;
  1190. }
  1191. //
  1192. // Free the list entry
  1193. //
  1194. HeapFree(GetProcessHeap(),
  1195. 0,
  1196. pii);
  1197. }
  1198. return NO_ERROR;
  1199. }
  1200. #ifdef KSL_IPINIP
  1201. DWORD
  1202. CreateInterface(
  1203. IN LPCWSTR pwszFriendlyName,
  1204. IN LPCWSTR pwszGuidName,
  1205. IN DWORD dwIfType,
  1206. IN BOOL bCreateRouterIf
  1207. )
  1208. {
  1209. DWORD i, dwErr, dwType, dwSize;
  1210. HANDLE hIfCfg, hIfAdmin, hIfTransport;
  1211. PBYTE pbyData;
  1212. PRTR_INFO_BLOCK_HEADER pInfo;
  1213. PINTERFACE_STATUS_INFO pStatus;
  1214. #if 0
  1215. PRTR_DISC_INFO pDisc;
  1216. #endif
  1217. //
  1218. // The only type we can create in the router is TUNNEL1
  1219. //
  1220. if(dwIfType != ROUTER_IF_TYPE_TUNNEL1)
  1221. {
  1222. ASSERT(FALSE);
  1223. return ERROR_INVALID_PARAMETER;
  1224. }
  1225. hIfAdmin = NULL;
  1226. hIfCfg = NULL;
  1227. if(bCreateRouterIf)
  1228. {
  1229. MPR_INTERFACE_0 IfInfo;
  1230. //
  1231. // The caller wants us to create an interface in the router, also
  1232. //
  1233. wcsncpy(IfInfo.wszInterfaceName,
  1234. pwszGuidName,
  1235. MAX_INTERFACE_NAME_LEN);
  1236. IfInfo.fEnabled = TRUE;
  1237. IfInfo.dwIfType = dwIfType;
  1238. IfInfo.wszInterfaceName[MAX_INTERFACE_NAME_LEN] = UNICODE_NULL;
  1239. dwErr = MprConfigInterfaceCreate(g_hMprConfig,
  1240. 0,
  1241. (PBYTE)&IfInfo,
  1242. &hIfCfg);
  1243. if(dwErr isnot NO_ERROR)
  1244. {
  1245. DisplayError(NULL,
  1246. dwErr);
  1247. return dwErr;
  1248. }
  1249. //
  1250. // if router service is running add the interface
  1251. // to it too.
  1252. //
  1253. if(IsRouterRunning())
  1254. {
  1255. dwErr = MprAdminInterfaceCreate(g_hMprAdmin,
  1256. 0,
  1257. (PBYTE)&IfInfo,
  1258. &hIfAdmin);
  1259. if(dwErr isnot NO_ERROR)
  1260. {
  1261. DisplayError(NULL,
  1262. dwErr);
  1263. MprConfigInterfaceDelete(g_hMprConfig,
  1264. hIfCfg);
  1265. return dwErr;
  1266. }
  1267. }
  1268. }
  1269. else
  1270. {
  1271. //
  1272. // The interface existed in the router but not in IP
  1273. //
  1274. dwErr = MprConfigInterfaceGetHandle(g_hMprConfig,
  1275. (LPWSTR)pwszGuidName,
  1276. &hIfCfg);
  1277. if(dwErr isnot NO_ERROR)
  1278. {
  1279. DisplayError(NULL,
  1280. dwErr);
  1281. return dwErr;
  1282. }
  1283. if(IsRouterRunning())
  1284. {
  1285. dwErr = MprAdminInterfaceGetHandle(g_hMprAdmin,
  1286. (LPWSTR)pwszGuidName,
  1287. &hIfAdmin,
  1288. FALSE);
  1289. if(dwErr isnot NO_ERROR)
  1290. {
  1291. DisplayError(NULL,
  1292. dwErr);
  1293. return dwErr;
  1294. }
  1295. }
  1296. }
  1297. //
  1298. // At this point we have an interface which doesnt have IP on it
  1299. // We have the handles to config and admin (if router is running)
  1300. // Set the default information for the interface
  1301. //
  1302. dwSize = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry[0]);
  1303. dwSize += (sizeof(INTERFACE_STATUS_INFO) +
  1304. sizeof(RTR_TOC_ENTRY) +
  1305. ALIGN_SIZE);
  1306. #if 0
  1307. dwSize += (sizeof(RTR_DISC_INFO) +
  1308. sizeof(RTR_TOC_ENTRY) +
  1309. ALIGN_SIZE);
  1310. #endif
  1311. pInfo = HeapAlloc(GetProcessHeap(),
  1312. 0,
  1313. dwSize);
  1314. if(pInfo is NULL)
  1315. {
  1316. DisplayError(NULL,
  1317. ERROR_NOT_ENOUGH_MEMORY);
  1318. if(bCreateRouterIf)
  1319. {
  1320. MprConfigInterfaceDelete(g_hMprConfig,
  1321. hIfCfg);
  1322. }
  1323. return ERROR_NOT_ENOUGH_MEMORY;
  1324. }
  1325. pInfo->Version = IP_ROUTER_MANAGER_VERSION;
  1326. pInfo->TocEntriesCount = 1;
  1327. pInfo->Size = dwSize;
  1328. //
  1329. // Make data point to N+1th entry
  1330. //
  1331. pbyData = (PBYTE)&(pInfo->TocEntry[1]);
  1332. ALIGN_POINTER(pbyData);
  1333. pStatus = (PINTERFACE_STATUS_INFO)pbyData;
  1334. pStatus->dwAdminStatus = IF_ADMIN_STATUS_UP;
  1335. pInfo->TocEntry[0].InfoSize = sizeof(INTERFACE_STATUS_INFO);
  1336. pInfo->TocEntry[0].InfoType = IP_INTERFACE_STATUS_INFO;
  1337. pInfo->TocEntry[0].Count = 1;
  1338. pInfo->TocEntry[0].Offset = (ULONG)(pbyData - (PBYTE)pInfo);
  1339. pbyData = (PBYTE)((ULONG_PTR)pbyData + sizeof(INTERFACE_STATUS_INFO));
  1340. ALIGN_POINTER(pbyData);
  1341. #if 0
  1342. pDisc = (PRTR_DISC_INFO)pbyData;
  1343. pDisc->wMaxAdvtInterval =
  1344. DEFAULT_MAX_ADVT_INTERVAL;
  1345. pDisc->wMinAdvtInterval =
  1346. (WORD)(DEFAULT_MIN_ADVT_INTERVAL_RATIO * DEFAULT_MAX_ADVT_INTERVAL);
  1347. pDisc->wAdvtLifetime =
  1348. DEFAULT_ADVT_LIFETIME_RATIO * DEFAULT_MAX_ADVT_INTERVAL;
  1349. pDisc->bAdvertise = FALSE;
  1350. pDisc->lPrefLevel = DEFAULT_PREF_LEVEL;
  1351. pInfo->TocEntry[1].InfoSize = sizeof(RTR_DISC_INFO);
  1352. pInfo->TocEntry[1].InfoType = IP_ROUTER_DISC_INFO;
  1353. pInfo->TocEntry[1].Count = 1;
  1354. pInfo->TocEntry[1].Offset = (ULONG)(pbyData - (PBYTE)pInfo);
  1355. #endif
  1356. dwErr = MprConfigInterfaceTransportAdd(g_hMprConfig,
  1357. hIfCfg,
  1358. PID_IP,
  1359. IP_KEY,
  1360. (PBYTE) pInfo,
  1361. dwSize,
  1362. &hIfTransport);
  1363. if(dwErr isnot NO_ERROR)
  1364. {
  1365. HeapFree(GetProcessHeap(),
  1366. 0,
  1367. pInfo);
  1368. DisplayMessage(g_hModule,
  1369. EMSG_CANT_CREATE_IF,
  1370. pwszFriendlyName,
  1371. dwErr);
  1372. if(bCreateRouterIf)
  1373. {
  1374. MprConfigInterfaceDelete(g_hMprConfig,
  1375. hIfCfg);
  1376. }
  1377. return dwErr;
  1378. }
  1379. if(hIfAdmin isnot NULL)
  1380. {
  1381. dwErr = MprAdminInterfaceTransportAdd(g_hMprAdmin,
  1382. hIfAdmin,
  1383. PID_IP,
  1384. (PBYTE) pInfo,
  1385. dwSize);
  1386. if(dwErr isnot NO_ERROR)
  1387. {
  1388. DisplayMessage(g_hModule,
  1389. EMSG_CANT_CREATE_IF,
  1390. pwszFriendlyName,
  1391. dwErr);
  1392. MprConfigInterfaceTransportRemove(g_hMprConfig,
  1393. hIfCfg,
  1394. hIfTransport);
  1395. if(bCreateRouterIf)
  1396. {
  1397. MprConfigInterfaceDelete(g_hMprConfig,
  1398. hIfCfg);
  1399. }
  1400. }
  1401. }
  1402. HeapFree(GetProcessHeap(),
  1403. 0,
  1404. pInfo);
  1405. return NO_ERROR;
  1406. }
  1407. #endif //KSL_IPINIP
  1408. DWORD
  1409. GetInterfaceClass(
  1410. IN LPCWSTR pwszIfName,
  1411. OUT PDWORD pdwIfClass
  1412. )
  1413. /*++
  1414. Description:
  1415. Determine whether an interface is of class Loopback, P2P,
  1416. Subnet, or NBMA. Currently there is no global way to do this,
  1417. so we test for some enumerated types and assume everything else
  1418. is Subnet.
  1419. Returns:
  1420. IFCLASS_xxx (see info.h)
  1421. --*/
  1422. {
  1423. DWORD dwErr, dwType;
  1424. dwErr = GetInterfaceInfo(pwszIfName,
  1425. NULL,
  1426. NULL,
  1427. &dwType);
  1428. if (dwErr)
  1429. {
  1430. return dwErr;
  1431. }
  1432. switch (dwType) {
  1433. case ROUTER_IF_TYPE_FULL_ROUTER : *pdwIfClass = IFCLASS_P2P; break;
  1434. case ROUTER_IF_TYPE_INTERNAL : *pdwIfClass = IFCLASS_NBMA; break;
  1435. case ROUTER_IF_TYPE_LOOPBACK : *pdwIfClass = IFCLASS_LOOPBACK; break;
  1436. #ifdef KSL_IPINIP
  1437. case ROUTER_IF_TYPE_TUNNEL1 : *pdwIfClass = IFCLASS_P2P; break;
  1438. #endif //KSL_IPINIP
  1439. case ROUTER_IF_TYPE_DIALOUT : *pdwIfClass = IFCLASS_P2P; break;
  1440. default: *pdwIfClass = IFCLASS_BROADCAST; break;
  1441. }
  1442. return NO_ERROR;
  1443. }