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.

3419 lines
76 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. arpif.c
  5. Abstract:
  6. ARP Interface Entry points. These are called (indirectly) by the IP
  7. layer. All these entry points have the common prefix "AtmArpIf".
  8. Revision History:
  9. Who When What
  10. -------- -------- ----------------------------------------------
  11. arvindm 07-17-96 Created
  12. Notes:
  13. --*/
  14. #include <precomp.h>
  15. #define _FILENUMBER 'FIRA'
  16. #if DBG_QRY
  17. ULONG AaIgnoreInstance = 0;
  18. #endif
  19. IP_MASK AtmArpIPMaskTable[] =
  20. {
  21. CLASSA_MASK,
  22. CLASSA_MASK,
  23. CLASSA_MASK,
  24. CLASSA_MASK,
  25. CLASSA_MASK,
  26. CLASSA_MASK,
  27. CLASSA_MASK,
  28. CLASSA_MASK,
  29. CLASSB_MASK,
  30. CLASSB_MASK,
  31. CLASSB_MASK,
  32. CLASSB_MASK,
  33. CLASSC_MASK,
  34. CLASSC_MASK,
  35. CLASSD_MASK,
  36. CLASSE_MASK
  37. };
  38. VOID
  39. AtmArpReStartInterface(
  40. IN PNDIS_WORK_ITEM pWorkItem,
  41. IN PVOID IfContext
  42. );
  43. #ifndef NEWARP
  44. NDIS_STATUS
  45. AtmArpInitIPInterface(
  46. VOID
  47. )
  48. /*++
  49. Routine Description:
  50. Initialize our interface with IP. This consists of querying IP for
  51. its "Add Interface" and "Delete Interface" entry points.
  52. Arguments:
  53. None. It is assumed that the caller has a lock to the ATMARP Global
  54. Info structure.
  55. Return Value:
  56. NDIS_STATUS_SUCCESS if initialization was successful
  57. NDIS_STATUS_XXX error code otherwise.
  58. --*/
  59. {
  60. NDIS_STATUS Status;
  61. #if !LINK_WITH_IP
  62. IP_GET_PNP_ARP_POINTERS IPInfo;
  63. UNICODE_STRING IPDeviceName;
  64. PIRP pIrp;
  65. PFILE_OBJECT pIpFileObject;
  66. PDEVICE_OBJECT pIpDeviceObject;
  67. IO_STATUS_BLOCK ioStatusBlock;
  68. //
  69. // Initialize.
  70. //
  71. pIrp = (PIRP)NULL;
  72. pIpFileObject = (PFILE_OBJECT)NULL;
  73. pIpDeviceObject = (PDEVICE_OBJECT)NULL;
  74. do
  75. {
  76. NdisInitUnicodeString(&IPDeviceName, DD_IP_DEVICE_NAME);
  77. //
  78. // Get the file and device objects for the IP device.
  79. //
  80. Status = IoGetDeviceObjectPointer(
  81. &IPDeviceName,
  82. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  83. &pIpFileObject,
  84. &pIpDeviceObject);
  85. if ((Status != STATUS_SUCCESS) || (pIpDeviceObject == NULL))
  86. {
  87. Status = NDIS_STATUS_FAILURE;
  88. break;
  89. }
  90. //
  91. // Reference the device object.
  92. //
  93. ObReferenceObject(pIpDeviceObject);
  94. pIrp = IoBuildDeviceIoControlRequest(IOCTL_IP_GET_PNP_ARP_POINTERS,
  95. pIpDeviceObject,
  96. NULL,
  97. 0,
  98. &IPInfo,
  99. sizeof (IPInfo),
  100. FALSE,
  101. NULL,
  102. &ioStatusBlock);
  103. if (pIrp == NULL)
  104. {
  105. Status = NDIS_STATUS_RESOURCES;
  106. break;
  107. }
  108. Status = IoCallDriver(pIpDeviceObject, pIrp);
  109. if (Status != STATUS_SUCCESS)
  110. {
  111. Status = NDIS_STATUS_FAILURE;
  112. break;
  113. }
  114. pAtmArpGlobalInfo->pIPAddInterfaceRtn = IPInfo.IPAddInterface;
  115. pAtmArpGlobalInfo->pIPDelInterfaceRtn = IPInfo.IPDelInterface;
  116. Status = NDIS_STATUS_SUCCESS;
  117. }
  118. while (FALSE);
  119. if (pIpFileObject != (PFILE_OBJECT)NULL)
  120. {
  121. //
  122. // Dereference the file object
  123. //
  124. ObDereferenceObject((PVOID)pIpFileObject);
  125. }
  126. if (pIpDeviceObject != (PDEVICE_OBJECT)NULL)
  127. {
  128. //
  129. // Close the device.
  130. //
  131. ObDereferenceObject((PVOID)pIpDeviceObject);
  132. }
  133. #else
  134. pAtmArpGlobalInfo->pIPAddInterfaceRtn = IPAddInterface;
  135. pAtmArpGlobalInfo->pIPDelInterfaceRtn = (IPDelInterfacePtr)IPDelInterface;
  136. Status = NDIS_STATUS_SUCCESS;
  137. #endif // !LINK_WITH_IP
  138. AADEBUGP(AAD_INFO, ("Init IP Interface: returning Status 0x%x\n", Status));
  139. return (Status);
  140. }
  141. INT
  142. AtmArpIfDynRegister(
  143. IN PNDIS_STRING pAdapterString,
  144. IN PVOID IPContext,
  145. IN IPRcvRtn IPRcvHandler,
  146. IN IPTxCmpltRtn IPTxCmpltHandler,
  147. IN IPStatusRtn IPStatusHandler,
  148. IN IPTDCmpltRtn IPTDCmpltHandler,
  149. IN IPRcvCmpltRtn IPRcvCmpltHandler,
  150. IN struct LLIPBindInfo *pBindInfo,
  151. IN UINT NumIFBound
  152. )
  153. /*++
  154. Routine Description:
  155. This routine is called from the IP layer when it wants to tell us,
  156. the ARP module, about its handlers for an Interface.
  157. Arguments:
  158. pAdapterString - Name of the logical adapter for this interface
  159. IPContext - IP's context for this interface
  160. IPRcvHandler - Up-call for receives
  161. IPTxCmpltHandler - Up-call for transmit completes
  162. IPStatusHandler - Up-call to indicate status changes
  163. IPTDCmpltHandler - Up-call to indicate completion of Transfer-Data
  164. IPRcvCmpltHandler - Up-call to indicate temporary completion of receives
  165. pBindInfo - Pointer to bind info with our information
  166. NumIFBound - Count for this interface
  167. Return Value:
  168. (UINT)TRUE always.
  169. --*/
  170. {
  171. PATMARP_INTERFACE pInterface;
  172. pInterface = (PATMARP_INTERFACE)(pBindInfo->lip_context);
  173. AA_STRUCT_ASSERT(pInterface, aai);
  174. AADEBUGP(AAD_INFO, ("IfDynRegister: pIf 0x%x\n", pInterface));
  175. pInterface->IPContext = IPContext;
  176. pInterface->IPRcvHandler = IPRcvHandler;
  177. pInterface->IPTxCmpltHandler = IPTxCmpltHandler;
  178. pInterface->IPStatusHandler = IPStatusHandler;
  179. pInterface->IPTDCmpltHandler = IPTDCmpltHandler;
  180. pInterface->IPRcvCmpltHandler = IPRcvCmpltHandler;
  181. pInterface->IFIndex = NumIFBound;
  182. return ((UINT)TRUE);
  183. }
  184. #else
  185. // NEWARP
  186. INT
  187. AtmArpIfDynRegister(
  188. IN PNDIS_STRING pAdapterString,
  189. IN PVOID IPContext,
  190. IN struct _IP_HANDLERS * pIpHandlers,
  191. IN struct LLIPBindInfo * pBindInfo,
  192. IN UINT InterfaceNumber
  193. )
  194. /*++
  195. Routine Description:
  196. This routine is called from the IP layer when it wants to tell us,
  197. the ARP module, about its handlers for an Interface.
  198. Arguments:
  199. pAdapterString - Name of the logical adapter for this interface
  200. IPContext - IP's context for this interface
  201. pIpHandlers - Points to struct containing the following handlers:
  202. IPRcvHandler - Up-call for receives
  203. IPTxCmpltHandler - Up-call for transmit completes
  204. IPStatusHandler - Up-call to indicate status changes
  205. IPTDCmpltHandler - Up-call to indicate completion of Transfer-Data
  206. IPRcvCmpltHandler - Up-call to indicate temporary completion of receives
  207. pBindInfo - Pointer to bind info with our information
  208. InterfaceNumber - ID for this interface
  209. Return Value:
  210. (UINT)TRUE always.
  211. --*/
  212. {
  213. PATMARP_INTERFACE pInterface;
  214. pInterface = (PATMARP_INTERFACE)(pBindInfo->lip_context);
  215. AA_STRUCT_ASSERT(pInterface, aai);
  216. AADEBUGP(AAD_INFO, ("IfDynRegister: pIf 0x%x\n", pInterface));
  217. pInterface->IPContext = IPContext;
  218. pInterface->IPRcvHandler = pIpHandlers->IpRcvHandler;
  219. pInterface->IPTxCmpltHandler = pIpHandlers->IpTxCompleteHandler;
  220. pInterface->IPStatusHandler = pIpHandlers->IpStatusHandler;
  221. pInterface->IPTDCmpltHandler = pIpHandlers->IpTransferCompleteHandler;
  222. pInterface->IPRcvCmpltHandler = pIpHandlers->IpRcvCompleteHandler;
  223. #ifdef _PNP_POWER_
  224. pInterface->IPPnPEventHandler = pIpHandlers->IpPnPHandler;
  225. pInterface->IPRcvPktHandler = pIpHandlers->IpRcvPktHandler;
  226. #endif // _PNP_POWER_
  227. pInterface->IFIndex = InterfaceNumber;
  228. return ((UINT)TRUE);
  229. }
  230. #endif // !NEWARP
  231. VOID
  232. AtmArpIfOpen(
  233. IN PVOID Context
  234. )
  235. /*++
  236. Routine Description:
  237. This routine is called when IP is ready to use this interface.
  238. This is equivalent to setting AdminState to UP.
  239. We register our SAP with the Call Manager, thus allowing incoming
  240. calls to reach us. If atleast one local IP address has been set,
  241. and the ATM interface is ip, we start registering ourselves with
  242. the server.
  243. Arguments:
  244. Context - Actually a pointer to our ATMARP Interface structure
  245. Return Value:
  246. None
  247. --*/
  248. {
  249. PATMARP_INTERFACE pInterface;
  250. NDIS_HANDLE ProtocolSapContext;
  251. PNDIS_HANDLE pNdisSapHandle;
  252. PCO_SAP pSap;
  253. BOOLEAN AtmInterfaceDown;
  254. #if DBG
  255. AA_IRQL EntryIrq, ExitIrq;
  256. #endif
  257. AA_GET_ENTRY_IRQL(EntryIrq);
  258. pInterface = (PATMARP_INTERFACE)Context;
  259. AA_STRUCT_ASSERT(pInterface, aai);
  260. AADEBUGP(AAD_INFO, ("IfOpen: pIf 0x%x\n", pInterface));
  261. AA_ACQUIRE_IF_LOCK(pInterface);
  262. AA_ASSERT(pInterface->NdisAfHandle != NULL);
  263. pInterface->AdminState = IF_STATUS_UP;
  264. AA_INIT_BLOCK_STRUCT(&(pInterface->Block));
  265. AtmInterfaceDown = !(pInterface->AtmInterfaceUp);
  266. AA_RELEASE_IF_LOCK(pInterface);
  267. //
  268. // Get the local ATM address if we haven't got it yet.
  269. //
  270. if (AtmInterfaceDown)
  271. {
  272. AtmArpGetAtmAddress(pInterface);
  273. }
  274. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  275. //
  276. // Register our SAP(s) with the Call Manager.
  277. //
  278. AtmArpRegisterSaps(pInterface);
  279. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  280. #ifdef ATMARP_WMI
  281. //
  282. // Make this interface a WMI provider.
  283. //
  284. AtmArpWmiInitInterface(pInterface, AtmArpGuidList, AtmArpGuidCount);
  285. #endif // ATMARP_WMI
  286. AA_ACQUIRE_IF_LOCK(pInterface);
  287. #ifdef IPMCAST
  288. //
  289. // Start multicast registration with MARS.
  290. //
  291. AtmArpMcStartRegistration(pInterface);
  292. //
  293. // IF lock is released within the above.
  294. //
  295. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  296. AA_ACQUIRE_IF_LOCK(pInterface);
  297. #endif // IPMCAST
  298. //
  299. // All necessary pre-conditions are checked within
  300. // AtmArpStartRegistration.
  301. //
  302. AtmArpStartRegistration(pInterface);
  303. //
  304. // IF lock is released within the above.
  305. //
  306. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  307. return;
  308. }
  309. VOID
  310. AtmArpIfClose(
  311. IN PVOID Context
  312. )
  313. /*++
  314. Routine Description:
  315. IP wants to stop using this Interface. We assume that this is called
  316. in response to our Up-call to IP's DelInterface entry point.
  317. We simply dereference the interface, unless we are actually in the process
  318. of bringing it down and up due to a reconfigure notification.
  319. Arguments:
  320. Context - Actually a pointer to our ATMARP Interface structure
  321. Return Value:
  322. None
  323. --*/
  324. {
  325. PATMARP_INTERFACE pInterface;
  326. ULONG rc; // Ref Count
  327. #if DBG
  328. AA_IRQL EntryIrq, ExitIrq;
  329. #endif
  330. BOOLEAN fQueueRestart = FALSE;
  331. PNDIS_WORK_ITEM pWorkItem;
  332. NDIS_STATUS NdisStatus;
  333. AA_GET_ENTRY_IRQL(EntryIrq);
  334. pInterface = (PATMARP_INTERFACE)Context;
  335. AA_STRUCT_ASSERT(pInterface, aai);
  336. AA_ACQUIRE_IF_LOCK(pInterface);
  337. //
  338. // Ensure that we won't send up an IPDelInterface on this
  339. // interface.
  340. //
  341. pInterface->IPContext = NULL;
  342. if (pInterface->ReconfigState==RECONFIG_SHUTDOWN_PENDING)
  343. {
  344. AA_ALLOC_MEM(pWorkItem, NDIS_WORK_ITEM, sizeof(NDIS_WORK_ITEM));
  345. if (pWorkItem == NULL)
  346. {
  347. AA_ASSERT(FALSE);
  348. }
  349. else
  350. {
  351. pInterface->ReconfigState=RECONFIG_RESTART_QUEUED;
  352. fQueueRestart = TRUE;
  353. }
  354. }
  355. else
  356. {
  357. AA_ASSERT(pInterface->ReconfigState==RECONFIG_NOT_IN_PROGRESS);
  358. }
  359. AA_RELEASE_IF_LOCK(pInterface);
  360. #ifdef ATMARP_WMI
  361. //
  362. // Deregister this Interface as a WMI provider.
  363. // We do this even when bringing down the interface for a reconfig
  364. // because certain IP information could potentially become stale.
  365. //
  366. AtmArpWmiShutdownInterface(pInterface);
  367. #endif // ATMARP_WMI
  368. if (fQueueRestart)
  369. {
  370. //
  371. // We have a request to reconfigure this interface. So we will
  372. // keep this structure allocated and queue
  373. // a work item to bring this interface back up -- reading the latest
  374. // configuration paramters from the registry.
  375. //
  376. //
  377. // We do not strictly need to reference the interface here because we
  378. // expect the interface to be still around. Nevertheless
  379. // we reference it here and dereference it when the work item fires.
  380. //
  381. AtmArpReferenceInterface(pInterface); // ReStart Work Item
  382. NdisInitializeWorkItem(
  383. pWorkItem,
  384. AtmArpReStartInterface,
  385. (PVOID)pInterface
  386. );
  387. NdisStatus = NdisScheduleWorkItem(pWorkItem);
  388. if (NdisStatus != NDIS_STATUS_SUCCESS)
  389. {
  390. //
  391. // Ouch, fall back to simply deleting the interface.
  392. //
  393. AA_FREE_MEM(pWorkItem);
  394. fQueueRestart = FALSE;
  395. }
  396. }
  397. if (!fQueueRestart)
  398. {
  399. AADEBUGP(AAD_INFO, ("IfClose: will deallocate pIf 0x%x, RefCount %d\n",
  400. pInterface, pInterface->RefCount));
  401. AA_ACQUIRE_IF_LOCK(pInterface);
  402. rc = AtmArpDereferenceInterface(pInterface);
  403. if (rc != 0)
  404. {
  405. AA_RELEASE_IF_LOCK(pInterface);
  406. }
  407. //
  408. // else the Interface is gone.
  409. //
  410. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  411. }
  412. return;
  413. }
  414. UINT
  415. AtmArpIfAddAddress(
  416. IN PVOID Context,
  417. IN UINT AddressType,
  418. IN IP_ADDRESS IPAddress,
  419. IN IP_MASK Mask
  420. #ifndef BUILD_FOR_1381
  421. ,
  422. IN PVOID Context2
  423. #endif // BUILD_FOR_1381
  424. )
  425. /*++
  426. Routine Description:
  427. The IP layer calls this when a new IP address (or block of IP addresses,
  428. as determined by AddressType) needs to be added to an Interface.
  429. We could see any of four address types: Local, Multicast, Broadcast
  430. and Proxy ARP. In the case of Proxy ARP, the address along with the mask
  431. can specify a block of contiguous IP addresses for which this host acts
  432. as a proxy. Currently, we only support the "Local", "Broadcast", and
  433. "Multicast" types.
  434. If we just added the only local address for this interface, and the
  435. ATM interface is up, and AdminState for this interface is UP, we initiate
  436. address registration with the ARP server.
  437. Arguments:
  438. Context - Actually a pointer to the ATMARP Interface structure
  439. AddressType - Type of address(es) being added.
  440. IPAddress - Address to be added.
  441. Mask - For the above.
  442. Context2 - Additional context (for what?)
  443. Return Value:
  444. (UINT)TRUE if successful, (UINT)FALSE otherwise.
  445. --*/
  446. {
  447. PATMARP_INTERFACE pInterface;
  448. PIP_ADDRESS_ENTRY pIpAddressEntry;
  449. UINT ReturnStatus;
  450. BOOLEAN LockAcquired;
  451. ReturnStatus = (UINT)FALSE; // Initialize to Failure
  452. pInterface = (PATMARP_INTERFACE)Context;
  453. AA_STRUCT_ASSERT(pInterface, aai);
  454. AA_ACQUIRE_IF_LOCK(pInterface);
  455. LockAcquired = TRUE;
  456. if (AddressType == LLIP_ADDR_LOCAL)
  457. {
  458. //
  459. // Find a place to put this new address in.
  460. //
  461. if (pInterface->NumOfIPAddresses == 0)
  462. {
  463. pIpAddressEntry = &(pInterface->LocalIPAddress);
  464. }
  465. else
  466. {
  467. AA_ALLOC_MEM(pIpAddressEntry, IP_ADDRESS_ENTRY, sizeof(IP_ADDRESS_ENTRY));
  468. if (pIpAddressEntry != (PIP_ADDRESS_ENTRY)NULL)
  469. {
  470. pIpAddressEntry->pNext = pInterface->LocalIPAddress.pNext;
  471. pInterface->LocalIPAddress.pNext = pIpAddressEntry;
  472. }
  473. }
  474. if (pIpAddressEntry != (PIP_ADDRESS_ENTRY)NULL)
  475. {
  476. ReturnStatus = (UINT)TRUE;
  477. pIpAddressEntry->IPAddress = IPAddress;
  478. pIpAddressEntry->IPMask = Mask;
  479. pIpAddressEntry->IsRegistered = FALSE;
  480. pIpAddressEntry->IsFirstRegistration = TRUE;
  481. pInterface->NumOfIPAddresses++;
  482. if (pInterface->NumOfIPAddresses == 1)
  483. {
  484. AtmArpStartRegistration(pInterface);
  485. //
  486. // IF Lock is released by above routine.
  487. //
  488. LockAcquired = FALSE;
  489. }
  490. else
  491. {
  492. if (AA_IS_FLAG_SET(
  493. pInterface->Flags,
  494. AA_IF_SERVER_STATE_MASK,
  495. AA_IF_SERVER_REGISTERED) &&
  496. (!pInterface->PVCOnly))
  497. {
  498. AA_RELEASE_IF_LOCK(pInterface);
  499. LockAcquired = FALSE;
  500. AtmArpSendARPRequest(
  501. pInterface,
  502. &IPAddress,
  503. &IPAddress
  504. );
  505. }
  506. //
  507. // else either
  508. // (a) registration is in progress; at the end of it,
  509. // we will register all unregistered IP addresses.
  510. // or
  511. // (b) we are in a PVC only environment, no ARP server.
  512. //
  513. }
  514. }
  515. //
  516. // else allocation failure -- fall thru
  517. //
  518. }
  519. #ifdef IPMCAST
  520. else if ((AddressType == LLIP_ADDR_BCAST) || (AddressType == LLIP_ADDR_MCAST))
  521. {
  522. if (AddressType == LLIP_ADDR_BCAST)
  523. {
  524. pInterface->BroadcastAddress = IPAddress;
  525. }
  526. ReturnStatus = AtmArpMcAddAddress(pInterface, IPAddress, Mask);
  527. //
  528. // IF Lock is released within the above.
  529. //
  530. LockAcquired = FALSE;
  531. }
  532. #else
  533. else if (AddressType == LLIP_ADDR_BCAST)
  534. {
  535. pInterface->BroadcastAddress = IPAddress;
  536. ReturnStatus = (UINT)TRUE;
  537. }
  538. #endif // IPMCAST
  539. if (LockAcquired)
  540. {
  541. AA_RELEASE_IF_LOCK(pInterface);
  542. }
  543. #ifdef BUILD_FOR_1381
  544. AADEBUGP(AAD_INFO,
  545. ("IfAddAddress: IF 0x%x, Type %d, Addr %d.%d.%d.%d, Mask 0x%x, Ret %d\n",
  546. pInterface,
  547. AddressType,
  548. ((PUCHAR)(&IPAddress))[0],
  549. ((PUCHAR)(&IPAddress))[1],
  550. ((PUCHAR)(&IPAddress))[2],
  551. ((PUCHAR)(&IPAddress))[3],
  552. Mask, ReturnStatus));
  553. #else
  554. AADEBUGP(AAD_INFO,
  555. ("IfAddAddress: IF 0x%x, Type %d, Addr %d.%d.%d.%d, Mask 0x%x, Ret %d, Ctx2 0x%x\n",
  556. pInterface,
  557. AddressType,
  558. ((PUCHAR)(&IPAddress))[0],
  559. ((PUCHAR)(&IPAddress))[1],
  560. ((PUCHAR)(&IPAddress))[2],
  561. ((PUCHAR)(&IPAddress))[3],
  562. Mask, ReturnStatus, Context2));
  563. #endif // BUILD_FOR_1381
  564. return (ReturnStatus);
  565. }
  566. UINT
  567. AtmArpIfDelAddress(
  568. IN PVOID Context,
  569. IN UINT AddressType,
  570. IN IP_ADDRESS IPAddress,
  571. IN IP_MASK Mask
  572. )
  573. /*++
  574. Routine Description:
  575. This is called from the IP layer when an address added via AtmArpIfAddAddress
  576. is to be deleted.
  577. Currently, only the "Local" Address type is supported.
  578. Assumption: the given address was successfully added earlier.
  579. Arguments:
  580. Context - Actually a pointer to the ATMARP Interface structure
  581. AddressType - Type of address(es) being deleted.
  582. IPAddress - Address to be deleted.
  583. Mask - For the above.
  584. Return Value:
  585. (UINT)TRUE if successful, (UINT)FALSE otherwise.
  586. --*/
  587. {
  588. PATMARP_INTERFACE pInterface;
  589. PIP_ADDRESS_ENTRY pIpAddressEntry;
  590. PIP_ADDRESS_ENTRY pPrevIpAddressEntry;
  591. PIP_ADDRESS_ENTRY pTmpIpAddressEntry;
  592. UINT ReturnValue;
  593. pInterface = (PATMARP_INTERFACE)Context;
  594. AA_STRUCT_ASSERT(pInterface, aai);
  595. if (AddressType == LLIP_ADDR_LOCAL)
  596. {
  597. AA_ACQUIRE_IF_LOCK(pInterface);
  598. //
  599. // Search for the entry to be deleted.
  600. //
  601. pPrevIpAddressEntry = (PIP_ADDRESS_ENTRY)NULL;
  602. pIpAddressEntry = &(pInterface->LocalIPAddress);
  603. while (!IP_ADDR_EQUAL(pIpAddressEntry->IPAddress, IPAddress))
  604. {
  605. pPrevIpAddressEntry = pIpAddressEntry;
  606. pIpAddressEntry = pIpAddressEntry->pNext;
  607. AA_ASSERT(pIpAddressEntry != (PIP_ADDRESS_ENTRY)NULL);
  608. }
  609. //
  610. // If it was the only one in the list, there is nothing
  611. // to be done. Otherwise, update the list.
  612. //
  613. if (pInterface->NumOfIPAddresses > 1)
  614. {
  615. //
  616. // More than one entry existed. Check if we deleted the
  617. // first one.
  618. //
  619. if (pPrevIpAddressEntry == (PIP_ADDRESS_ENTRY)NULL)
  620. {
  621. //
  622. // Copy in the contents of the second entry
  623. // into the head of the list, and delete the
  624. // second entry.
  625. //
  626. AA_ASSERT(pIpAddressEntry == &(pInterface->LocalIPAddress));
  627. AA_ASSERT(pIpAddressEntry->pNext != (PIP_ADDRESS_ENTRY)NULL);
  628. pIpAddressEntry->IPAddress = pIpAddressEntry->pNext->IPAddress;
  629. pIpAddressEntry->IPMask = pIpAddressEntry->pNext->IPMask;
  630. pTmpIpAddressEntry = pIpAddressEntry->pNext;
  631. pIpAddressEntry->pNext = pIpAddressEntry->pNext->pNext;
  632. pIpAddressEntry = pTmpIpAddressEntry;
  633. }
  634. else
  635. {
  636. pPrevIpAddressEntry->pNext = pIpAddressEntry->pNext;
  637. }
  638. AA_FREE_MEM(pIpAddressEntry);
  639. }
  640. pInterface->NumOfIPAddresses--;
  641. AA_RELEASE_IF_LOCK(pInterface);
  642. ReturnValue = (UINT)TRUE;
  643. }
  644. else
  645. #ifdef IPMCAST
  646. {
  647. if ((AddressType == LLIP_ADDR_BCAST) || (AddressType == LLIP_ADDR_MCAST))
  648. {
  649. AA_ACQUIRE_IF_LOCK(pInterface);
  650. ReturnValue = AtmArpMcDelAddress(pInterface, IPAddress, Mask);
  651. }
  652. else
  653. {
  654. ReturnValue = (UINT)FALSE;
  655. }
  656. }
  657. #else
  658. {
  659. ReturnValue = (UINT)FALSE;
  660. }
  661. #endif // IPMCAST
  662. AADEBUGP(AAD_INFO,
  663. ("IfDelAddress: Ctxt 0x%x, Type 0x%x, IPAddr 0x%x, Mask 0x%x, Ret %d\n",
  664. Context, AddressType, IPAddress, Mask, ReturnValue));
  665. return (ReturnValue);
  666. }
  667. #ifdef NEWARP
  668. NDIS_STATUS
  669. AtmArpIfMultiTransmit(
  670. IN PVOID Context,
  671. IN PNDIS_PACKET * pNdisPacketArray,
  672. IN UINT NumberOfPackets,
  673. IN IP_ADDRESS Destination,
  674. IN RouteCacheEntry * pRCE OPTIONAL
  675. #if P2MP
  676. ,
  677. IN void * ArpCtxt
  678. #endif
  679. )
  680. /*++
  681. Routine Description:
  682. This is called from the IP layer when it has a sequence of datagrams,
  683. each in the form of an NDIS buffer chain, to send over an Interface.
  684. Arguments:
  685. Context - Actually a pointer to our Interface structure
  686. pNdisPacketArray - Array of Packets to be sent on this Interface
  687. NumberOfPackets - Length of array
  688. Destination - IP address of next hop for this packet
  689. pRCE - Optional pointer to Route Cache Entry structure.
  690. Return Value:
  691. NDIS_STATUS_PENDING if all packets were queued for transmission.
  692. If one or more packets "failed", we set the packet status to reflect
  693. what happened to each, and return NDIS_STATUS_FAILURE.
  694. --*/
  695. {
  696. NDIS_STATUS Status;
  697. PNDIS_PACKET * ppNdisPacket;
  698. for (ppNdisPacket = pNdisPacketArray;
  699. NumberOfPackets > 0;
  700. NumberOfPackets--, ppNdisPacket++)
  701. {
  702. PNDIS_PACKET pNdisPacket;
  703. pNdisPacket = *ppNdisPacket;
  704. NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_PENDING);
  705. #if DBG
  706. AA_ASSERT(pNdisPacket->Private.Head != NULL);
  707. #endif // DBG
  708. Status = AtmArpIfTransmit(
  709. Context,
  710. *ppNdisPacket,
  711. Destination,
  712. pRCE
  713. #if P2MP
  714. ,NULL
  715. #endif
  716. );
  717. if (Status != NDIS_STATUS_PENDING)
  718. {
  719. NDIS_SET_PACKET_STATUS(*ppNdisPacket, Status);
  720. break;
  721. }
  722. }
  723. return (Status);
  724. }
  725. #endif // NEWARP
  726. NDIS_STATUS
  727. AtmArpIfTransmit(
  728. IN PVOID Context,
  729. IN PNDIS_PACKET pNdisPacket,
  730. IN IP_ADDRESS Destination,
  731. IN RouteCacheEntry * pRCE OPTIONAL
  732. #if P2MP
  733. ,
  734. IN void * ArpCtxt
  735. #endif
  736. )
  737. /*++
  738. Routine Description:
  739. This is called from the IP layer when it has a datagram (in the form of
  740. an NDIS buffer chain) to send over an Interface.
  741. The destination IP address is passed to us in this routine, which may
  742. or may not be the final destination for the packet.
  743. The Route Cache Entry is created by the IP layer, and is used to speed
  744. up our lookups. An RCE, if specified, uniquely identifies atleast the
  745. IP destination for this packet. The RCE contains space for the ARP layer
  746. to keep context information about this destination. When the first packet
  747. goes out to a Destination, our context info in the RCE will be NULL, and
  748. we search the ARP Table for the matching IP Entry. However, we then fill
  749. our context info (pointer to IP Entry) in the RCE, so that subsequent
  750. transmits aren't slowed down by an IP address lookup.
  751. Arguments:
  752. Context - Actually a pointer to our Interface structure
  753. pNdisPacket - Packet to be sent on this Interface
  754. Destination - IP address of next hop for this packet
  755. pRCE - Optional pointer to Route Cache Entry structure.
  756. Return Value:
  757. Status of the transmit: NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, or
  758. a failure.
  759. --*/
  760. {
  761. PATMARP_INTERFACE pInterface;
  762. PATMARP_IP_ENTRY pIpEntry; // IP Entry corresp to Destination
  763. PATMARP_ATM_ENTRY pAtmEntry; // ATM Entry for this destination
  764. PATMARP_RCE_CONTEXT pRCEContext; // Our context in the RCE
  765. PATMARP_FLOW_INFO pFlowInfo; // Flow to which this packet belongs
  766. PATMARP_FILTER_SPEC pFilterSpec; // Filter Spec for this packet
  767. PATMARP_FLOW_SPEC pFlowSpec; // Flow Spec for this packet
  768. PNDIS_BUFFER pHeaderBuffer; // NDIS Buffer for LLC/SNAP header
  769. PUCHAR pHeader; // Pointer to header area
  770. NDIS_STATUS Status; // Return value
  771. BOOLEAN IsBroadcastAddress;
  772. BOOLEAN CreateNewEntry; // Should we create a new IP entry?
  773. #ifdef IPMCAST
  774. BOOLEAN NeedMcRevalidation; // If Multicast, do we revalidate?
  775. #endif // IPMCAST
  776. ULONG rc;
  777. #if DBG
  778. AA_IRQL EntryIrq, ExitIrq;
  779. #endif
  780. AA_GET_ENTRY_IRQL(EntryIrq);
  781. pInterface = (PATMARP_INTERFACE)Context;
  782. AA_STRUCT_ASSERT(pInterface, aai);
  783. AADEBUGP(AAD_EXTRA_LOUD,
  784. ("IfTransmit: pIf 0x%x, Pkt 0x%x, Dst 0x%x, pRCE 0x%x\n",
  785. pInterface, pNdisPacket, Destination, pRCE));
  786. #if DBG
  787. if (AaDataDebugLevel & (AAD_DATA_OUT|AAD_TRACK_BIG_SENDS))
  788. {
  789. ULONG TotalLength;
  790. PNDIS_BUFFER pNdisBuffer;
  791. NdisQueryPacket(
  792. pNdisPacket,
  793. NULL,
  794. NULL,
  795. NULL,
  796. &TotalLength
  797. );
  798. if (AaDataDebugLevel & AAD_DATA_OUT)
  799. {
  800. AADEBUGP(AAD_WARNING, ("%d (", TotalLength));
  801. for (pNdisBuffer = pNdisPacket->Private.Head;
  802. pNdisBuffer != NULL;
  803. pNdisBuffer = pNdisBuffer->Next)
  804. {
  805. INT BufLength;
  806. NdisQueryBuffer(pNdisBuffer, NULL, &BufLength);
  807. AADEBUGP(AAD_WARNING, (" %d", BufLength));
  808. }
  809. AADEBUGP(AAD_WARNING, (") => %d.%d.%d.%d\n",
  810. (ULONG)(((PUCHAR)&Destination)[0]),
  811. (ULONG)(((PUCHAR)&Destination)[1]),
  812. (ULONG)(((PUCHAR)&Destination)[2]),
  813. (ULONG)(((PUCHAR)&Destination)[3])));
  814. }
  815. if ((AaDataDebugLevel & AAD_TRACK_BIG_SENDS) && ((INT)TotalLength > AadBigDataLength))
  816. {
  817. AADEBUGP(AAD_WARNING, ("%d => %d.%d.%d.%d\n",
  818. TotalLength,
  819. (ULONG)(((PUCHAR)&Destination)[0]),
  820. (ULONG)(((PUCHAR)&Destination)[1]),
  821. (ULONG)(((PUCHAR)&Destination)[2]),
  822. (ULONG)(((PUCHAR)&Destination)[3])));
  823. DbgBreakPoint();
  824. }
  825. }
  826. #endif // DBG
  827. #ifdef PERF
  828. AadLogSendStart(pNdisPacket, (ULONG)Destination, (PVOID)pRCE);
  829. #endif // PERF
  830. #ifdef IPMCAST
  831. NeedMcRevalidation = FALSE;
  832. #endif // IPMCAST
  833. do
  834. {
  835. //
  836. // Discard this packet if the AdminStatus for this interface
  837. // is not UP.
  838. //
  839. if (pInterface->AdminState != IF_STATUS_UP)
  840. {
  841. Status = NDIS_STATUS_INTERFACE_DOWN;
  842. break;
  843. }
  844. //
  845. // Get the filter and flow specs for this packet.
  846. //
  847. AA_GET_PACKET_SPECS(pInterface, pNdisPacket, &pFlowInfo, &pFlowSpec, &pFilterSpec);
  848. #ifdef GPC_MAYBE
  849. //
  850. // We may not do this stuff because there are things to be done
  851. // (see multicast case below) with the IP entry that would be
  852. // missed out if we do this.
  853. //
  854. pVc = AA_GET_VC_FOR_FLOW(pFlowInfo);
  855. if (pVc != NULL_PATMARP_VC)
  856. {
  857. AA_ACQUIRE_VC_LOCK(pVc);
  858. if ((pVc->FlowHandle == pFlowInfo) &&
  859. AA_IS_FLAG_SET(pVc->Flags,
  860. AA_VC_CALL_STATE_MASK,
  861. AA_VC_CALL_STATE_ACTIVE) &&
  862. !AA_IS_VC_GOING_DOWN(pVc)
  863. )
  864. {
  865. AA_PREPARE_HEADER(pNdisPacket, pInterface, pFlowSpec, &Status);
  866. if (Status == NDIS_STATUS_SUCCESS)
  867. {
  868. AtmArpRefreshTimer(&(pVc->Timer));
  869. AtmArpReferenceVc(pVc); // IfTransmit
  870. pVc->OutstandingSends++; // IfTransmit
  871. NdisVcHandle = pVc->NdisVcHandle;
  872. AA_RELEASE_VC_LOCK(pVc);
  873. NDIS_CO_SEND(
  874. NdisVcHandle,
  875. &pNdisPacket,
  876. 1
  877. );
  878. break;
  879. }
  880. }
  881. AA_RELEASE_VC_LOCK(pVc);
  882. //
  883. // Fall through
  884. //
  885. }
  886. #endif // GPC
  887. //
  888. // Get the IP Entry for this destination: see if we have
  889. // cached information that we can use.
  890. //
  891. if (pRCE != (RouteCacheEntry *)NULL)
  892. {
  893. pRCEContext = (PATMARP_RCE_CONTEXT)(pRCE->rce_context);
  894. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  895. pIpEntry = pRCEContext->pIpEntry;
  896. AADEBUGP(AAD_EXTRA_LOUD,
  897. ("Transmit: Dst 0x%x, RCE 0x%x, RCECntxt 0x%x, IPEntry 0x%x\n",
  898. Destination, pRCE, pRCEContext, pIpEntry));
  899. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  900. {
  901. AA_STRUCT_ASSERT(pIpEntry, aip);
  902. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  903. AA_ACQUIRE_IE_LOCK(pIpEntry);
  904. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  905. if (IP_ADDR_EQUAL(pIpEntry->IPAddress, Destination))
  906. {
  907. //
  908. // The Route Cache points to the right IP Entry.
  909. // Either send this packet, or queue it, and get out.
  910. //
  911. //
  912. // Check if this IP Address has been resolved to an ATM address,
  913. // and is "clean" (not aged out).
  914. //
  915. if (AA_IS_FLAG_SET(
  916. pIpEntry->Flags,
  917. AA_IP_ENTRY_STATE_MASK,
  918. AA_IP_ENTRY_RESOLVED))
  919. {
  920. ULONG rc;
  921. AA_ASSERT(pIpEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  922. pAtmEntry = pIpEntry->pAtmEntry;
  923. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  924. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: IfTransmit1
  925. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  926. #ifdef IPMCAST
  927. if (AA_IS_FLAG_SET(
  928. pIpEntry->Flags,
  929. AA_IP_ENTRY_MC_VALIDATE_MASK,
  930. AA_IP_ENTRY_MC_REVALIDATE))
  931. {
  932. AA_SET_FLAG(pIpEntry->Flags,
  933. AA_IP_ENTRY_MC_VALIDATE_MASK,
  934. AA_IP_ENTRY_MC_REVALIDATING);
  935. NeedMcRevalidation = TRUE;
  936. }
  937. #endif // IPMCAST
  938. IsBroadcastAddress = AA_IS_FLAG_SET(pIpEntry->Flags,
  939. AA_IP_ENTRY_ADDR_TYPE_MASK,
  940. AA_IP_ENTRY_ADDR_TYPE_NUCAST);
  941. AA_RELEASE_IE_LOCK(pIpEntry);
  942. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  943. Status = AtmArpSendPacketOnAtmEntry(
  944. pInterface,
  945. pAtmEntry,
  946. pNdisPacket,
  947. pFlowSpec,
  948. pFilterSpec,
  949. pFlowInfo,
  950. IsBroadcastAddress
  951. );
  952. //
  953. // The ATM Entry lock is released within the above.
  954. // Get rid of the temp ref:
  955. //
  956. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  957. rc = AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: IfTransmit1
  958. if (rc != 0)
  959. {
  960. AA_RELEASE_AE_LOCK(pAtmEntry);
  961. }
  962. break; // goto end of processing
  963. }
  964. else
  965. {
  966. //
  967. // We don't have the ATM address yet, but we have an
  968. // IP Entry for the Destination IP address. Queue this
  969. // packet on the IP Entry, and start Address resolution
  970. // if not already started.
  971. //
  972. // But first, a check to avoid starting address resolution
  973. // in a PVC-only environment.
  974. //
  975. if (pInterface->PVCOnly && (pIpEntry->pAtmEntry == NULL))
  976. {
  977. //
  978. // This can happen if we had an active PVC and
  979. // had learnt an IP address via InARP, and then
  980. // the user had deleted the PVC. We would then be
  981. // left with an IP entry, but no matching ATM entry.
  982. // Abort this entry now.
  983. //
  984. AADEBUGP(AAD_FATAL,
  985. ("IfTransmit (PVC 1): IPEntry %x, Ref %d, Flags %x has NULL ATM Entry\n",
  986. pIpEntry, pIpEntry->RefCount, pIpEntry->Flags));
  987. AtmArpAbortIPEntry(pIpEntry);
  988. //
  989. // IP Entry lock is released above.
  990. //
  991. Status = NDIS_STATUS_SUCCESS;
  992. break;
  993. }
  994. Status = AtmArpQueuePacketOnIPEntry(
  995. pIpEntry,
  996. pNdisPacket
  997. );
  998. //
  999. // The IP Entry lock is released within the above.
  1000. //
  1001. break; // goto end of processing
  1002. }
  1003. // NOTREACHED
  1004. }
  1005. else
  1006. {
  1007. //
  1008. // The cache entry points to the wrong IP Entry. Invalidate
  1009. // the cache entry, and continue to the hard road.
  1010. //
  1011. AADEBUGP(AAD_INFO,
  1012. ("IfTransmit: RCE (0x%x) points to wrong IP Entry (0x%x: %d.%d.%d.%d)\n",
  1013. pRCE,
  1014. pIpEntry,
  1015. ((PUCHAR)(&(pIpEntry->IPAddress)))[0],
  1016. ((PUCHAR)(&(pIpEntry->IPAddress)))[1],
  1017. ((PUCHAR)(&(pIpEntry->IPAddress)))[2],
  1018. ((PUCHAR)(&(pIpEntry->IPAddress)))[3]
  1019. ));
  1020. AADEBUGP(AAD_INFO,
  1021. ("RCE/IP Entry mismatch: Destn IP: %d.%d.%d.%d\n",
  1022. ((PUCHAR)&Destination)[0],
  1023. ((PUCHAR)&Destination)[1],
  1024. ((PUCHAR)&Destination)[2],
  1025. ((PUCHAR)&Destination)[3]
  1026. ));
  1027. if (AtmArpUnlinkRCE(pRCE, pIpEntry))
  1028. {
  1029. ULONG rc; // Ref Count for IP Entry
  1030. //
  1031. // The IP Entry did have this RCE in its list.
  1032. //
  1033. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_RCE); // RCE ref
  1034. if (rc > 0)
  1035. {
  1036. AA_RELEASE_IE_LOCK(pIpEntry);
  1037. }
  1038. // else the IP Entry is gone
  1039. }
  1040. else
  1041. {
  1042. //
  1043. // The IP Entry does not have this RCE in its list.
  1044. //
  1045. AA_RELEASE_IE_LOCK(pIpEntry);
  1046. }
  1047. //
  1048. // Continue processing below.
  1049. //
  1050. } // else -- if (RCE points to the right IP Entry)
  1051. } // if (RCE points to non-NULL IP Entry)
  1052. else
  1053. {
  1054. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1055. //
  1056. // Continue processing below
  1057. //
  1058. }
  1059. }
  1060. AA_ACQUIRE_IF_LOCK(pInterface);
  1061. IsBroadcastAddress = AtmArpIsBroadcastIPAddress(Destination, pInterface);
  1062. AA_RELEASE_IF_LOCK(pInterface);
  1063. #if DHCP_OVER_ATM
  1064. //
  1065. // Handle Broadcast packets separately.
  1066. //
  1067. if (IsBroadcastAddress)
  1068. {
  1069. Status = AtmArpSendBroadcast(
  1070. pInterface,
  1071. pNdisPacket,
  1072. pFlowSpec,
  1073. pFilterSpec
  1074. );
  1075. break;
  1076. }
  1077. #endif // DHCP_OVER_ATM
  1078. #ifdef IPMCAST
  1079. if (IsBroadcastAddress)
  1080. {
  1081. AAMCDEBUGP(AAD_EXTRA_LOUD,
  1082. ("IfTransmit: pIf 0x%x, to Broadcast addr: %d.%d.%d.%d\n",
  1083. pInterface,
  1084. ((PUCHAR)&Destination)[0],
  1085. ((PUCHAR)&Destination)[1],
  1086. ((PUCHAR)&Destination)[2],
  1087. ((PUCHAR)&Destination)[3]));
  1088. if (pInterface->MARSList.ListSize == 0)
  1089. {
  1090. //
  1091. // Drop this packet.
  1092. //
  1093. Status = NDIS_STATUS_FAILURE;
  1094. break;
  1095. }
  1096. //
  1097. // Make sure that we send all IP *broadcast* packets to
  1098. // the All 1's group.
  1099. //
  1100. #ifdef MERGE_BROADCASTS
  1101. Destination = pInterface->BroadcastAddress;
  1102. #else
  1103. if (!CLASSD_ADDR(Destination))
  1104. {
  1105. Destination = pInterface->BroadcastAddress;
  1106. }
  1107. #endif // MERGE_BROADCASTS
  1108. }
  1109. #endif // IPMCAST
  1110. //
  1111. // No Route Cache Entry: search for the IP Entry the hard way.
  1112. // NOTE: if we are running PVCs only, we won't create a new
  1113. // IP entry here: the only way a new IP Entry is created is
  1114. // when we learn the IP+ATM info of the station at the other
  1115. // end via InARP.
  1116. //
  1117. // Note: AtmArpSearchForIPAddress addrefs pIpEntry.
  1118. //
  1119. CreateNewEntry = (pInterface->PVCOnly? FALSE: TRUE);
  1120. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1121. pIpEntry = AtmArpSearchForIPAddress(
  1122. pInterface,
  1123. &Destination,
  1124. IE_REFTYPE_TMP,
  1125. IsBroadcastAddress,
  1126. CreateNewEntry
  1127. );
  1128. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1129. if (pIpEntry == NULL_PATMARP_IP_ENTRY)
  1130. {
  1131. Status = NDIS_STATUS_RESOURCES;
  1132. break;
  1133. }
  1134. AA_ACQUIRE_IE_LOCK(pIpEntry);
  1135. AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
  1136. if (pInterface->PVCOnly && (pIpEntry->pAtmEntry == NULL))
  1137. {
  1138. //
  1139. // This can happen if we had an active PVC and had learnt an IP address
  1140. // via InARP, and then the user had deleted the PVC. We would then be
  1141. // left with an IP entry, but no matching ATM entry. Abort this entry
  1142. // now.
  1143. //
  1144. AADEBUGP(AAD_FATAL,
  1145. ("IfTransmit (PVC 2): IPEntry %x, Ref %d, Flags %x has NULL ATM Entry\n",
  1146. pIpEntry, pIpEntry->RefCount, pIpEntry->Flags));
  1147. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TMP);
  1148. if (rc != 0)
  1149. {
  1150. AtmArpAbortIPEntry(pIpEntry);
  1151. //
  1152. // IE Lock is released above.
  1153. //
  1154. }
  1155. Status = NDIS_STATUS_SUCCESS;
  1156. break;
  1157. }
  1158. //
  1159. // Keep a pointer to this IP Entry in the Route Cache Entry
  1160. // to speed things up for the next packet.
  1161. //
  1162. if (pRCE != (RouteCacheEntry *)NULL)
  1163. {
  1164. AtmArpLinkRCE(pRCE, pIpEntry);
  1165. }
  1166. //
  1167. // Note: AtmArpSerchForIPAddress addrefd pIpEntry for us -- we don't
  1168. // deref it right now because it could be a new entry! Instead,
  1169. // we deref it once we're done with it..
  1170. //
  1171. //
  1172. // Check if this IP Address has been resolved to an ATM address,
  1173. // and is "clean" (not aged out).
  1174. //
  1175. if (AA_IS_FLAG_SET(
  1176. pIpEntry->Flags,
  1177. AA_IP_ENTRY_STATE_MASK,
  1178. AA_IP_ENTRY_RESOLVED))
  1179. {
  1180. AA_ASSERT(pIpEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  1181. pAtmEntry = pIpEntry->pAtmEntry;
  1182. AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
  1183. AA_REF_AE(pAtmEntry, AE_REFTYPE_TMP);// Temp ref: IfTransmit
  1184. AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
  1185. #ifdef IPMCAST
  1186. if (AA_IS_FLAG_SET(
  1187. pIpEntry->Flags,
  1188. AA_IP_ENTRY_MC_VALIDATE_MASK,
  1189. AA_IP_ENTRY_MC_REVALIDATE))
  1190. {
  1191. AA_SET_FLAG(pIpEntry->Flags,
  1192. AA_IP_ENTRY_MC_VALIDATE_MASK,
  1193. AA_IP_ENTRY_MC_REVALIDATING);
  1194. NeedMcRevalidation = TRUE;
  1195. }
  1196. #endif // IPMCAST
  1197. {
  1198. //
  1199. // AtmArpSearchForIPAddress addref'd pIpEntry for us, so
  1200. // before heading out of here, we deref it...
  1201. //
  1202. ULONG rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TMP);
  1203. if (rc > 0)
  1204. {
  1205. AA_RELEASE_IE_LOCK(pIpEntry);
  1206. }
  1207. else
  1208. {
  1209. //
  1210. // It's gone ...
  1211. //
  1212. pIpEntry = NULL_PATMARP_IP_ENTRY;
  1213. AA_ASSERT(!NeedMcRevalidation);
  1214. NeedMcRevalidation = FALSE; // just to be safe.
  1215. }
  1216. }
  1217. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1218. Status = AtmArpSendPacketOnAtmEntry(
  1219. pInterface,
  1220. pAtmEntry,
  1221. pNdisPacket,
  1222. pFlowSpec,
  1223. pFilterSpec,
  1224. pFlowInfo,
  1225. IsBroadcastAddress
  1226. );
  1227. //
  1228. // The ATM Entry lock is released within the above. Get rid of the
  1229. // temp ref:
  1230. //
  1231. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  1232. if (AA_DEREF_AE(pAtmEntry, AE_REFTYPE_TMP) != 0) // Temp ref: IfTransmit
  1233. {
  1234. AA_RELEASE_AE_LOCK(pAtmEntry);
  1235. }
  1236. break;
  1237. }
  1238. //
  1239. // We don't have the ATM address yet, but we have an
  1240. // IP Entry for the Destination IP address. Queue this
  1241. // packet on the IP Entry, and start Address resolution
  1242. // if not already started.
  1243. //
  1244. // SearchForIPAddress addrefd pIpEntry for us. We don't simply
  1245. // deref it here because it could be a brand new entry, with
  1246. // refcount == 1. So instead we simply decrement the refcount. Note
  1247. // that we do hold the lock on it at this time.
  1248. //
  1249. AA_ASSERT(pIpEntry->RefCount > 0);
  1250. AA_DEREF_IE_NO_DELETE(pIpEntry, IE_REFTYPE_TMP);
  1251. Status = AtmArpQueuePacketOnIPEntry(
  1252. pIpEntry,
  1253. pNdisPacket
  1254. );
  1255. //
  1256. // The IP Entry lock is released within the above.
  1257. //
  1258. break;
  1259. }
  1260. while (FALSE);
  1261. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  1262. #ifdef IPMCAST
  1263. if (NeedMcRevalidation)
  1264. {
  1265. AAMCDEBUGP(AAD_LOUD,
  1266. ("IfTransmit(MC): Revalidating pIpEntry 0x%x/0x%x, Addr %d.%d.%d.%d\n",
  1267. pIpEntry, pIpEntry->Flags,
  1268. ((PUCHAR)&(pIpEntry->IPAddress))[0],
  1269. ((PUCHAR)&(pIpEntry->IPAddress))[1],
  1270. ((PUCHAR)&(pIpEntry->IPAddress))[2],
  1271. ((PUCHAR)&(pIpEntry->IPAddress))[3]));
  1272. AtmArpMcSendRequest(
  1273. pInterface,
  1274. &Destination
  1275. );
  1276. }
  1277. #endif // IPMCAST
  1278. #ifdef PERF
  1279. if ((Status != NDIS_STATUS_SUCCESS) && (Status != NDIS_STATUS_PENDING))
  1280. {
  1281. AadLogSendAbort(pNdisPacket);
  1282. }
  1283. #endif // PERF
  1284. if (Status != NDIS_STATUS_PENDING)
  1285. {
  1286. Status = NDIS_STATUS_SUCCESS;
  1287. }
  1288. return (Status);
  1289. }
  1290. NDIS_STATUS
  1291. AtmArpIfTransfer(
  1292. IN PVOID Context,
  1293. IN NDIS_HANDLE Context1,
  1294. IN UINT ArpHdrOffset,
  1295. IN UINT ProtoOffset,
  1296. IN UINT BytesWanted,
  1297. IN PNDIS_PACKET pNdisPacket,
  1298. OUT PUINT pTransferCount
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This routine is called from the IP layer in order to copy in the
  1303. contents of a received packet that we indicated up earlier. The
  1304. context we had passed up in the receive indication is given back to
  1305. us, so that we can identify what it was that we passed up.
  1306. We simply call NDIS to do the transfer.
  1307. Arguments:
  1308. Context - Actually a pointer to our Interface structure
  1309. Context1 - Packet context we had passed up (pointer to NDIS packet)
  1310. ArpHdrOffset - Offset we had passed up in the receive indicate
  1311. ProtoOffset - The offset into higher layer protocol data to start copy from
  1312. BytesWanted - The amount of data to be copied
  1313. pNdisPacket - The packet to be copied into
  1314. pTransferCount - Where we return the actual #bytes copied
  1315. Return Value:
  1316. NDIS_STATUS_SUCCESS always.
  1317. --*/
  1318. {
  1319. AADEBUGP(AAD_EXTRA_LOUD,
  1320. ("IfTransfer: Ctx 0x%x, Ctx1 0x%x, HdrOff %d, ProtOff %d, Wanted %d, Pkt 0x%x\n",
  1321. Context,
  1322. Context1,
  1323. ArpHdrOffset,
  1324. ProtoOffset,
  1325. BytesWanted,
  1326. pNdisPacket));
  1327. NdisCopyFromPacketToPacket(
  1328. pNdisPacket,
  1329. 0,
  1330. BytesWanted,
  1331. (PNDIS_PACKET)Context1,
  1332. ArpHdrOffset+ProtoOffset,
  1333. pTransferCount
  1334. );
  1335. return (NDIS_STATUS_SUCCESS);
  1336. }
  1337. VOID
  1338. AtmArpIfInvalidate(
  1339. IN PVOID Context,
  1340. IN RouteCacheEntry * pRCE
  1341. )
  1342. /*++
  1343. Routine Description:
  1344. This routine is called from the IP layer to invalidate a Route Cache
  1345. Entry. If this RCE is associated with one of our IP Entries, unlink
  1346. it from the list of RCE's pointing to that IP entry.
  1347. Arguments:
  1348. Context - Actually a pointer to our Interface structure
  1349. pRCE - Pointer to Route Cache Entry being invalidated.
  1350. Return Value:
  1351. None
  1352. --*/
  1353. {
  1354. PATMARP_INTERFACE pInterface;
  1355. PATMARP_IP_ENTRY pIpEntry;
  1356. PATMARP_RCE_CONTEXT pRCEContext;
  1357. ULONG rc; // Ref Count for IP Entry
  1358. #if DBG
  1359. AA_IRQL EntryIrq, ExitIrq;
  1360. #endif
  1361. AA_GET_ENTRY_IRQL(EntryIrq);
  1362. AA_ASSERT(pRCE != (RouteCacheEntry *)NULL);
  1363. pInterface = (PATMARP_INTERFACE)Context;
  1364. AA_STRUCT_ASSERT(pInterface, aai);
  1365. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1366. pRCEContext = (PATMARP_RCE_CONTEXT)(&(pRCE->rce_context[0]));
  1367. //
  1368. // Get the ATMARP IP Entry associated with this RCE.
  1369. //
  1370. pIpEntry = (PATMARP_IP_ENTRY)pRCEContext->pIpEntry;
  1371. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  1372. {
  1373. AADEBUGP(AAD_LOUD, ("IfInvalidate: pIf 0x%x, pRCE 0x%x, pIpEntry 0x%x\n",
  1374. pInterface, pRCE, pIpEntry));
  1375. AA_ACQUIRE_IE_LOCK_DPC(pIpEntry);
  1376. if (AtmArpUnlinkRCE(pRCE, pIpEntry))
  1377. {
  1378. rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_RCE); // RCE
  1379. if (rc > 0)
  1380. {
  1381. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  1382. }
  1383. //
  1384. // else the IP Entry is gone.
  1385. //
  1386. }
  1387. else
  1388. {
  1389. AA_RELEASE_IE_LOCK_DPC(pIpEntry);
  1390. }
  1391. }
  1392. AA_SET_MEM((PUCHAR)(&(pRCE->rce_context[0])), 0, RCE_CONTEXT_SIZE);
  1393. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1394. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  1395. return;
  1396. }
  1397. BOOLEAN
  1398. AtmArpUnlinkRCE(
  1399. IN RouteCacheEntry * pRCE,
  1400. IN PATMARP_IP_ENTRY pIpEntry
  1401. )
  1402. /*++
  1403. Routine Description:
  1404. Unlink an RCE from the list of RCE's associated with an IP Entry.
  1405. It is assumed that the caller holds locks to the IF Table and
  1406. to the IP Entry.
  1407. Arguments:
  1408. pRCE - RCE to be unlinked.
  1409. pIpEntry - ATMARP IP Entry from which the RCE is to be
  1410. removed.
  1411. Return Value:
  1412. TRUE if the RCE was indeed in the list for the IP Entry, FALSE
  1413. otherwise.
  1414. --*/
  1415. {
  1416. BOOLEAN Found; // Did we find the RCE?
  1417. RouteCacheEntry ** ppRCE; // Used for walking the list of RCEs
  1418. PATMARP_RCE_CONTEXT pRCEContext;
  1419. //
  1420. // Initialize
  1421. //
  1422. Found = FALSE;
  1423. //
  1424. // Go down the list of RCEs attached to this IP Entry, and
  1425. // find this RCE's position. We remember a pointer to the
  1426. // place that keeps the address of this RCE (i.e. ppRCE),
  1427. // so that we can remove this RCE from the list quickly.
  1428. //
  1429. ppRCE = &(pIpEntry->pRCEList);
  1430. while (*ppRCE != pRCE)
  1431. {
  1432. pRCEContext = (PATMARP_RCE_CONTEXT)(&((*ppRCE)->rce_context[0]));
  1433. if (pRCEContext->pNextRCE == (RouteCacheEntry *)NULL)
  1434. {
  1435. //
  1436. // Allow for the RCE to be absent in the list?
  1437. //
  1438. AA_ASSERT(FALSE); // REMOVELATER
  1439. break;
  1440. }
  1441. else
  1442. {
  1443. //
  1444. // Walk down the list.
  1445. //
  1446. ppRCE = &(pRCEContext->pNextRCE);
  1447. }
  1448. }
  1449. if (*ppRCE == pRCE)
  1450. {
  1451. //
  1452. // We found it. Make the predecessor point to the successor.
  1453. //
  1454. pRCEContext = (PATMARP_RCE_CONTEXT)(&(pRCE->rce_context[0]));
  1455. *ppRCE = pRCEContext->pNextRCE;
  1456. pRCEContext->pIpEntry = NULL_PATMARP_IP_ENTRY;
  1457. Found = TRUE;
  1458. }
  1459. return (Found);
  1460. }
  1461. VOID
  1462. AtmArpLinkRCE(
  1463. IN RouteCacheEntry * pRCE,
  1464. IN PATMARP_IP_ENTRY pIpEntry LOCKIN LOCKOUT
  1465. )
  1466. /*++
  1467. Routine Description:
  1468. Link an RCE to an IP Entry's list of RCEs. Check if the RCE is already
  1469. present - if so, ignore this.
  1470. The caller is assumed to hold a lock to the IP Entry.
  1471. Arguments:
  1472. pRCE - RCE to be linked.
  1473. pIpEntry - ATMARP IP Entry to which the RCE is to be
  1474. linked.
  1475. Return Value:
  1476. None
  1477. --*/
  1478. {
  1479. RouteCacheEntry ** ppRCE; // Used for walking the list of RCEs
  1480. PATMARP_RCE_CONTEXT pRCEContext;
  1481. ppRCE = &(pIpEntry->pRCEList);
  1482. //
  1483. // Check if the RCE is already present.
  1484. //
  1485. while (*ppRCE != NULL)
  1486. {
  1487. if (*ppRCE == pRCE)
  1488. {
  1489. //
  1490. // Found it.
  1491. //
  1492. break;
  1493. }
  1494. //
  1495. // Move to the next.
  1496. //
  1497. pRCEContext = (PATMARP_RCE_CONTEXT)(&((*ppRCE)->rce_context[0]));
  1498. ppRCE = &(pRCEContext->pNextRCE);
  1499. }
  1500. if (*ppRCE == NULL)
  1501. {
  1502. //
  1503. // This RCE is not present in the IP Entry's list. Add it.
  1504. //
  1505. pRCEContext = (PATMARP_RCE_CONTEXT)&(pRCE->rce_context[0]);
  1506. pRCEContext->pIpEntry = pIpEntry;
  1507. pRCEContext->pNextRCE = pIpEntry->pRCEList;
  1508. pIpEntry->pRCEList = pRCE;
  1509. AA_REF_IE(pIpEntry, IE_REFTYPE_RCE); // RCE ref
  1510. }
  1511. else
  1512. {
  1513. AADEBUGP(AAD_LOUD, ("AtmArpLinkRCE: RCE 0x%x already linked to IP Entry 0x%x\n",
  1514. pRCE, pIpEntry));
  1515. }
  1516. }
  1517. INT
  1518. AtmArpIfQueryInfo(
  1519. IN PVOID Context,
  1520. IN TDIObjectID * pID,
  1521. IN PNDIS_BUFFER pNdisBuffer,
  1522. IN OUT PUINT pBufferSize,
  1523. IN PVOID QueryContext
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. This is called from the IP layer to query for statistics or other
  1528. information about an interface.
  1529. Arguments:
  1530. Context - Actually a pointer to our ATMARP Interface
  1531. pID - Describes the object being queried
  1532. pNdisBuffer - Space for returning information
  1533. pBufferSize - Pointer to size of above. On return, we fill
  1534. it with the actual bytes copied.
  1535. QueryContext - Context value pertaining to the query.
  1536. Return Value:
  1537. TDI Status code.
  1538. --*/
  1539. {
  1540. PATMARP_INTERFACE pInterface;
  1541. UINT EntityType;
  1542. UINT Instance;
  1543. UINT BufferSize;
  1544. UINT ByteOffset;
  1545. UINT BytesCopied;
  1546. INT ReturnStatus;
  1547. BOOLEAN DataLeft;
  1548. BOOLEAN ContextValid;
  1549. UCHAR InfoBuff[sizeof(IFEntry)]; // Temp space for return value
  1550. #if DBG
  1551. AA_IRQL EntryIrq, ExitIrq;
  1552. ULONG OldDebugLevel;
  1553. #endif
  1554. AA_GET_ENTRY_IRQL(EntryIrq);
  1555. EntityType = pID->toi_entity.tei_entity;
  1556. Instance = pID->toi_entity.tei_instance;
  1557. BufferSize = *pBufferSize;
  1558. pInterface = (PATMARP_INTERFACE)Context;
  1559. AA_STRUCT_ASSERT(pInterface, aai);
  1560. #if DBG
  1561. OldDebugLevel = AaDebugLevel;
  1562. #endif
  1563. AADEBUGP(AAD_LOUD,
  1564. ("IfQueryInfo: pIf 0x%x, pID 0x%x, pBuf 0x%x, Size %d, Ent %d, Inst %d\n",
  1565. pInterface, pID, pNdisBuffer, BufferSize, EntityType, Instance));
  1566. //
  1567. // Initialize
  1568. //
  1569. ByteOffset = 0;
  1570. ReturnStatus = TDI_INVALID_PARAMETER;
  1571. do
  1572. {
  1573. if (pInterface->AdminState == IF_STATUS_DOWN)
  1574. {
  1575. ReturnStatus = TDI_INVALID_REQUEST;
  1576. break;
  1577. }
  1578. //
  1579. // Check the Entity and Instance values.
  1580. //
  1581. if ((EntityType != AT_ENTITY || Instance != pInterface->ATInstance) &&
  1582. (EntityType != IF_ENTITY || Instance != pInterface->IFInstance))
  1583. {
  1584. AADEBUGP(AAD_VERY_LOUD,
  1585. ("Mismatch: Entity %d, AT_ENTITY %d, Inst %d, IF AT Inst %d, IF_ENTITY %d, IF IF Inst %d\n",
  1586. EntityType,
  1587. AT_ENTITY,
  1588. Instance,
  1589. pInterface->ATInstance,
  1590. IF_ENTITY,
  1591. pInterface->IFInstance
  1592. ));
  1593. #if DBG_QRY
  1594. if (!AaIgnoreInstance)
  1595. {
  1596. ReturnStatus = TDI_INVALID_REQUEST;
  1597. break;
  1598. }
  1599. #else
  1600. #ifndef ATMARP_WIN98
  1601. ReturnStatus = TDI_INVALID_REQUEST;
  1602. break;
  1603. #endif // !ATMARP_WIN98
  1604. #endif // DBG_QRY
  1605. }
  1606. AADEBUGP(AAD_LOUD, ("QueryInfo: pID 0x%x, toi_type %d, toi_class %d, toi_id %d\n",
  1607. pID, pID->toi_type, pID->toi_class, pID->toi_id));
  1608. *pBufferSize = 0;
  1609. if (pID->toi_type != INFO_TYPE_PROVIDER)
  1610. {
  1611. AADEBUGP(AAD_VERY_LOUD, ("toi_type %d != PROVIDER (%d)\n",
  1612. pID->toi_type,
  1613. INFO_TYPE_PROVIDER));
  1614. ReturnStatus = TDI_INVALID_PARAMETER;
  1615. break;
  1616. }
  1617. if (pID->toi_class == INFO_CLASS_GENERIC)
  1618. {
  1619. if (pID->toi_id == ENTITY_TYPE_ID)
  1620. {
  1621. if (BufferSize >= sizeof(UINT))
  1622. {
  1623. AADEBUGP(AAD_VERY_LOUD,
  1624. ("INFO GENERIC, ENTITY TYPE, BufferSize %d\n", BufferSize));
  1625. *((PUINT)&(InfoBuff[0])) = ((EntityType == AT_ENTITY) ? AT_ARP: IF_MIB);
  1626. if (AtmArpCopyToNdisBuffer(
  1627. pNdisBuffer,
  1628. InfoBuff,
  1629. sizeof(UINT),
  1630. &ByteOffset) != NULL)
  1631. {
  1632. // *pBufferSize = sizeof(UINT);
  1633. ReturnStatus = TDI_SUCCESS;
  1634. }
  1635. else
  1636. {
  1637. ReturnStatus = TDI_NO_RESOURCES;
  1638. }
  1639. }
  1640. else
  1641. {
  1642. ReturnStatus = TDI_BUFFER_TOO_SMALL;
  1643. }
  1644. }
  1645. else
  1646. {
  1647. ReturnStatus = TDI_INVALID_PARAMETER;
  1648. }
  1649. break;
  1650. }
  1651. if (EntityType == AT_ENTITY)
  1652. {
  1653. //
  1654. // This query is for an Address Translation Object.
  1655. //
  1656. if (pID->toi_id == AT_MIB_ADDRXLAT_INFO_ID)
  1657. {
  1658. //
  1659. // Request for the number of entries in the address translation
  1660. // table, and the IF index.
  1661. //
  1662. AddrXlatInfo *pAXI;
  1663. AADEBUGP(AAD_VERY_LOUD, ("QueryInfo: AT Entity, for IF index, ATE size\n"));
  1664. if (BufferSize >= sizeof(AddrXlatInfo))
  1665. {
  1666. *pBufferSize = sizeof(AddrXlatInfo);
  1667. pAXI = (AddrXlatInfo *)InfoBuff;
  1668. pAXI->axi_count = pInterface->NumOfArpEntries;
  1669. pAXI->axi_index = pInterface->IFIndex;
  1670. if (AtmArpCopyToNdisBuffer(
  1671. pNdisBuffer,
  1672. InfoBuff,
  1673. sizeof(AddrXlatInfo),
  1674. &ByteOffset) != NULL)
  1675. {
  1676. ReturnStatus = TDI_SUCCESS;
  1677. }
  1678. else
  1679. {
  1680. ReturnStatus = TDI_NO_RESOURCES;
  1681. }
  1682. }
  1683. else
  1684. {
  1685. ReturnStatus = TDI_BUFFER_TOO_SMALL;
  1686. }
  1687. break;
  1688. }
  1689. if (pID->toi_id == AT_MIB_ADDRXLAT_ENTRY_ID)
  1690. {
  1691. //
  1692. // Request for reading the address translation table.
  1693. //
  1694. AADEBUGP(AAD_VERY_LOUD, ("QueryInfo: AT Entity, for reading ATE\n"));
  1695. AA_ACQUIRE_IF_TABLE_LOCK(pInterface);
  1696. DataLeft = AtmArpValidateTableContext(
  1697. QueryContext,
  1698. pInterface,
  1699. &ContextValid
  1700. );
  1701. if (!ContextValid)
  1702. {
  1703. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1704. ReturnStatus = TDI_INVALID_PARAMETER;
  1705. break;
  1706. }
  1707. BytesCopied = 0;
  1708. ReturnStatus = TDI_SUCCESS;
  1709. while (DataLeft)
  1710. {
  1711. if ((INT)BufferSize - (INT)BytesCopied >=
  1712. sizeof(IPNetToMediaEntry))
  1713. {
  1714. //
  1715. // Space left in output buffer.
  1716. //
  1717. DataLeft = AtmArpReadNextTableEntry(
  1718. QueryContext,
  1719. pInterface,
  1720. InfoBuff
  1721. );
  1722. BytesCopied += sizeof(IPNetToMediaEntry);
  1723. pNdisBuffer = AtmArpCopyToNdisBuffer(
  1724. pNdisBuffer,
  1725. InfoBuff,
  1726. sizeof(IPNetToMediaEntry),
  1727. &ByteOffset
  1728. );
  1729. if (pNdisBuffer == NULL)
  1730. {
  1731. BytesCopied = 0;
  1732. ReturnStatus = TDI_NO_RESOURCES;
  1733. break;
  1734. }
  1735. }
  1736. else
  1737. {
  1738. break;
  1739. }
  1740. }
  1741. AA_RELEASE_IF_TABLE_LOCK(pInterface);
  1742. *pBufferSize = BytesCopied;
  1743. if (ReturnStatus == TDI_SUCCESS)
  1744. {
  1745. ReturnStatus = (!DataLeft? TDI_SUCCESS : TDI_BUFFER_OVERFLOW);
  1746. }
  1747. break;
  1748. }
  1749. ReturnStatus = TDI_INVALID_PARAMETER;
  1750. break;
  1751. }
  1752. if (pID->toi_class != INFO_CLASS_PROTOCOL)
  1753. {
  1754. ReturnStatus = TDI_INVALID_PARAMETER;
  1755. break;
  1756. }
  1757. if (pID->toi_id == IF_MIB_STATS_ID)
  1758. {
  1759. //
  1760. // Request for Interface level statistics.
  1761. //
  1762. IFEntry *pIFEntry = (IFEntry *)InfoBuff;
  1763. AADEBUGP(AAD_VERY_LOUD, ("QueryInfo: MIB statistics\n"));
  1764. //
  1765. // Check if we have enough space.
  1766. //
  1767. if (BufferSize < IFE_FIXED_SIZE)
  1768. {
  1769. ReturnStatus = TDI_BUFFER_TOO_SMALL;
  1770. break;
  1771. }
  1772. pIFEntry->if_index = pInterface->IFIndex;
  1773. pIFEntry->if_mtu = pInterface->MTU;
  1774. pIFEntry->if_type = IF_TYPE_OTHER;
  1775. pIFEntry->if_speed = pInterface->Speed;
  1776. pIFEntry->if_adminstatus = pInterface->AdminState;
  1777. if (pInterface->State == IF_STATUS_UP)
  1778. {
  1779. pIFEntry->if_operstatus = IF_OPER_STATUS_OPERATIONAL;
  1780. }
  1781. else
  1782. {
  1783. pIFEntry->if_operstatus = IF_OPER_STATUS_NON_OPERATIONAL;
  1784. }
  1785. pIFEntry->if_lastchange = pInterface->LastChangeTime;
  1786. pIFEntry->if_inoctets = pInterface->InOctets;
  1787. pIFEntry->if_inucastpkts = pInterface->InUnicastPkts;
  1788. pIFEntry->if_innucastpkts = pInterface->InNonUnicastPkts;
  1789. pIFEntry->if_indiscards = pInterface->InDiscards;
  1790. pIFEntry->if_inerrors = pInterface->InErrors;
  1791. pIFEntry->if_inunknownprotos = pInterface->UnknownProtos;
  1792. pIFEntry->if_outoctets = pInterface->OutOctets;
  1793. pIFEntry->if_outucastpkts = pInterface->OutUnicastPkts;
  1794. pIFEntry->if_outnucastpkts = pInterface->OutNonUnicastPkts;
  1795. pIFEntry->if_outdiscards = pInterface->OutDiscards;
  1796. pIFEntry->if_outerrors = pInterface->OutErrors;
  1797. pIFEntry->if_outqlen = 0;
  1798. pIFEntry->if_descrlen = pInterface->pAdapter->DescrLength;
  1799. #ifndef ATMARP_WIN98
  1800. pIFEntry->if_physaddrlen = AA_ATM_PHYSADDR_LEN;
  1801. AA_COPY_MEM(
  1802. pIFEntry->if_physaddr,
  1803. &(pInterface->pAdapter->MacAddress[0]),
  1804. AA_ATM_ESI_LEN
  1805. );
  1806. pIFEntry->if_physaddr[AA_ATM_PHYSADDR_LEN-1] = (UCHAR)pInterface->SapSelector;
  1807. #else
  1808. //
  1809. // Win98: winipcfg doesn't like 7 byte long physical address.
  1810. //
  1811. pIFEntry->if_physaddrlen = AA_ATM_ESI_LEN;
  1812. AA_COPY_MEM(
  1813. pIFEntry->if_physaddr,
  1814. &(pInterface->pAdapter->MacAddress[0]),
  1815. AA_ATM_ESI_LEN
  1816. );
  1817. //
  1818. // Since w're only reporting 6 bytes, we need to make the reported
  1819. // MAC address look different from what LANE reports (LANE reports
  1820. // the MAC address). So we simply put the special value 0x0a 0xac
  1821. // (for aac, or "atm arp client") in the 1st USHORTS.
  1822. //
  1823. pIFEntry->if_physaddr[0] = 0x0a;
  1824. pIFEntry->if_physaddr[1] = 0xac;
  1825. #endif
  1826. if (AtmArpCopyToNdisBuffer(
  1827. pNdisBuffer,
  1828. InfoBuff,
  1829. IFE_FIXED_SIZE,
  1830. &ByteOffset) == NULL)
  1831. {
  1832. *pBufferSize = 0;
  1833. ReturnStatus = TDI_NO_RESOURCES;
  1834. break;
  1835. }
  1836. if (BufferSize >= (IFE_FIXED_SIZE + pIFEntry->if_descrlen))
  1837. {
  1838. *pBufferSize = IFE_FIXED_SIZE + pIFEntry->if_descrlen;
  1839. ReturnStatus = TDI_SUCCESS;
  1840. if (pIFEntry->if_descrlen != 0)
  1841. {
  1842. if (AtmArpCopyToNdisBuffer(
  1843. pNdisBuffer,
  1844. pInterface->pAdapter->pDescrString,
  1845. pIFEntry->if_descrlen,
  1846. &ByteOffset) == NULL)
  1847. {
  1848. // Failed to copy descr string
  1849. *pBufferSize = IFE_FIXED_SIZE;
  1850. ReturnStatus = TDI_NO_RESOURCES;
  1851. }
  1852. }
  1853. }
  1854. else
  1855. {
  1856. *pBufferSize = IFE_FIXED_SIZE;
  1857. ReturnStatus = TDI_BUFFER_OVERFLOW;
  1858. }
  1859. break;
  1860. }
  1861. }
  1862. while (FALSE);
  1863. AA_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  1864. AADEBUGP(AAD_LOUD, ("QueryInfo: returning 0x%x (%s), BufferSize %d\n",
  1865. ReturnStatus,
  1866. ((ReturnStatus == TDI_SUCCESS)? "SUCCESS": "FAILURE"),
  1867. *pBufferSize
  1868. ));
  1869. #if DBG
  1870. AaDebugLevel = OldDebugLevel;
  1871. #endif
  1872. return (ReturnStatus);
  1873. }
  1874. INT
  1875. AtmArpIfSetInfo(
  1876. IN PVOID Context,
  1877. IN TDIObjectID * pID,
  1878. IN PVOID pBuffer,
  1879. IN UINT BufferSize
  1880. )
  1881. /*++
  1882. Routine Description:
  1883. This is called from the IP layer to set the value of an object
  1884. for an interface.
  1885. Arguments:
  1886. Context - Actually a pointer to our ATMARP Interface
  1887. pID - Describes the object being set
  1888. pBuffer - Value for the object
  1889. BufferSize - Size of above
  1890. Return Value:
  1891. TDI Status code.
  1892. --*/
  1893. {
  1894. AADEBUGP(AAD_ERROR, ("IfSetInfo: pIf 0x%x, Will return failure!\n",
  1895. Context));
  1896. return (TDI_INVALID_REQUEST); // TBD: support Sets.
  1897. }
  1898. INT
  1899. AtmArpIfGetEList(
  1900. IN PVOID Context,
  1901. IN TDIEntityID * pEntityList,
  1902. IN OUT PUINT pEntityListSize
  1903. )
  1904. /*++
  1905. Routine Description:
  1906. This routine is called when the interface starts up, in order to
  1907. assign all relevant Entity Instance numbers for an interface.
  1908. The ATMARP module belongs to the "AT" and "IF" types. The entity
  1909. list is a list of <Entity type, Instance number> tuples that have
  1910. been filled in by other modules.
  1911. For each of the entity types we support, we find the largest
  1912. instance number in use (by walking thru the Entity list), and
  1913. assign to ourselves the next larger number in each case. Using
  1914. these numbers, we append our tuples to the end of the Entity list,
  1915. if there is enough space.
  1916. NT 5: we may find that our entries are already present, in which
  1917. case we don't create new entries.
  1918. It is assumed that this isn't reentered. If this assumption is
  1919. false, we should acquire our Interface lock in here.
  1920. Arguments:
  1921. Context - Actually a pointer to our ATMARP Interface
  1922. pEntityList - Pointer to TDI Entity list
  1923. pEntityListSize - Pointer to length of above list. We update
  1924. this if we add our entries to the list.
  1925. Return Value:
  1926. TRUE if successful, FALSE otherwise.
  1927. --*/
  1928. {
  1929. PATMARP_INTERFACE pInterface;
  1930. UINT EntityCount; // Total elements in Entity list
  1931. UINT i; // Iteration counter
  1932. UINT MyATInstance; // "AT" Instance number we assign to ourselves
  1933. UINT MyIFInstance; // "IF" Instance number we assign to ourselves
  1934. INT ReturnValue;
  1935. TDIEntityID * pATEntity; // Points to our AT entry
  1936. TDIEntityID * pIFEntity; // Points to our IF entry
  1937. pInterface = (PATMARP_INTERFACE)Context;
  1938. AA_STRUCT_ASSERT(pInterface, aai);
  1939. EntityCount = *pEntityListSize;
  1940. pATEntity = NULL;
  1941. pIFEntity = NULL;
  1942. MyATInstance = MyIFInstance = 0;
  1943. AADEBUGP(AAD_INFO, ("IfGetEList: pIf 0x%x, pList 0x%x, Cnt %d\n",
  1944. pInterface, pEntityList, EntityCount));
  1945. do
  1946. {
  1947. #ifdef OLD_ENTITY_LIST
  1948. //
  1949. // We need space for 2 entries; see if this is available.
  1950. //
  1951. if (EntityCount + 2 > MAX_TDI_ENTITIES)
  1952. {
  1953. ReturnValue = FALSE;
  1954. break;
  1955. }
  1956. //
  1957. // Search for the max used-up instance numbers for the "AT"
  1958. // and "IF" types.
  1959. //
  1960. MyATInstance = MyIFInstance = 0;
  1961. for (i = 0; i < EntityCount; i++, pEntityList++)
  1962. {
  1963. if (pEntityList->tei_entity == AT_ENTITY)
  1964. {
  1965. MyATInstance = MAX(MyATInstance, pEntityList->tei_instance + 1);
  1966. }
  1967. else if (pEntityList->tei_entity == IF_ENTITY)
  1968. {
  1969. MyIFInstance = MAX(MyIFInstance, pEntityList->tei_instance + 1);
  1970. }
  1971. }
  1972. //
  1973. // Save our instance numbers for later use.
  1974. //
  1975. pInterface->ATInstance = MyATInstance;
  1976. pInterface->IFInstance = MyIFInstance;
  1977. //
  1978. // Append our AT and IF entries to the Entity list.
  1979. // Recall that we just traversed the list fully, so we
  1980. // are pointing to the right place to add entries.
  1981. //
  1982. pEntityList->tei_entity = AT_ENTITY;
  1983. pEntityList->tei_instance = MyATInstance;
  1984. pEntityList++;
  1985. pEntityList->tei_entity = IF_ENTITY;
  1986. pEntityList->tei_instance = MyIFInstance;
  1987. //
  1988. // Return the new list size.
  1989. //
  1990. *pEntityListSize += 2;
  1991. ReturnValue = TRUE;
  1992. #else
  1993. //
  1994. // Walk down the list, looking for AT/IF entries matching our
  1995. // instance values. Also remember the largest AT and IF instance
  1996. // values we see, so that we can allocate the next larger values
  1997. // for ourselves, in case we don't have instance values assigned.
  1998. //
  1999. for (i = 0; i < EntityCount; i++, pEntityList++)
  2000. {
  2001. //
  2002. // Skip invalid entries.
  2003. //
  2004. if (pEntityList->tei_instance == INVALID_ENTITY_INSTANCE)
  2005. {
  2006. continue;
  2007. }
  2008. if (pEntityList->tei_entity == AT_ENTITY)
  2009. {
  2010. if (pEntityList->tei_instance == pInterface->ATInstance)
  2011. {
  2012. //
  2013. // This is our AT entry.
  2014. //
  2015. pATEntity = pEntityList;
  2016. }
  2017. else
  2018. {
  2019. MyATInstance = MAX(MyATInstance, pEntityList->tei_instance + 1);
  2020. }
  2021. }
  2022. else if (pEntityList->tei_entity == IF_ENTITY)
  2023. {
  2024. if (pEntityList->tei_instance == pInterface->IFInstance)
  2025. {
  2026. //
  2027. // This is our IF entry.
  2028. //
  2029. pIFEntity = pEntityList;
  2030. }
  2031. else
  2032. {
  2033. MyIFInstance = MAX(MyIFInstance, pEntityList->tei_instance + 1);
  2034. }
  2035. }
  2036. }
  2037. ReturnValue = TRUE;
  2038. //
  2039. // Update or create our Address Translation entry.
  2040. //
  2041. if (pATEntity)
  2042. {
  2043. //
  2044. // We found our entry.
  2045. //
  2046. if (pInterface->AdminState == IF_STATUS_DOWN)
  2047. {
  2048. pATEntity->tei_instance = INVALID_ENTITY_INSTANCE;
  2049. }
  2050. }
  2051. else
  2052. {
  2053. //
  2054. // Grab an entry for ourselves, unless we are shutting down.
  2055. //
  2056. if (pInterface->AdminState == IF_STATUS_DOWN)
  2057. {
  2058. break;
  2059. }
  2060. if (EntityCount >= MAX_TDI_ENTITIES)
  2061. {
  2062. ReturnValue = FALSE;
  2063. break;
  2064. }
  2065. pEntityList->tei_entity = AT_ENTITY;
  2066. pEntityList->tei_instance = MyATInstance;
  2067. pInterface->ATInstance = MyATInstance;
  2068. pEntityList++;
  2069. (*pEntityListSize)++;
  2070. EntityCount++;
  2071. }
  2072. //
  2073. // Update or create or IF entry.
  2074. //
  2075. if (pIFEntity)
  2076. {
  2077. //
  2078. // We found our entry.
  2079. //
  2080. if (pInterface->AdminState == IF_STATUS_DOWN)
  2081. {
  2082. pIFEntity->tei_instance = INVALID_ENTITY_INSTANCE;
  2083. }
  2084. }
  2085. else
  2086. {
  2087. //
  2088. // Grab an entry for ourselves, unless we are shutting down.
  2089. //
  2090. if (pInterface->AdminState == IF_STATUS_DOWN)
  2091. {
  2092. break;
  2093. }
  2094. if (EntityCount >= MAX_TDI_ENTITIES)
  2095. {
  2096. ReturnValue = FALSE;
  2097. break;
  2098. }
  2099. pEntityList->tei_entity = IF_ENTITY;
  2100. pEntityList->tei_instance = MyIFInstance;
  2101. pInterface->IFInstance = MyIFInstance;
  2102. pEntityList++;
  2103. (*pEntityListSize)++;
  2104. EntityCount++;
  2105. }
  2106. #endif // OLD_ENTITY_LIST
  2107. }
  2108. while (FALSE);
  2109. AADEBUGP(AAD_INFO,
  2110. ("IfGetEList: returning %d, MyAT %d, MyIF %d, pList 0x%x, Size %d\n",
  2111. ReturnValue, MyATInstance, MyIFInstance, pEntityList, *pEntityListSize));
  2112. return (ReturnValue);
  2113. }
  2114. #ifdef _PNP_POWER_
  2115. VOID
  2116. AtmArpIfPnPComplete(
  2117. IN PVOID Context,
  2118. IN NDIS_STATUS Status,
  2119. IN PNET_PNP_EVENT pNetPnPEvent
  2120. )
  2121. /*++
  2122. Routine Description:
  2123. This routine is called by IP when it completes a previous call
  2124. we made to its PnP event handler.
  2125. If this is the last Interface on the adapter, we complete the
  2126. NDIS PNP notification that lead to this. Otherwise, we indicate
  2127. this same event to IP on the next Interface on the adapter.
  2128. Arguments:
  2129. Context - Actually a pointer to our ATMARP Interface
  2130. Status - Completion status from IP
  2131. pNetPnPEvent - The PNP event
  2132. Return Value:
  2133. None
  2134. --*/
  2135. {
  2136. PATMARP_INTERFACE pInterface;
  2137. pInterface = (PATMARP_INTERFACE)Context;
  2138. AADEBUGP(AAD_INFO,
  2139. ("IfPnPComplete: IF 0x%x, Status 0x%x, Event 0x%x\n",
  2140. pInterface, Status, pNetPnPEvent));
  2141. if (pInterface != NULL_PATMARP_INTERFACE)
  2142. {
  2143. AA_STRUCT_ASSERT(pInterface, aai);
  2144. if (pInterface->pNextInterface == NULL_PATMARP_INTERFACE)
  2145. {
  2146. NdisCompletePnPEvent(
  2147. Status,
  2148. pInterface->pAdapter->NdisAdapterHandle,
  2149. pNetPnPEvent
  2150. );
  2151. }
  2152. else
  2153. {
  2154. pInterface = pInterface->pNextInterface;
  2155. (*pInterface->IPPnPEventHandler)(
  2156. pInterface->IPContext,
  2157. pNetPnPEvent
  2158. );
  2159. }
  2160. }
  2161. else
  2162. {
  2163. NdisCompletePnPEvent(
  2164. Status,
  2165. NULL,
  2166. pNetPnPEvent
  2167. );
  2168. }
  2169. return;
  2170. }
  2171. #endif // _PNP_POWER_
  2172. #ifdef PROMIS
  2173. EXTERN
  2174. NDIS_STATUS
  2175. AtmArpIfSetNdisRequest(
  2176. IN PVOID Context,
  2177. IN NDIS_OID Oid,
  2178. IN UINT On
  2179. )
  2180. /*++
  2181. Routine Description:
  2182. ARP Ndisrequest handler.
  2183. Called by the upper driver to set the packet filter for the interface.
  2184. Arguments:
  2185. Context - Actually a pointer to our ATMARP Interface
  2186. OID - Object ID to set/unset
  2187. On - Set_if, clear_if or clear_card
  2188. Return Value:
  2189. Status
  2190. --*/
  2191. {
  2192. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2193. PATMARP_INTERFACE pInterface = (PATMARP_INTERFACE)Context;
  2194. AADEBUGP(AAD_INFO,("IfSetNdisRequest: pIF =0x%x; Oid=0x%x; On=%u\n",
  2195. pInterface,
  2196. Oid,
  2197. On
  2198. ));
  2199. do
  2200. {
  2201. //
  2202. // We set IPAddress and mask to span the entire mcast address range...
  2203. //
  2204. IP_ADDRESS IPAddress = IP_CLASSD_MIN;
  2205. IP_MASK Mask = IP_CLASSD_MASK;
  2206. UINT ReturnStatus = TRUE;
  2207. NDIS_OID PrevOidValue;
  2208. if (Oid != NDIS_PACKET_TYPE_ALL_MULTICAST)
  2209. {
  2210. Status = NDIS_STATUS_NOT_SUPPORTED;
  2211. break;
  2212. }
  2213. AA_STRUCT_ASSERT(pInterface, aai);
  2214. AA_ACQUIRE_IF_LOCK(pInterface);
  2215. PrevOidValue = pInterface->EnabledIPFilters & NDIS_PACKET_TYPE_ALL_MULTICAST;
  2216. if (On)
  2217. {
  2218. if (PrevOidValue == 0)
  2219. {
  2220. pInterface->EnabledIPFilters |= NDIS_PACKET_TYPE_ALL_MULTICAST;
  2221. ReturnStatus = AtmArpMcAddAddress(pInterface, IPAddress, Mask);
  2222. //
  2223. // IF lock released above
  2224. //
  2225. }
  2226. else
  2227. {
  2228. AA_RELEASE_IF_LOCK(pInterface);
  2229. }
  2230. }
  2231. else
  2232. {
  2233. if (PrevOidValue != 0)
  2234. {
  2235. pInterface->EnabledIPFilters &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
  2236. ReturnStatus = AtmArpMcDelAddress(pInterface, IPAddress, Mask);
  2237. //
  2238. // IF lock released above
  2239. //
  2240. }
  2241. else
  2242. {
  2243. AA_RELEASE_IF_LOCK(pInterface);
  2244. }
  2245. }
  2246. if (ReturnStatus != TRUE)
  2247. {
  2248. //
  2249. // We've got to restore EnabledIPFilters to it's original value.
  2250. //
  2251. AA_ACQUIRE_IF_LOCK(pInterface);
  2252. pInterface->EnabledIPFilters &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
  2253. pInterface->EnabledIPFilters |= PrevOidValue;
  2254. AA_RELEASE_IF_LOCK(pInterface);
  2255. Status = NDIS_STATUS_FAILURE;
  2256. }
  2257. }
  2258. while (FALSE);
  2259. AADEBUGP(AAD_INFO, ("IfSetNdisRequest(pIF =0x%x) returns 0x%x\n",
  2260. pInterface,
  2261. Status
  2262. ));
  2263. return Status;
  2264. }
  2265. #endif // PROMIS
  2266. PNDIS_BUFFER AtmArpFreeingBuffer = NULL;
  2267. PNDIS_PACKET AtmArpFreeingPacket = NULL;
  2268. AA_HEADER_TYPE AtmArpFreeingHdrType = 0;
  2269. VOID
  2270. AtmArpFreeSendPackets(
  2271. IN PATMARP_INTERFACE pInterface,
  2272. IN PNDIS_PACKET PacketList,
  2273. IN BOOLEAN HdrPresent
  2274. )
  2275. /*++
  2276. Routine Description:
  2277. Free a list of packets that were queued to be sent, but have been
  2278. "aborted". Each packet in this list is one of the following types:
  2279. (a) Belonging to IP (b) Belonging to the ATMARP module. In the case
  2280. of an IP packet, HdrPresent tells us whether or not we had prepended
  2281. an LLC/SNAP header to this packet, and its type: we need this information
  2282. because we need to reclaim such headers.
  2283. Also, in the case of IP packets, we call IP's Transmit Complete up-call,
  2284. to inform IP of a failed transmission.
  2285. Arguments:
  2286. pInterface - Pointer to ATMARP Interface on which these
  2287. packets would have been sent.
  2288. PacketList - Pointer to first packet in a list.
  2289. HdrPresent - Is an LLC/SNAP header present
  2290. Return Value:
  2291. None
  2292. --*/
  2293. {
  2294. PNDIS_PACKET pNdisPacket;
  2295. PNDIS_PACKET pNextPacket;
  2296. PNDIS_BUFFER pNdisBuffer;
  2297. ULONG NumberOfDiscards;
  2298. PacketContext *PC;
  2299. AA_HEADER_TYPE HdrType;
  2300. NumberOfDiscards = 0;
  2301. pNdisPacket = PacketList;
  2302. while (pNdisPacket != (PNDIS_PACKET)NULL)
  2303. {
  2304. NumberOfDiscards++;
  2305. pNextPacket = AA_GET_NEXT_PACKET(pNdisPacket);
  2306. AA_SET_NEXT_PACKET(pNdisPacket, NULL);
  2307. PC = (PacketContext *)pNdisPacket->ProtocolReserved;
  2308. if (PC->pc_common.pc_owner != PACKET_OWNER_LINK)
  2309. {
  2310. //
  2311. // Belongs to IP.
  2312. //
  2313. if (HdrPresent)
  2314. {
  2315. PUCHAR pData;
  2316. UINT Length;
  2317. #ifdef BACK_FILL
  2318. NdisQueryPacket(pNdisPacket, NULL, NULL, &pNdisBuffer, NULL);
  2319. AA_ASSERT(pNdisBuffer != NULL);
  2320. NdisQueryBuffer(pNdisBuffer, &pData, &Length);
  2321. if (pData[5] == LLC_SNAP_OUI2)
  2322. {
  2323. HdrType = AA_HEADER_TYPE_UNICAST;
  2324. }
  2325. else
  2326. {
  2327. HdrType = AA_HEADER_TYPE_NUNICAST;
  2328. }
  2329. //
  2330. // Now check if we had attached a header buffer or not.
  2331. //
  2332. if (AtmArpDoBackFill && AA_BACK_FILL_POSSIBLE(pNdisBuffer))
  2333. {
  2334. ULONG HeaderLength;
  2335. AADEBUGP(AAD_VERY_LOUD,
  2336. ("FreeSendPackets: IF %x, Pkt %x Buf %x has been backfilled\n",
  2337. pInterface, pNdisPacket, pNdisBuffer));
  2338. //
  2339. // We would have back-filled IP's buffer with the LLC/SNAP
  2340. // header. Remove the back-fill.
  2341. //
  2342. HeaderLength = ((HdrType == AA_HEADER_TYPE_UNICAST)?
  2343. sizeof(AtmArpLlcSnapHeader) :
  2344. #ifdef IPMCAST
  2345. sizeof(AtmArpMcType1ShortHeader));
  2346. #else
  2347. 0);
  2348. #endif // IPMCAST
  2349. (PUCHAR)pNdisBuffer->MappedSystemVa += HeaderLength;
  2350. pNdisBuffer->ByteOffset += HeaderLength;
  2351. pNdisBuffer->ByteCount -= HeaderLength;
  2352. }
  2353. else
  2354. {
  2355. //
  2356. // The first buffer would be our header buffer. Remove
  2357. // it from the packet and return to our pool.
  2358. //
  2359. NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuffer);
  2360. AtmArpFreeingBuffer = pNdisBuffer; // to help debugging
  2361. AtmArpFreeingPacket = pNdisPacket; // to help debugging
  2362. AtmArpFreeingHdrType = HdrType;
  2363. AtmArpFreeHeader(pInterface, pNdisBuffer, HdrType);
  2364. }
  2365. #else // BACK_FILL
  2366. //
  2367. // Free the LLC/SNAP header buffer.
  2368. //
  2369. NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuffer);
  2370. AA_ASSERT(pNdisBuffer != NULL);
  2371. NdisQueryBuffer(pNdisBuffer, &pData, &Length);
  2372. if (pData[5] == LLC_SNAP_OUI2)
  2373. {
  2374. HdrType = AA_HEADER_TYPE_UNICAST;
  2375. }
  2376. else
  2377. {
  2378. AA_ASSERT(pData[5] == MC_LLC_SNAP_OUI2);
  2379. HdrType = AA_HEADER_TYPE_NUNICAST;
  2380. }
  2381. AtmArpFreeHeader(pInterface, pNdisBuffer, HdrType);
  2382. #endif // BACK_FILL
  2383. }
  2384. //
  2385. // Inform IP of send completion.
  2386. //
  2387. (*(pInterface->IPTxCmpltHandler))(
  2388. pInterface->IPContext,
  2389. pNdisPacket,
  2390. NDIS_STATUS_FAILURE
  2391. );
  2392. }
  2393. else
  2394. {
  2395. //
  2396. // Belongs to us.
  2397. //
  2398. NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuffer);
  2399. AtmArpFreeProtoBuffer(pInterface, pNdisBuffer);
  2400. AtmArpFreePacket(pInterface, pNdisPacket);
  2401. }
  2402. //
  2403. // Go to next packet in the list.
  2404. //
  2405. pNdisPacket = pNextPacket;
  2406. }
  2407. //
  2408. // Update IF statistics
  2409. //
  2410. AA_IF_STAT_ADD(pInterface, OutDiscards, NumberOfDiscards);
  2411. }
  2412. #define IPNetMask(a) AtmArpIPMaskTable[(*(uchar *)&(a)) >> 4]
  2413. BOOLEAN
  2414. AtmArpIsBroadcastIPAddress(
  2415. IN IP_ADDRESS Addr,
  2416. IN PATMARP_INTERFACE pInterface LOCKIN LOCKOUT
  2417. )
  2418. /*++
  2419. Routine Description:
  2420. Check if the given IP address is a broadcast address for the
  2421. interface.
  2422. Copied from the LAN ARP module.
  2423. Arguments:
  2424. Addr - The IP Address to be checked
  2425. pInterface - Pointer to our Interface structure
  2426. Return Value:
  2427. TRUE if the address is a broadcast address, FALSE otherwise.
  2428. --*/
  2429. {
  2430. IP_ADDRESS BCast;
  2431. IP_MASK Mask;
  2432. PIP_ADDRESS_ENTRY pIpAddressEntry;
  2433. IP_ADDRESS LocalAddr;
  2434. // First get the interface broadcast address.
  2435. BCast = pInterface->BroadcastAddress;
  2436. // First check for global broadcast.
  2437. if (IP_ADDR_EQUAL(BCast, Addr) || CLASSD_ADDR(Addr))
  2438. return TRUE;
  2439. // Now walk the local addresses, and check for net/subnet bcast on each
  2440. // one.
  2441. pIpAddressEntry = &(pInterface->LocalIPAddress);
  2442. do {
  2443. // See if this one is valid.
  2444. LocalAddr = pIpAddressEntry->IPAddress;
  2445. if (!IP_ADDR_EQUAL(LocalAddr, NULL_IP_ADDR)) {
  2446. // He's valid.
  2447. Mask = pIpAddressEntry->IPMask;
  2448. // First check for subnet bcast.
  2449. if (IP_ADDR_EQUAL((LocalAddr & Mask) | (BCast & ~Mask), Addr))
  2450. return TRUE;
  2451. // Now check all nets broadcast.
  2452. Mask = IPNetMask(LocalAddr);
  2453. if (IP_ADDR_EQUAL((LocalAddr & Mask) | (BCast & ~Mask), Addr))
  2454. return TRUE;
  2455. }
  2456. pIpAddressEntry = pIpAddressEntry->pNext;
  2457. } while (pIpAddressEntry != NULL);
  2458. // If we're here, it's not a broadcast.
  2459. return FALSE;
  2460. }
  2461. BOOLEAN
  2462. AtmArpValidateTableContext(
  2463. IN PVOID QueryContext,
  2464. IN PATMARP_INTERFACE pInterface,
  2465. IN BOOLEAN * pIsValid
  2466. )
  2467. /*++
  2468. Routine Description:
  2469. Check if a given ARP Table Query context is valid. It is valid if it
  2470. is either NULL (looking for the first entry) or indicates a valid
  2471. ARP Table Entry.
  2472. Arguments:
  2473. QueryContext - The context to be validated
  2474. pInterface - The IF on which the query is being performed
  2475. pIsValid - Where we return the validity of the Query Context.
  2476. Return Value:
  2477. TRUE if the ARP Table has data to be read beyond the given context,
  2478. FALSE otherwise.
  2479. --*/
  2480. {
  2481. IPNMEContext *pNMContext = (IPNMEContext *)QueryContext;
  2482. PATMARP_IP_ENTRY pIpEntry;
  2483. PATMARP_IP_ENTRY pTargetIpEntry;
  2484. UINT i;
  2485. BOOLEAN ReturnValue;
  2486. i = pNMContext->inc_index;
  2487. pTargetIpEntry = (PATMARP_IP_ENTRY)(pNMContext->inc_entry);
  2488. //
  2489. // Check if we are starting at the beginning of the ARP Table.
  2490. //
  2491. if ((i == 0) && (pTargetIpEntry == NULL_PATMARP_IP_ENTRY))
  2492. {
  2493. //
  2494. // Yes, we are. Find the very first entry in the hash table.
  2495. //
  2496. *pIsValid = TRUE;
  2497. do
  2498. {
  2499. if ((pIpEntry = pInterface->pArpTable[i]) != NULL_PATMARP_IP_ENTRY)
  2500. {
  2501. break;
  2502. }
  2503. i++;
  2504. }
  2505. while (i < ATMARP_TABLE_SIZE);
  2506. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2507. {
  2508. pNMContext->inc_index = i;
  2509. pNMContext->inc_entry = pIpEntry;
  2510. ReturnValue = TRUE;
  2511. }
  2512. else
  2513. {
  2514. ReturnValue = FALSE;
  2515. }
  2516. }
  2517. else
  2518. {
  2519. //
  2520. // We are given a context. Check if it is valid.
  2521. //
  2522. //
  2523. // Initialize.
  2524. //
  2525. *pIsValid = FALSE;
  2526. ReturnValue = FALSE;
  2527. if (i < ATMARP_TABLE_SIZE)
  2528. {
  2529. pIpEntry = pInterface->pArpTable[i];
  2530. while (pIpEntry != NULL_PATMARP_IP_ENTRY)
  2531. {
  2532. if (pIpEntry == pTargetIpEntry)
  2533. {
  2534. *pIsValid = TRUE;
  2535. ReturnValue = TRUE;
  2536. break;
  2537. }
  2538. else
  2539. {
  2540. pIpEntry = pIpEntry->pNextEntry;
  2541. }
  2542. }
  2543. }
  2544. }
  2545. return (ReturnValue);
  2546. }
  2547. BOOLEAN
  2548. AtmArpReadNextTableEntry(
  2549. IN PVOID QueryContext,
  2550. IN PATMARP_INTERFACE pInterface,
  2551. IN PUCHAR pSpace
  2552. )
  2553. /*++
  2554. Routine Description:
  2555. Read the next ARP Table Entry for the specified interface. The QueryContext
  2556. tells us which entry is to be read.
  2557. Arguments:
  2558. QueryContext - Indicates the entry to be read.
  2559. pInterface - The IF on which the query is being performed
  2560. pSpace - where we copy in the desired table entry.
  2561. Return Value:
  2562. TRUE if the ARP Table has entries beyond the indicated one, FALSE
  2563. otherwise.
  2564. --*/
  2565. {
  2566. IPNMEContext *pNMContext;
  2567. IPNetToMediaEntry *pIPNMEntry;
  2568. PATMARP_IP_ENTRY pIpEntry;
  2569. UINT i;
  2570. BOOLEAN ReturnValue;
  2571. pNMContext = (IPNMEContext *)QueryContext;
  2572. pIPNMEntry = (IPNetToMediaEntry *)pSpace;
  2573. pIpEntry = (PATMARP_IP_ENTRY)(pNMContext->inc_entry);
  2574. AA_STRUCT_ASSERT(pIpEntry, aip);
  2575. pIPNMEntry->inme_index = pInterface->IFIndex;
  2576. pIPNMEntry->inme_addr = pIpEntry->IPAddress;
  2577. if (AA_IS_FLAG_SET(pIpEntry->Flags, AA_IP_ENTRY_STATE_MASK, AA_IP_ENTRY_RESOLVED))
  2578. {
  2579. AADEBUGP(AAD_EXTRA_LOUD, ("ReadNext: found IP Entry 0x%x, Addr %d.%d.%d.%d\n",
  2580. pIpEntry,
  2581. ((PUCHAR)(&(pIpEntry->IPAddress)))[0],
  2582. ((PUCHAR)(&(pIpEntry->IPAddress)))[1],
  2583. ((PUCHAR)(&(pIpEntry->IPAddress)))[2],
  2584. ((PUCHAR)(&(pIpEntry->IPAddress)))[3]
  2585. ));
  2586. pIPNMEntry->inme_physaddrlen = AA_ATM_PHYSADDR_LEN;
  2587. AA_ASSERT(pIpEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  2588. AA_COPY_MEM(pIPNMEntry->inme_physaddr,
  2589. &pIpEntry->pAtmEntry->ATMAddress.Address[AA_ATM_ESI_OFFSET],
  2590. AA_ATM_PHYSADDR_LEN);
  2591. if (pIpEntry->Flags & AA_IP_ENTRY_IS_STATIC)
  2592. {
  2593. pIPNMEntry->inme_type = INME_TYPE_STATIC;
  2594. }
  2595. else
  2596. {
  2597. pIPNMEntry->inme_type = INME_TYPE_DYNAMIC;
  2598. }
  2599. }
  2600. else
  2601. {
  2602. pIPNMEntry->inme_physaddrlen = 0;
  2603. pIPNMEntry->inme_type = INME_TYPE_INVALID;
  2604. }
  2605. //
  2606. // Update the context for the next entry.
  2607. //
  2608. if (pIpEntry->pNextEntry != NULL_PATMARP_IP_ENTRY)
  2609. {
  2610. pNMContext->inc_entry = pIpEntry->pNextEntry;
  2611. ReturnValue = TRUE;
  2612. }
  2613. else
  2614. {
  2615. //
  2616. // Initialize.
  2617. ReturnValue = FALSE;
  2618. i = pNMContext->inc_index + 1;
  2619. pNMContext->inc_index = 0;
  2620. pNMContext->inc_entry = NULL;
  2621. while (i < ATMARP_TABLE_SIZE)
  2622. {
  2623. if (pInterface->pArpTable[i] != NULL_PATMARP_IP_ENTRY)
  2624. {
  2625. pNMContext->inc_entry = pInterface->pArpTable[i];
  2626. pNMContext->inc_index = i;
  2627. ReturnValue = TRUE;
  2628. break;
  2629. }
  2630. else
  2631. {
  2632. i++;
  2633. }
  2634. }
  2635. }
  2636. return (ReturnValue);
  2637. }
  2638. VOID
  2639. AtmArpReStartInterface(
  2640. IN PNDIS_WORK_ITEM pWorkItem,
  2641. IN PVOID IfContext
  2642. )
  2643. /*++
  2644. Routine Description:
  2645. Bring back up the IP interface.
  2646. Arguments:
  2647. pWorkItem
  2648. IfContextw - The IF, which is expected to have reconfig
  2649. state RECONFIG_QUEUED.
  2650. Return Value:
  2651. None
  2652. --*/
  2653. {
  2654. PATMARP_INTERFACE pInterface;
  2655. ULONG rc;
  2656. BOOLEAN fRestart = FALSE;
  2657. #if DBG
  2658. AA_IRQL EntryIrq, ExitIrq;
  2659. #endif
  2660. AA_GET_ENTRY_IRQL(EntryIrq);
  2661. #if !BINARY_COMPATIBLE
  2662. AA_ASSERT(EntryIrq == PASSIVE_LEVEL);
  2663. #endif
  2664. pInterface = (PATMARP_INTERFACE)IfContext;
  2665. AA_STRUCT_ASSERT(pInterface, aai);
  2666. AA_FREE_MEM(pWorkItem);
  2667. AA_ACQUIRE_IF_LOCK(pInterface);
  2668. if (pInterface->ReconfigState != RECONFIG_RESTART_QUEUED)
  2669. {
  2670. //
  2671. // Shouldn't get here.
  2672. //
  2673. AA_ASSERT(FALSE);
  2674. }
  2675. else
  2676. {
  2677. pInterface->ReconfigState = RECONFIG_RESTART_PENDING;
  2678. fRestart = TRUE;
  2679. }
  2680. rc = AtmArpDereferenceInterface(pInterface); // Reconfig Work item
  2681. AADEBUGP(AAD_WARNING, ("RestartIF: IF %x/%x, fRestart %d, rc %d\n",
  2682. pInterface, pInterface->Flags, fRestart, rc));
  2683. //
  2684. // If we're restarting, there should be at least 2 references to the
  2685. // pInterface -- 1- the old carryover and 2- the pending completion
  2686. // completion of the reconfig event.
  2687. //
  2688. if (rc < 2 || !fRestart)
  2689. {
  2690. //
  2691. // Must be at least 2 if we're in the middle of a reconfig!
  2692. //
  2693. AA_ASSERT(!fRestart);
  2694. if (rc != 0)
  2695. {
  2696. AA_RELEASE_IF_LOCK(pInterface);
  2697. }
  2698. }
  2699. else
  2700. {
  2701. //
  2702. // At this point we know that we are doing a restart of the interface.
  2703. //
  2704. // We will extract the pointer to the adapter, the
  2705. // configuration string for the interface, and the pointer to the
  2706. // pending netPnpEvent (we'll need these later),
  2707. // and then do a FORCED DEALLOCATION of the interface.
  2708. // We will then allocate the interface. We go through this
  2709. // deallocate-allocate sequence to make sure that the interface
  2710. // structure and all it's sub-structures are properly initialized.
  2711. //
  2712. // We could have tried to re-use the old interface, but if so we
  2713. // would have to write code to clean up the old interface. Given
  2714. // that we expect restarting of the interface to be an infrequent
  2715. // event, it is more important to conserve code size in this case.
  2716. //
  2717. NDIS_STRING IPConfigString = pInterface->IPConfigString; // struct copy
  2718. PATMARP_ADAPTER pAdapter = pInterface->pAdapter;
  2719. PNET_PNP_EVENT pReconfigEvent = pInterface->pReconfigEvent;
  2720. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2721. do
  2722. {
  2723. NDIS_HANDLE LISConfigHandle;
  2724. rc = AtmArpDereferenceInterface(pInterface);
  2725. if (rc)
  2726. {
  2727. rc = AtmArpDereferenceInterface(pInterface);
  2728. }
  2729. if (rc != 0)
  2730. {
  2731. AA_RELEASE_IF_LOCK(pInterface);
  2732. }
  2733. pInterface = NULL;
  2734. //
  2735. // Open the configuration section for this LIS.
  2736. //
  2737. LISConfigHandle = AtmArpCfgOpenLISConfigurationByName(
  2738. pAdapter,
  2739. &IPConfigString
  2740. );
  2741. if (LISConfigHandle == NULL)
  2742. {
  2743. //
  2744. // This is the normal termination condition, i.e.
  2745. // we reached the end of the LIS list for this
  2746. // adapter.
  2747. //
  2748. AADEBUGP(AAD_INFO, ("ReStartInterface: cannot open LIS\n"));
  2749. Status = NDIS_STATUS_FAILURE;
  2750. break;
  2751. }
  2752. pInterface = AtmArpAddInterfaceToAdapter (
  2753. pAdapter,
  2754. LISConfigHandle,
  2755. &IPConfigString
  2756. );
  2757. //
  2758. // Close the configuration section for this LIS.
  2759. //
  2760. AtmArpCfgCloseLISConfiguration(LISConfigHandle);
  2761. LISConfigHandle = NULL;
  2762. if (pInterface == NULL_PATMARP_INTERFACE)
  2763. {
  2764. Status = NDIS_STATUS_FAILURE;
  2765. break;
  2766. }
  2767. } while(FALSE);
  2768. #ifdef _PNP_POWER_
  2769. //
  2770. // Complete the pending PnPReconfig event, if any.
  2771. //
  2772. if (pReconfigEvent)
  2773. {
  2774. NdisCompletePnPEvent(
  2775. Status,
  2776. pAdapter->NdisAdapterHandle,
  2777. pReconfigEvent
  2778. );
  2779. AADEBUGP( AAD_INFO,
  2780. ("ReStartInterface: IF 0x%x, Status 0x%x, Event 0x%x\n",
  2781. pInterface, Status, pReconfigEvent));
  2782. }
  2783. #else
  2784. AA_ASSERT(!pReconfigEvent);
  2785. #endif
  2786. }
  2787. }