Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

934 lines
22 KiB

  1. //============================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. //
  4. // File: if.c
  5. //
  6. // History:
  7. // V Raman June-25-1997 Created.
  8. //
  9. // routines that manipulate interface entries
  10. //============================================================================
  11. #include "pchmgm.h"
  12. #pragma hdrstop
  13. //----------------------------------------------------------------------------
  14. // CreateIfEntry
  15. //
  16. // This function creates a new interface entry. Duh
  17. // Assumes that the interface list is locked.
  18. //----------------------------------------------------------------------------
  19. DWORD
  20. CreateIfEntry(
  21. PLIST_ENTRY pleIfList,
  22. DWORD dwIfIndex,
  23. DWORD dwIfNextHopAddr,
  24. DWORD dwProtocolId,
  25. DWORD dwComponentId
  26. )
  27. {
  28. DWORD dwErr = NO_ERROR;
  29. PIF_ENTRY pie = NULL, pieEntry = NULL;
  30. TRACEIF4(
  31. IF,
  32. "ENTERED CreateIfEntry : Interface %x, %x : Protocol %x, %x",
  33. dwIfIndex, dwIfNextHopAddr, dwProtocolId, dwComponentId
  34. );
  35. do
  36. {
  37. //
  38. // allocate an interface entry.
  39. //
  40. pie = MGM_ALLOC( sizeof( IF_ENTRY ) );
  41. if ( pie == NULL )
  42. {
  43. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  44. TRACE1(
  45. ANY, "CreateIfEntry : Failed to allocate entry %x", dwErr
  46. );
  47. LOGERR0( HEAP_ALLOC_FAILED, dwErr );
  48. break;
  49. }
  50. ZeroMemory( pie, sizeof( IF_ENTRY ) );
  51. //
  52. // init. i/f structure
  53. //
  54. pie-> dwIfIndex = dwIfIndex;
  55. pie-> dwIfNextHopAddr = dwIfNextHopAddr;
  56. pie-> dwOwningProtocol = dwProtocolId;
  57. pie-> dwOwningComponent = dwComponentId;
  58. pie-> wAddedByFlag = 0;
  59. if ( IS_PROTOCOL_ID_IGMP( dwProtocolId ) )
  60. {
  61. SET_ADDED_BY_IGMP( pie );
  62. }
  63. else
  64. {
  65. SET_ADDED_BY_PROTOCOL( pie );
  66. }
  67. InitializeListHead( &pie-> leInIfList );
  68. InitializeListHead( &pie-> leOutIfList );
  69. //
  70. // insert in protocol list
  71. //
  72. InitializeListHead( &pie-> leIfHashList );
  73. InsertTailList( pleIfList, &pie-> leIfHashList );
  74. } while ( FALSE );
  75. TRACEIF1( IF, "LEAVING CreateIfEntry : %x", dwErr );
  76. return dwErr;
  77. }
  78. //----------------------------------------------------------------------------
  79. // DeleteIfEntry
  80. //
  81. // This function deletes an interface entry. Duh
  82. // Assumes that the interface list is locked.
  83. //----------------------------------------------------------------------------
  84. VOID
  85. DeleteIfEntry(
  86. PIF_ENTRY pieEntry
  87. )
  88. {
  89. TRACEIF0( IF, "ENTERED DeleteIfEntry" );
  90. RemoveEntryList( &pieEntry-> leIfHashList );
  91. MGM_FREE( pieEntry );
  92. TRACEIF0( IF, "LEAVING DeleteIfEntry" );
  93. }
  94. //----------------------------------------------------------------------------
  95. // GetIfEntry
  96. //
  97. // This function retrieves an interface entry. Duh
  98. //
  99. // Assumes that the interface list is locked.
  100. //----------------------------------------------------------------------------
  101. PIF_ENTRY
  102. GetIfEntry(
  103. PLIST_ENTRY pleIfList,
  104. DWORD dwIfIndex,
  105. DWORD dwIfNextHopAddr
  106. )
  107. {
  108. PIF_ENTRY pie;
  109. if ( FindIfEntry( pleIfList, dwIfIndex, dwIfNextHopAddr, &pie ) )
  110. {
  111. return pie;
  112. }
  113. return NULL;
  114. }
  115. //----------------------------------------------------------------------------
  116. // FindIfEntry
  117. //
  118. // This function retrieves an interface entry. Duh
  119. //
  120. // Assumes that the interface list is locked.
  121. //----------------------------------------------------------------------------
  122. BOOL
  123. FindIfEntry(
  124. PLIST_ENTRY pleIfList,
  125. DWORD dwIfIndex,
  126. DWORD dwIfNextHopAddr,
  127. PIF_ENTRY * ppie
  128. )
  129. {
  130. BOOL bFound = FALSE;
  131. INT iCmp = 0;
  132. PIF_ENTRY pie = NULL;
  133. PLIST_ENTRY ple = NULL;
  134. TRACEIF2( IF, "ENTERED FindIfEntry : %x, %x", dwIfIndex, dwIfNextHopAddr );
  135. //
  136. // Scan interface list. Interface list is ordered by
  137. // interface index, next hop address
  138. //
  139. *ppie = NULL;
  140. for ( ple = pleIfList-> Flink; ple != pleIfList; ple = ple-> Flink )
  141. {
  142. pie = CONTAINING_RECORD( ple, IF_ENTRY, leIfHashList );
  143. if ( pie-> dwIfIndex < dwIfIndex )
  144. {
  145. continue;
  146. }
  147. else if ( pie-> dwIfIndex > dwIfIndex )
  148. {
  149. //
  150. // Entry not present
  151. //
  152. *ppie = pie;
  153. break;
  154. }
  155. if ( INET_CMP( pie-> dwIfNextHopAddr, dwIfNextHopAddr, iCmp ) < 0 )
  156. {
  157. continue;
  158. }
  159. else if ( iCmp > 0 )
  160. {
  161. *ppie = pie;
  162. break;
  163. }
  164. *ppie = pie;
  165. bFound = TRUE;
  166. break;
  167. }
  168. TRACEIF1( IF, "LEAVING FindIfEntry : %x", bFound );
  169. return bFound;
  170. }
  171. //----------------------------------------------------------------------------
  172. // AddSourceToOutList
  173. //
  174. // Each interface entry maintains a list of (source, group) entries that
  175. // reference this interface in their outgoing interface list. Each time
  176. // membership entry is added the (source, group) to the reference list.
  177. // When this interface is eventually deleted these (source, group) entries
  178. // need to be updated to reflect the deletion of this interface.
  179. //
  180. // Assumes that the interface entry is locked.
  181. //----------------------------------------------------------------------------
  182. VOID
  183. AddSourceToRefList(
  184. PLIST_ENTRY pleRefList,
  185. DWORD dwSourceAddr,
  186. DWORD dwSourceMask,
  187. DWORD dwGroupAddr,
  188. DWORD dwGroupMask,
  189. BOOL bIGMP
  190. )
  191. {
  192. BOOL bFound = FALSE;
  193. DWORD dwErr = NO_ERROR;
  194. PIF_REFERENCE_ENTRY pire = NULL, pireNew = NULL;
  195. TRACEIF5(
  196. IF,
  197. "ENTERED AddSourceToIfEntry : Source %x, %x : Group %x, %x"
  198. " : IGMP %x",
  199. dwSourceAddr, dwSourceMask, dwGroupAddr, dwGroupMask, bIGMP
  200. );
  201. do
  202. {
  203. //
  204. // Check if reference already present
  205. //
  206. bFound = FindRefEntry(
  207. pleRefList, dwSourceAddr, dwSourceMask,
  208. dwGroupAddr, dwGroupMask, &pire
  209. );
  210. if ( !bFound )
  211. {
  212. //
  213. // no previous reference for this (source, group) was found
  214. // create a new one.
  215. //
  216. pireNew = MGM_ALLOC( sizeof( IF_REFERENCE_ENTRY ) );
  217. if ( pireNew == NULL )
  218. {
  219. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  220. TRACE1(
  221. ANY,
  222. "AddSourceToOutList : Failed to allocate reference entry %x",
  223. dwErr
  224. );
  225. LOGERR0( HEAP_ALLOC_FAILED, dwErr );
  226. break;
  227. }
  228. ZeroMemory( pireNew, sizeof( IF_REFERENCE_ENTRY ) );
  229. pireNew-> dwSourceAddr = dwSourceAddr;
  230. pireNew-> dwSourceMask = dwSourceMask;
  231. pireNew-> dwGroupAddr = dwGroupAddr;
  232. pireNew-> dwGroupMask = dwGroupMask;
  233. pireNew-> wAddedByFlag = 0;
  234. //
  235. // set the appropriate bit for the protocol
  236. //
  237. if ( bIGMP )
  238. {
  239. SET_ADDED_BY_IGMP( pireNew );
  240. }
  241. else
  242. {
  243. SET_ADDED_BY_PROTOCOL( pireNew );
  244. }
  245. //
  246. // insert into ref list
  247. //
  248. if ( pire == NULL )
  249. {
  250. InsertTailList( pleRefList, &pireNew-> leRefList );
  251. }
  252. else
  253. {
  254. InsertTailList( &pire-> leRefList, &pireNew-> leRefList );
  255. }
  256. }
  257. else
  258. {
  259. //
  260. // set the appropriate bit for the protocol
  261. //
  262. if ( bIGMP )
  263. {
  264. SET_ADDED_BY_IGMP( pire );
  265. }
  266. else
  267. {
  268. SET_ADDED_BY_PROTOCOL( pire );
  269. }
  270. }
  271. } while ( FALSE );
  272. TRACEIF1( IF, "LEAVING AddSourceToRefList : %x", bFound );
  273. return;
  274. }
  275. //----------------------------------------------------------------------------
  276. // DeleeSourceFomrRefList
  277. //
  278. // Delete a reference to a (source, group).
  279. //----------------------------------------------------------------------------
  280. VOID
  281. DeleteSourceFromRefList(
  282. PLIST_ENTRY pleIfRefList,
  283. DWORD dwSourceAddr,
  284. DWORD dwSourceMask,
  285. DWORD dwGroupAddr,
  286. DWORD dwGroupMask,
  287. BOOL bIGMP
  288. )
  289. {
  290. BOOL bFound = FALSE;
  291. PIF_REFERENCE_ENTRY pire = NULL, pireEntry = NULL;
  292. TRACEIF5(
  293. IF,
  294. "ENTERED DeleteSourceFromIfEntry : Source %x %x, Group : %x, %x"
  295. " : IGMP %x",
  296. dwSourceAddr, dwSourceMask, dwGroupAddr, dwGroupMask, bIGMP
  297. );
  298. //
  299. // find the entry is already present.
  300. // list is arranged in descending order in terms of
  301. // Group address, source address
  302. //
  303. bFound = FindRefEntry(
  304. pleIfRefList, dwSourceAddr, dwSourceMask,
  305. dwGroupAddr, dwGroupMask, &pire
  306. );
  307. //
  308. // if entry was not found
  309. //
  310. if ( !bFound )
  311. {
  312. TRACE1( IF, "LEAVING DeleteSourceFromRefList : %x", FALSE );
  313. return;
  314. }
  315. //
  316. // reset the appropriate bit for the protocol
  317. //
  318. if ( bIGMP )
  319. {
  320. CLEAR_ADDED_BY_IGMP( pire );
  321. }
  322. else
  323. {
  324. CLEAR_ADDED_BY_PROTOCOL( pire );
  325. }
  326. //
  327. // if no more references left, remove this entry
  328. //
  329. if ( !IS_ADDED_BY_IGMP( pire ) &&
  330. !IS_ADDED_BY_PROTOCOL( pire ) )
  331. {
  332. RemoveEntryList( &pire-> leRefList );
  333. MGM_FREE( pire );
  334. }
  335. TRACEIF1( IF, "LEAVING DeleteSourceFromRefList : %x", TRUE );
  336. return;
  337. }
  338. //----------------------------------------------------------------------------
  339. // FindRefEntry
  340. //
  341. // Locate a reference entry. If not found return the expected location in
  342. // the list.
  343. //----------------------------------------------------------------------------
  344. BOOL
  345. FindRefEntry(
  346. PLIST_ENTRY pleRefList,
  347. DWORD dwSourceAddr,
  348. DWORD dwSourceMask,
  349. DWORD dwGroupAddr,
  350. DWORD dwGroupMask,
  351. PIF_REFERENCE_ENTRY * ppire
  352. )
  353. {
  354. INT iCmp;
  355. PLIST_ENTRY ple = NULL;
  356. PIF_REFERENCE_ENTRY pire = NULL;
  357. BOOL bFound = FALSE;
  358. TRACEIF4(
  359. IF,
  360. "ENTERED FindRefEntry : Source %x, %x : Group %x, %x",
  361. dwSourceAddr, dwSourceMask, dwGroupAddr, dwGroupMask
  362. );
  363. *ppire = NULL;
  364. for ( ple = pleRefList-> Flink; ple != pleRefList; ple = ple-> Flink )
  365. {
  366. pire = CONTAINING_RECORD( ple, IF_REFERENCE_ENTRY, leRefList );
  367. if ( INET_CMP( pire-> dwGroupAddr, dwGroupAddr, iCmp ) < 0 )
  368. {
  369. continue;
  370. }
  371. else if ( iCmp > 0 )
  372. {
  373. //
  374. // you are now past the position where an existing
  375. // entry would be.
  376. //
  377. *ppire = pire;
  378. break;
  379. }
  380. if ( INET_CMP( pire-> dwSourceAddr, dwSourceAddr, iCmp ) < 0 )
  381. {
  382. continue;
  383. }
  384. else if ( iCmp > 0 )
  385. {
  386. //
  387. // you are now past the position where an existing
  388. // entry would be.
  389. //
  390. *ppire = pire;
  391. break;
  392. }
  393. //
  394. // entry found
  395. //
  396. *ppire = pire;
  397. bFound = TRUE;
  398. break;
  399. }
  400. TRACEIF1( IF, "LEAVING FindRefEntry : %x", bFound );
  401. return bFound;
  402. }
  403. //----------------------------------------------------------------------------
  404. // DeleteOutInterfaceRefs
  405. //
  406. // When a interface is deleted by a protocol (or IGMP) all (source, group)
  407. // entries that use this interface in their outgoing interface lists have to
  408. // be updated to reflect ththe deletion.
  409. //
  410. //----------------------------------------------------------------------------
  411. VOID
  412. DeleteOutInterfaceRefs(
  413. PPROTOCOL_ENTRY ppe,
  414. PIF_ENTRY pie,
  415. BOOL bIGMP
  416. )
  417. {
  418. PLIST_ENTRY ple = NULL, pleRefList = NULL, pleNext = NULL;
  419. PIF_REFERENCE_ENTRY pire = NULL;
  420. TRACEIF1( IF, "ENTERED DeleteOutInterfaceRefs: IGMP %x", bIGMP );
  421. do
  422. {
  423. //
  424. // No references for this interface in any outgoing
  425. // interface lists of source entries
  426. //
  427. pleRefList = &pie-> leOutIfList;
  428. if ( IsListEmpty( pleRefList ) )
  429. {
  430. break;
  431. }
  432. //
  433. // walk the reference list and remove the (source, group) entries
  434. // for each reference
  435. //
  436. for ( ple = pleRefList-> Flink; ple != pleRefList; )
  437. {
  438. pire = CONTAINING_RECORD( ple, IF_REFERENCE_ENTRY, leRefList );
  439. //
  440. // was this reference added by this protocol
  441. //
  442. if ( ( bIGMP && !IS_ADDED_BY_IGMP( pire ) ) ||
  443. ( !bIGMP && !IS_ADDED_BY_PROTOCOL( pire ) ) )
  444. {
  445. //
  446. // no, skip it
  447. //
  448. ple = ple-> Flink;
  449. continue;
  450. }
  451. //
  452. // Delete this interface from the (source, group) entry.
  453. //
  454. DeleteInterfaceFromSourceEntry(
  455. ppe,
  456. pire-> dwGroupAddr, pire-> dwGroupMask,
  457. pire-> dwSourceAddr, pire-> dwSourceMask,
  458. pie-> dwIfIndex, pie-> dwIfNextHopAddr,
  459. bIGMP
  460. );
  461. if ( bIGMP )
  462. {
  463. CLEAR_ADDED_BY_IGMP( pire );
  464. }
  465. else
  466. {
  467. CLEAR_ADDED_BY_PROTOCOL( pire );
  468. }
  469. //
  470. // remove reference entry.
  471. //
  472. if ( !IS_ADDED_BY_IGMP( pire ) &&
  473. !IS_ADDED_BY_PROTOCOL( pire ) )
  474. {
  475. //
  476. // no more references to interface for IGMP
  477. // or for routing protocol.
  478. // remove this reference entry altogether.
  479. //
  480. pleNext = ple-> Flink;
  481. RemoveEntryList( ple );
  482. MGM_FREE ( pire );
  483. ple = pleNext;
  484. }
  485. else
  486. {
  487. ple = ple-> Flink;
  488. }
  489. }
  490. } while ( FALSE );
  491. TRACEIF0( IF, "LEAVING DeleteOutInterfaceRefs:" );
  492. return;
  493. }
  494. //----------------------------------------------------------------------------
  495. // DeleteInInterfaceRefs
  496. //
  497. // When a interface is deleted by a protocol (or IGMP) all (source, group)
  498. // entries that use this interface as their incoming interface have to
  499. // be updated to reflect the deletion.
  500. //----------------------------------------------------------------------------
  501. VOID
  502. DeleteInInterfaceRefs(
  503. PLIST_ENTRY pleRefList
  504. )
  505. {
  506. PLIST_ENTRY ple = NULL;
  507. PIF_REFERENCE_ENTRY pire = NULL;
  508. TRACEIF0( IF, "Entering DeleteInInterfaceRefs" );
  509. while ( !IsListEmpty( pleRefList ) )
  510. {
  511. ple = RemoveHeadList( pleRefList );
  512. pire = CONTAINING_RECORD( ple, IF_REFERENCE_ENTRY, leRefList );
  513. //
  514. // A Zappaesque function call here
  515. //
  516. LookupAndDeleteYourMfe(
  517. pire-> dwSourceAddr, pire-> dwSourceMask,
  518. pire-> dwGroupAddr, pire-> dwGroupMask,
  519. TRUE, NULL, NULL
  520. );
  521. MGM_FREE( pire );
  522. }
  523. TRACEIF0( IF, "LEAVING DeleteInInterfaceRefs" );
  524. }
  525. //----------------------------------------------------------------------------
  526. // TransferInterfaceOwnershipToProtocol
  527. //
  528. //
  529. //----------------------------------------------------------------------------
  530. DWORD
  531. TransferInterfaceOwnershipToProtocol(
  532. PPROTOCOL_ENTRY ppe,
  533. PIF_ENTRY pie
  534. )
  535. {
  536. DWORD dwErr = NO_ERROR;
  537. PPROTOCOL_ENTRY ppeIgmp;
  538. do
  539. {
  540. //
  541. // get protocol entry for IGMP
  542. //
  543. ppeIgmp = GetProtocolEntry(
  544. PROTOCOL_LIST_HEAD(), pie-> dwOwningProtocol,
  545. pie-> dwOwningComponent
  546. );
  547. if ( ppeIgmp == NULL )
  548. {
  549. //
  550. // interface is owned by IGMP, but protocol entry is not
  551. // present for IGMP. MGM data is in an inconsistent state
  552. //
  553. dwErr = ERROR_UNKNOWN;
  554. TRACE2(
  555. ANY, "TransferInterfaceOwnershipToProtocol : Could not find"
  556. " IGMP protocol entry", pie-> dwIfIndex,
  557. pie-> dwIfNextHopAddr
  558. );
  559. break;
  560. }
  561. //
  562. // indicate to IGMP that interface has been disabled. This should
  563. // stop IGMP from adding state to this interface while it is being
  564. // transferred to the protocol
  565. //
  566. IGMP_DISABLE_CALLBACK( ppeIgmp ) (
  567. pie-> dwIfIndex, pie-> dwIfNextHopAddr
  568. );
  569. //
  570. // delete all IGMP references in and out
  571. //
  572. DeleteInInterfaceRefs( &pie-> leInIfList );
  573. DeleteOutInterfaceRefs( ppeIgmp, pie, TRUE );
  574. //
  575. // mark interface as added by Routing protocol
  576. //
  577. SET_ADDED_BY_PROTOCOL( pie );
  578. pie-> dwOwningProtocol = ppe-> dwProtocolId;
  579. pie-> dwOwningComponent = ppe-> dwComponentId;
  580. //
  581. // indicate to IGMP that interface has been enabled.
  582. //
  583. IGMP_ENABLE_CALLBACK( ppeIgmp ) (
  584. pie-> dwIfIndex, pie-> dwIfNextHopAddr
  585. );
  586. } while ( FALSE );
  587. return dwErr;
  588. }
  589. //----------------------------------------------------------------------------
  590. // TransferInterfaceOwnershipToIGMP
  591. //
  592. //
  593. //----------------------------------------------------------------------------
  594. DWORD
  595. TransferInterfaceOwnershipToIGMP(
  596. PPROTOCOL_ENTRY ppe,
  597. PIF_ENTRY pie
  598. )
  599. {
  600. DWORD dwErr = NO_ERROR;
  601. PPROTOCOL_ENTRY ppeIgmp;
  602. do
  603. {
  604. //
  605. // get IGMP protocol entry
  606. //
  607. ppeIgmp = GetIgmpProtocolEntry( PROTOCOL_LIST_HEAD() );
  608. if ( ppeIgmp == NULL )
  609. {
  610. //
  611. // interface is has IGMP enabled on it, but a protocol entry is not
  612. // present for IGMP. MGM data is in an inconsistent state
  613. //
  614. dwErr = ERROR_UNKNOWN;
  615. TRACE2(
  616. ANY, "TransferInterfaceOwnershipToProtocol : Could not find"
  617. " IGMP protocol entry", pie-> dwIfIndex,
  618. pie-> dwIfNextHopAddr
  619. );
  620. break;
  621. }
  622. //
  623. // indicate to IGMP that interface has been disabled. This should
  624. // stop IGMP from adding state to this interface while it is being
  625. // transferred to IGMP
  626. //
  627. IGMP_DISABLE_CALLBACK( ppeIgmp ) (
  628. pie-> dwIfIndex, pie-> dwIfNextHopAddr
  629. );
  630. //
  631. // delete all protocol references (in and out)
  632. //
  633. DeleteInInterfaceRefs( &pie-> leInIfList );
  634. DeleteOutInterfaceRefs( ppe, pie, FALSE );
  635. CLEAR_ADDED_BY_PROTOCOL( pie );
  636. //
  637. // delete all IGMP references, these will get added back by
  638. // IGMP when is enabled on this interface. This is done
  639. // below.
  640. //
  641. DeleteOutInterfaceRefs( ppe, pie, TRUE );
  642. //
  643. // Mark interface as being owned by IGMP
  644. //
  645. pie-> dwOwningProtocol = ppeIgmp-> dwProtocolId;
  646. pie-> dwOwningComponent = ppeIgmp-> dwComponentId;
  647. //
  648. // enable IGMP on the interface
  649. //
  650. IGMP_ENABLE_CALLBACK( ppeIgmp ) (
  651. pie-> dwIfIndex, pie-> dwIfNextHopAddr
  652. );
  653. } while ( FALSE );
  654. return dwErr;
  655. }