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.

1317 lines
32 KiB

  1. /*++
  2. Copyright (c) 1999, Microsoft Corporation
  3. Module Name:
  4. sample\networkentry.c
  5. Abstract:
  6. The file contains functions to deal with the network entry and its
  7. associated data structures.
  8. --*/
  9. #include "pchsample.h"
  10. #pragma hdrstop
  11. DWORD
  12. BE_CreateTable (
  13. IN PIP_ADAPTER_BINDING_INFO pBinding,
  14. OUT PBINDING_ENTRY *ppbeBindingTable,
  15. OUT PIPADDRESS pipLowestAddress)
  16. /*++
  17. Routine Description
  18. Creates a table of binding entries and returns the binding with the
  19. lowest ip address. Ensures that there is atleast one binding.
  20. Locks
  21. None
  22. Arguments
  23. pBinding structure containing info about addresses bindings
  24. ppbeBindingTable pointer to the binding table address
  25. pipLowestAddress pointer to the lowest ip address in the binding
  26. Return Value
  27. NO_ERROR if success
  28. Failure code o/w
  29. --*/
  30. {
  31. ULONG i;
  32. DWORD dwErr = NO_ERROR;
  33. PBINDING_ENTRY pbe; // scratch
  34. // validate parameters
  35. if (!pBinding or !ppbeBindingTable or !pipLowestAddress)
  36. return ERROR_INVALID_PARAMETER;
  37. // a binding already exists
  38. if (*ppbeBindingTable != NULL)
  39. return ERROR_INVALID_PARAMETER;
  40. IP_ASSIGN(pipLowestAddress, IP_HIGHEST);
  41. do // breakout loop
  42. {
  43. if (pBinding->AddressCount is 0)
  44. {
  45. dwErr = ERROR_INVALID_PARAMETER;
  46. TRACE0(NETWORK, "Error, no bindings specified");
  47. break;
  48. }
  49. for (i = 0; i < pBinding->AddressCount; i++)
  50. if (!IP_VALID((pBinding->Address)[i].Address))
  51. break;
  52. if (i != pBinding->AddressCount)
  53. {
  54. dwErr = ERROR_INVALID_PARAMETER;
  55. TRACE0(NETWORK, "Error, an invalid binding specified");
  56. break;
  57. }
  58. // allocate the binding table
  59. MALLOC(&pbe, pBinding->AddressCount * sizeof(BINDING_ENTRY), &dwErr);
  60. if (dwErr != NO_ERROR)
  61. break;
  62. for (i = 0; i < pBinding->AddressCount; i++)
  63. {
  64. // initialize fields
  65. IP_ASSIGN(&(pbe[i].ipAddress), (pBinding->Address)[i].Address);
  66. IP_ASSIGN(&(pbe[i].ipMask), pBinding->Address[i].Mask);
  67. // update lowest ip address
  68. if (IP_COMPARE(pbe[i].ipAddress, *pipLowestAddress) is -1)
  69. IP_ASSIGN(pipLowestAddress,pbe[i].ipAddress);
  70. }
  71. *ppbeBindingTable = pbe;
  72. } while (FALSE);
  73. return dwErr;
  74. }
  75. DWORD
  76. BE_DestroyTable (
  77. IN PBINDING_ENTRY pbeBindingTable)
  78. /*++
  79. Routine Description
  80. Destroys a binding table.
  81. Locks
  82. None.
  83. Arguments
  84. pbeBindingTable pointer to the table of binding entries
  85. Return Value
  86. NO_ERROR always
  87. --*/
  88. {
  89. if (!pbeBindingTable)
  90. return NO_ERROR;
  91. FREE(pbeBindingTable);
  92. return NO_ERROR;
  93. }
  94. #ifdef DEBUG
  95. DWORD
  96. BE_DisplayTable (
  97. IN PBINDING_ENTRY pbeBindingTable,
  98. IN ULONG ulNumBindings)
  99. /*++
  100. Routine Description
  101. Displays a binding entry.
  102. Locks
  103. None.
  104. Arguments
  105. pbeBindingTable pointer to the table of binding entries
  106. ulNumBindings # binding entries in the table
  107. Return Value
  108. NO_ERROR always
  109. --*/
  110. {
  111. ULONG i;
  112. if (!pbeBindingTable)
  113. return NO_ERROR;
  114. for (i = 0; i < ulNumBindings; i++)
  115. {
  116. TRACE1(NETWORK, "ipAddress %s",
  117. INET_NTOA(pbeBindingTable[i].ipAddress));
  118. TRACE1(NETWORK, "ipMask %s",
  119. INET_NTOA(pbeBindingTable[i].ipMask));
  120. }
  121. return NO_ERROR;
  122. }
  123. #endif // DEBUG
  124. #ifdef DEBUG
  125. static
  126. VOID
  127. DisplayInterfaceEntry (
  128. IN PLIST_ENTRY pleEntry)
  129. /*++
  130. Routine Description
  131. Displays an INTERFACE_ENTRY object.
  132. Locks
  133. None
  134. Arguments
  135. pleEntry address of the 'leInterfaceTableLink' field
  136. Return Value
  137. None
  138. --*/
  139. {
  140. IE_Display(CONTAINING_RECORD(pleEntry,
  141. INTERFACE_ENTRY,
  142. leInterfaceTableLink));
  143. }
  144. #else
  145. #define DisplayInterfaceEntry NULL
  146. #endif // DEBUG
  147. static
  148. VOID
  149. FreeInterfaceEntry (
  150. IN PLIST_ENTRY pleEntry)
  151. /*++
  152. Routine Description
  153. Called by HT_Destroy, the destructor of the primary access structure.
  154. Removes an INTERFACE_ENTRY object from all secondary access structures.
  155. Locks
  156. None
  157. Arguments
  158. pleEntry address of the 'leInterfaceTableLink' field
  159. Return Value
  160. None
  161. --*/
  162. {
  163. PINTERFACE_ENTRY pie = NULL;
  164. pie = CONTAINING_RECORD(pleEntry, INTERFACE_ENTRY, leInterfaceTableLink);
  165. // remove from all secondary access structures.
  166. RemoveEntryList(&(pie->leIndexSortedListLink));
  167. // initialize pointers to indicate that the entry has been deleted
  168. InitializeListHead(&(pie->leInterfaceTableLink));
  169. InitializeListHead(&(pie->leIndexSortedListLink));
  170. IE_Destroy(pie);
  171. }
  172. static
  173. ULONG
  174. HashInterfaceEntry (
  175. IN PLIST_ENTRY pleEntry)
  176. /*++
  177. Routine Description
  178. Computes the hash value of an INTERFACE_ENTRY object.
  179. Locks
  180. None
  181. Arguments
  182. pleEntry address of the 'leInterfaceTableLink' field
  183. Return Value
  184. None
  185. --*/
  186. {
  187. PINTERFACE_ENTRY pie = CONTAINING_RECORD(pleEntry,
  188. INTERFACE_ENTRY,
  189. leInterfaceTableLink);
  190. return (pie->dwIfIndex % INTERFACE_TABLE_BUCKETS);
  191. }
  192. static
  193. LONG
  194. CompareInterfaceEntry (
  195. IN PLIST_ENTRY pleKeyEntry,
  196. IN PLIST_ENTRY pleTableEntry)
  197. /*++
  198. Routine Description
  199. Compares the interface indices of two INTERFACE_ENTRY objects.
  200. Locks
  201. None
  202. Arguments
  203. pleTableEntry address of the 'leInterfaceTableLink' fields
  204. pleKeyEntry within the two objects
  205. Return Value
  206. None
  207. --*/
  208. {
  209. PINTERFACE_ENTRY pieA, pieB;
  210. pieA = CONTAINING_RECORD(pleKeyEntry,
  211. INTERFACE_ENTRY,
  212. leInterfaceTableLink);
  213. pieB = CONTAINING_RECORD(pleTableEntry,
  214. INTERFACE_ENTRY,
  215. leInterfaceTableLink);
  216. if (pieA->dwIfIndex < pieB->dwIfIndex)
  217. return -1;
  218. else if (pieA->dwIfIndex is pieB->dwIfIndex)
  219. return 0;
  220. else
  221. return 1;
  222. }
  223. #ifdef DEBUG
  224. static
  225. VOID
  226. DisplayIndexInterfaceEntry (
  227. IN PLIST_ENTRY pleEntry)
  228. /*++
  229. Routine Description
  230. Displays an INTERFACE_ENTRY object.
  231. Locks
  232. None
  233. Arguments
  234. pleEntry address of the 'leIndexSortedListLink' field
  235. Return Value
  236. None
  237. --*/
  238. {
  239. IE_Display(CONTAINING_RECORD(pleEntry,
  240. INTERFACE_ENTRY,
  241. leIndexSortedListLink));
  242. }
  243. #else
  244. #define DisplayIndexInterfaceEntry NULL
  245. #endif // DEBUG
  246. static
  247. LONG
  248. CompareIndexInterfaceEntry (
  249. IN PLIST_ENTRY pleKeyEntry,
  250. IN PLIST_ENTRY pleTableEntry)
  251. /*++
  252. Routine Description
  253. Compares the interface indices of two INTERFACE_ENTRY objects.
  254. Locks
  255. None
  256. Arguments
  257. pleTableEntry address of the 'leIndexSortedListLink' fields
  258. pleKeyEntry within the two objects
  259. Return Value
  260. None
  261. --*/
  262. {
  263. PINTERFACE_ENTRY pieA, pieB;
  264. pieA = CONTAINING_RECORD(pleKeyEntry,
  265. INTERFACE_ENTRY,
  266. leIndexSortedListLink);
  267. pieB = CONTAINING_RECORD(pleTableEntry,
  268. INTERFACE_ENTRY,
  269. leIndexSortedListLink);
  270. if (pieA->dwIfIndex < pieB->dwIfIndex)
  271. return -1;
  272. else if (pieA->dwIfIndex is pieB->dwIfIndex)
  273. return 0;
  274. else
  275. return 1;
  276. }
  277. DWORD
  278. IE_Create (
  279. IN PWCHAR pwszIfName,
  280. IN DWORD dwIfIndex,
  281. IN WORD wAccessType,
  282. OUT PINTERFACE_ENTRY *ppieInterfaceEntry)
  283. /*++
  284. Routine Description
  285. Creates an interface entry.
  286. Locks
  287. None
  288. Arguments
  289. ppieInterfaceEntry pointer to the interface entry address
  290. Return Value
  291. NO_ERROR if success
  292. Failure code o/w
  293. --*/
  294. {
  295. DWORD dwErr = NO_ERROR;
  296. ULONG ulNameLength;
  297. PINTERFACE_ENTRY pieEntry; // scratch
  298. // validate parameters
  299. if (!ppieInterfaceEntry)
  300. return ERROR_INVALID_PARAMETER;
  301. *ppieInterfaceEntry = NULL;
  302. do // breakout loop
  303. {
  304. // allocate and zero out the interface entry structure
  305. MALLOC(&pieEntry, sizeof(INTERFACE_ENTRY), &dwErr);
  306. if (dwErr != NO_ERROR)
  307. break;
  308. // initialize fields with default values
  309. InitializeListHead(&(pieEntry->leInterfaceTableLink));
  310. InitializeListHead(&(pieEntry->leIndexSortedListLink));
  311. // pieEntry->pwszIfName = NULL;
  312. pieEntry->dwIfIndex = dwIfIndex;
  313. // pieEntry->ulNumBindings = 0;
  314. // pieEntry->pbeBindingTable = NULL;
  315. // pieEntry->dwFlags = 0; // disabled unbound pointtopoint
  316. if (wAccessType is IF_ACCESS_BROADCAST)
  317. pieEntry->dwFlags |= IEFLAG_MULTIACCESS;
  318. IP_ASSIGN(&(pieEntry->ipAddress), IP_LOWEST);
  319. pieEntry->sRawSocket = INVALID_SOCKET;
  320. // pieEntry->hReceiveEvent = NULL;
  321. // pieEntry->hReceiveWait = NULL;
  322. // pieEntry->hPeriodicTimer = NULL;
  323. // pieEntry->ulMetric = 0;
  324. // pieEntry->iisStats zero'ed out
  325. // initialize name
  326. ulNameLength = wcslen(pwszIfName) + 1;
  327. MALLOC(&(pieEntry->pwszIfName), ulNameLength * sizeof(WCHAR), &dwErr);
  328. if(dwErr != NO_ERROR)
  329. break;
  330. wcscpy(pieEntry->pwszIfName, pwszIfName);
  331. // initialize ReceiveEvent (signalled when input arrives).
  332. // Auto-Reset Event: state automatically reset to nonsignaled after
  333. // a single waiting thread is released. Initially non signalled
  334. pieEntry->hReceiveEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  335. if (pieEntry->hReceiveEvent is NULL)
  336. {
  337. dwErr = GetLastError();
  338. TRACE1(NETWORK, "Error %u creating Receive Event", dwErr);
  339. LOGERR0(CREATE_EVENT_FAILED, dwErr);
  340. break;
  341. }
  342. // register ReceiveWait for this interface
  343. if (!RegisterWaitForSingleObject(&(pieEntry->hReceiveWait),
  344. pieEntry->hReceiveEvent,
  345. NM_CallbackNetworkEvent,
  346. (PVOID) dwIfIndex,
  347. INFINITE,
  348. WT_EXECUTEONLYONCE))
  349. {
  350. dwErr = GetLastError();
  351. TRACE1(NETWORK, "Error %u registering ReceiveWait", dwErr);
  352. LOGERR0(REGISTER_WAIT_FAILED, dwErr);
  353. break;
  354. }
  355. *ppieInterfaceEntry = pieEntry; // all's well :)
  356. } while (FALSE);
  357. if (dwErr != NO_ERROR)
  358. {
  359. // something went wrong, so cleanup.
  360. TRACE2(NETWORK, "Failed to create interface entry for %S (%u)",
  361. pwszIfName, dwIfIndex);
  362. IE_Destroy(pieEntry);
  363. }
  364. return dwErr;
  365. }
  366. DWORD
  367. IE_Destroy (
  368. IN PINTERFACE_ENTRY pieInterfaceEntry)
  369. /*++
  370. Routine Description
  371. Destroys an interface entry.
  372. Locks
  373. Assumes exclusive access to the entry by virute of it having been
  374. removed from all access data structures (lists, tables, ...)
  375. NOTE: Should NOT be called with g_ce.neNetworkEntry.rwlLock held! The
  376. call to UnregisterWaitEx blocks till all queued callbacks for
  377. pieInterfaceEntry->hReceiveEvent finish execution. These callbacks may
  378. acquire g_ce.neNetworkEntry.rwlLock, causing deadlock.
  379. Arguments
  380. pieInterfaceEntry pointer to the interface entry
  381. Return Value
  382. NO_ERROR always
  383. --*/
  384. {
  385. if (!pieInterfaceEntry)
  386. return NO_ERROR;
  387. if (INTERFACE_IS_BOUND(pieInterfaceEntry))
  388. IE_UnBindInterface(pieInterfaceEntry);
  389. if (INTERFACE_IS_ACTIVE(pieInterfaceEntry))
  390. IE_DeactivateInterface(pieInterfaceEntry);
  391. // PeriodicTimer should have been destroyed
  392. RTASSERT(pieInterfaceEntry->hPeriodicTimer is NULL);
  393. // deregister ReceiveWait
  394. if (pieInterfaceEntry->hReceiveWait)
  395. UnregisterWaitEx(pieInterfaceEntry->hReceiveWait,
  396. INVALID_HANDLE_VALUE);
  397. // delete ReceiveEvent
  398. if (pieInterfaceEntry->hReceiveEvent)
  399. CloseHandle(pieInterfaceEntry->hReceiveEvent);
  400. // BindingTable and RawSocket should have been destroyed
  401. RTASSERT(pieInterfaceEntry->pbeBindingTable is NULL);
  402. RTASSERT(pieInterfaceEntry->sRawSocket is INVALID_SOCKET);
  403. // delete IfName
  404. FREE(pieInterfaceEntry->pwszIfName);
  405. // Entry should have been removed from all access structures
  406. RTASSERT(IsListEmpty(&(pieInterfaceEntry->leInterfaceTableLink)));
  407. RTASSERT(IsListEmpty(&(pieInterfaceEntry->leIndexSortedListLink)));
  408. // deallocate the interface entry structure
  409. FREE(pieInterfaceEntry);
  410. return NO_ERROR;
  411. }
  412. #ifdef DEBUG
  413. DWORD
  414. IE_Display (
  415. IN PINTERFACE_ENTRY pieInterfaceEntry)
  416. /*++
  417. Routine Description
  418. Displays an interface entry.
  419. Locks
  420. Assumes the interface entry is locked for reading.
  421. Arguments
  422. pieInterfaceEntry pointer to the interface entry to be displayed
  423. Return Value
  424. NO_ERROR always
  425. --*/
  426. {
  427. if (!pieInterfaceEntry)
  428. return NO_ERROR;
  429. TRACE3(NETWORK,
  430. "IfName %S, IfIndex %u, AccessType %u",
  431. pieInterfaceEntry->pwszIfName,
  432. pieInterfaceEntry->dwIfIndex,
  433. INTERFACE_IS_MULTIACCESS(pieInterfaceEntry));
  434. TRACE1(NETWORK, "NumBindings %u", pieInterfaceEntry->ulNumBindings);
  435. BE_DisplayTable(pieInterfaceEntry->pbeBindingTable,
  436. pieInterfaceEntry->ulNumBindings);
  437. TRACE2(NETWORK,
  438. "IfAddress %s Flags %u",
  439. INET_NTOA(pieInterfaceEntry->ipAddress),
  440. pieInterfaceEntry->dwFlags);
  441. TRACE2(NETWORK,
  442. "Metric %u, NumPackets %u",
  443. pieInterfaceEntry->ulMetric,
  444. pieInterfaceEntry->iisStats.ulNumPackets);
  445. return NO_ERROR;
  446. }
  447. #endif // DEBUG
  448. DWORD
  449. IE_Insert (
  450. IN PINTERFACE_ENTRY pieIfEntry)
  451. /*++
  452. Routine Description
  453. Inserts an interface entry in all access structures,
  454. primary and secondary.
  455. Locks
  456. Assumes exclusive access to the interface table and index sorted list
  457. i.e. (g_ce.pneNetworkEntry)->rwlLock held in write mode.
  458. Arguments
  459. pieIfEntry pointer to the interface entry
  460. Return Value
  461. NO_ERROR success
  462. ERROR_INVALID_PARAMETER o/w (interface entry already exists)
  463. --*/
  464. {
  465. DWORD dwErr = NO_ERROR;
  466. do // breakout loop
  467. {
  468. dwErr = HT_InsertEntry((g_ce.pneNetworkEntry)->phtInterfaceTable,
  469. &(pieIfEntry->leInterfaceTableLink));
  470. if (dwErr != NO_ERROR)
  471. {
  472. TRACE2(NETWORK, "Error interface %S (%u) already exists",
  473. pieIfEntry->pwszIfName, pieIfEntry->dwIfIndex);
  474. LOGERR0(INTERFACE_PRESENT, dwErr);
  475. break;
  476. }
  477. // insert in all tables, lists...
  478. InsertSortedList(&((g_ce.pneNetworkEntry)->leIndexSortedList),
  479. &(pieIfEntry->leIndexSortedListLink),
  480. CompareIndexInterfaceEntry);
  481. } while (FALSE);
  482. return dwErr;
  483. }
  484. DWORD
  485. IE_Delete (
  486. IN DWORD dwIfIndex,
  487. OUT PINTERFACE_ENTRY *ppieIfEntry)
  488. /*++
  489. Routine Description
  490. Deletes an interface entry from all access structures,
  491. primary and secondary.
  492. Locks
  493. Assumes exclusive access to the interface table and index sorted list
  494. i.e. (g_ce.pneNetworkEntry)->rwlLock held in write mode.
  495. Arguments
  496. dwIfIndex the positive integer used to identify the interface.
  497. ppieIfEntry address of the pointer to the interface entry
  498. Return Value
  499. NO_ERROR success
  500. ERROR_INVALID_PARAMETER o/w (interface entry does not exist)
  501. --*/
  502. {
  503. DWORD dwErr = NO_ERROR;
  504. INTERFACE_ENTRY ieKey;
  505. PLIST_ENTRY pleListEntry = NULL;
  506. *ppieIfEntry = NULL;
  507. do // breakout loop
  508. {
  509. // remove from interface table (primary)
  510. ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY));
  511. ieKey.dwIfIndex = dwIfIndex;
  512. dwErr = HT_DeleteEntry((g_ce.pneNetworkEntry)->phtInterfaceTable,
  513. &(ieKey.leInterfaceTableLink),
  514. &pleListEntry);
  515. if (dwErr != NO_ERROR)
  516. {
  517. TRACE1(NETWORK, "Error interface %u has vanished", dwIfIndex);
  518. LOGWARN0(INTERFACE_ABSENT, dwErr);
  519. break;
  520. }
  521. *ppieIfEntry = CONTAINING_RECORD(pleListEntry,
  522. INTERFACE_ENTRY,
  523. leInterfaceTableLink);
  524. // remove from all other tables, lists... (secondary)
  525. RemoveEntryList(&((*ppieIfEntry)->leIndexSortedListLink));
  526. // initialize pointers to indicate that the entry has been deleted
  527. InitializeListHead(&((*ppieIfEntry)->leInterfaceTableLink));
  528. InitializeListHead(&((*ppieIfEntry)->leIndexSortedListLink));
  529. } while (FALSE);
  530. return dwErr;
  531. }
  532. BOOL
  533. IE_IsPresent (
  534. IN DWORD dwIfIndex)
  535. /*++
  536. Routine Description
  537. Is interface entry present in interface table?
  538. Locks
  539. Assumes shared access to the interface table
  540. i.e. (g_ce.pneNetworkEntry)->rwlLock held in read mode.
  541. Arguments
  542. dwIfIndex the positive integer used to identify the interface.
  543. Return Value
  544. TRUE entry present
  545. FALSE o/w
  546. --*/
  547. {
  548. DWORD dwErr = NO_ERROR;
  549. INTERFACE_ENTRY ieKey;
  550. ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY));
  551. ieKey.dwIfIndex = dwIfIndex;
  552. return HT_IsPresentEntry((g_ce.pneNetworkEntry)->phtInterfaceTable,
  553. &(ieKey.leInterfaceTableLink));
  554. }
  555. DWORD
  556. IE_Get (
  557. IN DWORD dwIfIndex,
  558. OUT PINTERFACE_ENTRY *ppieIfEntry)
  559. /*++
  560. Routine Description
  561. Retrieves an interface entry from the interface table,
  562. the primary address strucutre.
  563. Locks
  564. Assumes shared access to the interface table
  565. i.e. (g_ce.pneNetworkEntry)->rwlLock held in read mode.
  566. Arguments
  567. dwIfIndex the positive integer used to identify the interface.
  568. ppieIfEntry address of the pointer to the interface entry
  569. Return Value
  570. NO_ERROR success
  571. ERROR_INVALID_PARAMETER o/w (interface entry does not exist)
  572. --*/
  573. {
  574. DWORD dwErr = NO_ERROR;
  575. INTERFACE_ENTRY ieKey;
  576. PLIST_ENTRY pleListEntry = NULL;
  577. *ppieIfEntry = NULL;
  578. do // breakout loop
  579. {
  580. ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY));
  581. ieKey.dwIfIndex = dwIfIndex;
  582. dwErr = HT_GetEntry((g_ce.pneNetworkEntry)->phtInterfaceTable,
  583. &(ieKey.leInterfaceTableLink),
  584. &pleListEntry);
  585. if (dwErr != NO_ERROR)
  586. {
  587. TRACE1(NETWORK, "Error interface %u has vanished", dwIfIndex);
  588. LOGWARN0(INTERFACE_ABSENT, dwErr);
  589. break;
  590. }
  591. *ppieIfEntry = CONTAINING_RECORD(pleListEntry,
  592. INTERFACE_ENTRY,
  593. leInterfaceTableLink);
  594. } while (FALSE);
  595. return dwErr;
  596. }
  597. DWORD
  598. IE_GetIndex (
  599. IN DWORD dwIfIndex,
  600. IN MODE mMode,
  601. OUT PINTERFACE_ENTRY *ppieIfEntry)
  602. /*++
  603. Routine Description
  604. Retrieves an interface entry from the index sorted list,
  605. the secondary address strucutre.
  606. Locks
  607. Assumes shared access to the index sorted list
  608. i.e. (g_ce.pneNetworkEntry)->rwlLock held in read mode.
  609. Arguments
  610. dwIfIndex the positive integer used to identify the interface.
  611. mMode mode of access (GET_EXACT, GET_FIRST, GET_NEXT)
  612. ppieIfEntry address of the pointer to the interface entry
  613. Return Value
  614. NO_ERROR success
  615. ERROR_NO_MORE_ITEMS o/w
  616. --*/
  617. {
  618. INTERFACE_ENTRY ieKey;
  619. PLIST_ENTRY pleHead = NULL, pleEntry = NULL;
  620. *ppieIfEntry = NULL;
  621. pleHead = &((g_ce.pneNetworkEntry)->leIndexSortedList);
  622. if (IsListEmpty(pleHead))
  623. return ERROR_NO_MORE_ITEMS;
  624. ZeroMemory(&ieKey, sizeof(INTERFACE_ENTRY));
  625. ieKey.dwIfIndex = (mMode is GET_FIRST) ? 0 : dwIfIndex;
  626. // this either gets the exact match or the next entry
  627. FindSortedList(pleHead,
  628. &(ieKey.leIndexSortedListLink),
  629. &pleEntry,
  630. CompareIndexInterfaceEntry);
  631. // reached end of list
  632. if (pleEntry is NULL)
  633. {
  634. RTASSERT(mMode != GET_FIRST); // should have got the first entry
  635. return ERROR_NO_MORE_ITEMS;
  636. }
  637. *ppieIfEntry = CONTAINING_RECORD(pleEntry,
  638. INTERFACE_ENTRY,
  639. leIndexSortedListLink);
  640. switch (mMode)
  641. {
  642. case GET_FIRST:
  643. return NO_ERROR;
  644. case GET_EXACT:
  645. // found an exact match
  646. if ((*ppieIfEntry)->dwIfIndex is dwIfIndex)
  647. return NO_ERROR;
  648. else
  649. {
  650. *ppieIfEntry = NULL;
  651. return ERROR_NO_MORE_ITEMS;
  652. }
  653. case GET_NEXT:
  654. // found an exact match
  655. if ((*ppieIfEntry)->dwIfIndex is dwIfIndex)
  656. {
  657. pleEntry = pleEntry->Flink; // get next entry
  658. if (pleEntry is pleHead) // end of list
  659. {
  660. *ppieIfEntry = NULL;
  661. return ERROR_NO_MORE_ITEMS;
  662. }
  663. *ppieIfEntry = CONTAINING_RECORD(pleEntry,
  664. INTERFACE_ENTRY,
  665. leIndexSortedListLink);
  666. }
  667. return NO_ERROR;
  668. default:
  669. RTASSERT(FALSE); // never reached
  670. }
  671. }
  672. DWORD
  673. IE_BindInterface (
  674. IN PINTERFACE_ENTRY pie,
  675. IN PIP_ADAPTER_BINDING_INFO pBinding)
  676. /*++
  677. Routine Description
  678. Binds an interface.
  679. Locks
  680. Assumes the interface entry is locked for writing.
  681. Arguments
  682. pie pointer to the interface entry
  683. pBinding info about the addresses on the interface
  684. Return Value
  685. NO_ERROR success
  686. Error Code o/w
  687. --*/
  688. {
  689. DWORD dwErr = NO_ERROR;
  690. ULONG i, j;
  691. do // breakout loop
  692. {
  693. // fail if the interface is already bound
  694. if (INTERFACE_IS_BOUND(pie))
  695. {
  696. dwErr = ERROR_INVALID_PARAMETER;
  697. TRACE2(NETWORK, "Error interface %S (%u) is already bound",
  698. pie->pwszIfName, pie->dwIfIndex);
  699. break;
  700. }
  701. dwErr = BE_CreateTable (pBinding,
  702. &(pie->pbeBindingTable),
  703. &(pie->ipAddress));
  704. if (dwErr != NO_ERROR)
  705. break;
  706. pie->ulNumBindings = pBinding->AddressCount;
  707. // set the "bound" flag
  708. pie->dwFlags |= IEFLAG_BOUND;
  709. } while (FALSE);
  710. return dwErr;
  711. }
  712. DWORD
  713. IE_UnBindInterface (
  714. IN PINTERFACE_ENTRY pie)
  715. /*++
  716. Routine Description
  717. UnBinds an interface.
  718. Locks
  719. Assumes the interface entry is locked for writing.
  720. Arguments
  721. pie pointer to the interface entry
  722. Return Value
  723. NO_ERROR success
  724. Error Code o/w
  725. --*/
  726. {
  727. DWORD dwErr = NO_ERROR;
  728. do // breakout loop
  729. {
  730. // fail if the interface is already unbound
  731. if (INTERFACE_IS_UNBOUND(pie))
  732. {
  733. dwErr = ERROR_INVALID_PARAMETER;
  734. TRACE2(NETWORK, "interface %S (%u) already unbound",
  735. pie->pwszIfName, pie->dwIfIndex);
  736. break;
  737. }
  738. // clear the "bound" flag
  739. pie->dwFlags &= ~IEFLAG_BOUND;
  740. IP_ASSIGN(&(pie->ipAddress), IP_LOWEST);
  741. BE_DestroyTable(pie->pbeBindingTable);
  742. pie->pbeBindingTable = NULL;
  743. pie->ulNumBindings = 0;
  744. } while (FALSE);
  745. return dwErr;
  746. }
  747. DWORD
  748. IE_ActivateInterface (
  749. IN PINTERFACE_ENTRY pie)
  750. /*++
  751. Routine Description
  752. Activates an interface by creating a socket and starting a timer.
  753. The socket is bound to the interface address.
  754. Interface is assumed to have atleast one binding.
  755. Locks
  756. Assumes the interface entry is locked for writing.
  757. Arguments
  758. pie pointer to the interface entry
  759. Return Value
  760. NO_ERROR success
  761. Error Code o/w
  762. --*/
  763. {
  764. DWORD dwErr = NO_ERROR;
  765. do // breakout loop
  766. {
  767. // fail if the interface is already active
  768. if (INTERFACE_IS_ACTIVE(pie))
  769. {
  770. dwErr = ERROR_INVALID_PARAMETER;
  771. TRACE0(NETWORK, "Interface already active");
  772. break;
  773. }
  774. // set the "active" flag
  775. pie->dwFlags |= IEFLAG_ACTIVE;
  776. // create a socket for the interface
  777. dwErr = SocketCreate(pie->ipAddress,
  778. pie->hReceiveEvent,
  779. &(pie->sRawSocket));
  780. if (dwErr != NO_ERROR)
  781. {
  782. TRACE1(NETWORK, "Error creating socket for %s",
  783. INET_NTOA(pie->ipAddress));
  784. break;
  785. }
  786. // start timer for sending protocol packets
  787. CREATE_TIMER(&pie->hPeriodicTimer ,
  788. NM_CallbackPeriodicTimer,
  789. (PVOID) pie->dwIfIndex,
  790. PERIODIC_INTERVAL,
  791. &dwErr);
  792. if (dwErr != NO_ERROR)
  793. break;
  794. } while (FALSE);
  795. if (dwErr != NO_ERROR)
  796. {
  797. TRACE3(NETWORK, "Error %u activating interface %S (%u)",
  798. dwErr, pie->pwszIfName, pie->dwIfIndex);
  799. IE_DeactivateInterface(pie);
  800. }
  801. return dwErr;
  802. }
  803. DWORD
  804. IE_DeactivateInterface (
  805. IN PINTERFACE_ENTRY pie)
  806. /*++
  807. Routine Description
  808. Deactivates an interface by stopping the timer and destroying the socket.
  809. Locks
  810. Assumes the interface entry is locked for writing.
  811. Arguments
  812. pie pointer to the interface entry
  813. Return Value
  814. NO_ERROR success
  815. Error Code o/w
  816. --*/
  817. {
  818. DWORD dwErr = NO_ERROR;
  819. do // breakout loop
  820. {
  821. // fail if the interface is already inactive
  822. if (INTERFACE_IS_INACTIVE(pie))
  823. {
  824. dwErr = ERROR_INVALID_PARAMETER;
  825. TRACE2(NETWORK, "interface %S (%u) already inactive",
  826. pie->pwszIfName, pie->dwIfIndex);
  827. break;
  828. }
  829. // stop the timer
  830. if (pie->hPeriodicTimer)
  831. DELETE_TIMER(pie->hPeriodicTimer, &dwErr);
  832. pie->hPeriodicTimer = NULL;
  833. // destroy the socket for the interface
  834. dwErr = SocketDestroy(pie->sRawSocket);
  835. pie->sRawSocket = INVALID_SOCKET;
  836. // clear the "active" flag
  837. pie->dwFlags &= ~IEFLAG_ACTIVE;
  838. } while (FALSE);
  839. return dwErr;
  840. }
  841. DWORD
  842. NE_Create (
  843. OUT PNETWORK_ENTRY *ppneNetworkEntry)
  844. /*++
  845. Routine Description
  846. Creates a network entry.
  847. Locks
  848. None
  849. Arguments
  850. ppneNetworkEntry pointer to the network entry address
  851. Return Value
  852. NO_ERROR if success
  853. Failure code o/w
  854. --*/
  855. {
  856. DWORD dwErr = NO_ERROR;
  857. PNETWORK_ENTRY pneEntry; // scratch
  858. // validate parameters
  859. if (!ppneNetworkEntry)
  860. return ERROR_INVALID_PARAMETER;
  861. *ppneNetworkEntry = NULL;
  862. do // breakout loop
  863. {
  864. // allocate and zero out the network entry structure
  865. MALLOC(&pneEntry, sizeof(NETWORK_ENTRY), &dwErr);
  866. if (dwErr != NO_ERROR)
  867. break;
  868. // initialize fields with default values
  869. // pneEntry->rwlLock zero'ed out
  870. // pneEntry->phtInterfaceTable = NULL;
  871. InitializeListHead(&(pneEntry->leIndexSortedList));
  872. // initialize the read-write lock
  873. dwErr = CREATE_READ_WRITE_LOCK(&(pneEntry->rwlLock));
  874. if (dwErr != NO_ERROR)
  875. {
  876. TRACE1(NETWORK, "Error %u creating read-write-lock", dwErr);
  877. LOGERR0(CREATE_RWL_FAILED, dwErr);
  878. break;
  879. }
  880. // allocate the interface table
  881. dwErr = HT_Create(GLOBAL_HEAP,
  882. INTERFACE_TABLE_BUCKETS,
  883. DisplayInterfaceEntry,
  884. FreeInterfaceEntry,
  885. HashInterfaceEntry,
  886. CompareInterfaceEntry,
  887. &(pneEntry->phtInterfaceTable));
  888. if (dwErr != NO_ERROR)
  889. {
  890. TRACE1(NETWORK, "Error %u creating hash-table", dwErr);
  891. LOGERR0(CREATE_HASHTABLE_FAILED, dwErr);
  892. break;
  893. }
  894. *ppneNetworkEntry = pneEntry;
  895. } while (FALSE);
  896. if (dwErr != NO_ERROR)
  897. {
  898. // something went wrong, so cleanup.
  899. TRACE0(NETWORK, "Failed to create nework entry");
  900. NE_Destroy(pneEntry);
  901. pneEntry = NULL;
  902. }
  903. return dwErr;
  904. }
  905. DWORD
  906. NE_Destroy (
  907. IN PNETWORK_ENTRY pneNetworkEntry)
  908. /*++
  909. Routine Description
  910. Destroys a network entry.
  911. Locks
  912. Assumes exclusive access to rwlLock by virtue of of no competing threads.
  913. Arguments
  914. pneNetworkEntry pointer to the network entry
  915. Return Value
  916. NO_ERROR always
  917. --*/
  918. {
  919. if (!pneNetworkEntry)
  920. return NO_ERROR;
  921. // deallocate the interface table...
  922. // this removes the interface entries from all secondary access
  923. // structures (IndexSortedList, ...) as well since all of them
  924. // share interface entries by containing pointers to the same object.
  925. HT_Destroy(GLOBAL_HEAP, pneNetworkEntry->phtInterfaceTable);
  926. pneNetworkEntry->phtInterfaceTable = NULL;
  927. RTASSERT(IsListEmpty(&(pneNetworkEntry->leIndexSortedList)));
  928. // delete read-write-lock
  929. if (READ_WRITE_LOCK_CREATED(&(pneNetworkEntry->rwlLock)))
  930. DELETE_READ_WRITE_LOCK(&(pneNetworkEntry->rwlLock));
  931. // deallocate the network entry structure
  932. FREE(pneNetworkEntry);
  933. return NO_ERROR;
  934. }
  935. #ifdef DEBUG
  936. DWORD
  937. NE_Display (
  938. IN PNETWORK_ENTRY pneNetworkEntry)
  939. /*++
  940. Routine Description
  941. Displays a network entry.
  942. Locks
  943. Acquires shared pneNetworkEntry->rwlLock
  944. Releases pneNetworkEntry->rwlLock
  945. Arguments
  946. pne pointer to the network entry to be displayed
  947. Return Value
  948. NO_ERROR always
  949. --*/
  950. {
  951. if (!pneNetworkEntry)
  952. return NO_ERROR;
  953. ACQUIRE_READ_LOCK(&(pneNetworkEntry->rwlLock));
  954. TRACE0(NETWORK, "Network Entry...");
  955. TRACE1(NETWORK,
  956. "Interface Table Size %u",
  957. HT_Size(pneNetworkEntry->phtInterfaceTable));
  958. TRACE0(NETWORK, "Interface Table...");
  959. HT_Display(pneNetworkEntry->phtInterfaceTable);
  960. TRACE0(NETWORK, "Index Sorted List...");
  961. MapCarList(&(pneNetworkEntry->leIndexSortedList),
  962. DisplayIndexInterfaceEntry);
  963. RELEASE_READ_LOCK(&(pneNetworkEntry->rwlLock));
  964. return NO_ERROR;
  965. }
  966. #endif // DEBUG