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.

5571 lines
140 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. routing\ip\rtrmgr\if.c
  5. Abstract:
  6. IP Router Manager interface related functions
  7. Revision History:
  8. Gurdeep Singh Pall 6/26/95 Created
  9. --*/
  10. #include "allinc.h"
  11. //////////////////////////////////////////////////////////////////////////////
  12. // //
  13. // The interface state machine: //
  14. // //
  15. // ---------- //
  16. // | Unbound | //
  17. // ------------>| Disabled |<--------------- //
  18. // | ---------- | //
  19. // V V //
  20. // ---------- --------- //
  21. // | Bound | | Unbound | //
  22. // | Disabled | | Enabled | //
  23. // ---------- --------- //
  24. // ^ ^ //
  25. // | --------- | //
  26. // ------------->| Bound |<---------------- //
  27. // | Enabled | //
  28. // --------- //
  29. // //
  30. // //
  31. // LAN interfaces: //
  32. // //
  33. // Characteristics UP (Operational) DOWN (Non-Operational) //
  34. // ------------------------------------------------------------------ //
  35. // Binding (IP Address) Yes No //
  36. // Protocols Added Yes Yes //
  37. // Static Routes Yes No //
  38. // Other Routes Yes No //
  39. // Added to Filter Driver Yes Yes //
  40. // Filters Added Not added //
  41. // Filter Ctxt in IP Stack Set (Valid) Not Set (Invalid) //
  42. // Router Discovery Active (if necc) Inactive //
  43. // Adapter ID (and Map) Valid Invalid //
  44. // //
  45. // WAN interfaces: //
  46. // //
  47. // Characteristics CONNECTED DISCON/CONNECTING UNREACHABLE //
  48. // ------------------------------------------------------------------- //
  49. // Binding (IP Address) Yes No No //
  50. // Protocols Added Yes Yes Yes //
  51. // Static Routes Yes Yes No //
  52. // Other Routes Yes No No //
  53. // Added to Filter Driver Yes Yes Yes //
  54. // Filters Yes Yes No //
  55. // Filter Ctxt in IP Stack Set (Valid) Not Set (Invalid) Not Set //
  56. // Router Discovery Active Inactive Inactive //
  57. // Adapter ID (and Map) Valid Invalid Invalid //
  58. // //
  59. // Enabled/Disabled depends upon the AdminState and not upon the //
  60. // operational state //
  61. // //
  62. //////////////////////////////////////////////////////////////////////////////
  63. #if __PIX__
  64. BOOL
  65. IsRemoteAddressPrivate(PICB pIcb);
  66. #endif
  67. PICB
  68. CreateIcb(
  69. PWSTR pwszInterfaceName,
  70. HANDLE hDIMInterface,
  71. ROUTER_INTERFACE_TYPE InterfaceType,
  72. DWORD dwAdminState,
  73. DWORD dwIfIndex OPTIONAL
  74. )
  75. /*++
  76. Routine Description
  77. This function creates an interface control block
  78. Locks
  79. None
  80. Arguments
  81. None
  82. Return Value
  83. None
  84. --*/
  85. {
  86. DWORD dwResult;
  87. PICB pNewInterfaceCb;
  88. GUID Guid;
  89. #ifdef KSL_IPINIP
  90. //
  91. // Make sure this is a valid name
  92. //
  93. if(InterfaceType is ROUTER_IF_TYPE_TUNNEL1)
  94. {
  95. UNICODE_STRING usTempName;
  96. //
  97. // For now only these interfaces are GUIDs
  98. //
  99. usTempName.Length = wcslen(pwszInterfaceName) * sizeof(WCHAR);
  100. usTempName.MaximumLength = usTempName.Length + sizeof(WCHAR);
  101. usTempName.Buffer = pwszInterfaceName;
  102. if(RtlGUIDFromString(&usTempName,
  103. &Guid) isnot STATUS_SUCCESS)
  104. {
  105. Trace1(ERR,
  106. "CreateIcb: %S is not a GUID\n",
  107. pwszInterfaceName);
  108. return NULL;
  109. }
  110. }
  111. #endif //KSL_IPINIP
  112. //
  113. // Allocate an ICB
  114. //
  115. dwResult = AllocateIcb(pwszInterfaceName,
  116. &pNewInterfaceCb);
  117. if(dwResult isnot NO_ERROR)
  118. {
  119. return NULL;
  120. }
  121. pNewInterfaceCb->dwIfIndex = INVALID_IF_INDEX;
  122. pNewInterfaceCb->hDIMHandle = hDIMInterface;
  123. pNewInterfaceCb->ritType = InterfaceType;
  124. pNewInterfaceCb->dwMcastTtl = 1;
  125. //
  126. // "Unique" interface ID used for ICBs.
  127. // This ID is passed to WANARP and DIM and they in
  128. // turn pass this back to Router Manager when
  129. // requesting/indicating actions on the interface.
  130. //
  131. pNewInterfaceCb->dwSeqNumber = g_dwNextICBSeqNumberCounter;
  132. //
  133. // Initialize the filter, and wanarp contexts to invalid values
  134. // (NAT invalid is NULL)
  135. //
  136. pNewInterfaceCb->ihFilterInterface = INVALID_HANDLE_VALUE;
  137. pNewInterfaceCb->ihDemandFilterInterface = INVALID_HANDLE_VALUE;
  138. //
  139. // Initialize the lists of which async notifications and
  140. // the protocol blocks are queued
  141. //
  142. InitializeListHead(&pNewInterfaceCb->lePendingResultList);
  143. InitializeListHead(&pNewInterfaceCb->leProtocolList);
  144. //
  145. // Since we HEAP zeroed the ICB, all our binding related
  146. // stuff is already zero, the bBound is FALSE and dwNumAddress is 0
  147. // The adapter id was set to invalid in InitializeInterfaceContext
  148. //
  149. //
  150. // set the operational status based on the interface type
  151. // Also figure out the interface index
  152. //
  153. dwResult = NO_ERROR;
  154. switch(pNewInterfaceCb->ritType)
  155. {
  156. case ROUTER_IF_TYPE_CLIENT:
  157. {
  158. //
  159. // Clients come up in connecting, since we dont get a LINE_UP for
  160. // them. We also set the notification flags to fake the LINE UP
  161. //
  162. pNewInterfaceCb->dwAdminState = IF_ADMIN_STATUS_UP;
  163. pNewInterfaceCb->dwOperationalState = CONNECTING;
  164. pNewInterfaceCb->nitProtocolType = REMOTE_WORKSTATION_DIAL;
  165. SetNdiswanNotification(pNewInterfaceCb);
  166. pNewInterfaceCb->dwBCastBit = 1;
  167. pNewInterfaceCb->dwReassemblySize = DEFAULT_MTU;
  168. //
  169. // We dont really care about dial out ifIndex
  170. // so clients will have an index of -1 (since we init to -1)
  171. //
  172. break;
  173. }
  174. case ROUTER_IF_TYPE_HOME_ROUTER:
  175. case ROUTER_IF_TYPE_FULL_ROUTER:
  176. {
  177. //
  178. // HOME and FULL routers are disconnected
  179. //
  180. pNewInterfaceCb->dwAdminState = dwAdminState;
  181. pNewInterfaceCb->dwOperationalState = DISCONNECTED;
  182. pNewInterfaceCb->nitProtocolType = DEMAND_DIAL;
  183. pNewInterfaceCb->dwBCastBit = 1;
  184. pNewInterfaceCb->dwReassemblySize = DEFAULT_MTU;
  185. //
  186. // WANARP reserves and index when we add an interface to it
  187. //
  188. dwResult = AddInterfaceToWanArp(pNewInterfaceCb);
  189. break;
  190. }
  191. case ROUTER_IF_TYPE_DEDICATED:
  192. {
  193. //
  194. // LAN interfaces come up as NON_OPERATIONAL. If the admin
  195. // wants them up we will try to do a LanInterfaceDownToUp()
  196. // If that succeeds, it will set the operational state
  197. // correctly
  198. //
  199. pNewInterfaceCb->dwAdminState = dwAdminState;
  200. pNewInterfaceCb->dwOperationalState = NON_OPERATIONAL;
  201. pNewInterfaceCb->nitProtocolType = PERMANENT;
  202. dwResult = NhpGetInterfaceIndexFromStack(
  203. pNewInterfaceCb->pwszName,
  204. &(pNewInterfaceCb->dwIfIndex)
  205. );
  206. break;
  207. }
  208. case ROUTER_IF_TYPE_INTERNAL:
  209. {
  210. pNewInterfaceCb->dwAdminState = IF_ADMIN_STATUS_UP;
  211. pNewInterfaceCb->dwOperationalState = DISCONNECTED;
  212. pNewInterfaceCb->nitProtocolType = LOCAL_WORKSTATION_DIAL;
  213. pNewInterfaceCb->dwBCastBit = 1;
  214. pNewInterfaceCb->dwReassemblySize = DEFAULT_MTU;
  215. //
  216. // WANARP reserves and index when we add an interface to it
  217. //
  218. dwResult = AddInterfaceToWanArp(pNewInterfaceCb);
  219. break;
  220. }
  221. case ROUTER_IF_TYPE_LOOPBACK:
  222. {
  223. pNewInterfaceCb->dwAdminState = IF_ADMIN_STATUS_UP;
  224. pNewInterfaceCb->dwOperationalState = OPERATIONAL;
  225. pNewInterfaceCb->nitProtocolType = PERMANENT;
  226. //
  227. // Note that IP uses 1
  228. //
  229. pNewInterfaceCb->dwIfIndex = LOOPBACK_INTERFACE_INDEX;
  230. break;
  231. }
  232. #ifdef KSL_IPINIP
  233. case ROUTER_IF_TYPE_TUNNEL1:
  234. {
  235. pNewInterfaceCb->dwAdminState = dwAdminState;
  236. pNewInterfaceCb->dwOperationalState = NON_OPERATIONAL;
  237. pNewInterfaceCb->nitProtocolType = PERMANENT;
  238. pNewInterfaceCb->dwBCastBit = 1;
  239. pNewInterfaceCb->dwReassemblySize = DEFAULT_MTU;
  240. //
  241. // IP in IP does the same thing as WANARP
  242. //
  243. dwResult = AddInterfaceToIpInIp(&Guid,
  244. pNewInterfaceCb);
  245. break;
  246. }
  247. #endif //KSL_IPINIP
  248. case ROUTER_IF_TYPE_DIALOUT:
  249. {
  250. //
  251. // Dial out interface are not known to DIM. We learn about
  252. // them via a back door mechanism.
  253. //
  254. IpRtAssert(dwIfIndex isnot INVALID_IF_INDEX);
  255. IpRtAssert(dwIfIndex isnot 0);
  256. pNewInterfaceCb->dwAdminState = IF_ADMIN_STATUS_UP;
  257. pNewInterfaceCb->dwOperationalState = CONNECTED;
  258. pNewInterfaceCb->nitProtocolType = REMOTE_WORKSTATION_DIAL;
  259. pNewInterfaceCb->dwIfIndex = dwIfIndex;
  260. pNewInterfaceCb->dwBCastBit = 1;
  261. pNewInterfaceCb->dwReassemblySize = DEFAULT_MTU;
  262. break;
  263. }
  264. default:
  265. {
  266. IpRtAssert(FALSE);
  267. break;
  268. }
  269. }
  270. if(dwResult isnot NO_ERROR)
  271. {
  272. Trace2(ERR,
  273. "CreateIcb: Error %d in getting index for %S\n",
  274. dwResult,
  275. pNewInterfaceCb->pwszName);
  276. HeapFree(IPRouterHeap,
  277. 0,
  278. pNewInterfaceCb);
  279. return NULL;
  280. }
  281. //
  282. // Once the interface index is done we can Initialize the bindings
  283. //
  284. dwResult = CreateBindingForNewIcb(pNewInterfaceCb);
  285. if(dwResult isnot NO_ERROR)
  286. {
  287. Trace2(ERR,
  288. "CreateIcb: Error %d in creating binding for %S\n",
  289. dwResult,
  290. pNewInterfaceCb->pwszName);
  291. HeapFree(IPRouterHeap,
  292. 0,
  293. pNewInterfaceCb);
  294. return NULL;
  295. }
  296. return pNewInterfaceCb;
  297. }
  298. DWORD
  299. AllocateIcb(
  300. PWCHAR pwszName,
  301. ICB **ppIcb
  302. )
  303. /*++
  304. Routine Description
  305. Allocates memory for the ICB
  306. Locks
  307. None
  308. Arguments
  309. pwszName Interface name
  310. ppIcb OUT: pointer to allocate ICB
  311. Return Value
  312. NO_ERROR
  313. --*/
  314. {
  315. DWORD dwNameLen, dwAllocSize;
  316. PICB pNewInterfaceCb;
  317. *ppIcb = NULL;
  318. dwNameLen = sizeof(WCHAR) * (wcslen(pwszName) + 1); // +1 for NULL
  319. dwNameLen = min(dwNameLen, MAX_INTERFACE_NAME_LEN);
  320. dwAllocSize = sizeof (ICB) + dwNameLen + 4; // +4 for alignment
  321. pNewInterfaceCb = HeapAlloc(IPRouterHeap,
  322. HEAP_ZERO_MEMORY,
  323. dwAllocSize);
  324. if(pNewInterfaceCb is NULL)
  325. {
  326. return ERROR_NOT_ENOUGH_MEMORY;
  327. }
  328. //
  329. // The interface name is after the ICB
  330. //
  331. pNewInterfaceCb->pwszName = (PWCHAR)((PBYTE)pNewInterfaceCb +
  332. sizeof (ICB));
  333. //
  334. // Align it to DWORD boundary - easier to copy out the name
  335. //
  336. pNewInterfaceCb->pwszName =
  337. (PWCHAR)(((ULONG_PTR)pNewInterfaceCb->pwszName + 3) & ~((ULONG_PTR)0x3));
  338. //
  339. // Initialize the name
  340. //
  341. CopyMemory(pNewInterfaceCb->pwszName,
  342. pwszName,
  343. dwNameLen);
  344. pNewInterfaceCb->pwszName[wcslen(pwszName)] = UNICODE_NULL;
  345. *ppIcb = pNewInterfaceCb;
  346. return NO_ERROR;
  347. }
  348. DWORD
  349. CreateBindingForNewIcb(
  350. PICB pNewIcb
  351. )
  352. /*++
  353. Routine Description
  354. Creates a binding and bind node for the ICB
  355. LAN interfaces get the binding setup when they are being brought UP.
  356. Since the other interfaces will ALWAYS have ONLY 1 address, we can
  357. set their binding info here, even if we dont have the address
  358. We skip INTERNAL, too because of the way the internal address is
  359. got. Otherwise we will get an assert in UpdateBindingInformation
  360. when we find an existing binding with no address
  361. Locks
  362. Arguments
  363. Return Value
  364. --*/
  365. {
  366. PADAPTER_INFO pBindNode;
  367. PICB_BINDING pBinding;
  368. #ifdef KSL_IPINIP
  369. if((pNewIcb->ritType is ROUTER_IF_TYPE_TUNNEL1) or
  370. #endif //KSL_IPINIP
  371. if((pNewIcb->ritType is ROUTER_IF_TYPE_HOME_ROUTER) or
  372. (pNewIcb->ritType is ROUTER_IF_TYPE_FULL_ROUTER) or
  373. (pNewIcb->ritType is ROUTER_IF_TYPE_LOOPBACK) or
  374. (pNewIcb->ritType is ROUTER_IF_TYPE_DIALOUT))
  375. {
  376. IpRtAssert(pNewIcb->dwIfIndex isnot INVALID_IF_INDEX);
  377. pBindNode = HeapAlloc(IPRouterHeap,
  378. HEAP_ZERO_MEMORY,
  379. SIZEOF_ADAPTER_INFO(1));
  380. pBinding = HeapAlloc(IPRouterHeap,
  381. HEAP_ZERO_MEMORY,
  382. sizeof(ICB_BINDING));
  383. if((pBinding is NULL) or
  384. (pBindNode is NULL))
  385. {
  386. return ERROR_NOT_ENOUGH_MEMORY;
  387. }
  388. pBindNode->pInterfaceCB = pNewIcb;
  389. pBindNode->dwIfIndex = pNewIcb->dwIfIndex;
  390. pBindNode->dwSeqNumber = pNewIcb->dwSeqNumber;
  391. pBindNode->bBound = pNewIcb->bBound;
  392. pBindNode->dwRemoteAddress = INVALID_IP_ADDRESS;
  393. pBindNode->rgibBinding[0].dwAddress = INVALID_IP_ADDRESS;
  394. pBindNode->rgibBinding[0].dwMask = INVALID_IP_ADDRESS;
  395. pBindNode->dwBCastBit = pNewIcb->dwBCastBit;
  396. pBindNode->dwReassemblySize = pNewIcb->dwReassemblySize;
  397. pBindNode->ritType = pNewIcb->ritType;
  398. pNewIcb->pibBindings = pBinding;
  399. //
  400. // Set the binding in the hash table
  401. //
  402. ENTER_WRITER(BINDING_LIST);
  403. InsertHeadList(
  404. &g_leBindingTable[BIND_HASH(pNewIcb->dwIfIndex)],
  405. &(pBindNode->leHashLink)
  406. );
  407. g_ulNumBindings++;
  408. g_LastUpdateTable[IPADDRCACHE] = 0;
  409. EXIT_LOCK(BINDING_LIST);
  410. return NO_ERROR;
  411. }
  412. //
  413. // For client (dial in our out) interfaces, we only create the BINDING
  414. //
  415. if((pNewIcb->ritType is ROUTER_IF_TYPE_CLIENT) or
  416. (pNewIcb->ritType is ROUTER_IF_TYPE_DIALOUT))
  417. {
  418. pBinding = HeapAlloc(IPRouterHeap,
  419. HEAP_ZERO_MEMORY,
  420. sizeof(ICB_BINDING));
  421. if(pBinding is NULL)
  422. {
  423. return ERROR_NOT_ENOUGH_MEMORY;
  424. }
  425. pNewIcb->pibBindings = pBinding;
  426. return NO_ERROR;
  427. }
  428. return NO_ERROR;
  429. }
  430. VOID
  431. InsertInterfaceInLists(
  432. PICB pNewIcb
  433. )
  434. /*++
  435. Routine Description
  436. Insert the new ICB. The newicb must have a valid interface
  437. index. The code walks all the current ICBs and inserts this
  438. ICB in increasing ifIndex order. It also sets a sequence
  439. number in the ICB and increments the global counter.
  440. Locks
  441. ICB_LIST as writer
  442. Arguments
  443. newicb The ICB of the interface to init
  444. Return Value
  445. None
  446. --*/
  447. {
  448. PLIST_ENTRY pleNode;
  449. PICB pIcb;
  450. for(pleNode = &ICBList;
  451. pleNode->Flink != &ICBList;
  452. pleNode = pleNode->Flink)
  453. {
  454. pIcb = CONTAINING_RECORD(pleNode->Flink,
  455. ICB,
  456. leIfLink);
  457. if(pIcb->dwIfIndex > pNewIcb->dwIfIndex)
  458. {
  459. break;
  460. }
  461. }
  462. InsertHeadList(pleNode,
  463. &pNewIcb->leIfLink);
  464. AddInterfaceLookup(pNewIcb);
  465. //
  466. // Find next unassigned ICB number
  467. //
  468. do
  469. {
  470. InterlockedIncrement(&g_dwNextICBSeqNumberCounter);
  471. //
  472. // WANARP considers 0 to be an invalid value for an
  473. // interface
  474. //
  475. if ((g_dwNextICBSeqNumberCounter == 0) or
  476. (g_dwNextICBSeqNumberCounter == INVALID_IF_INDEX))
  477. {
  478. InterlockedIncrement(&g_dwNextICBSeqNumberCounter);
  479. }
  480. } while(InterfaceLookupByICBSeqNumber(g_dwNextICBSeqNumberCounter) != NULL);
  481. //
  482. // Increment total number of interfaces
  483. //
  484. InterlockedIncrement(&g_ulNumInterfaces);
  485. //
  486. // Count for non client interfaces
  487. //
  488. if(pNewIcb->ritType isnot ROUTER_IF_TYPE_CLIENT)
  489. {
  490. InterlockedIncrement(&g_ulNumNonClientInterfaces);
  491. }
  492. }
  493. VOID
  494. RemoveInterfaceFromLists(
  495. PICB pIcb
  496. )
  497. /*++
  498. Routine Description
  499. This
  500. Locks
  501. None
  502. Arguments
  503. None
  504. Return Value
  505. None
  506. --*/
  507. {
  508. RemoveEntryList(&(pIcb->leIfLink));
  509. pIcb->leIfLink.Flink = NULL;
  510. pIcb->leIfLink.Blink = NULL;
  511. RemoveInterfaceLookup(pIcb);
  512. if(pIcb->ritType isnot ROUTER_IF_TYPE_CLIENT)
  513. {
  514. InterlockedDecrement(&g_ulNumNonClientInterfaces);
  515. }
  516. InterlockedDecrement(&g_ulNumInterfaces);
  517. }
  518. DWORD
  519. BindInterfaceInAllProtocols(
  520. PICB pIcb
  521. )
  522. /*++
  523. Routine Description
  524. Binds the interface in all protocols running over the interface
  525. Locks
  526. The ICB_LIST lock must be held as READER.
  527. Acquires the PROTOCOL_CB_LIST as READER
  528. Arguments
  529. pIcb ICB of the interface to bind
  530. Return Value
  531. NO_ERROR
  532. --*/
  533. {
  534. IP_ADAPTER_BINDING_INFO *pBindInfo;
  535. DWORD i = 0 ;
  536. DWORD dwResult,dwReturn;
  537. PLIST_ENTRY pleNode;
  538. TraceEnter("BindInterfaceInAllProtocols");
  539. CheckBindingConsistency(pIcb);
  540. if(!pIcb->bBound)
  541. {
  542. //
  543. // This may happen if we are in non operational state
  544. // It is not an error. We could do this check at the place
  545. // we called the function but it would make it tougher
  546. //
  547. Trace1(IF,
  548. "BindInterfaceInAllProtocols: Not binding %S since no addresses present",
  549. pIcb->pwszName);
  550. return NO_ERROR;
  551. }
  552. pBindInfo = HeapAlloc(IPRouterHeap,
  553. 0,
  554. SIZEOF_IP_BINDING(pIcb->dwNumAddresses));
  555. if(pBindInfo is NULL)
  556. {
  557. Trace1(ERR,
  558. "BindInterfaceInAllProtocols: Error allocating %d bytes for bindings",
  559. SIZEOF_IP_BINDING(pIcb->dwNumAddresses));
  560. return ERROR_NOT_ENOUGH_MEMORY;
  561. }
  562. pBindInfo->AddressCount = pIcb->dwNumAddresses ;
  563. pBindInfo->RemoteAddress = pIcb->dwRemoteAddress;
  564. pBindInfo->Mtu = pIcb->ulMtu;
  565. pBindInfo->Speed = pIcb->ullSpeed;
  566. for (i = 0; i < pIcb->dwNumAddresses; i++)
  567. {
  568. pBindInfo->Address[i].Address = pIcb->pibBindings[i].dwAddress;
  569. pBindInfo->Address[i].Mask = pIcb->pibBindings[i].dwMask;
  570. }
  571. //
  572. // walk the array of routing protocols to activate
  573. //
  574. dwReturn = NO_ERROR;
  575. // *** Exclusion Begin ***
  576. ENTER_READER(PROTOCOL_CB_LIST);
  577. for(pleNode = pIcb->leProtocolList.Flink;
  578. pleNode isnot &(pIcb->leProtocolList);
  579. pleNode = pleNode->Flink)
  580. {
  581. PIF_PROTO pProto;
  582. pProto = CONTAINING_RECORD(pleNode,
  583. IF_PROTO,
  584. leIfProtoLink);
  585. dwResult = BindInterfaceInProtocol(pIcb,
  586. pProto->pActiveProto,
  587. pBindInfo);
  588. if(dwResult isnot NO_ERROR)
  589. {
  590. Trace3(ERR,
  591. "BindInterfaceInAllProtocols: Couldnt bind interface %S to %S. Error %d",
  592. pIcb->pwszName,
  593. pProto->pActiveProto->pwszDisplayName,
  594. dwResult);
  595. dwReturn = ERROR_CAN_NOT_COMPLETE;
  596. }
  597. }
  598. HeapFree(IPRouterHeap,
  599. 0,
  600. pBindInfo);
  601. // *** Exclusion End ***
  602. EXIT_LOCK(PROTOCOL_CB_LIST);
  603. return dwReturn;
  604. }
  605. DWORD
  606. BindInterfaceInProtocol(
  607. PICB pIcb,
  608. PPROTO_CB pProto,
  609. PIP_ADAPTER_BINDING_INFO pBindInfo
  610. )
  611. /*++
  612. Routine Description
  613. Binds the interface in the given protocol
  614. Locks
  615. The ICB_LIST lock must be held as READER.
  616. The PROTOCOL_CB_LIST lock must also be held as READER
  617. Arguments
  618. pIcb ICB of the interface to bind
  619. pProto PROTO_CB of the protocol
  620. pBindInfo Binding info
  621. Return Value
  622. NO_ERROR
  623. --*/
  624. {
  625. DWORD dwResult;
  626. //
  627. // If this is a mcast protocol and the interface is not
  628. // mcast enabled, do so now
  629. //
  630. if((pIcb->bMcastEnabled is FALSE) and
  631. (TYPE_FROM_PROTO_ID(pProto->dwProtocolId) is PROTO_TYPE_MCAST))
  632. {
  633. dwResult = SetMcastOnIf(pIcb,
  634. TRUE);
  635. if(dwResult isnot NO_ERROR)
  636. {
  637. WCHAR rgwcName[MAX_INTERFACE_NAME_LEN + 2];
  638. PWCHAR pName;
  639. Trace2(ERR,
  640. "BindInterfaceInProtocol: Err %d activating mcast on %S",
  641. dwResult,
  642. pIcb->pwszName);
  643. if(MprConfigGetFriendlyName(g_hMprConfig,
  644. pIcb->pwszName,
  645. rgwcName,
  646. sizeof(rgwcName)) is NO_ERROR)
  647. {
  648. pName = rgwcName;
  649. }
  650. else
  651. {
  652. pName = pIcb->pwszName;
  653. }
  654. RouterLogEventEx(g_hLogHandle,
  655. EVENTLOG_ERROR_TYPE,
  656. dwResult,
  657. ROUTERLOG_IP_MCAST_NOT_ENABLED,
  658. TEXT("%S%S"),
  659. pName,
  660. pProto->pwszDisplayName);
  661. //
  662. // Dont add this protocol
  663. //
  664. return dwResult;
  665. }
  666. pIcb->bMcastEnabled = TRUE;
  667. }
  668. //
  669. // Call the routing protocol's BindInterface() entrypoint
  670. //
  671. dwResult = (pProto->pfnInterfaceStatus)(
  672. pIcb->dwIfIndex,
  673. (pIcb->dwOperationalState >= CONNECTED),
  674. RIS_INTERFACE_ADDRESS_CHANGE,
  675. pBindInfo
  676. );
  677. if(dwResult isnot NO_ERROR)
  678. {
  679. Trace3(ERR,
  680. "BindInterfaceInProtocol: Couldnt bind interface %S to %S.Error %d",
  681. pIcb->pwszName,
  682. pProto->pwszDisplayName,
  683. dwResult);
  684. }
  685. return dwResult;
  686. }
  687. DWORD
  688. UnbindInterfaceInAllProtocols(
  689. PICB pIcb
  690. )
  691. /*++
  692. Routine Description
  693. Removes the binding information from the protocols on this interface
  694. Locks
  695. ICB_LIST lock as READER
  696. Acquires the PROTOCOL_CB_LIST as READER
  697. Arguments
  698. Return Value
  699. NO_ERROR
  700. --*/
  701. {
  702. PLIST_ENTRY pleNode;
  703. DWORD dwResult,dwReturn = NO_ERROR;
  704. IP_ADAPTER_BINDING_INFO BindInfo;
  705. BindInfo.AddressCount = 0;
  706. TraceEnter("UnbindInterfaceInAllProtocols");
  707. // *** Exclusion Begin ***
  708. ENTER_READER(PROTOCOL_CB_LIST);
  709. for(pleNode = pIcb->leProtocolList.Flink;
  710. pleNode isnot &(pIcb->leProtocolList);
  711. pleNode = pleNode->Flink)
  712. {
  713. PIF_PROTO pProto;
  714. pProto = CONTAINING_RECORD(pleNode,IF_PROTO,leIfProtoLink);
  715. dwResult = (pProto->pActiveProto->pfnInterfaceStatus)(
  716. pIcb->dwIfIndex,
  717. FALSE,
  718. RIS_INTERFACE_ADDRESS_CHANGE,
  719. &BindInfo
  720. );
  721. if(dwResult isnot NO_ERROR)
  722. {
  723. Trace3(ERR,
  724. "UnbindInterfaceInAllProtocols: Error %d unbinding %S in %S",
  725. dwResult,
  726. pIcb->pwszName,
  727. pProto->pActiveProto->pwszDisplayName);
  728. dwReturn = ERROR_CAN_NOT_COMPLETE;
  729. }
  730. }
  731. // *** Exclusion Begin ***
  732. EXIT_LOCK(PROTOCOL_CB_LIST);
  733. return dwReturn;
  734. }
  735. DWORD
  736. AddInterfaceToAllProtocols(
  737. PICB pIcb,
  738. PRTR_INFO_BLOCK_HEADER pInfoHdr
  739. )
  740. /*++
  741. Routine Description
  742. Walks thru list of routing protocols and calls AddInterface if
  743. TOC and info for that protocol exists
  744. Locks
  745. ICB_LIST lock as WRITER
  746. Acquires PROTOCOL_CB_LIST as READER
  747. Arguments
  748. Return Value
  749. NO_ERROR
  750. --*/
  751. {
  752. DWORD i = 0 , dwResult;
  753. LPVOID pvProtoInfo ;
  754. PPROTO_CB pProtoCbPtr ;
  755. PLIST_ENTRY pleNode;
  756. PRTR_TOC_ENTRY pToc;
  757. ULONG ulStructureVersion, ulStructureSize, ulStructureCount;
  758. TraceEnter("AddInterfaceToAllProtocols");
  759. if(!ARGUMENT_PRESENT(pInfoHdr))
  760. {
  761. Trace1(IF,
  762. "AddInterfaceToAllProtocols: No interface info for %S. Not adding to any protocols",
  763. pIcb->pwszName);
  764. return NO_ERROR;
  765. }
  766. // *** Exclusion Begin ***
  767. ENTER_READER(PROTOCOL_CB_LIST);
  768. for(pleNode = g_leProtoCbList.Flink;
  769. pleNode != &g_leProtoCbList;
  770. pleNode = pleNode->Flink)
  771. {
  772. pProtoCbPtr = CONTAINING_RECORD(pleNode, PROTO_CB, leList);
  773. pToc = GetPointerToTocEntry(pProtoCbPtr->dwProtocolId,
  774. pInfoHdr);
  775. pvProtoInfo = NULL;
  776. if(pToc and (pToc->InfoSize > 0))
  777. {
  778. pvProtoInfo = GetInfoFromTocEntry(pInfoHdr,
  779. pToc);
  780. //ulStructureVersion = pInfoHdr->TocEntry[i].InfoVersion;
  781. ulStructureVersion = 0x500;
  782. ulStructureSize = pInfoHdr->TocEntry[i].InfoSize;
  783. ulStructureCount = pInfoHdr->TocEntry[i].Count;
  784. }
  785. //
  786. // If the protocol block is found, add the interface with the
  787. // routing protocol.
  788. //
  789. if((pProtoCbPtr->fSupportedFunctionality & RF_ADD_ALL_INTERFACES) or
  790. (pvProtoInfo))
  791. {
  792. dwResult = AddInterfaceToProtocol(pIcb,
  793. pProtoCbPtr,
  794. pvProtoInfo,
  795. ulStructureVersion,
  796. ulStructureSize,
  797. ulStructureCount);
  798. if(dwResult isnot NO_ERROR)
  799. {
  800. Trace3(ERR,
  801. "AddInterfaceToAllProtocols: Error %d adding %S to %S",
  802. dwResult,
  803. pIcb->pwszName,
  804. pProtoCbPtr->pwszDisplayName);
  805. }
  806. }
  807. }
  808. // *** Exclusion End ***
  809. EXIT_LOCK(PROTOCOL_CB_LIST);
  810. return NO_ERROR;
  811. }
  812. DWORD
  813. AddInterfaceToProtocol(
  814. IN PICB pIcb,
  815. IN PPROTO_CB pProtocolCb,
  816. IN PVOID pvProtoInfo,
  817. IN ULONG ulStructureVersion,
  818. IN ULONG ulStructureSize,
  819. IN ULONG ulStructureCount
  820. )
  821. /*++
  822. Routine Description
  823. Adds an interface to a single routing protocol
  824. Locks
  825. Arguments
  826. Return Value
  827. --*/
  828. {
  829. PIF_PROTO pProto;
  830. DWORD dwResult;
  831. pProto = HeapAlloc(IPRouterHeap,
  832. 0,
  833. sizeof(IF_PROTO));
  834. if(pProto is NULL)
  835. {
  836. Trace3(ERR,
  837. "AddInterfaceToProtocol: Error allocating %d bytes to add %S to %S",
  838. sizeof(IF_PROTO),
  839. pIcb->pwszName,
  840. pProtocolCb->pwszDisplayName);
  841. return ERROR_NOT_ENOUGH_MEMORY;
  842. }
  843. //
  844. // The protocol wants all the interfaces indicated to it or
  845. // there is info for this protocol
  846. //
  847. Trace2(IF,
  848. "AddInterfaceToProtocol: Adding %S to %S",
  849. pIcb->pwszName,
  850. pProtocolCb->pwszDisplayName);
  851. dwResult = (pProtocolCb->pfnAddInterface)(pIcb->pwszName,
  852. pIcb->dwIfIndex,
  853. pIcb->nitProtocolType,
  854. pIcb->dwMediaType,
  855. pIcb->wAccessType,
  856. pIcb->wConnectionType,
  857. pvProtoInfo,
  858. ulStructureVersion,
  859. ulStructureSize,
  860. ulStructureCount);
  861. if(dwResult isnot NO_ERROR)
  862. {
  863. Trace3(ERR,
  864. "AddInterfaceToProtocol: Error %d adding %S to %S",
  865. dwResult,
  866. pIcb->pwszName,
  867. pProtocolCb->pwszDisplayName);
  868. HeapFree(IPRouterHeap,
  869. 0,
  870. pProto);
  871. }
  872. else
  873. {
  874. pProto->pActiveProto = pProtocolCb;
  875. //
  876. // Mark this block as being added, because of prom.
  877. // mode, if that is the case
  878. //
  879. pProto->bPromiscuous = (pvProtoInfo is NULL);
  880. InsertTailList(&(pIcb->leProtocolList),
  881. &(pProto->leIfProtoLink));
  882. }
  883. return dwResult;
  884. }
  885. DWORD
  886. DeleteInterfaceFromAllProtocols(
  887. PICB pIcb
  888. )
  889. /*++
  890. Routine Description
  891. Deletes the interface from all protocols running on it
  892. Frees the protocol info on the interface
  893. Locks
  894. Called with ICB_LIST as WRITER
  895. Acquires PROTOCOL_CB_LIST as READER
  896. Arguments
  897. pIcb ICB of interface
  898. Return Value
  899. NO_ERROR
  900. --*/
  901. {
  902. DWORD i = 0 ;
  903. PLIST_ENTRY pleNode;
  904. TraceEnter("DeleteInterfaceFromAllProtocols");
  905. //
  906. // If the router has stopped we do not need to delete the interface
  907. // from the routing protocol. This is handled before we get here by
  908. // the UnloadRoutingProtocol()
  909. //
  910. if (RouterState.IRS_State is RTR_STATE_STOPPED)
  911. {
  912. return NO_ERROR;
  913. }
  914. // *** Exclusion Begin ***
  915. ENTER_READER(PROTOCOL_CB_LIST);
  916. while(!(IsListEmpty(&(pIcb->leProtocolList))))
  917. {
  918. PIF_PROTO pProto;
  919. pleNode = RemoveHeadList(&(pIcb->leProtocolList));
  920. pProto = CONTAINING_RECORD(pleNode,IF_PROTO,leIfProtoLink);
  921. //
  922. // Call the routing protocol's deleteinterface entrypoint
  923. //
  924. (pProto->pActiveProto->pfnDeleteInterface) (pIcb->dwIfIndex);
  925. //
  926. // Delete this protocol from the list of protocols in the Interface
  927. //
  928. HeapFree(IPRouterHeap,0,pProto);
  929. }
  930. // *** Exclusion End ***
  931. EXIT_LOCK(PROTOCOL_CB_LIST);
  932. return NO_ERROR;
  933. }
  934. DWORD
  935. DisableInterfaceWithAllProtocols(
  936. PICB pIcb
  937. )
  938. {
  939. PLIST_ENTRY pleNode;
  940. DWORD dwResult,dwReturn = NO_ERROR;
  941. TraceEnter("DisableInterfaceWithAllProtocols");
  942. ENTER_READER(PROTOCOL_CB_LIST);
  943. for(pleNode = pIcb->leProtocolList.Flink;
  944. pleNode isnot &(pIcb->leProtocolList);
  945. pleNode = pleNode->Flink)
  946. {
  947. PIF_PROTO pProto;
  948. pProto = CONTAINING_RECORD(pleNode,IF_PROTO,leIfProtoLink);
  949. //
  950. // Call the routing protocol's DisableInterface() entrypoint
  951. //
  952. dwResult = (pProto->pActiveProto->pfnInterfaceStatus)(
  953. pIcb->dwIfIndex,
  954. FALSE,
  955. RIS_INTERFACE_DISABLED,
  956. NULL
  957. );
  958. if(dwResult isnot NO_ERROR)
  959. {
  960. Trace3(ERR,
  961. "DisableInterfaceWithAllProtocols: Couldnt disable %S with %S. Error %d",
  962. pIcb->pwszName,
  963. pProto->pActiveProto->pwszDisplayName,
  964. dwResult);
  965. dwReturn = ERROR_CAN_NOT_COMPLETE;
  966. }
  967. }
  968. EXIT_LOCK(PROTOCOL_CB_LIST);
  969. return dwReturn;
  970. }
  971. DWORD
  972. EnableInterfaceWithAllProtocols(
  973. PICB pIcb
  974. )
  975. {
  976. PLIST_ENTRY pleNode;
  977. DWORD dwResult, dwReturn = NO_ERROR;
  978. TraceEnter("EnableInterfaceWithAllProtocols");
  979. ENTER_READER(PROTOCOL_CB_LIST);
  980. for(pleNode = pIcb->leProtocolList.Flink;
  981. pleNode isnot &(pIcb->leProtocolList);
  982. pleNode = pleNode->Flink)
  983. {
  984. PIF_PROTO pProto;
  985. pProto = CONTAINING_RECORD(pleNode,IF_PROTO,leIfProtoLink);
  986. dwResult = (pProto->pActiveProto->pfnInterfaceStatus)(
  987. pIcb->dwIfIndex,
  988. (pIcb->dwOperationalState >= CONNECTED),
  989. RIS_INTERFACE_ENABLED,
  990. NULL
  991. );
  992. if(dwResult isnot NO_ERROR)
  993. {
  994. Trace3(ERR,
  995. "EnableInterfaceWithAllProtocols: Couldnt enable %S with %S. Error %d",
  996. pIcb->pwszName,
  997. pProto->pActiveProto->pwszDisplayName,
  998. dwResult);
  999. dwReturn = ERROR_CAN_NOT_COMPLETE;
  1000. continue;
  1001. }
  1002. }
  1003. EXIT_LOCK(PROTOCOL_CB_LIST);
  1004. return dwReturn;
  1005. }
  1006. VOID
  1007. DeleteAllInterfaces(
  1008. VOID
  1009. )
  1010. {
  1011. PLIST_ENTRY pleNode ;
  1012. PICB pIcb ;
  1013. TraceEnter("DeleteAllInterfaces");
  1014. // *** Exclusion Begin ***
  1015. ENTER_WRITER(ICB_LIST);
  1016. //
  1017. // We do this backwards. Quick hack for fixing OSPF
  1018. //
  1019. //
  1020. // First we unlink the internal interface because if the worker function
  1021. // finds the ICB list non empty, it loops, waiting for the interfaces
  1022. // to get deleted. After all interfaces are deleted it deletes the
  1023. // internal interface
  1024. // Hence we remove the i/f from the list here and decrement the count.
  1025. //
  1026. if(g_pInternalInterfaceCb)
  1027. {
  1028. RemoveEntryList(&(g_pInternalInterfaceCb->leIfLink));
  1029. InterlockedDecrement(&g_ulNumInterfaces);
  1030. }
  1031. if(g_pLoopbackInterfaceCb)
  1032. {
  1033. g_pLoopbackInterfaceCb = NULL;
  1034. }
  1035. for(pleNode = ICBList.Blink; pleNode != &ICBList;)
  1036. {
  1037. pIcb = CONTAINING_RECORD (pleNode, ICB, leIfLink) ;
  1038. if((pIcb->dwOperationalState is CONNECTED) and
  1039. ((pIcb->ritType is ROUTER_IF_TYPE_HOME_ROUTER) or
  1040. (pIcb->ritType is ROUTER_IF_TYPE_FULL_ROUTER)))
  1041. {
  1042. MarkInterfaceForDeletion(pIcb);
  1043. pleNode = pleNode->Blink;
  1044. continue;
  1045. }
  1046. pleNode = pleNode->Blink;
  1047. RemoveInterfaceFromLists(pIcb);
  1048. DeleteSingleInterface(pIcb); // clean up interface.
  1049. //
  1050. // Free the ICB
  1051. //
  1052. HeapFree(IPRouterHeap,
  1053. 0,
  1054. pIcb);
  1055. }
  1056. // *** Exclusion End ***
  1057. EXIT_LOCK(ICB_LIST);
  1058. }
  1059. DWORD
  1060. DeleteSingleInterface(
  1061. PICB pIcb
  1062. )
  1063. {
  1064. PICB_BINDING pBinding;
  1065. PADAPTER_INFO pBindNode;
  1066. DWORD dwResult;
  1067. TraceEnter("DeleteSingleInterface");
  1068. if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
  1069. {
  1070. IpRtAssert(g_pInternalInterfaceCb);
  1071. if(pIcb->bBound)
  1072. {
  1073. PLIST_ENTRY pleNode;
  1074. IP_LOCAL_BINDING clientAddr;
  1075. clientAddr.Address = pIcb->pibBindings->dwAddress;
  1076. clientAddr.Mask = pIcb->pibBindings->dwMask;
  1077. #if 0
  1078. //
  1079. // Remove the client host route
  1080. //
  1081. DeleteSingleRoute(g_pInternalInterfaceCb->dwIfIndex,
  1082. clientAddr.Address,
  1083. HOST_ROUTE_MASK,
  1084. clientAddr.Address,
  1085. MIB_IPPROTO_NETMGMT,
  1086. FALSE);
  1087. #endif
  1088. if (g_pInternalInterfaceCb isnot NULL)
  1089. {
  1090. ENTER_READER(PROTOCOL_CB_LIST);
  1091. //
  1092. // Call ConnectClient for all the protocols configured
  1093. // over the ServerInterface
  1094. //
  1095. for(pleNode = g_pInternalInterfaceCb->leProtocolList.Flink;
  1096. pleNode isnot &(g_pInternalInterfaceCb->leProtocolList);
  1097. pleNode = pleNode->Flink)
  1098. {
  1099. PIF_PROTO pIfProto;
  1100. pIfProto = CONTAINING_RECORD(pleNode,
  1101. IF_PROTO,
  1102. leIfProtoLink);
  1103. if(pIfProto->pActiveProto->pfnDisconnectClient)
  1104. {
  1105. pIfProto->pActiveProto->pfnDisconnectClient(
  1106. g_pInternalInterfaceCb->dwIfIndex,
  1107. &clientAddr
  1108. );
  1109. }
  1110. }
  1111. EXIT_LOCK(PROTOCOL_CB_LIST);
  1112. //
  1113. // Delete static routes from RTM (and the stack)
  1114. //
  1115. DeleteAllClientRoutes(pIcb,
  1116. g_pInternalInterfaceCb->dwIfIndex);
  1117. }
  1118. if(pIcb->pStoredRoutes)
  1119. {
  1120. HeapFree(IPRouterHeap,
  1121. 0,
  1122. pIcb->pStoredRoutes);
  1123. pIcb->pStoredRoutes = NULL;
  1124. }
  1125. HeapFree(IPRouterHeap,
  1126. 0,
  1127. pIcb->pibBindings);
  1128. pIcb->pibBindings = NULL;
  1129. }
  1130. //
  1131. // Delete the interface from the filter driver
  1132. //
  1133. DeleteFilterInterface(pIcb);
  1134. return NO_ERROR;
  1135. }
  1136. if(pIcb->ritType is ROUTER_IF_TYPE_DIALOUT)
  1137. {
  1138. IpRtAssert(pIcb->bBound);
  1139. pBinding = pIcb->pibBindings;
  1140. IpRtAssert(pBinding);
  1141. DeleteAutomaticRoutes(pIcb,
  1142. pBinding[0].dwAddress,
  1143. pBinding[0].dwMask);
  1144. DeleteAllRoutes(pIcb->dwIfIndex,
  1145. FALSE);
  1146. ENTER_WRITER(BINDING_LIST);
  1147. #if DBG
  1148. pBindNode = GetInterfaceBinding(pIcb->dwIfIndex);
  1149. IpRtAssert(pBindNode);
  1150. #endif // DBG
  1151. RemoveBinding(pIcb);
  1152. EXIT_LOCK(BINDING_LIST);
  1153. HeapFree(IPRouterHeap,
  1154. 0,
  1155. pBinding);
  1156. pIcb->pibBindings = NULL;
  1157. return NO_ERROR;
  1158. }
  1159. //
  1160. // So at this point we are only dealing with FULL_ROUTER, HOME_ROUTER and
  1161. // DEDICATED type interfaces
  1162. //
  1163. //
  1164. // Delete static routes from RTM (and the stack)
  1165. //
  1166. DeleteAllRoutes(pIcb->dwIfIndex,
  1167. FALSE);
  1168. //
  1169. // WAN interfaces: bringing down an interface will not delete
  1170. // the binding. Hence we do it here
  1171. //
  1172. pBinding = NULL;
  1173. pBindNode = NULL;
  1174. if((pIcb->ritType is ROUTER_IF_TYPE_FULL_ROUTER) or
  1175. (pIcb->ritType is ROUTER_IF_TYPE_HOME_ROUTER))
  1176. {
  1177. pBinding = pIcb->pibBindings;
  1178. pBindNode = GetInterfaceBinding(pIcb->dwIfIndex);
  1179. }
  1180. //
  1181. // Bringing down the interfaces clears out stack contexts
  1182. //
  1183. if((pIcb->ritType is ROUTER_IF_TYPE_DEDICATED) or
  1184. (pIcb->ritType is ROUTER_IF_TYPE_LOOPBACK) or
  1185. #ifdef KSL_IPINIP
  1186. (pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1) or
  1187. #endif //KSL_IPINIP
  1188. (pIcb->ritType is ROUTER_IF_TYPE_INTERNAL))
  1189. {
  1190. LanEtcInterfaceUpToDown(pIcb,
  1191. TRUE);
  1192. }
  1193. else
  1194. {
  1195. WanInterfaceInactiveToDown(pIcb,
  1196. TRUE);
  1197. }
  1198. //
  1199. // This also frees up the list of IF_PROTO blocks
  1200. //
  1201. DeleteInterfaceFromAllProtocols(pIcb);
  1202. //
  1203. // Now remove the interface from the stack components
  1204. //
  1205. if((pIcb->ritType is ROUTER_IF_TYPE_FULL_ROUTER) or
  1206. (pIcb->ritType is ROUTER_IF_TYPE_HOME_ROUTER) or
  1207. (pIcb->ritType is ROUTER_IF_TYPE_INTERNAL))
  1208. {
  1209. if(pIcb->ritType isnot ROUTER_IF_TYPE_INTERNAL)
  1210. {
  1211. DeleteDemandFilterInterface(pIcb);
  1212. }
  1213. DeleteInterfaceWithWanArp(pIcb);
  1214. }
  1215. if((pIcb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  1216. (pIcb->ritType isnot ROUTER_IF_TYPE_LOOPBACK))
  1217. {
  1218. dwResult = DeleteFilterInterface(pIcb);
  1219. if(dwResult isnot NO_ERROR)
  1220. {
  1221. Trace2(ERR,
  1222. "Error %d deleting %S from the filter driver",
  1223. dwResult,
  1224. pIcb->pwszName);
  1225. }
  1226. }
  1227. #ifdef KSL_IPINIP
  1228. if(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1)
  1229. {
  1230. dwResult = DeleteInterfaceFromIpInIp(pIcb);
  1231. if(dwResult isnot NO_ERROR)
  1232. {
  1233. Trace2(ERR,
  1234. "Error %d deleting %S from the IpInIp driver",
  1235. dwResult,
  1236. pIcb->pwszName);
  1237. }
  1238. RemoveBinding(pIcb);
  1239. }
  1240. #endif //KSL_IPINIP
  1241. //
  1242. // Delete the binding for wan interfaces
  1243. //
  1244. if(pBindNode)
  1245. {
  1246. ENTER_WRITER(BINDING_LIST);
  1247. RemoveBinding(pIcb);
  1248. EXIT_LOCK(BINDING_LIST);
  1249. }
  1250. if(pBinding)
  1251. {
  1252. HeapFree(IPRouterHeap,
  1253. 0,
  1254. pBinding);
  1255. }
  1256. if(pIcb->pRtrDiscAdvt)
  1257. {
  1258. HeapFree(IPRouterHeap,
  1259. 0,
  1260. pIcb->pRtrDiscAdvt);
  1261. pIcb->pRtrDiscAdvt = NULL;
  1262. }
  1263. return NO_ERROR;
  1264. }
  1265. #ifdef KSL_IPINIP
  1266. DWORD
  1267. IpIpTunnelDownToUp(
  1268. PICB pIcb
  1269. )
  1270. {
  1271. return NO_ERROR;
  1272. }
  1273. #endif //KSL_IPINIP
  1274. DWORD
  1275. LanEtcInterfaceDownToUp(
  1276. PICB pIcb,
  1277. BOOL bAdding
  1278. )
  1279. /*++
  1280. Routine Description
  1281. The interface's admin state MUST be UP or this function will simply
  1282. return
  1283. The interface to adapter map MUST have already been stored before this
  1284. is called
  1285. Locks
  1286. ICB_LIST lock held as writer
  1287. Arguments
  1288. pIcb ICB of the interface to bring up
  1289. bAdding Set to TRUE if we are adding the interface (as opposed to bringing
  1290. it up when the admin state changed etc)
  1291. Return Value
  1292. NO_ERROR
  1293. --*/
  1294. {
  1295. DWORD dwResult;
  1296. PRESTORE_INFO_CONTEXT pricInfo;
  1297. TraceEnter("LanInterfaceDownToUp");
  1298. if(pIcb->dwAdminState isnot IF_ADMIN_STATUS_UP)
  1299. {
  1300. Trace2(ERR,
  1301. "LanInterfaceDownToUp: Tried to bring up %S when its admin state is %d",
  1302. pIcb->pwszName,
  1303. pIcb->dwAdminState);
  1304. return ERROR_INVALID_PARAMETER;
  1305. }
  1306. //
  1307. // Read the address from the registry for LAN interfaces. This function
  1308. // is also called for the INTERNAL interface, whose address is already
  1309. // plumbed by the time it is called and for TUNNEL which currently
  1310. // run in unnumbered mode
  1311. //
  1312. if(pIcb->ritType is ROUTER_IF_TYPE_DEDICATED)
  1313. {
  1314. IpRtAssert(!pIcb->bBound);
  1315. IpRtAssert(pIcb->dwNumAddresses is 0);
  1316. CheckBindingConsistency(pIcb);
  1317. dwResult = UpdateBindingInformation(pIcb);
  1318. if(dwResult isnot NO_ERROR)
  1319. {
  1320. //
  1321. // UpdateBindingInf can return ERROR_ALREADY_ASSOC,
  1322. // but since we have asserted earlier that we dont have
  1323. // an address, that error only means we still dont have an
  1324. // address
  1325. //
  1326. if(dwResult isnot ERROR_ADDRESS_ALREADY_ASSOCIATED)
  1327. {
  1328. Trace1(ERR,
  1329. "LanInterfaceDownToUp: Couldnt read binding information for %S",
  1330. pIcb->pwszName);
  1331. }
  1332. pIcb->dwOperationalState = IF_OPER_STATUS_NON_OPERATIONAL;
  1333. return ERROR_CAN_NOT_COMPLETE;
  1334. }
  1335. }
  1336. IpRtAssert(pIcb->bBound);
  1337. if(pIcb->ritType isnot ROUTER_IF_TYPE_INTERNAL)
  1338. {
  1339. pIcb->dwOperationalState = IF_OPER_STATUS_OPERATIONAL;
  1340. }
  1341. else
  1342. {
  1343. pIcb->dwOperationalState = IF_OPER_STATUS_CONNECTED;
  1344. }
  1345. //
  1346. // First do the generic interface to up stuff
  1347. //
  1348. GenericInterfaceComingUp(pIcb);
  1349. //
  1350. // We restore routes even when this function is being called from
  1351. // add interface, because that is the only way to pick up stack
  1352. // routes
  1353. //
  1354. pricInfo = HeapAlloc(IPRouterHeap,
  1355. 0,
  1356. sizeof(RESTORE_INFO_CONTEXT));
  1357. if(pricInfo isnot NULL)
  1358. {
  1359. pricInfo->dwIfIndex = pIcb->dwIfIndex;
  1360. pIcb->bRestoringRoutes = TRUE;
  1361. dwResult = QueueAsyncFunction(RestoreStaticRoutes,
  1362. (PVOID)pricInfo,
  1363. FALSE);
  1364. if(dwResult isnot NO_ERROR)
  1365. {
  1366. pIcb->bRestoringRoutes = FALSE;
  1367. IpRtAssert(FALSE);
  1368. Trace2(ERR,
  1369. "LanInterfaceDownToUp: Error %d queueing function for %S",
  1370. dwResult,
  1371. pIcb->pwszName);
  1372. }
  1373. }
  1374. else
  1375. {
  1376. IpRtAssert(FALSE);
  1377. Trace1(ERR,
  1378. "LanInterfaceDownToUp: Error allocating context for %S",
  1379. pIcb->pwszName);
  1380. }
  1381. return NO_ERROR;
  1382. }
  1383. DWORD
  1384. WanInterfaceInactiveToUp(
  1385. PICB pIcb
  1386. )
  1387. /*++
  1388. Routine Description
  1389. This function does things slighlty differently from above because, for
  1390. one, there is no UpdateBindingInfo() call for such adapters
  1391. Locks
  1392. Arguments
  1393. Return Value
  1394. --*/
  1395. {
  1396. PRESTORE_INFO_CONTEXT pricInfo;
  1397. DWORD dwResult;
  1398. INTERFACE_ROUTE_INFO rifRoute;
  1399. TraceEnter("WanInterfaceInactiveToUp");
  1400. CheckBindingConsistency(pIcb);
  1401. Trace1(IF,
  1402. "WanInterfaceInactiveToUp: %S coming up",
  1403. pIcb->pwszName);
  1404. //
  1405. // quick look up of interface given the adapter index.
  1406. // This is done in UpdateBindingInfo for LAN interfaces.
  1407. //
  1408. //StoreAdapterToInterfaceMap(pIcb->dwAdapterId,
  1409. // pIcb->dwIfIndex);
  1410. //
  1411. // First do the generic thing
  1412. //
  1413. GenericInterfaceComingUp(pIcb);
  1414. //
  1415. // Delete all static routes. These will be re-added
  1416. // by RestoreStaticRoutes (below) with the correct next hop
  1417. //
  1418. DeleteAllRoutes(pIcb->dwIfIndex, TRUE);
  1419. //
  1420. // Restore all static and NON-Dod routes on this interface
  1421. //
  1422. pricInfo = HeapAlloc(IPRouterHeap,
  1423. 0,
  1424. sizeof(RESTORE_INFO_CONTEXT));
  1425. if(pricInfo isnot NULL)
  1426. {
  1427. pricInfo->dwIfIndex = pIcb->dwIfIndex;
  1428. pIcb->bRestoringRoutes = TRUE;
  1429. dwResult = QueueAsyncFunction(RestoreStaticRoutes,
  1430. (PVOID)pricInfo,
  1431. FALSE);
  1432. if(dwResult isnot NO_ERROR)
  1433. {
  1434. pIcb->bRestoringRoutes = FALSE;
  1435. IpRtAssert(FALSE);
  1436. Trace2(ERR,
  1437. "WanInterfaceInactiveToUp: Error %d queueing function for %S",
  1438. dwResult,
  1439. pIcb->pwszName);
  1440. }
  1441. }
  1442. else
  1443. {
  1444. IpRtAssert(FALSE);
  1445. Trace1(ERR,
  1446. "WanInterfaceInactiveToUp: Error allocating context for %S",
  1447. pIcb->pwszName);
  1448. }
  1449. //
  1450. // Change Static route so that it uses the correct adapter index
  1451. //
  1452. // ChangeAdapterIndexForDodRoutes(pIcb->dwIfIndex);
  1453. //
  1454. // Add a host route for the remote side
  1455. //
  1456. if(pIcb->dwRemoteAddress isnot INVALID_IP_ADDRESS
  1457. #if __PIX__
  1458. && (IsRemoteAddressPrivate(pIcb)))
  1459. #else
  1460. )
  1461. #endif
  1462. {
  1463. rifRoute.dwRtInfoMask = HOST_ROUTE_MASK;
  1464. rifRoute.dwRtInfoNextHop = pIcb->pibBindings[0].dwAddress;
  1465. rifRoute.dwRtInfoDest = pIcb->dwRemoteAddress;
  1466. rifRoute.dwRtInfoIfIndex = pIcb->dwIfIndex;
  1467. rifRoute.dwRtInfoMetric1 = 1;
  1468. rifRoute.dwRtInfoMetric2 = 0;
  1469. rifRoute.dwRtInfoMetric3 = 0;
  1470. rifRoute.dwRtInfoPreference =
  1471. ComputeRouteMetric(MIB_IPPROTO_NETMGMT);
  1472. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  1473. RTM_VIEW_MASK_MCAST; // XXX config
  1474. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1475. rifRoute.dwRtInfoProto = MIB_IPPROTO_NETMGMT;
  1476. rifRoute.dwRtInfoAge = 0;
  1477. rifRoute.dwRtInfoNextHopAS = 0;
  1478. rifRoute.dwRtInfoPolicy = 0;
  1479. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  1480. &rifRoute,
  1481. pIcb->pibBindings[0].dwMask,
  1482. 0, // RTM_ROUTE_INFO::Flags
  1483. TRUE, // Valid route
  1484. TRUE,
  1485. TRUE,
  1486. NULL);
  1487. if(dwResult isnot NO_ERROR)
  1488. {
  1489. Trace1(ERR,
  1490. "WanInterfaceInactiveToUp: Couldnt add host route for %x",
  1491. pIcb->dwRemoteAddress);
  1492. }
  1493. }
  1494. return NO_ERROR;
  1495. }
  1496. DWORD
  1497. GenericInterfaceComingUp(
  1498. PICB pIcb
  1499. )
  1500. /*++
  1501. Routine Description
  1502. This function has the common code for bringing up an interface.
  1503. It assumes that the interface is bound.
  1504. If NAT is running and we have an address (not unnumbered) we add the
  1505. address to NAT.
  1506. We activate router discovery and multicast heartbeat (if they are present)
  1507. Then we add
  1508. (i) local loopback
  1509. (ii) local multicast
  1510. (iii) all subnets broadcast
  1511. (iv) all 1's broadcast
  1512. routes
  1513. Then we call out to the routing protocols and the filter driver to inform
  1514. them of the binding
  1515. Locks
  1516. ICB_LIST lock held as WRITER
  1517. Arguments
  1518. pIcb ICB of the interface to bring up
  1519. Return Value
  1520. --*/
  1521. {
  1522. DWORD dwResult, i;
  1523. MIB_IPFORWARDROW rifRoute;
  1524. PADAPTER_INFO pBinding;
  1525. TraceEnter("GenericInterfaceComingUp");
  1526. Trace1(IF,
  1527. "GenericInterfaceComingUp: %S coming UP",
  1528. pIcb->pwszName);
  1529. // Join the All-Routers multicast group
  1530. {
  1531. extern SOCKET McMiscSocket;
  1532. Trace1(IF,
  1533. "CreateSockets: Joining ALL_ROUTERS on %S",
  1534. pIcb->pwszName);
  1535. if ( McJoinGroupByIndex( McMiscSocket,
  1536. SOCK_RAW,
  1537. ALL_ROUTERS_MULTICAST_GROUP,
  1538. pIcb->dwIfIndex ) is SOCKET_ERROR )
  1539. {
  1540. Trace2(ERR,
  1541. "GenericInterfaceComingUp: Error %d joining all-routers group on %S",
  1542. WSAGetLastError(),
  1543. pIcb->pwszName);
  1544. }
  1545. }
  1546. //
  1547. // Start router discovery on this interface. This will cause
  1548. // the advertisement to get updated
  1549. //
  1550. dwResult = ActivateRouterDiscovery(pIcb);
  1551. if(dwResult isnot NO_ERROR)
  1552. {
  1553. Trace2(ERR,
  1554. "GenericInterfaceComingUp: Error %d activating router discovery on %S",
  1555. dwResult,
  1556. pIcb->pwszName);
  1557. }
  1558. dwResult = ActivateMHeartbeat(pIcb);
  1559. if(dwResult isnot NO_ERROR)
  1560. {
  1561. Trace2(ERR,
  1562. "GenericInterfaceComingUp: Error %d activating router discovery on %S",
  1563. dwResult,
  1564. pIcb->pwszName);
  1565. }
  1566. //
  1567. // Add default routes for the connected network
  1568. //
  1569. for(i = 0; i < pIcb->dwNumAddresses; i++)
  1570. {
  1571. if(pIcb->pibBindings[i].dwAddress is INVALID_IP_ADDRESS)
  1572. {
  1573. continue;
  1574. }
  1575. AddAutomaticRoutes(pIcb,
  1576. pIcb->pibBindings[i].dwAddress,
  1577. pIcb->pibBindings[i].dwMask);
  1578. }
  1579. //
  1580. // Interfaces going to UP must have valid binding information.
  1581. // This is passed to the routing protocols
  1582. //
  1583. BindInterfaceInAllProtocols(pIcb);
  1584. // Set Multicast limits in stack
  1585. ActivateMcastLimits(pIcb);
  1586. for (i=0; i<NUM_INFO_CBS; i++)
  1587. {
  1588. if (!g_rgicInfoCb[i].pfnBindInterface)
  1589. {
  1590. continue;
  1591. }
  1592. dwResult = g_rgicInfoCb[i].pfnBindInterface(pIcb);
  1593. if (dwResult isnot NO_ERROR)
  1594. {
  1595. Trace3(ERR,
  1596. "GenericInterfaceComingUp: Error %d binding %S for %s info",
  1597. dwResult,
  1598. pIcb->pwszName,
  1599. g_rgicInfoCb[i].pszInfoName);
  1600. }
  1601. }
  1602. return NO_ERROR ;
  1603. }
  1604. DWORD
  1605. LanEtcInterfaceUpToDown(
  1606. PICB pIcb,
  1607. BOOL bDeleted
  1608. )
  1609. /*++
  1610. Routine Description
  1611. This function is called when a LAN, INTERNAL or LOOPBACK interface goes
  1612. down.
  1613. If the interface is not being deleted, we delete all the static routes.
  1614. We then disable the interface with the routing protocols and call
  1615. the generic routing to handle all the rest
  1616. Locks
  1617. ICB_LOCK held as WRITER
  1618. Arguments
  1619. pIcb
  1620. bDeleted
  1621. Return Value
  1622. None
  1623. --*/
  1624. {
  1625. DWORD i,dwResult;
  1626. TraceEnter("LanInterfaceUpToDown");
  1627. if(!bDeleted)
  1628. {
  1629. DeleteAllRoutes(pIcb->dwIfIndex,
  1630. FALSE);
  1631. }
  1632. GenericInterfaceNoLongerUp(pIcb,
  1633. bDeleted);
  1634. pIcb->dwOperationalState = IF_OPER_STATUS_NON_OPERATIONAL;
  1635. return NO_ERROR;
  1636. }
  1637. DWORD
  1638. WanInterfaceUpToInactive(
  1639. PICB pIcb,
  1640. BOOL bDeleted
  1641. )
  1642. {
  1643. DWORD dwResult;
  1644. PRESTORE_INFO_CONTEXT pricInfo;
  1645. TraceEnter("WanInterfaceUpToInactive");
  1646. //
  1647. // Delete the route before deallocating the address (which is called in
  1648. // GenericInterfaceNoLongerUp), because that will set Remote addr to
  1649. // invalid and then this route will never be deleted
  1650. //
  1651. CheckBindingConsistency(pIcb);
  1652. //
  1653. // If it was up, it should be bound
  1654. //
  1655. IpRtAssert(pIcb->bBound);
  1656. if(!bDeleted and
  1657. (pIcb->dwRemoteAddress isnot INVALID_IP_ADDRESS))
  1658. {
  1659. dwResult = DeleteSingleRoute(pIcb->dwIfIndex,
  1660. pIcb->dwRemoteAddress,
  1661. HOST_ROUTE_MASK,
  1662. pIcb->pibBindings[0].dwAddress,
  1663. PROTO_IP_NETMGMT,
  1664. TRUE);
  1665. if(dwResult isnot NO_ERROR)
  1666. {
  1667. Trace1(ERR,
  1668. "WanInterfaceUpToInactive: Couldnt delete host route for %d.%d.%d.%d",
  1669. PRINT_IPADDR(pIcb->dwRemoteAddress));
  1670. }
  1671. }
  1672. GenericInterfaceNoLongerUp(pIcb,
  1673. bDeleted);
  1674. if(!bDeleted)
  1675. {
  1676. #if 1
  1677. //
  1678. // Delete all static routes/nexthops
  1679. //
  1680. DeleteAllRoutes(pIcb->dwIfIndex, FALSE);
  1681. /*
  1682. //
  1683. // Delete all netmgmt routes/nexthops
  1684. //
  1685. dwResult = DeleteRtmRoutes(g_hNetMgmtRoute, pIcb->dwIfIndex, FALSE);
  1686. if (dwResult is NO_ERROR)
  1687. {
  1688. dwResult = DeleteRtmNexthopsOnInterface(
  1689. g_hNetMgmtRoute, pIcb->dwIfIndex
  1690. );
  1691. if (dwResult isnot NO_ERROR)
  1692. {
  1693. Trace1(
  1694. ERR,
  1695. "WanInterfaceUpToInactive: Couldnt delete next hops for "
  1696. "Interface 0x%x",
  1697. pIcb->dwIfIndex
  1698. );
  1699. }
  1700. }
  1701. */
  1702. //
  1703. // Restore all static and NON-Dod routes on this interface
  1704. //
  1705. pricInfo = HeapAlloc(
  1706. IPRouterHeap, 0, sizeof(RESTORE_INFO_CONTEXT)
  1707. );
  1708. if(pricInfo isnot NULL)
  1709. {
  1710. pricInfo->dwIfIndex = pIcb->dwIfIndex;
  1711. pIcb->bRestoringRoutes = TRUE;
  1712. dwResult = QueueAsyncFunction(RestoreStaticRoutes,
  1713. (PVOID)pricInfo,
  1714. FALSE);
  1715. if(dwResult isnot NO_ERROR)
  1716. {
  1717. pIcb->bRestoringRoutes = FALSE;
  1718. IpRtAssert(FALSE);
  1719. Trace2(ERR,
  1720. "WanInterfaceUpToInactive: Error %d queueing"
  1721. " function for %S",
  1722. dwResult,
  1723. pIcb->pwszName);
  1724. }
  1725. }
  1726. else
  1727. {
  1728. IpRtAssert(FALSE);
  1729. Trace1(ERR,
  1730. "WanInterfaceInactiveToUp: Error allocating context for %S",
  1731. pIcb->pwszName);
  1732. }
  1733. #else
  1734. //
  1735. // Delete all NON-Dod, Netmgmt routes on this interface
  1736. //
  1737. DeleteRtmRoutes(g_hNonDodRoute, pIcb->dwIfIndex, FALSE);
  1738. DeleteRtmRoutes(g_hNetMgmtRoute, pIcb->dwIfIndex, FALSE);
  1739. ChangeAdapterIndexForDodRoutes(pIcb->dwIfIndex);
  1740. #endif
  1741. }
  1742. pIcb->dwOperationalState = IF_OPER_STATUS_DISCONNECTED;
  1743. return NO_ERROR;
  1744. }
  1745. DWORD
  1746. GenericInterfaceNoLongerUp(
  1747. PICB pIcb,
  1748. BOOL bDeleted
  1749. )
  1750. /*++
  1751. Routine Description
  1752. This function is called by all interfaces (other than CLIENT) when
  1753. they go to DOWN state (The actual state depends upon the interface). This
  1754. may happen because of state change or because the interface is being
  1755. deleted
  1756. If we are not deleting the interface, we delete all the automatically
  1757. generated routes
  1758. We deactivate router discovery and multicast hearbeat.
  1759. If NAT is running, we remove the FIREWALL context for the interface
  1760. from IP and THEN unbind the address in NAT
  1761. (This MUST be done in this order)
  1762. Then we Unbind the interface in the routing protocols running over it.
  1763. We delete the Adapter->Interface map, deallocate the bindings (which does
  1764. different things depending on LAN/WAN) and if there is a DIM event we
  1765. set the event
  1766. Locks
  1767. ICB_LIST lock held as WRITER
  1768. Arguments
  1769. pIcb ICB of the interface
  1770. bDeleted Set to TRUE if the state change is because of deletion
  1771. Return Value
  1772. None
  1773. --*/
  1774. {
  1775. DWORD dwResult;
  1776. DWORD i, j;
  1777. TraceEnter("GenericInterfaceNoLongerUp");
  1778. Trace1(IF,
  1779. "GenericInterfaceNoLongerUp: %S no longer UP",
  1780. pIcb->pwszName);
  1781. if(pIcb->bMcastEnabled)
  1782. {
  1783. pIcb->bMcastEnabled = FALSE;
  1784. dwResult = SetMcastOnIf(pIcb,
  1785. FALSE);
  1786. if(dwResult isnot NO_ERROR)
  1787. {
  1788. Trace2(ERR,
  1789. "GenericIfNoLongerUp: Error %d deactivating mcast on %S",
  1790. dwResult,
  1791. pIcb->pwszName);
  1792. }
  1793. }
  1794. if(!bDeleted)
  1795. {
  1796. for (i = 0; i < pIcb->dwNumAddresses; i++)
  1797. {
  1798. if(pIcb->pibBindings[i].dwAddress isnot INVALID_IP_ADDRESS)
  1799. {
  1800. DeleteAutomaticRoutes(pIcb,
  1801. pIcb->pibBindings[i].dwAddress,
  1802. pIcb->pibBindings[i].dwMask);
  1803. }
  1804. }
  1805. }
  1806. //
  1807. // Delete any gateways on this
  1808. //
  1809. for(i = 0; i < g_ulGatewayMaxCount; i++)
  1810. {
  1811. if(g_pGateways[i].dwIfIndex is pIcb->dwIfIndex)
  1812. {
  1813. g_pGateways[i].dwAddress = 0;
  1814. }
  1815. }
  1816. //
  1817. // Compress the array
  1818. //
  1819. for(i = 0, j = 1; j < g_ulGatewayMaxCount;j++)
  1820. {
  1821. if(g_pGateways[i].dwAddress isnot 0)
  1822. {
  1823. i++;
  1824. }
  1825. else
  1826. {
  1827. if(g_pGateways[j].dwAddress isnot 0)
  1828. {
  1829. g_pGateways[i] = g_pGateways[j];
  1830. g_pGateways[j].dwAddress = 0;
  1831. i++;
  1832. }
  1833. }
  1834. }
  1835. g_ulGatewayCount = i;
  1836. dwResult = DeActivateRouterDiscovery(pIcb);
  1837. if(dwResult isnot NO_ERROR)
  1838. {
  1839. Trace2(ERR,
  1840. "GenericInterfaceNoLongerUp: Error %d deactivating router discovery on %S",
  1841. dwResult,
  1842. pIcb->pwszName);
  1843. }
  1844. dwResult = DeActivateMHeartbeat(pIcb);
  1845. if(dwResult isnot NO_ERROR)
  1846. {
  1847. Trace2(ERR,
  1848. "GenericInterfaceNoLongerUp: Error %d deactivating multicast heartbeat on %S",
  1849. dwResult,
  1850. pIcb->pwszName);
  1851. }
  1852. if((pIcb->ritType isnot ROUTER_IF_TYPE_INTERNAL) and
  1853. (pIcb->ritType isnot ROUTER_IF_TYPE_LOOPBACK))
  1854. {
  1855. UnbindFilterInterface(pIcb);
  1856. }
  1857. //
  1858. // When going out of UP state, the interface loses its address
  1859. //
  1860. UnbindInterfaceInAllProtocols(pIcb);
  1861. //if(pIcb->pibBindings)
  1862. //{
  1863. // DeleteAdapterToInterfaceMap(pIcb->dwAdapterId) ;
  1864. //}
  1865. DeAllocateBindings(pIcb);
  1866. if(pIcb->hDIMNotificationEvent isnot NULL)
  1867. {
  1868. //
  1869. // There was an update pending. Set the event, when the user asks us
  1870. // for info, we will fail the request
  1871. //
  1872. if(!SetEvent(pIcb->hDIMNotificationEvent))
  1873. {
  1874. Trace1(ERR,
  1875. "GenericInterfaceNoLongerUp: Error %d setting update route event",
  1876. GetLastError());
  1877. }
  1878. CloseHandle(pIcb->hDIMNotificationEvent);
  1879. pIcb->hDIMNotificationEvent = NULL;
  1880. }
  1881. return NO_ERROR ;
  1882. }
  1883. DWORD
  1884. WanInterfaceInactiveToDown(
  1885. PICB pIcb,
  1886. BOOL bDeleted
  1887. )
  1888. {
  1889. TraceEnter("WanInterfaceInactiveToDown");
  1890. CheckBindingConsistency(pIcb);
  1891. IpRtAssert(!pIcb->bBound);
  1892. if(!bDeleted)
  1893. {
  1894. DeleteAllRoutes(pIcb->dwIfIndex,
  1895. FALSE);
  1896. }
  1897. pIcb->dwOperationalState = UNREACHABLE;
  1898. //DisableInterfacewithWanArp(pIcb);
  1899. return NO_ERROR;
  1900. }
  1901. DWORD
  1902. WanInterfaceDownToInactive(
  1903. PICB pIcb
  1904. )
  1905. {
  1906. PRESTORE_INFO_CONTEXT pricInfo;
  1907. DWORD dwResult;
  1908. PADAPTER_INFO pBinding;
  1909. TraceEnter("WanInterfaceDownToInactive");
  1910. #if STATIC_RT_DBG
  1911. ENTER_WRITER(BINDING_LIST);
  1912. pBinding = GetInterfaceBinding(pIcb->dwIfIndex);
  1913. pBinding->bUnreach = FALSE;
  1914. EXIT_LOCK(BINDING_LIST);
  1915. #endif
  1916. //
  1917. // Set the state before calling restore
  1918. //
  1919. pIcb->dwOperationalState = DISCONNECTED;
  1920. pricInfo = HeapAlloc(IPRouterHeap,
  1921. 0,
  1922. sizeof(RESTORE_INFO_CONTEXT));
  1923. if(pricInfo isnot NULL)
  1924. {
  1925. pricInfo->dwIfIndex = pIcb->dwIfIndex;
  1926. pIcb->bRestoringRoutes = TRUE;
  1927. dwResult = QueueAsyncFunction(RestoreStaticRoutes,
  1928. (PVOID)pricInfo,
  1929. FALSE);
  1930. if(dwResult isnot NO_ERROR)
  1931. {
  1932. pIcb->bRestoringRoutes = FALSE;
  1933. IpRtAssert(FALSE);
  1934. Trace2(ERR,
  1935. "WanInterfaceDownToInactive: Error %d queueing function for %S",
  1936. dwResult,
  1937. pIcb->pwszName);
  1938. HeapFree(
  1939. IPRouterHeap,
  1940. 0,
  1941. pricInfo
  1942. );
  1943. }
  1944. }
  1945. else
  1946. {
  1947. IpRtAssert(FALSE);
  1948. Trace1(ERR,
  1949. "WanInterfaceDownToInactive: Error allocating context for %S",
  1950. pIcb->pwszName);
  1951. }
  1952. return NO_ERROR;
  1953. }
  1954. DWORD
  1955. GetInterfaceStatusInfo(
  1956. IN PICB pIcb,
  1957. IN PRTR_TOC_ENTRY pToc,
  1958. IN PBYTE pbDataPtr,
  1959. IN OUT PRTR_INFO_BLOCK_HEADER pInfoHdr,
  1960. IN OUT PDWORD pdwInfoSize
  1961. )
  1962. {
  1963. PINTERFACE_STATUS_INFO pisiInfo;
  1964. TraceEnter("GetInterfaceStatusInfo");
  1965. if(*pdwInfoSize < sizeof(INTERFACE_STATUS_INFO))
  1966. {
  1967. *pdwInfoSize = sizeof(INTERFACE_STATUS_INFO);
  1968. return ERROR_INSUFFICIENT_BUFFER;
  1969. }
  1970. *pdwInfoSize = sizeof(INTERFACE_STATUS_INFO);
  1971. //pToc->InfoVersion sizeof(INTERFACE_STATUS_INFO);
  1972. pToc->InfoSize = sizeof(INTERFACE_STATUS_INFO);
  1973. pToc->InfoType = IP_INTERFACE_STATUS_INFO;
  1974. pToc->Count = 1;
  1975. pToc->Offset = (ULONG)(pbDataPtr - (PBYTE) pInfoHdr) ;
  1976. pisiInfo = (PINTERFACE_STATUS_INFO)pbDataPtr;
  1977. pisiInfo->dwAdminStatus = pIcb->dwAdminState;
  1978. return NO_ERROR;
  1979. }
  1980. DWORD
  1981. SetInterfaceStatusInfo(
  1982. PICB pIcb,
  1983. PRTR_INFO_BLOCK_HEADER pInfoHdr,
  1984. PBOOL pbUpdateDIM
  1985. )
  1986. {
  1987. PINTERFACE_STATUS_INFO pisiInfo;
  1988. PRTR_TOC_ENTRY pToc;
  1989. DWORD dwResult;
  1990. TraceEnter("SetInterfaceStatusInfo");
  1991. pToc = GetPointerToTocEntry(IP_INTERFACE_STATUS_INFO, pInfoHdr);
  1992. if((pToc is NULL) or
  1993. (pToc->InfoSize is 0))
  1994. {
  1995. //
  1996. // No TOC means no change. Also empty TOC means no change (IN THIS
  1997. // ONE CASE ONLY)
  1998. //
  1999. return NO_ERROR;
  2000. }
  2001. pisiInfo = (PINTERFACE_STATUS_INFO)GetInfoFromTocEntry(pInfoHdr,
  2002. pToc);
  2003. if (pisiInfo is NULL)
  2004. {
  2005. //
  2006. // no info block means no change.
  2007. //
  2008. return NO_ERROR;
  2009. }
  2010. dwResult = SetInterfaceAdminStatus(pIcb,
  2011. pisiInfo->dwAdminStatus,
  2012. pbUpdateDIM);
  2013. if(dwResult isnot NO_ERROR)
  2014. {
  2015. Trace2(ERR,
  2016. "SetInterfaceStatusInfo: Error %d setting admin status for %S",
  2017. dwResult,
  2018. pIcb->pwszName);
  2019. }
  2020. return dwResult;
  2021. }
  2022. VOID
  2023. DeAllocateBindings(
  2024. PICB pIcb
  2025. )
  2026. {
  2027. PADAPTER_INFO pBinding;
  2028. TraceEnter("DeAllocateBindings");
  2029. ENTER_WRITER(BINDING_LIST);
  2030. //
  2031. // For LAN interfaces we remove the binding from the
  2032. // list and free the addresses
  2033. // For WAN interfaces, to avoid allocations when
  2034. // connections are coming up and down, we zero out the fields and keep
  2035. // the memory around. Which means we need to free the memory and the
  2036. // binding when the interface is deleted
  2037. //
  2038. if((pIcb->ritType is ROUTER_IF_TYPE_DEDICATED) or
  2039. (pIcb->ritType is ROUTER_IF_TYPE_INTERNAL) or
  2040. (pIcb->ritType is ROUTER_IF_TYPE_LOOPBACK))
  2041. {
  2042. if(pIcb->bBound)
  2043. {
  2044. //
  2045. // These can not be unnumbered
  2046. //
  2047. IpRtAssert(pIcb->dwNumAddresses isnot 0);
  2048. IpRtAssert(pIcb->pibBindings);
  2049. RemoveBinding(pIcb);
  2050. HeapFree(IPRouterHeap, 0, pIcb->pibBindings);
  2051. pIcb->pibBindings = NULL;
  2052. pIcb->dwNumAddresses = 0;
  2053. pIcb->bBound = FALSE;
  2054. pIcb->dwRemoteAddress = INVALID_IP_ADDRESS;
  2055. }
  2056. }
  2057. else
  2058. {
  2059. pBinding = GetInterfaceBinding(pIcb->dwIfIndex);
  2060. if (pBinding) {
  2061. IpRtAssert(pBinding isnot NULL);
  2062. pIcb->bBound = FALSE;
  2063. pBinding->bBound = FALSE;
  2064. pIcb->dwNumAddresses = 0;
  2065. pBinding->dwNumAddresses = 0;
  2066. pIcb->dwRemoteAddress = INVALID_IP_ADDRESS;
  2067. pBinding->dwRemoteAddress = INVALID_IP_ADDRESS;
  2068. pIcb->pibBindings[0].dwAddress = INVALID_IP_ADDRESS;
  2069. pIcb->pibBindings[0].dwMask = INVALID_IP_ADDRESS;
  2070. pBinding->rgibBinding[0].dwAddress = INVALID_IP_ADDRESS;
  2071. pBinding->rgibBinding[0].dwMask = INVALID_IP_ADDRESS;
  2072. g_LastUpdateTable[IPADDRCACHE] = 0;
  2073. }
  2074. }
  2075. EXIT_LOCK(BINDING_LIST);
  2076. }
  2077. DWORD
  2078. GetInterfaceStatistics(
  2079. IN PICB pIcb,
  2080. OUT PMIB_IFROW pOutBuffer
  2081. )
  2082. {
  2083. DWORD dwResult;
  2084. dwResult = NO_ERROR;
  2085. TraceEnter("GetInterfaceStatistics");
  2086. switch(pIcb->ritType)
  2087. {
  2088. case ROUTER_IF_TYPE_HOME_ROUTER:
  2089. case ROUTER_IF_TYPE_FULL_ROUTER:
  2090. {
  2091. dwResult = AccessIfEntryWanArp(ACCESS_GET,
  2092. pIcb,
  2093. pOutBuffer);
  2094. pOutBuffer->dwIndex = pIcb->dwIfIndex;
  2095. wcscpy(pOutBuffer->wszName, pIcb->pwszName);
  2096. pOutBuffer->dwAdminStatus = pIcb->dwAdminState;
  2097. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2098. strncpy(pOutBuffer->bDescr,
  2099. g_rgcWanString,
  2100. MAXLEN_IFDESCR - 1);
  2101. pOutBuffer->dwDescrLen =
  2102. min((MAXLEN_IFDESCR-1),strlen(g_rgcWanString));
  2103. pOutBuffer->bDescr[MAXLEN_IFDESCR -1] = '\0';
  2104. break;
  2105. }
  2106. case ROUTER_IF_TYPE_DEDICATED:
  2107. #ifdef KSL_IPINIP
  2108. case ROUTER_IF_TYPE_TUNNEL1:
  2109. #endif //KSL_IPINIP
  2110. case ROUTER_IF_TYPE_DIALOUT:
  2111. {
  2112. //
  2113. // A Lan Interface that is up
  2114. //
  2115. dwResult = GetIfEntryFromStack(pOutBuffer,
  2116. pIcb->dwIfIndex,
  2117. FALSE);
  2118. if(dwResult is NO_ERROR)
  2119. {
  2120. //
  2121. // Bug 486465
  2122. //
  2123. // The stack and user mode RRAS service are out
  2124. // of sync. with respect to IF indices. This
  2125. // problem appears to be PnP related.
  2126. // For now, flag this error and return.
  2127. // Investigate this further in the next release.
  2128. //
  2129. if(pOutBuffer->dwIndex isnot pIcb->dwIfIndex)
  2130. {
  2131. Trace2(ERR,
  2132. "GetInterfaceStatistics: failed due to i/f index "
  2133. "mistmatch, stack %d, IP Router Manager %d",
  2134. pOutBuffer->dwIndex,
  2135. pIcb->dwIfIndex);
  2136. dwResult = ERROR_INVALID_PARAMETER;
  2137. break;
  2138. }
  2139. //IpRtAssert(pOutBuffer->dwIndex is pIcb->dwIfIndex);
  2140. //
  2141. // Copy out the name too
  2142. //
  2143. wcscpy(pOutBuffer->wszName, pIcb->pwszName);
  2144. //
  2145. // Set the user mode status
  2146. //
  2147. pOutBuffer->dwAdminStatus = pIcb->dwAdminState;
  2148. #ifdef KSL_IPINIP
  2149. //
  2150. // Till the notification from ipinip to router is done
  2151. // pass the driver status back for tunnels
  2152. //pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2153. if(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1)
  2154. {
  2155. strncpy(pOutBuffer->bDescr,
  2156. g_rgcIpIpString,
  2157. MAXLEN_IFDESCR - 1);
  2158. pOutBuffer->dwDescrLen =
  2159. min((MAXLEN_IFDESCR-1),
  2160. strlen(g_rgcIpIpString));
  2161. pOutBuffer->bDescr[MAXLEN_IFDESCR -1] = '\0';
  2162. }
  2163. else
  2164. {
  2165. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2166. }
  2167. #endif //KSL_IPINIP
  2168. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2169. }
  2170. break;
  2171. }
  2172. case ROUTER_IF_TYPE_INTERNAL:
  2173. {
  2174. pOutBuffer->dwIndex = pIcb->dwIfIndex;
  2175. wcscpy(pOutBuffer->wszName, pIcb->pwszName);
  2176. pOutBuffer->dwAdminStatus = pIcb->dwAdminState;
  2177. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2178. strncpy(pOutBuffer->bDescr,
  2179. g_rgcInternalString,
  2180. MAXLEN_IFDESCR - 1);
  2181. pOutBuffer->dwDescrLen =
  2182. min((MAXLEN_IFDESCR-1),strlen(g_rgcInternalString));
  2183. pOutBuffer->bDescr[MAXLEN_IFDESCR -1] = '\0';
  2184. pOutBuffer->dwType = IF_TYPE_PPP;
  2185. dwResult = NO_ERROR;
  2186. break;
  2187. }
  2188. case ROUTER_IF_TYPE_LOOPBACK:
  2189. {
  2190. pOutBuffer->dwIndex = pIcb->dwIfIndex;
  2191. wcscpy(pOutBuffer->wszName, pIcb->pwszName);
  2192. pOutBuffer->dwAdminStatus = pIcb->dwAdminState;
  2193. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2194. strncpy(pOutBuffer->bDescr,
  2195. g_rgcLoopbackString,
  2196. MAXLEN_IFDESCR - 1);
  2197. pOutBuffer->dwDescrLen =
  2198. min((MAXLEN_IFDESCR-1),strlen(g_rgcLoopbackString));
  2199. pOutBuffer->bDescr[MAXLEN_IFDESCR - 1] = '\0';
  2200. pOutBuffer->dwType = IF_TYPE_SOFTWARE_LOOPBACK;
  2201. pOutBuffer->dwMtu = 32768;
  2202. pOutBuffer->dwSpeed = 10000000;
  2203. dwResult = NO_ERROR;
  2204. break;
  2205. }
  2206. case ROUTER_IF_TYPE_CLIENT:
  2207. {
  2208. RtlZeroMemory(pOutBuffer,
  2209. sizeof(MIB_IFROW));
  2210. pOutBuffer->dwIndex = pIcb->dwIfIndex;
  2211. wcscpy(pOutBuffer->wszName, pIcb->pwszName);
  2212. pOutBuffer->dwAdminStatus = pIcb->dwAdminState;
  2213. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2214. pOutBuffer->dwType = IF_TYPE_PPP;
  2215. dwResult = NO_ERROR;
  2216. }
  2217. default:
  2218. {
  2219. IpRtAssert(FALSE);
  2220. }
  2221. }
  2222. if((dwResult isnot NO_ERROR) and
  2223. ((pIcb->dwOperationalState is NON_OPERATIONAL) or
  2224. (pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN)))
  2225. {
  2226. RtlZeroMemory(pOutBuffer,
  2227. sizeof(MIB_IFROW));
  2228. pOutBuffer->dwIndex = pIcb->dwIfIndex;
  2229. wcscpy(pOutBuffer->wszName, pIcb->pwszName);
  2230. pOutBuffer->dwAdminStatus = pIcb->dwAdminState;
  2231. pOutBuffer->dwOperStatus = pIcb->dwOperationalState;
  2232. if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
  2233. {
  2234. pOutBuffer->dwType = IF_TYPE_PPP;
  2235. }
  2236. else
  2237. {
  2238. #ifdef KSL_IPINIP
  2239. if(pIcb->ritType is ROUTER_IF_TYPE_TUNNEL1)
  2240. {
  2241. strncpy(pOutBuffer->bDescr,
  2242. g_rgcIpIpString,
  2243. MAXLEN_IFDESCR - 1);
  2244. pOutBuffer->dwDescrLen =
  2245. min((MAXLEN_IFDESCR-1),
  2246. strlen(g_rgcIpIpString));
  2247. pOutBuffer->bDescr[MAXLEN_IFDESCR -1] = '\0';
  2248. pOutBuffer->dwType = IF_TYPE_TUNNEL;
  2249. }
  2250. #endif //KSL_IPINIP
  2251. pOutBuffer->dwType = IF_TYPE_OTHER;
  2252. }
  2253. dwResult = NO_ERROR;
  2254. }
  2255. return dwResult;
  2256. }
  2257. DWORD
  2258. SetInterfaceStatistics(
  2259. IN PICB pIcb,
  2260. IN PMIB_IFROW lpInBuffer,
  2261. OUT PBOOL pbUpdateDIM
  2262. )
  2263. {
  2264. DWORD dwResult = NO_ERROR;
  2265. TraceEnter("SetInterfaceStatistics");
  2266. dwResult = SetInterfaceAdminStatus(pIcb,
  2267. lpInBuffer->dwAdminStatus,
  2268. pbUpdateDIM);
  2269. if(dwResult isnot NO_ERROR)
  2270. {
  2271. Trace2(ERR,
  2272. "SetInterfaceStatistics: Error %d setting admin status for %S",
  2273. dwResult,
  2274. pIcb->pwszName);
  2275. }
  2276. return dwResult;
  2277. }
  2278. DWORD
  2279. SetInterfaceAdminStatus(
  2280. IN PICB pIcb,
  2281. IN DWORD dwAdminStatus,
  2282. OUT PBOOL pbUpdateDIM
  2283. )
  2284. {
  2285. DWORD dwResult;
  2286. TraceEnter("SetInterfaceAdminStatus");
  2287. //
  2288. // Not allowed to set to TESTING in NT
  2289. //
  2290. CheckBindingConsistency(pIcb);
  2291. if(!((dwAdminStatus is IF_ADMIN_STATUS_DOWN) or
  2292. (dwAdminStatus is IF_ADMIN_STATUS_UP)))
  2293. {
  2294. return ERROR_INVALID_PARAMETER;
  2295. }
  2296. dwResult = NO_ERROR;
  2297. *pbUpdateDIM = FALSE;
  2298. if((pIcb->dwAdminState is IF_ADMIN_STATUS_UP) and
  2299. (dwAdminStatus is IF_ADMIN_STATUS_DOWN))
  2300. {
  2301. //
  2302. // Going from up to down
  2303. //
  2304. dwResult = InterfaceAdminStatusSetToDown(pIcb, pbUpdateDIM);
  2305. if(dwResult isnot NO_ERROR)
  2306. {
  2307. Trace2(ERR,
  2308. "SetInterfaceAdminStatus: Error %d bringing down %S",
  2309. dwResult,
  2310. pIcb->pwszName);
  2311. }
  2312. }
  2313. if((pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN) and
  2314. (dwAdminStatus is IF_ADMIN_STATUS_UP))
  2315. {
  2316. //
  2317. // Going from down to up
  2318. //
  2319. dwResult = InterfaceAdminStatusSetToUp(pIcb, pbUpdateDIM);
  2320. if(dwResult isnot NO_ERROR)
  2321. {
  2322. Trace2(ERR,
  2323. "SetInterfaceAdminStatus: Error %d bringing up %S",
  2324. dwResult,
  2325. pIcb->pwszName);
  2326. }
  2327. }
  2328. //
  2329. // Check the state after you leave
  2330. //
  2331. CheckBindingConsistency(pIcb);
  2332. //
  2333. // All other cases, no change
  2334. //
  2335. return dwResult;
  2336. }
  2337. DWORD
  2338. InterfaceAdminStatusSetToUp(
  2339. IN PICB pIcb,
  2340. OUT PBOOL pbUpdateDIM
  2341. )
  2342. {
  2343. DWORD dwResult;
  2344. MIB_IFROW riInBuffer;
  2345. TraceEnter("InterfaceAdminStatusSetToUp");
  2346. riInBuffer.dwIndex = pIcb->dwIfIndex;
  2347. riInBuffer.dwAdminStatus = IF_ADMIN_STATUS_UP;
  2348. //
  2349. // Going from Down to UP
  2350. //
  2351. dwResult = NO_ERROR;
  2352. //
  2353. // Set the state to UP first so that any functions that checks it sees that
  2354. // we want to be up
  2355. //
  2356. pIcb->dwAdminState = IF_ADMIN_STATUS_UP;
  2357. switch(pIcb->ritType)
  2358. {
  2359. case ROUTER_IF_TYPE_HOME_ROUTER:
  2360. case ROUTER_IF_TYPE_FULL_ROUTER:
  2361. {
  2362. //
  2363. // Couldnt be in down state and have been connecting or
  2364. // connected
  2365. //
  2366. IpRtAssert((pIcb->dwOperationalState isnot CONNECTING) and
  2367. (pIcb->dwOperationalState isnot CONNECTED));
  2368. dwResult = AccessIfEntryWanArp(ACCESS_SET,
  2369. pIcb,
  2370. &riInBuffer);
  2371. if(dwResult isnot NO_ERROR)
  2372. {
  2373. Trace1(ERR,
  2374. "InterfaceAdminStatusSetToUp: Couldnt set IFEntry for %S",
  2375. pIcb->pwszName);
  2376. pIcb->dwAdminState = IF_ADMIN_STATUS_DOWN;
  2377. }
  2378. else
  2379. {
  2380. WanInterfaceDownToInactive(pIcb);
  2381. }
  2382. break;
  2383. }
  2384. case ROUTER_IF_TYPE_DEDICATED:
  2385. #ifdef KSL_IPINIP
  2386. case ROUTER_IF_TYPE_TUNNEL1:
  2387. #endif //KSL_IPINIP
  2388. {
  2389. //
  2390. // Bring the stuff up in stack
  2391. // We need to set to stack before we add routes etc
  2392. //
  2393. riInBuffer.dwIndex = pIcb->dwIfIndex;
  2394. //
  2395. // Force an update
  2396. //
  2397. dwResult = SetIfEntryToStack(&riInBuffer,
  2398. TRUE);
  2399. if(dwResult isnot NO_ERROR)
  2400. {
  2401. Trace2(ERR,
  2402. "InterfaceAdminStatusSetToDown: Couldnt set IFEntry for %S. Error %d",
  2403. pIcb->pwszName,
  2404. dwResult);
  2405. LanEtcInterfaceUpToDown(pIcb,
  2406. FALSE);
  2407. pIcb->dwAdminState = IF_ADMIN_STATUS_DOWN;
  2408. dwResult = ERROR_CAN_NOT_COMPLETE;
  2409. break;
  2410. }
  2411. dwResult = LanEtcInterfaceDownToUp(pIcb,
  2412. FALSE);
  2413. if(dwResult isnot NO_ERROR)
  2414. {
  2415. Trace1(ERR,
  2416. "InterfaceAdminStatusSetToUp: Error %d bringing up LanInterface",
  2417. dwResult);
  2418. pIcb->dwAdminState = IF_ADMIN_STATUS_DOWN;
  2419. }
  2420. break;
  2421. }
  2422. default:
  2423. {
  2424. // TBD: Handle other types too
  2425. Trace1(ERR,
  2426. "InterfaceAdminStatusSetToUp: Tried to set status for %S",
  2427. pIcb->pwszName);
  2428. break;
  2429. }
  2430. }
  2431. //
  2432. // If we succeeded in setting status, let DIM know
  2433. //
  2434. if(dwResult is NO_ERROR)
  2435. {
  2436. IpRtAssert(pIcb->dwAdminState is IF_ADMIN_STATUS_UP);
  2437. EnableInterfaceWithAllProtocols(pIcb);
  2438. *pbUpdateDIM = TRUE;
  2439. //EnableInterfaceWithDIM(pIcb->hDIMHandle,
  2440. // PID_IP,
  2441. // TRUE);
  2442. }
  2443. return dwResult;
  2444. }
  2445. DWORD
  2446. InterfaceAdminStatusSetToDown(
  2447. IN PICB pIcb,
  2448. OUT PBOOL pbUpdateDIM
  2449. )
  2450. {
  2451. DWORD dwResult;
  2452. MIB_IFROW riInBuffer;
  2453. TraceEnter("InterfaceAdminStatusSetToDown");
  2454. riInBuffer.dwIndex = pIcb->dwIfIndex;
  2455. riInBuffer.dwAdminStatus = IF_ADMIN_STATUS_DOWN;
  2456. //
  2457. // Going from up to down
  2458. //
  2459. dwResult = NO_ERROR;
  2460. switch(pIcb->ritType)
  2461. {
  2462. case ROUTER_IF_TYPE_DEDICATED:
  2463. #ifdef KSL_IPINIP
  2464. case ROUTER_IF_TYPE_TUNNEL1:
  2465. #endif //KSL_IPINIP
  2466. {
  2467. //
  2468. // A Lan Interface that is up or non operational. We can only go
  2469. // to stack if we have an IP Address
  2470. //
  2471. if(pIcb->bBound)
  2472. {
  2473. riInBuffer.dwIndex = pIcb->dwIfIndex;
  2474. //
  2475. // Force an update
  2476. //
  2477. dwResult = SetIfEntryToStack(&riInBuffer,
  2478. TRUE);
  2479. }
  2480. if(dwResult isnot NO_ERROR)
  2481. {
  2482. Trace1(ERR,
  2483. "InterfaceAdminStatusSetToDown: Couldnt set IFEntry for %S",
  2484. pIcb->pwszName);
  2485. }
  2486. else
  2487. {
  2488. LanEtcInterfaceUpToDown(pIcb,
  2489. FALSE);
  2490. pIcb->dwAdminState = IF_ADMIN_STATUS_DOWN;
  2491. }
  2492. break;
  2493. }
  2494. case ROUTER_IF_TYPE_HOME_ROUTER:
  2495. case ROUTER_IF_TYPE_FULL_ROUTER:
  2496. {
  2497. //
  2498. // A Wan Interface that is down.We need to disable
  2499. // the interface and set the status in WANARP
  2500. //
  2501. if((pIcb->dwOperationalState is CONNECTED) or
  2502. (pIcb->dwOperationalState is CONNECTING))
  2503. {
  2504. Trace1(ERR,
  2505. "InterfaceAdminStatusSetToDown: Can set %S down since it is a connected WAN interface",
  2506. pIcb->pwszName);
  2507. dwResult = ERROR_INVALID_DATA;
  2508. break;
  2509. }
  2510. dwResult = AccessIfEntryWanArp(ACCESS_SET,
  2511. pIcb,
  2512. &riInBuffer);
  2513. if(dwResult isnot NO_ERROR)
  2514. {
  2515. Trace1(ERR,
  2516. "InterfaceAdminStatusSetToDown: Couldnt set IFEntry for %S",
  2517. pIcb->pwszName);
  2518. }
  2519. else
  2520. {
  2521. WanInterfaceInactiveToDown(pIcb,
  2522. FALSE);
  2523. pIcb->dwAdminState = IF_ADMIN_STATUS_DOWN;
  2524. }
  2525. break;
  2526. }
  2527. default:
  2528. {
  2529. // TBD: Handle other types too
  2530. Trace1(ERR,
  2531. "InterfaceAdminStatusSetToDown: Tried to set status for %S",
  2532. pIcb->pwszName);
  2533. break;
  2534. }
  2535. }
  2536. //
  2537. // If we succeeded in setting status, let DIM know
  2538. //
  2539. if(dwResult is NO_ERROR)
  2540. {
  2541. IpRtAssert(pIcb->dwAdminState is IF_ADMIN_STATUS_DOWN);
  2542. DisableInterfaceWithAllProtocols(pIcb);
  2543. *pbUpdateDIM = TRUE;
  2544. //EnableInterfaceWithDIM(pIcb->hDIMHandle,
  2545. // PID_IP,
  2546. // FALSE);
  2547. }
  2548. return dwResult;
  2549. }
  2550. VOID
  2551. HandleAddressChangeNotification(
  2552. VOID
  2553. )
  2554. /*++
  2555. Routine Description
  2556. Called in the context of the worker thread when we get a address change
  2557. notification from winsock
  2558. Locks
  2559. Acquires the ICB LOCK as WRITER
  2560. Arguments
  2561. None
  2562. Return Value
  2563. None
  2564. --*/
  2565. {
  2566. DWORD dwResult;
  2567. PLIST_ENTRY pleNode;
  2568. PICB pIcb;
  2569. ENTER_WRITER(ICB_LIST);
  2570. if(g_pInternalInterfaceCb isnot NULL)
  2571. {
  2572. dwResult = UpdateBindingInformation(g_pInternalInterfaceCb);
  2573. if(dwResult isnot NO_ERROR)
  2574. {
  2575. //
  2576. // Cases in which no address was found
  2577. //
  2578. if(dwResult is ERROR_ADDRESS_ALREADY_ASSOCIATED)
  2579. {
  2580. //
  2581. // This may mean that the i/f had no
  2582. // address and still has no address
  2583. //
  2584. Trace1(IF,
  2585. "AddressChange: No address change for %S",
  2586. g_pInternalInterfaceCb->pwszName);
  2587. }
  2588. else
  2589. {
  2590. if(dwResult is ERROR_NO_DATA)
  2591. {
  2592. //
  2593. // No data means we had an address and now have none
  2594. //
  2595. IpRtAssert(!g_bUninitServer);
  2596. dwResult = LanEtcInterfaceUpToDown(g_pInternalInterfaceCb,
  2597. FALSE);
  2598. g_bUninitServer = TRUE;
  2599. if(dwResult isnot NO_ERROR)
  2600. {
  2601. Trace2(ERR,
  2602. "AddressChange: Error %d bringing down interface %S",
  2603. dwResult,
  2604. g_pInternalInterfaceCb->pwszName);
  2605. }
  2606. }
  2607. else
  2608. {
  2609. //
  2610. // All others
  2611. //
  2612. Trace2(ERR,
  2613. "AddressChange: Error %d trying to update binding for %S",
  2614. dwResult,
  2615. g_pInternalInterfaceCb->pwszName);
  2616. }
  2617. }
  2618. }
  2619. else
  2620. {
  2621. //
  2622. // Cases in which an address was actually read out
  2623. //
  2624. if(g_bUninitServer)
  2625. {
  2626. //
  2627. // First time we are getting an address
  2628. //
  2629. g_bUninitServer = FALSE;
  2630. dwResult = LanEtcInterfaceDownToUp(g_pInternalInterfaceCb,
  2631. FALSE);
  2632. if(dwResult isnot NO_ERROR)
  2633. {
  2634. Trace1(ERR,
  2635. "AddressChange: Error %d bringing up server if",
  2636. dwResult);
  2637. }
  2638. }
  2639. else
  2640. {
  2641. //
  2642. // We had an address, it is changing
  2643. //
  2644. UnbindInterfaceInAllProtocols(g_pInternalInterfaceCb);
  2645. BindInterfaceInAllProtocols(g_pInternalInterfaceCb);
  2646. }
  2647. }
  2648. }
  2649. for(pleNode = &ICBList;
  2650. pleNode->Flink isnot &ICBList;
  2651. pleNode = pleNode->Flink)
  2652. {
  2653. pIcb = CONTAINING_RECORD(pleNode->Flink,
  2654. ICB,
  2655. leIfLink);
  2656. //
  2657. // Already handled the INTERNAL case above, We only
  2658. // handle LAN cards here
  2659. //
  2660. if(pIcb->ritType isnot ROUTER_IF_TYPE_DEDICATED)
  2661. {
  2662. continue;
  2663. }
  2664. if(pIcb->dwOperationalState is IF_OPER_STATUS_NON_OPERATIONAL)
  2665. {
  2666. //
  2667. // If the admin state is down, we skip the interface
  2668. //
  2669. if(pIcb->dwAdminState isnot IF_ADMIN_STATUS_UP)
  2670. {
  2671. continue;
  2672. }
  2673. //
  2674. // If the interface is DOWN, maybe this DHCP event will get it
  2675. // up. So lets try that first
  2676. //
  2677. IpRtAssert(pIcb->bBound is FALSE);
  2678. dwResult = LanEtcInterfaceDownToUp(pIcb,
  2679. FALSE);
  2680. if(dwResult isnot NO_ERROR)
  2681. {
  2682. Trace2(IF,
  2683. "AddressChange: Tried to bring up %S on receiving DHCP notification. However LanInterfaceDownToUp() returned error %d",
  2684. pIcb->pwszName,
  2685. dwResult);
  2686. }
  2687. else
  2688. {
  2689. Trace1(IF,
  2690. "AddressChange: Succesfully brought up %S",
  2691. pIcb->pwszName);
  2692. }
  2693. continue;
  2694. }
  2695. //
  2696. // This interface was already up. Maybe the
  2697. // address is changing
  2698. //
  2699. IpRtAssert(pIcb->bBound);
  2700. dwResult = UpdateBindingInformation(pIcb);
  2701. CheckBindingConsistency(pIcb);
  2702. if(dwResult isnot NO_ERROR)
  2703. {
  2704. if(dwResult is ERROR_ADDRESS_ALREADY_ASSOCIATED)
  2705. {
  2706. //
  2707. // This may mean that the i/f had no
  2708. // address and still has no address
  2709. //
  2710. Trace1(IF,
  2711. "AddressChange: No address change for %S",
  2712. pIcb->pwszName);
  2713. continue;
  2714. }
  2715. if(dwResult is ERROR_NO_DATA)
  2716. {
  2717. //
  2718. // No data means we lost addresses
  2719. //
  2720. dwResult = LanEtcInterfaceUpToDown(pIcb,
  2721. FALSE);
  2722. if(dwResult isnot NO_ERROR)
  2723. {
  2724. Trace2(ERR,
  2725. "AddressChange: Error %d bringing down interface %S",
  2726. dwResult,
  2727. pIcb->pwszName);
  2728. }
  2729. continue;
  2730. }
  2731. Trace2(ERR,
  2732. "AddressChange: Error %d trying to update binding for %S",
  2733. dwResult,
  2734. pIcb->pwszName);
  2735. continue;
  2736. }
  2737. //
  2738. // Addresses changed so bind and unbind
  2739. // with all protocols
  2740. //
  2741. UnbindInterfaceInAllProtocols(pIcb);
  2742. BindInterfaceInAllProtocols(pIcb);
  2743. UpdateAdvertisement(pIcb);
  2744. }
  2745. EXIT_LOCK(ICB_LIST);
  2746. }
  2747. DWORD
  2748. UpdateBindingInformation(
  2749. PICB pIcb
  2750. )
  2751. /*++
  2752. Routine Description
  2753. Reads the registry for the ip address and mask associated with the
  2754. interface. Then calls down into the stack to get a valid index
  2755. Locks
  2756. Arguments
  2757. Return Value
  2758. NO_ERROR There was an address change and a new address was found
  2759. ERROR_NO_DATA No addresses were found (and there were addresses on
  2760. this interface originally)
  2761. ERROR_ADDRESS_ALREADY_ASSOCIATED
  2762. If there is no change in addresses. Also returned if the interface
  2763. had no addresses to begin with and still has no addresses
  2764. --*/
  2765. {
  2766. DWORD dwResult, dwNumNewAddresses, dwNumOldAddresses;
  2767. PICB_BINDING pNewBinding,pOldBinding;
  2768. DWORD dwNewIfIndex,dwBCastBit,dwReasmSize;
  2769. BOOL bFound, bChange, bStack;
  2770. DWORD i, j;
  2771. PWCHAR pwszName;
  2772. DWORD dwAddr, dwLen;
  2773. TraceEnter("UpdateBindingInformation");
  2774. CheckBindingConsistency(pIcb);
  2775. //
  2776. // Only called for LAN and ras server interfaces. These DO NOT run in
  2777. // unnumbered mode. Thus we can continue making assumptions that
  2778. // if bound, dwNumAddresses != 0
  2779. //
  2780. if((pIcb->ritType isnot ROUTER_IF_TYPE_DEDICATED) and
  2781. (pIcb->ritType isnot ROUTER_IF_TYPE_INTERNAL))
  2782. {
  2783. Trace2(IF,
  2784. "UpdateBindingInformation: %S is type %d so not updating binding information",
  2785. pIcb->pwszName,
  2786. pIcb->ritType);
  2787. return ERROR_ADDRESS_ALREADY_ASSOCIATED;
  2788. }
  2789. IpRtAssert((pIcb->dwIfIndex isnot 0) and
  2790. (pIcb->dwIfIndex isnot INVALID_IF_INDEX));
  2791. dwNumNewAddresses = 0;
  2792. pNewBinding = NULL;
  2793. pOldBinding = pIcb->pibBindings;
  2794. dwNumOldAddresses = pIcb->dwNumAddresses;
  2795. dwResult = GetIpInfoForInterface(pIcb->dwIfIndex,
  2796. &dwNumNewAddresses,
  2797. &pNewBinding,
  2798. &dwBCastBit,
  2799. &dwReasmSize);
  2800. if(dwResult isnot NO_ERROR)
  2801. {
  2802. if(dwResult isnot ERROR_NO_DATA)
  2803. {
  2804. Trace2(ERR,
  2805. "UpdateBindingInformation: Error %d getting IP info for interface %S",
  2806. dwResult,
  2807. pIcb->pwszName);
  2808. }
  2809. else
  2810. {
  2811. //
  2812. // If no addresses were found and there were no addresses to begin
  2813. // with, then change the error code
  2814. //
  2815. if(pIcb->dwNumAddresses is 0)
  2816. {
  2817. dwResult = ERROR_ADDRESS_ALREADY_ASSOCIATED;
  2818. }
  2819. }
  2820. return dwResult;
  2821. }
  2822. IpRtAssert(dwNumNewAddresses);
  2823. IpRtAssert(pNewBinding);
  2824. //
  2825. // Make sure you will find an adapter index. Otherwise all this is no use
  2826. //
  2827. #if DBG
  2828. for(i = 0; i < dwNumNewAddresses; i++)
  2829. {
  2830. Trace4(IF,
  2831. "UpdateBindingInformation: Interface: %S, Address: %d.%d.%d.%d Mask: %d.%d.%d.%d Index: 0x%x",
  2832. pIcb->pwszName,
  2833. PRINT_IPADDR(pNewBinding[i].dwAddress),
  2834. PRINT_IPADDR(pNewBinding[i].dwMask),
  2835. pIcb->dwIfIndex);
  2836. }
  2837. #endif
  2838. //
  2839. // At this point the interface can be considered bound
  2840. //
  2841. pIcb->bBound = TRUE;
  2842. //
  2843. // Go through the address you have and if they dont appear in the list of
  2844. // the ones you read out, delete the associated static route
  2845. //
  2846. bChange = FALSE;
  2847. for(i = 0; i < dwNumOldAddresses; i++)
  2848. {
  2849. bFound = FALSE;
  2850. for(j = 0; j < dwNumNewAddresses; j++)
  2851. {
  2852. //
  2853. // Check both the mask and the address
  2854. //
  2855. if((pOldBinding[i].dwAddress is pNewBinding[j].dwAddress) and
  2856. (pOldBinding[i].dwMask is pNewBinding[j].dwMask))
  2857. {
  2858. bFound = TRUE;
  2859. break;
  2860. }
  2861. }
  2862. if(!bFound)
  2863. {
  2864. bChange = TRUE;
  2865. //
  2866. // Only delete routes we would have added in the first place
  2867. //
  2868. Trace2(IF,
  2869. "UpdateBindingInformation: Address %d.%d.%d.%d existed on %S earlier, but is now absent",
  2870. PRINT_IPADDR(pOldBinding[i].dwAddress),
  2871. pIcb->pwszName);
  2872. DeleteAutomaticRoutes(pIcb,
  2873. pOldBinding[i].dwAddress,
  2874. pOldBinding[i].dwMask);
  2875. }
  2876. }
  2877. //
  2878. // Now go through the stuff read out from the registry and see if you
  2879. // already have the address(es).
  2880. //
  2881. for(i = 0; i < dwNumNewAddresses; i++)
  2882. {
  2883. bFound = FALSE;
  2884. for(j = 0; j < dwNumOldAddresses; j++)
  2885. {
  2886. if((pNewBinding[i].dwAddress is pOldBinding[j].dwAddress) and
  2887. (pNewBinding[i].dwMask is pOldBinding[j].dwMask))
  2888. {
  2889. bFound = TRUE;
  2890. break;
  2891. }
  2892. }
  2893. if(!bFound)
  2894. {
  2895. bChange = TRUE;
  2896. }
  2897. }
  2898. if(!bChange)
  2899. {
  2900. //
  2901. // No change so we can leave
  2902. //
  2903. if(pNewBinding)
  2904. {
  2905. HeapFree(IPRouterHeap,
  2906. 0,
  2907. pNewBinding);
  2908. }
  2909. return ERROR_ADDRESS_ALREADY_ASSOCIATED;
  2910. }
  2911. //
  2912. // So there has been some change
  2913. // At this point we need to add the binding to the hash table
  2914. //
  2915. ENTER_WRITER(BINDING_LIST);
  2916. //
  2917. // If you had old bindings, remove them
  2918. // Also remove the adapter to Interface map
  2919. //
  2920. if(pOldBinding)
  2921. {
  2922. RemoveBinding(pIcb);
  2923. }
  2924. pIcb->pibBindings = pNewBinding;
  2925. pIcb->dwNumAddresses = dwNumNewAddresses;
  2926. pIcb->dwBCastBit = dwBCastBit;
  2927. pIcb->dwReassemblySize = dwReasmSize;
  2928. AddBinding(pIcb);
  2929. //
  2930. // We do the same thing we did above, but now we add the routes.
  2931. // We cant do this before because the adapter id and binding info
  2932. // hasnt been set in the hash table
  2933. //
  2934. for(i = 0; i < dwNumNewAddresses; i++)
  2935. {
  2936. bFound = FALSE;
  2937. for(j = 0; j < dwNumOldAddresses; j++)
  2938. {
  2939. if((pNewBinding[i].dwAddress is pOldBinding[j].dwAddress) and
  2940. (pNewBinding[i].dwMask is pOldBinding[j].dwMask))
  2941. {
  2942. bFound = TRUE;
  2943. }
  2944. }
  2945. if(!bFound)
  2946. {
  2947. Trace3(IF,
  2948. "UpdateBindingInformation: Address %d.%d.%d.%d/%d.%d.%d.%d new for %S",
  2949. PRINT_IPADDR(pNewBinding[i].dwAddress),
  2950. PRINT_IPADDR(pNewBinding[i].dwMask),
  2951. pIcb->pwszName);
  2952. AddAutomaticRoutes(pIcb,
  2953. pNewBinding[i].dwAddress,
  2954. pNewBinding[i].dwMask);
  2955. }
  2956. }
  2957. if(pOldBinding)
  2958. {
  2959. HeapFree(IPRouterHeap,
  2960. 0,
  2961. pOldBinding);
  2962. }
  2963. //
  2964. // Such interfaces can not have a kernel context
  2965. //
  2966. EXIT_LOCK(BINDING_LIST);
  2967. return NO_ERROR;
  2968. }
  2969. DWORD
  2970. GetAdapterInfo(
  2971. DWORD dwIpAddress,
  2972. PDWORD pdwAdapterId,
  2973. PDWORD pdwBCastBit,
  2974. PDWORD pdwReasmSize
  2975. )
  2976. /*++
  2977. Routine Description
  2978. Queries the tcpip driver with IP_MIB_STATS to figure out the
  2979. adapter index for the adapter with the given ip address.
  2980. Locks
  2981. Arguments
  2982. Return Value
  2983. Index if successfule
  2984. INVALID_IF_INDEX otherwise
  2985. --*/
  2986. {
  2987. DWORD i, dwNumEntries, MatchIndex, dwResult, Size;
  2988. PMIB_IPADDRTABLE pAddrTable;
  2989. *pdwAdapterId = INVALID_ADAPTER_ID;
  2990. *pdwBCastBit = 1;
  2991. *pdwReasmSize = 0;
  2992. dwResult = AllocateAndGetIpAddrTableFromStack(&pAddrTable,
  2993. FALSE,
  2994. IPRouterHeap,
  2995. 0);
  2996. if(dwResult isnot NO_ERROR)
  2997. {
  2998. Trace1(ERR,
  2999. "GetAdapterInfo: Error %d getting IP Address table from stack",
  3000. dwResult);
  3001. return dwResult;
  3002. }
  3003. for (i = 0; i < pAddrTable->dwNumEntries; i++)
  3004. {
  3005. if(pAddrTable->table[i].dwAddr is dwIpAddress)
  3006. {
  3007. *pdwAdapterId = pAddrTable->table[i].dwIndex;
  3008. *pdwBCastBit = pAddrTable->table[i].dwBCastAddr;
  3009. *pdwReasmSize = pAddrTable->table[i].dwReasmSize;
  3010. HeapFree(IPRouterHeap,
  3011. 0,
  3012. pAddrTable);
  3013. return NO_ERROR;
  3014. }
  3015. }
  3016. HeapFree(IPRouterHeap,
  3017. 0,
  3018. pAddrTable);
  3019. return ERROR_INVALID_DATA;
  3020. }
  3021. DWORD
  3022. GetBestNextHopMaskGivenICB(
  3023. PICB pIcb,
  3024. DWORD dwNextHopAddr
  3025. )
  3026. /*++
  3027. Routine Description
  3028. Gets the longest mask for the next hop
  3029. Locks
  3030. Arguments
  3031. pIcb the Interface Control Block over which the route goes out
  3032. dwNextHopAddr The next hop addr
  3033. Return Value
  3034. 0xFFFFFFFF if not found
  3035. --*/
  3036. {
  3037. DWORD i, dwLastMask;
  3038. #if DBG
  3039. BOOL bFound = FALSE;
  3040. #endif
  3041. CheckBindingConsistency(pIcb);
  3042. dwLastMask = 0;
  3043. for(i = 0; i < pIcb->dwNumAddresses; i++)
  3044. {
  3045. if((pIcb->pibBindings[i].dwAddress & pIcb->pibBindings[i].dwMask) is
  3046. (dwNextHopAddr & pIcb->pibBindings[i].dwMask))
  3047. {
  3048. #if DBG
  3049. bFound = TRUE;
  3050. #endif
  3051. if(pIcb->pibBindings[i].dwMask > dwLastMask)
  3052. {
  3053. dwLastMask = pIcb->pibBindings[i].dwMask;
  3054. }
  3055. }
  3056. }
  3057. #if DBG
  3058. if(!bFound)
  3059. {
  3060. Trace2(ERR,
  3061. "GetBestNextHopMaskGivenICB: Didnt find match. I/f 0x%x Nexthop %x",
  3062. pIcb->dwIfIndex,
  3063. dwNextHopAddr);
  3064. }
  3065. #endif
  3066. if(dwLastMask is 0x00000000)
  3067. {
  3068. return 0xFFFFFFFF;
  3069. }
  3070. else
  3071. {
  3072. return dwLastMask;
  3073. }
  3074. }
  3075. DWORD
  3076. GetBestNextHopMaskGivenIndex(
  3077. DWORD dwIfIndex,
  3078. DWORD dwNextHopAddr
  3079. )
  3080. /*++
  3081. Routine Description
  3082. Gets the longest mask for the next hop
  3083. Locks
  3084. Arguments
  3085. pIcb the Interface Control Block over which the route goes out
  3086. dwNextHopAddr The next hop addr
  3087. Return Value
  3088. 0x00000000 if not found
  3089. --*/
  3090. {
  3091. PICB pIcb;
  3092. pIcb = InterfaceLookupByIfIndex(dwIfIndex);
  3093. if(pIcb is NULL)
  3094. {
  3095. Trace1(ERR,
  3096. "GetBestNextHopMaskGivenIndex: Couldnt find pIcb for index 0x%x",
  3097. dwIfIndex);
  3098. return 0x00000000;
  3099. }
  3100. return GetBestNextHopMaskGivenICB(pIcb,
  3101. dwNextHopAddr);
  3102. }
  3103. DWORD
  3104. InitializeLoopbackInterface(
  3105. PICB pIcb
  3106. )
  3107. {
  3108. DWORD dwResult, i, j;
  3109. PADAPTER_INFO pBindNode;
  3110. INTERFACE_ROUTE_INFO rifRoute;
  3111. PLIST_ENTRY pleNode;
  3112. TraceEnter("InitLoopIf");
  3113. g_pLoopbackInterfaceCb = pIcb;
  3114. dwResult = GetAdapterInfo(IP_LOOPBACK_ADDRESS,
  3115. &(pIcb->dwIfIndex),
  3116. &(pIcb->dwBCastBit),
  3117. &(pIcb->dwReassemblySize));
  3118. if(dwResult isnot NO_ERROR)
  3119. {
  3120. Trace0(ERR,
  3121. "InitLoopIf: Couldnt find adapter id for loopback interface");
  3122. return ERROR_CAN_NOT_COMPLETE;
  3123. }
  3124. IpRtAssert(pIcb->dwIfIndex is LOOPBACK_INTERFACE_INDEX);
  3125. IpRtAssert(pIcb->pibBindings isnot NULL);
  3126. //
  3127. // This will always have one address
  3128. //
  3129. pIcb->dwNumAddresses = 1;
  3130. pIcb->bBound = TRUE;
  3131. //
  3132. // Loopback interfaces have a class A mask
  3133. //
  3134. pIcb->pibBindings[0].dwAddress = IP_LOOPBACK_ADDRESS;
  3135. pIcb->pibBindings[0].dwMask = CLASSA_MASK;
  3136. ENTER_WRITER(BINDING_LIST);
  3137. pBindNode = GetInterfaceBinding(pIcb->dwIfIndex);
  3138. if(!pBindNode)
  3139. {
  3140. Trace1(ERR,
  3141. "IniteLoopIf: Binding not found for %S",
  3142. pIcb->pwszName);
  3143. IpRtAssert(FALSE);
  3144. //
  3145. // Something really bad happened and we didnt have a
  3146. // bind block for the interface
  3147. //
  3148. AddBinding(pIcb);
  3149. }
  3150. else
  3151. {
  3152. pBindNode->bBound = TRUE;
  3153. pBindNode->dwNumAddresses = 1;
  3154. pBindNode->dwRemoteAddress = INVALID_IP_ADDRESS;
  3155. pBindNode->rgibBinding[0].dwAddress = IP_LOOPBACK_ADDRESS;
  3156. pBindNode->rgibBinding[0].dwMask = CLASSA_MASK;
  3157. pBindNode->dwBCastBit = pIcb->dwBCastBit;
  3158. pBindNode->dwReassemblySize = pIcb->dwReassemblySize;
  3159. pBindNode->ritType = pIcb->ritType;
  3160. }
  3161. EXIT_LOCK(BINDING_LIST);
  3162. rifRoute.dwRtInfoMask = CLASSA_MASK;
  3163. rifRoute.dwRtInfoNextHop = IP_LOOPBACK_ADDRESS;
  3164. rifRoute.dwRtInfoDest = (IP_LOOPBACK_ADDRESS & CLASSA_MASK);
  3165. rifRoute.dwRtInfoIfIndex = pIcb->dwIfIndex;
  3166. rifRoute.dwRtInfoMetric1 = 1;
  3167. rifRoute.dwRtInfoMetric2 = 0;
  3168. rifRoute.dwRtInfoMetric3 = 0;
  3169. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  3170. RTM_VIEW_MASK_MCAST; // XXX config
  3171. rifRoute.dwRtInfoPreference = ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  3172. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  3173. rifRoute.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  3174. rifRoute.dwRtInfoAge = 0;
  3175. rifRoute.dwRtInfoNextHopAS = 0;
  3176. rifRoute.dwRtInfoPolicy = 0;
  3177. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  3178. &rifRoute,
  3179. CLASSA_MASK,
  3180. 0, // RTM_ROUTE_INFO::Flags
  3181. FALSE, // We dont know what protocols might do
  3182. FALSE, // No need to add to stack
  3183. FALSE,
  3184. NULL);
  3185. //
  3186. // Now we need to go through all the bindings that are there
  3187. // and add the loopback route for them. We do this here because
  3188. // the loopback interface may be add AFTER the other interfaces
  3189. //
  3190. //
  3191. // NOTE - this is going to take a lock recursively when it goes
  3192. // to rtmif.c
  3193. //
  3194. ENTER_READER(BINDING_LIST);
  3195. for(i = 0; i < BINDING_HASH_TABLE_SIZE; i++)
  3196. {
  3197. for(pleNode = g_leBindingTable[i].Flink;
  3198. pleNode isnot &g_leBindingTable[i];
  3199. pleNode = pleNode->Flink)
  3200. {
  3201. PADAPTER_INFO pBinding;
  3202. pBinding = CONTAINING_RECORD(pleNode, ADAPTER_INFO, leHashLink);
  3203. for(j = 0; j < pBinding->dwNumAddresses; j++)
  3204. {
  3205. if(pBinding->rgibBinding[j].dwAddress is INVALID_IP_ADDRESS)
  3206. {
  3207. continue;
  3208. }
  3209. AddLoopbackRoute(
  3210. pBinding->rgibBinding[j].dwAddress,
  3211. pBinding->rgibBinding[j].dwMask
  3212. );
  3213. }
  3214. }
  3215. }
  3216. EXIT_LOCK(BINDING_LIST);
  3217. return NO_ERROR;
  3218. }
  3219. #ifdef KSL_IPINIP
  3220. DWORD
  3221. IpIpTunnelInitToDown(
  3222. PICB pIcb
  3223. )
  3224. {
  3225. return NO_ERROR;
  3226. }
  3227. #endif //KSL_IPINIP
  3228. DWORD
  3229. LanEtcInterfaceInitToDown(
  3230. PICB pIcb
  3231. )
  3232. {
  3233. DWORD dwResult, dwNumAddresses, dwMask;
  3234. PICB_BINDING pBinding;
  3235. DWORD dwIfIndex = INVALID_IF_INDEX,dwBCastBit,dwReasmSize;
  3236. DWORD i;
  3237. MIB_IFROW riInBuffer;
  3238. PWCHAR pwszName;
  3239. PLIST_ENTRY ple;
  3240. PROUTE_LIST_ENTRY prl;
  3241. IPRouteEntry *pRouteEntry;
  3242. TraceEnter("LanInterfaceInitToDown");
  3243. dwNumAddresses = 0;
  3244. pBinding = NULL;
  3245. pwszName = pIcb->pwszName;
  3246. dwResult = ReadAddressFromRegistry(pwszName,
  3247. &dwNumAddresses,
  3248. &pBinding,
  3249. FALSE);
  3250. if(dwResult isnot NO_ERROR)
  3251. {
  3252. //
  3253. // If there is no data, means the lan card wasnot UP anyway
  3254. //
  3255. if(dwResult is ERROR_NO_DATA)
  3256. {
  3257. return NO_ERROR;
  3258. }
  3259. Trace2(ERR,
  3260. "LanInterfaceInitToDown: Error %d reading IP Address information for interface %S",
  3261. dwResult,
  3262. pIcb->pwszName);
  3263. return dwResult;
  3264. }
  3265. //
  3266. // Make sure you will find an adapter index. Otherwise all this is no use
  3267. //
  3268. for(i = 0; i < dwNumAddresses; i++)
  3269. {
  3270. //
  3271. // Try to get an index using all possible addresses
  3272. //
  3273. dwResult = GetAdapterInfo(pBinding[i].dwAddress,
  3274. &dwIfIndex,
  3275. &dwBCastBit,
  3276. &dwReasmSize);
  3277. if(dwResult is NO_ERROR)
  3278. {
  3279. //
  3280. // Ok so we found a valid index from a good address
  3281. //
  3282. break;
  3283. }
  3284. }
  3285. if((dwIfIndex is INVALID_IF_INDEX) or
  3286. (dwIfIndex isnot pIcb->dwIfIndex))
  3287. {
  3288. Trace2(ERR,
  3289. "LanInterfaceInitToDown: Couldnt find adapter index for interface %S using %d.%d.%d.%d",
  3290. pIcb->pwszName,
  3291. PRINT_IPADDR(pBinding[0].dwAddress));
  3292. HeapFree(IPRouterHeap,
  3293. 0,
  3294. pBinding);
  3295. return ERROR_CAN_NOT_COMPLETE;
  3296. }
  3297. //
  3298. // Delete all the routes in the stack
  3299. //
  3300. for (ple = g_leStackRoutesToRestore.Flink;
  3301. ple != &g_leStackRoutesToRestore;
  3302. ple = ple->Flink)
  3303. {
  3304. prl = (PROUTE_LIST_ENTRY)
  3305. CONTAINING_RECORD(ple, ROUTE_LIST_ENTRY, leRouteList);
  3306. TraceRoute2(
  3307. ROUTE, "%d.%d.%d.%d/%d.%d.%d.%d",
  3308. PRINT_IPADDR( prl->mibRoute.dwForwardDest ),
  3309. PRINT_IPADDR( prl->mibRoute.dwForwardMask )
  3310. );
  3311. if(prl->mibRoute.dwForwardIfIndex isnot dwIfIndex)
  3312. {
  3313. //
  3314. // Not going out over this interface
  3315. //
  3316. continue;
  3317. }
  3318. prl->mibRoute.dwForwardType = MIB_IPROUTE_TYPE_INVALID;
  3319. dwResult = SetIpForwardEntryToStack(&(prl->mibRoute));
  3320. if (dwResult isnot NO_ERROR)
  3321. {
  3322. Trace2(ERR,
  3323. "ReinstallOldRoutes: Failed to add route to %x from "
  3324. " init table. Error %x",
  3325. prl->mibRoute.dwForwardDest,
  3326. dwResult);
  3327. }
  3328. }
  3329. //
  3330. // Dont really need it anymore
  3331. //
  3332. HeapFree(IPRouterHeap,
  3333. 0,
  3334. pBinding);
  3335. //
  3336. // Going from up to down
  3337. //
  3338. riInBuffer.dwIndex = dwIfIndex;
  3339. riInBuffer.dwAdminStatus = IF_ADMIN_STATUS_DOWN;
  3340. dwResult = SetIfEntryToStack(&riInBuffer,
  3341. TRUE);
  3342. if(dwResult isnot NO_ERROR)
  3343. {
  3344. Trace1(ERR,
  3345. "LanInterfaceInitToDown: Couldnt set IFEntry for %S",
  3346. pIcb->pwszName);
  3347. }
  3348. DeleteAllRoutes(pIcb->dwIfIndex,
  3349. FALSE);
  3350. return dwResult;
  3351. }
  3352. DWORD
  3353. GetIpInfoForInterface(
  3354. IN DWORD dwIfIndex,
  3355. OUT PULONG pulNumAddresses,
  3356. OUT ICB_BINDING **ppAddresses,
  3357. OUT PDWORD pdwBCastBit,
  3358. OUT PDWORD pdwReasmSize
  3359. )
  3360. /*++
  3361. Routine Description
  3362. Gets the addresses and other ip information for an interface
  3363. Locks
  3364. None needed
  3365. Arguments
  3366. dwIfIndex,
  3367. pdwNumAddresses
  3368. ppAddresses
  3369. pdwBCastBit
  3370. pdwReasmSize
  3371. Return Value
  3372. NO_ERROR
  3373. Win32 Errorcode
  3374. --*/
  3375. {
  3376. DWORD dwResult, i;
  3377. ULONG ulAddrIndex, ulCount, ulValid;
  3378. PMIB_IPADDRTABLE pAddrTable;
  3379. *pulNumAddresses = 0;
  3380. *pdwBCastBit = 1;
  3381. *pdwReasmSize = 0;
  3382. *ppAddresses = NULL;
  3383. dwResult = AllocateAndGetIpAddrTableFromStack(&pAddrTable,
  3384. TRUE,
  3385. IPRouterHeap,
  3386. 0);
  3387. if(dwResult isnot NO_ERROR)
  3388. {
  3389. Trace1(ERR,
  3390. "GetIpInfoForInterface: Error %d getting IP Address table from stack",
  3391. dwResult);
  3392. return dwResult;
  3393. }
  3394. ulCount = 0;
  3395. ulValid = 0;
  3396. for (i = 0; i < pAddrTable->dwNumEntries; i++)
  3397. {
  3398. if(pAddrTable->table[i].dwIndex is dwIfIndex)
  3399. {
  3400. ulCount++;
  3401. if(!(IsValidIpAddress(pAddrTable->table[i].dwAddr)) or
  3402. (pAddrTable->table[i].dwMask is 0))
  3403. {
  3404. //
  3405. // Since this is only called for numbered links
  3406. //
  3407. continue;
  3408. }
  3409. //
  3410. // Make sure this is not a duplicate. Since this is ordered, we
  3411. // merely check the next address
  3412. //
  3413. if((i isnot (pAddrTable->dwNumEntries - 1)) and
  3414. (pAddrTable->table[i].dwAddr is pAddrTable->table[i + 1].dwAddr))
  3415. {
  3416. Trace1(ERR,
  3417. "GetIpInfoForInterface: %d.%d.%d.%d duplicate address",
  3418. PRINT_IPADDR(pAddrTable->table[i].dwAddr));
  3419. continue;
  3420. }
  3421. ulValid++;
  3422. }
  3423. }
  3424. //
  3425. // See if we have good addresses
  3426. //
  3427. if(ulValid is 0)
  3428. {
  3429. if(ulCount isnot 0)
  3430. {
  3431. Trace1(ERR,
  3432. "GetIpInfoForInterface: If 0x%x has addresses entries which are 0s",
  3433. dwIfIndex);
  3434. }
  3435. HeapFree(IPRouterHeap,
  3436. 0,
  3437. pAddrTable);
  3438. return ERROR_NO_DATA;
  3439. }
  3440. //
  3441. // Allocate from private heap
  3442. //
  3443. *ppAddresses = HeapAlloc(IPRouterHeap,
  3444. HEAP_ZERO_MEMORY,
  3445. (sizeof(ICB_BINDING) * ulValid));
  3446. if(*ppAddresses is NULL)
  3447. {
  3448. Trace0(ERR,
  3449. "GetIpInfoForInterface: Error allocating memory");
  3450. HeapFree(IPRouterHeap,
  3451. 0,
  3452. pAddrTable);
  3453. return ERROR_NOT_ENOUGH_MEMORY;
  3454. }
  3455. //
  3456. // Now copy out the valid addresses
  3457. //
  3458. ulAddrIndex = 0;
  3459. for (i = 0; i < pAddrTable->dwNumEntries; i++)
  3460. {
  3461. if(pAddrTable->table[i].dwIndex is dwIfIndex)
  3462. {
  3463. if(!(IsValidIpAddress(pAddrTable->table[i].dwAddr)) or
  3464. (pAddrTable->table[i].dwMask is 0))
  3465. {
  3466. continue;
  3467. }
  3468. if((i isnot (pAddrTable->dwNumEntries - 1)) and
  3469. (pAddrTable->table[i].dwAddr is pAddrTable->table[i + 1].dwAddr))
  3470. {
  3471. continue;
  3472. }
  3473. if(!(*pdwReasmSize))
  3474. {
  3475. *pdwReasmSize = pAddrTable->table[i].dwReasmSize;
  3476. *pdwBCastBit = pAddrTable->table[i].dwBCastAddr;
  3477. }
  3478. (*ppAddresses)[ulAddrIndex].dwAddress = pAddrTable->table[i].dwAddr;
  3479. (*ppAddresses)[ulAddrIndex].dwMask = pAddrTable->table[i].dwMask;
  3480. ulAddrIndex++;
  3481. }
  3482. }
  3483. IpRtAssert(ulAddrIndex is ulValid);
  3484. *pulNumAddresses = ulValid;
  3485. HeapFree(IPRouterHeap,
  3486. 0,
  3487. pAddrTable);
  3488. return NO_ERROR;
  3489. }
  3490. DWORD
  3491. ReadAddressFromRegistry(
  3492. IN PWCHAR pwszIfName,
  3493. OUT PDWORD pdwNumAddresses,
  3494. OUT ICB_BINDING **ppibAddressInfo,
  3495. IN BOOL bInternalIf
  3496. )
  3497. {
  3498. HKEY hadapkey ;
  3499. CHAR buff[512], pszInterfaceName[256];
  3500. DWORD dwDhcp, dwResult, dwSize, dwType;
  3501. TraceEnter("ReadAddressFromRegistry");
  3502. Trace1(IF,
  3503. "ReadAddressFromRegistry: Reading address for %S",
  3504. pwszIfName);
  3505. wcstombs(pszInterfaceName, pwszIfName, wcslen(pwszIfName));
  3506. pszInterfaceName[wcslen(pwszIfName)] = '\0';
  3507. *pdwNumAddresses = 0;
  3508. *ppibAddressInfo = NULL;
  3509. //
  3510. // The IP address should be in the registry
  3511. //
  3512. strcpy(buff, REG_KEY_TCPIP_INTERFACES);
  3513. strcat(buff,"\\");
  3514. strcat(buff, pszInterfaceName) ;
  3515. dwResult = RegOpenKey(HKEY_LOCAL_MACHINE,
  3516. buff,
  3517. &hadapkey);
  3518. if(dwResult isnot NO_ERROR)
  3519. {
  3520. Trace1(ERR,
  3521. "ReadAddressFromRegistry: Unable to open key %s",
  3522. buff);
  3523. return dwResult;
  3524. }
  3525. dwDhcp = 0;
  3526. if(!bInternalIf)
  3527. {
  3528. //
  3529. // Get the EnableDHCP flag
  3530. //
  3531. dwSize = sizeof(DWORD);
  3532. dwResult = RegQueryValueEx(hadapkey,
  3533. REGISTRY_ENABLE_DHCP,
  3534. NULL,
  3535. &dwType,
  3536. (PBYTE)&dwDhcp,
  3537. &dwSize);
  3538. if(dwResult isnot NO_ERROR)
  3539. {
  3540. Trace0(ERR,
  3541. "ReadAddressFromRegistry: Unable to read DHCP Enabled key");
  3542. RegCloseKey(hadapkey);
  3543. return dwResult;
  3544. }
  3545. }
  3546. else
  3547. {
  3548. //
  3549. // tcpcfg writes server adapter address as DHCP but
  3550. // does not set dhcp enable
  3551. //
  3552. dwDhcp = 1;
  3553. }
  3554. //
  3555. // Get the ip address for the net interface
  3556. //
  3557. dwSize = 0 ;
  3558. if(dwDhcp == 0)
  3559. {
  3560. dwResult = ReadAddressAndMaskValues(hadapkey,
  3561. REGISTRY_IPADDRESS,
  3562. REGISTRY_SUBNETMASK,
  3563. ppibAddressInfo,
  3564. pdwNumAddresses);
  3565. }
  3566. else
  3567. {
  3568. //
  3569. // First try autonet, and if that fails, read the DHCP
  3570. // This needs to be done because the DHCP address is not cleared
  3571. // out when running in autonet mode, but the autonet address is set
  3572. // to 0.0.0.0 when in DHCP mode
  3573. //
  3574. dwResult = ReadAddressAndMaskValues(hadapkey,
  3575. REGISTRY_AUTOCONFIGIPADDRESS,
  3576. REGISTRY_AUTOCONFIGSUBNETMASK,
  3577. ppibAddressInfo,
  3578. pdwNumAddresses);
  3579. if(dwResult isnot NO_ERROR)
  3580. {
  3581. dwResult = ReadAddressAndMaskValues(hadapkey,
  3582. REGISTRY_DHCPIPADDRESS,
  3583. REGISTRY_DHCPSUBNETMASK,
  3584. ppibAddressInfo,
  3585. pdwNumAddresses);
  3586. }
  3587. }
  3588. RegCloseKey(hadapkey);
  3589. if(dwResult isnot NO_ERROR)
  3590. {
  3591. Trace3(ERR,
  3592. "ReadAddressFromRegistry: Couldnt read address for %S. Error %d. DHCP %d",
  3593. pwszIfName,
  3594. dwResult,
  3595. dwDhcp);
  3596. return dwResult;
  3597. }
  3598. else
  3599. {
  3600. #if DBG
  3601. DWORD i;
  3602. Trace2(IF,
  3603. "--%d addresses on %S\n",
  3604. *pdwNumAddresses,
  3605. pwszIfName);
  3606. for(i = 0; i < *pdwNumAddresses; i++)
  3607. {
  3608. Trace1(IF, "%d.%d.%d.%d",
  3609. PRINT_IPADDR((*ppibAddressInfo)[i].dwAddress));
  3610. }
  3611. #endif
  3612. }
  3613. return dwResult;
  3614. }
  3615. DWORD
  3616. ReadAddressAndMaskValues(
  3617. IN HKEY hkeyAdapterSection,
  3618. IN PSZ pszRegAddressValue,
  3619. IN PSZ pszRegMaskValue,
  3620. OUT ICB_BINDING **ppibAddressInfo,
  3621. OUT PDWORD pdwNumAddresses
  3622. )
  3623. {
  3624. DWORD dwResult, dwType;
  3625. PBYTE pbyAddresses,pbyMasks;
  3626. DWORD dwAddressSize, dwMaskSize;
  3627. dwAddressSize = dwMaskSize = 0;
  3628. dwResult = RegQueryValueEx(hkeyAdapterSection,
  3629. pszRegAddressValue,
  3630. NULL,
  3631. &dwType,
  3632. NULL,
  3633. &dwAddressSize);
  3634. if((dwAddressSize is 0) or (dwResult isnot NO_ERROR))
  3635. {
  3636. Trace3(ERR,
  3637. "ReadAddressAndMaskValues: Registry reported size = %d with error %d for size of %s",
  3638. dwAddressSize,
  3639. dwResult,
  3640. pszRegAddressValue);
  3641. return ERROR_REGISTRY_CORRUPT;
  3642. }
  3643. //
  3644. // We allocate size+4 so that even if we read out a REG_SZ, it looks
  3645. // like a REG_MULTI_SZ to the parse routine because we guarantee atleast
  3646. // 2 terminating NULLS
  3647. //
  3648. pbyAddresses = HeapAlloc(IPRouterHeap,
  3649. HEAP_ZERO_MEMORY,
  3650. dwAddressSize + 4);
  3651. if(pbyAddresses is NULL)
  3652. {
  3653. Trace2(ERR,
  3654. "ReadAddressAndMaskValues: Error allocating %d bytes for %s",
  3655. dwAddressSize + 4,
  3656. pszRegAddressValue);
  3657. return ERROR_NOT_ENOUGH_MEMORY;
  3658. }
  3659. dwResult = RegQueryValueEx(hkeyAdapterSection,
  3660. pszRegAddressValue,
  3661. NULL,
  3662. &dwType,
  3663. pbyAddresses,
  3664. &dwAddressSize);
  3665. if(dwResult isnot NO_ERROR)
  3666. {
  3667. HeapFree(IPRouterHeap,
  3668. 0,
  3669. pbyAddresses);
  3670. Trace2(ERR,
  3671. "ReadAddressAndMaskValues: Error %d reading %s from registry",
  3672. dwResult,
  3673. pszRegAddressValue);
  3674. return dwResult;
  3675. }
  3676. //
  3677. // Now get the subnet mask for the net interface
  3678. //
  3679. dwResult = RegQueryValueEx(hkeyAdapterSection,
  3680. pszRegMaskValue,
  3681. NULL,
  3682. &dwType,
  3683. NULL,
  3684. &dwMaskSize);
  3685. if((dwMaskSize is 0) or (dwResult isnot NO_ERROR))
  3686. {
  3687. HeapFree(IPRouterHeap,
  3688. 0,
  3689. pbyAddresses);
  3690. Trace3(ERR,
  3691. "ReadAddressAndMaskValues: Registry reported size = %d with error %d for size of %s",
  3692. dwMaskSize,
  3693. dwResult,
  3694. pszRegMaskValue);
  3695. return ERROR_REGISTRY_CORRUPT;
  3696. }
  3697. pbyMasks = HeapAlloc(IPRouterHeap,
  3698. HEAP_ZERO_MEMORY,
  3699. dwMaskSize + 4);
  3700. if(pbyMasks is NULL)
  3701. {
  3702. HeapFree(IPRouterHeap,
  3703. 0,
  3704. pbyAddresses);
  3705. Trace2(ERR,
  3706. "ReadAddressAndMaskValues: Error allocating %d bytes for %s",
  3707. dwMaskSize + 4,
  3708. pszRegMaskValue);
  3709. return ERROR_NOT_ENOUGH_MEMORY;
  3710. }
  3711. dwResult = RegQueryValueEx(hkeyAdapterSection,
  3712. pszRegMaskValue,
  3713. NULL,
  3714. &dwType,
  3715. pbyMasks,
  3716. &dwMaskSize) ;
  3717. if(dwResult isnot NO_ERROR)
  3718. {
  3719. HeapFree(IPRouterHeap,
  3720. 0,
  3721. pbyAddresses);
  3722. HeapFree(IPRouterHeap,
  3723. 0,
  3724. pbyMasks);
  3725. Trace2(ERR,
  3726. "ReadAddressAndMaskValues: Error %d reading %s from registry",
  3727. dwResult,
  3728. pszRegMaskValue);
  3729. return dwResult;
  3730. }
  3731. dwResult = ParseAddressAndMask(pbyAddresses,
  3732. dwAddressSize,
  3733. pbyMasks,
  3734. dwMaskSize,
  3735. ppibAddressInfo,
  3736. pdwNumAddresses);
  3737. HeapFree(IPRouterHeap,
  3738. 0,
  3739. pbyAddresses);
  3740. HeapFree(IPRouterHeap,
  3741. 0,
  3742. pbyMasks);
  3743. return dwResult;
  3744. }
  3745. DWORD
  3746. ParseAddressAndMask(
  3747. IN PBYTE pbyAddresses,
  3748. IN DWORD dwAddressSize,
  3749. IN PBYTE pbyMasks,
  3750. IN DWORD dwMaskSize,
  3751. OUT ICB_BINDING **ppibAddressInfo,
  3752. OUT PDWORD pdwNumAddresses
  3753. )
  3754. {
  3755. DWORD dwAddrCount, dwMaskCount, dwTempLen, dwAddrIndex;
  3756. DWORD dwMask, dwAddr, i, j;
  3757. PBYTE pbyTempAddr, pbyTempMask;
  3758. BOOL bDuplicate;
  3759. *pdwNumAddresses = 0;
  3760. *ppibAddressInfo = NULL;
  3761. //
  3762. // If there are only two characters in the string or if the
  3763. // the first two are NULL, we have no data. Due to tcp/ip config
  3764. // we may be passed a REG_SZ instead of a REG_MULTI_SZ. The code works
  3765. // around that by assuming that if a REG_SZ was read out then extra
  3766. // padding was added to the end so that we ALWAYS have 2 terminating NULLs
  3767. //
  3768. if((dwAddressSize < 2) or
  3769. ((pbyAddresses[0] is '\0') and
  3770. (pbyAddresses[1] is '\0')))
  3771. {
  3772. Trace0(IF,
  3773. "ParseAddressAndMask: No addresses found");
  3774. return ERROR_NO_DATA;
  3775. }
  3776. //
  3777. // The mask should also have some data
  3778. //
  3779. if((dwMaskSize < 2) or
  3780. ((pbyMasks[0] is '\0') and
  3781. (pbyMasks[1] is '\0')))
  3782. {
  3783. Trace0(IF,
  3784. "ParseAddressAndMask: No masks found");
  3785. return ERROR_NO_DATA;
  3786. }
  3787. //
  3788. // Count the number of addresses
  3789. //
  3790. dwAddrCount = 0;
  3791. pbyTempAddr = pbyAddresses;
  3792. dwTempLen = dwAddressSize;
  3793. while(dwTempLen)
  3794. {
  3795. if(*pbyTempAddr == '\0')
  3796. {
  3797. dwAddrCount++;
  3798. if(*(pbyTempAddr+1) == '\0')
  3799. {
  3800. break;
  3801. }
  3802. }
  3803. pbyTempAddr++ ;
  3804. dwTempLen-- ;
  3805. }
  3806. if(dwAddrCount is 0)
  3807. {
  3808. Trace0(IF,
  3809. "ParseAddressAndMask: No addresses found");
  3810. return ERROR_NO_DATA;
  3811. }
  3812. //
  3813. // Count the number of masks
  3814. //
  3815. dwMaskCount = 0;
  3816. pbyTempMask = pbyMasks;
  3817. dwTempLen = dwMaskSize;
  3818. while(dwTempLen)
  3819. {
  3820. if(*pbyTempMask is '\0')
  3821. {
  3822. dwMaskCount++;
  3823. if(*(pbyTempMask+1) is '\0')
  3824. {
  3825. break;
  3826. }
  3827. }
  3828. pbyTempMask++ ;
  3829. dwTempLen-- ;
  3830. }
  3831. //
  3832. // Make sure that the two are the same
  3833. //
  3834. if(dwAddrCount isnot dwMaskCount)
  3835. {
  3836. Trace0(IF,
  3837. "ParseAddressAndMask: Address and mask count is not same");
  3838. return ERROR_NO_DATA;
  3839. }
  3840. //
  3841. // Allocate the memory required to store all the addresses
  3842. //
  3843. *ppibAddressInfo = HeapAlloc(IPRouterHeap,
  3844. HEAP_ZERO_MEMORY,
  3845. (sizeof(ICB_BINDING) * dwAddrCount));
  3846. if(*ppibAddressInfo is NULL)
  3847. {
  3848. Trace1(ERR,
  3849. "ParseAddressAndMask: Error allocating %d bytes for AddressInfo",
  3850. sizeof(ICB_BINDING) * dwAddrCount);
  3851. return ERROR_NOT_ENOUGH_MEMORY;
  3852. }
  3853. pbyTempAddr = pbyAddresses;
  3854. pbyTempMask = pbyMasks;
  3855. dwAddrIndex = 0;
  3856. for (i = 0; i < dwAddrCount; i++)
  3857. {
  3858. dwAddr = inet_addr(pbyTempAddr);
  3859. dwMask = inet_addr(pbyTempMask);
  3860. pbyTempAddr = strchr(pbyTempAddr, '\0');
  3861. pbyTempMask = strchr(pbyTempMask, '\0');
  3862. pbyTempAddr++;
  3863. pbyTempMask++;
  3864. bDuplicate = FALSE;
  3865. for(j = 0; j < dwAddrIndex; j++)
  3866. {
  3867. if((*ppibAddressInfo)[j].dwAddress is dwAddr)
  3868. {
  3869. Trace1(ERR,
  3870. "ParseAddressAndMask: Addr %x is duplicate",
  3871. dwAddr);
  3872. bDuplicate = TRUE;
  3873. break;
  3874. }
  3875. }
  3876. if(bDuplicate or
  3877. (dwAddr is INVALID_IP_ADDRESS) or
  3878. (dwMask is 0x00000000))
  3879. {
  3880. continue;
  3881. }
  3882. (*ppibAddressInfo)[dwAddrIndex].dwAddress = dwAddr;
  3883. (*ppibAddressInfo)[dwAddrIndex].dwMask = dwMask;
  3884. dwAddrIndex++;
  3885. }
  3886. *pdwNumAddresses = dwAddrIndex;
  3887. //
  3888. // Make sure that there is atleast one valid address
  3889. //
  3890. if(dwAddrIndex is 0)
  3891. {
  3892. Trace0(ERR,
  3893. "ParseAddressAndMask: No valid addresses found");
  3894. HeapFree(IPRouterHeap,
  3895. 0,
  3896. *ppibAddressInfo);
  3897. *ppibAddressInfo = NULL;
  3898. return ERROR_NO_DATA;
  3899. }
  3900. return NO_ERROR;
  3901. }
  3902. DWORD
  3903. SetInterfaceReceiveType(
  3904. IN DWORD dwProtocolId,
  3905. IN DWORD dwIfIndex,
  3906. IN DWORD dwInterfaceReceiveType,
  3907. IN BOOL bActivate
  3908. )
  3909. {
  3910. DWORD dwResult;
  3911. IO_STATUS_BLOCK ioStatus;
  3912. IP_SET_IF_PROMISCUOUS_INFO PromInfo;
  3913. HANDLE hEvent;
  3914. hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  3915. if(hEvent is NULL)
  3916. {
  3917. dwResult = GetLastError();
  3918. Trace1(ERR,
  3919. "SetInterfaceReceiveType: Error %d creating event",
  3920. dwResult);
  3921. return dwResult;
  3922. }
  3923. if(dwInterfaceReceiveType is IR_PROMISCUOUS_MULTICAST)
  3924. {
  3925. PromInfo.Type = PROMISCUOUS_MCAST;
  3926. }
  3927. else
  3928. {
  3929. if(dwInterfaceReceiveType is IR_PROMISCUOUS)
  3930. {
  3931. PromInfo.Type = PROMISCUOUS_BCAST;
  3932. }
  3933. else
  3934. {
  3935. return ERROR_INVALID_PARAMETER;
  3936. }
  3937. }
  3938. PromInfo.Index = dwIfIndex;
  3939. PromInfo.Add = bActivate?1:0;
  3940. dwResult = NtDeviceIoControlFile(g_hIpDevice,
  3941. hEvent,
  3942. NULL,
  3943. NULL,
  3944. &ioStatus,
  3945. IOCTL_IP_SET_IF_PROMISCUOUS,
  3946. (PVOID)&PromInfo,
  3947. sizeof(IP_SET_IF_PROMISCUOUS_INFO),
  3948. NULL,
  3949. 0);
  3950. if(dwResult is STATUS_PENDING)
  3951. {
  3952. Trace0(ERR,
  3953. "SetInterfaceReceiveType: Pending from ioctl");
  3954. dwResult = WaitForSingleObject(hEvent,
  3955. INFINITE);
  3956. if(dwResult isnot WAIT_OBJECT_0) // 0
  3957. {
  3958. Trace1(ERR,
  3959. "SetInterfaceReceiveType: Error %d from wait",
  3960. dwResult);
  3961. dwResult = GetLastError();
  3962. }
  3963. else
  3964. {
  3965. dwResult = STATUS_SUCCESS;
  3966. }
  3967. }
  3968. if(dwResult isnot STATUS_SUCCESS)
  3969. {
  3970. Trace4(ERR,
  3971. "SetInterfaceReceiveType: NtStatus %x while %s i/f %x into %s mode",
  3972. dwResult,
  3973. (PromInfo.Add == 1) ? "activating" : "deactivating",
  3974. dwIfIndex,
  3975. (PromInfo.Type == PROMISCUOUS_MCAST) ? "prom mcast" : "prom all");
  3976. return dwResult;
  3977. }
  3978. return NO_ERROR;
  3979. }
  3980. DWORD
  3981. HandleMediaSenseEvent(
  3982. IN PICB pIcb,
  3983. IN BOOL bSensed
  3984. )
  3985. /*++
  3986. Routine Description:
  3987. Called when media sense status changes for a LAN interface
  3988. Locks:
  3989. Called with the ICB list lock held as WRITER
  3990. Arguments:
  3991. pIcb ICB of the interface for which the event it
  3992. bSensed TRUE is cable is present
  3993. Return Value:
  3994. NO_ERROR
  3995. --*/
  3996. {
  3997. DWORD dwErr;
  3998. return NO_ERROR;
  3999. //
  4000. // Not for NT 5.0
  4001. //
  4002. if(pIcb->ritType isnot ROUTER_IF_TYPE_DEDICATED)
  4003. {
  4004. IpRtAssert(FALSE);
  4005. return ERROR_INVALID_PARAMETER;
  4006. }
  4007. if(bSensed)
  4008. {
  4009. //
  4010. // Bring the interface up
  4011. //
  4012. dwErr = LanEtcInterfaceDownToUp(pIcb,
  4013. FALSE);
  4014. }
  4015. else
  4016. {
  4017. dwErr = LanEtcInterfaceUpToDown(pIcb,
  4018. FALSE);
  4019. }
  4020. if(dwErr isnot NO_ERROR)
  4021. {
  4022. Trace2(ERR,
  4023. "HandleMediaSense: Err %d when changing status for %S",
  4024. dwErr,
  4025. pIcb->pwszName);
  4026. }
  4027. return dwErr;
  4028. }
  4029. DWORD
  4030. GetRouterId()
  4031. {
  4032. PLIST_ENTRY pleNode;
  4033. PICB picb;
  4034. ULONG ulIdx;
  4035. DWORD dwRouterId = -1; // lower is better
  4036. DWORD dwRouterTypePri = -1; // lower is better
  4037. DWORD dwTypePri;
  4038. TraceEnter("GetRouterId");
  4039. ENTER_READER(ICB_LIST);
  4040. for (pleNode = ICBList.Flink; // walk the ICBList
  4041. pleNode isnot &ICBList;
  4042. pleNode = pleNode->Flink)
  4043. {
  4044. picb = CONTAINING_RECORD (pleNode, ICB, leIfLink) ;
  4045. // Get Type priority
  4046. switch(picb->ritType) {
  4047. case ROUTER_IF_TYPE_LOOPBACK : dwTypePri = 0; break; // best
  4048. case ROUTER_IF_TYPE_INTERNAL : dwTypePri = 1; break;
  4049. #ifdef KSL_IPINIP
  4050. case ROUTER_IF_TYPE_TUNNEL1 : dwTypePri = 2; break;
  4051. #endif //KSL_IPINIP
  4052. case ROUTER_IF_TYPE_DEDICATED: dwTypePri = 2; break;
  4053. default: dwTypePri = 10; break; // worst
  4054. }
  4055. // Walk addresses
  4056. for (ulIdx=0; ulIdx<picb->dwNumAddresses; ulIdx++)
  4057. {
  4058. if (!IS_ROUTABLE(picb->pibBindings[ulIdx].dwAddress))
  4059. {
  4060. continue;
  4061. }
  4062. // update if better
  4063. if (dwTypePri < dwRouterTypePri
  4064. || (dwTypePri==dwRouterTypePri
  4065. && picb->pibBindings[ulIdx].dwAddress<dwRouterId))
  4066. {
  4067. dwRouterTypePri = dwTypePri;
  4068. dwRouterId = picb->pibBindings[ulIdx].dwAddress;
  4069. }
  4070. }
  4071. }
  4072. // *** Exclusion End ***
  4073. EXIT_LOCK(ICB_LIST);
  4074. TraceLeave("GetRouterId");
  4075. return dwRouterId;
  4076. }
  4077. #if __PIX__
  4078. BOOL
  4079. IsRemoteAddressPrivate(
  4080. PICB pIcb
  4081. )
  4082. /*++
  4083. Routine Description:
  4084. Checks to see if the address of the remote end point of the DoD (VPN/PPP)
  4085. interface is private.
  4086. This is done by querying the TCPIP stack for the forwarding table and
  4087. ensuring that a host route does not already exist for the remote end-point.
  4088. This is at best a heuristic to solve the following problem:
  4089. - Third party VPN/PPP servers e.g. Cisco PIX firewall return the public
  4090. address rather than the address of the PPP interface or the private
  4091. network address as the remote address of the PPP link.
  4092. - Adding a host route to the public address of the VPN/PPP server over the
  4093. PPP interface causes the host route added by PPTP (for its control
  4094. traffic) to be overwritten. This causes PPTP control packets
  4095. to be routed over the PPP interface rather than the public interface.
  4096. This in turn causes the control traffic to loop in the TCPIP stack and
  4097. never make it to the other end.
  4098. --*/
  4099. {
  4100. DWORD dwErr, dwSize = 0, dwCount = 0;
  4101. MIB_IPFORWARDROW mibRoute;
  4102. TraceEnter("IsRemoteAddressPrivate");
  4103. //
  4104. // Query stack for route table
  4105. //
  4106. SecureZeroMemory(&mibRoute, sizeof(MIB_IPFORWARDROW));
  4107. dwErr = GetBestRouteFromStack(
  4108. pIcb->dwRemoteAddress,
  4109. 0,
  4110. &mibRoute
  4111. );
  4112. if(dwErr isnot NO_ERROR)
  4113. {
  4114. Trace1(
  4115. ERR, "IsRemoteAddressPrivate: error %d querying best route",
  4116. dwErr
  4117. );
  4118. TraceLeave("IsRemoteAddressPrivate");
  4119. return FALSE;
  4120. }
  4121. TraceRoute4(
  4122. ROUTE, "%d.%d.%d.%d/%d.%d.%d.%d via %d.%d.%d.%d over %d",
  4123. PRINT_IPADDR( mibRoute.dwForwardDest ),
  4124. PRINT_IPADDR( mibRoute.dwForwardMask ),
  4125. PRINT_IPADDR( mibRoute.dwForwardNextHop ),
  4126. mibRoute.dwForwardIfIndex
  4127. );
  4128. //
  4129. // Check if this is host route and that is dest is the remote address
  4130. //
  4131. if((mibRoute.dwForwardMask is ALL_ONES_MASK) and
  4132. (mibRoute.dwForwardDest is pIcb->dwRemoteAddress))
  4133. {
  4134. //
  4135. // A host route to the remote address of the PPP interface
  4136. // is already present
  4137. //
  4138. Trace0(
  4139. IF, "IsRemoteAddressPrivate: matching host route already "
  4140. "present in the stack"
  4141. );
  4142. TraceLeave("IsRemoteAddressPrivate");
  4143. return FALSE;
  4144. }
  4145. Trace0(
  4146. IF, "IsRemoteAddressPrivate: no matching host route present "
  4147. "in the stack"
  4148. );
  4149. TraceLeave("IsRemoteAddressPrivate");
  4150. return TRUE;
  4151. }
  4152. #endif