Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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