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.

3047 lines
67 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. arps.c
  5. Abstract:
  6. This file contains the code to implement the initialization
  7. functions for the atmarp server.
  8. Author:
  9. Jameel Hyder (jameelh@microsoft.com) July 1996
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include <precomp.h>
  15. #define _FILENUM_ FILENUM_ARPS
  16. ULONG MCastDiscards = 0;
  17. NTSTATUS
  18. DriverEntry(
  19. IN PDRIVER_OBJECT DriverObject,
  20. IN PUNICODE_STRING RegistryPath
  21. )
  22. /*++
  23. Routine Description:
  24. IP/ATM Arp Server driver entry point.
  25. Arguments:
  26. DriverObject - Pointer to the driver object created by the system.
  27. RegistryPath - Pointer to the registry section where the parameters reside.
  28. Return Value:
  29. Return value from IoCreateDevice
  30. --*/
  31. {
  32. NTSTATUS Status;
  33. UNICODE_STRING DeviceName, GlobalPath, SymbolicName;
  34. HANDLE ThreadHandle = NULL;
  35. INT i;
  36. #if DBG
  37. DbgPrint("AtmArpS: ArpSDebugLevel @ %p, MarsDebugLevel @ %p\n",
  38. &ArpSDebugLevel, &MarsDebugLevel);
  39. #endif // DBG
  40. InitializeListHead(&ArpSEntryOfDeath);
  41. KeInitializeEvent(&ArpSReqThreadEvent, NotificationEvent, FALSE);
  42. KeInitializeQueue(&ArpSReqQueue, 0);
  43. KeInitializeQueue(&MarsReqQueue, 0);
  44. INITIALIZE_SPIN_LOCK(&ArpSIfListLock);
  45. ASSERT (ADDR_TYPE_NSAP == ATM_NSAP);
  46. ASSERT (ADDR_TYPE_E164 == ATM_E164);
  47. //
  48. // Create an NON-EXCLUSIVE device object
  49. //
  50. RtlInitUnicodeString(&DeviceName,
  51. ARP_SERVER_DEVICE_NAME);
  52. RtlInitUnicodeString(&SymbolicName, ARP_SERVER_SYMBOLIC_NAME);
  53. Status = IoCreateDevice(DriverObject,
  54. 0,
  55. &DeviceName,
  56. FILE_DEVICE_NETWORK,
  57. FILE_DEVICE_SECURE_OPEN,
  58. FALSE,
  59. &ArpSDeviceObject);
  60. if (!NT_SUCCESS(Status))
  61. {
  62. DBGPRINT(DBG_LEVEL_INFO, ("DriverEntry: IoCreateDevice failed %lx\n", Status));
  63. }
  64. else do
  65. {
  66. IoCreateSymbolicLink(&SymbolicName, &DeviceName);
  67. IoRegisterShutdownNotification(ArpSDeviceObject);
  68. ArpSDriverObject = DriverObject;
  69. //
  70. // Initialize the driver object
  71. //
  72. DriverObject->DriverUnload = ArpSUnload;
  73. DriverObject->FastIoDispatch = NULL;
  74. for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  75. DriverObject->MajorFunction[i] = ArpSDispatch;
  76. RtlInitUnicodeString(&GlobalPath, L"AtmArpS\\Parameters");
  77. Status = ArpSReadGlobalConfiguration(&GlobalPath);
  78. if (!NT_SUCCESS(Status))
  79. {
  80. break;
  81. }
  82. //
  83. // Now create a thread to handle the Arp requests.
  84. // We do this so that the arp cache can be allocated
  85. // out of paged memory. Do this prior to initializing
  86. // the NDIS interface.
  87. //
  88. Status = PsCreateSystemThread(&ThreadHandle,
  89. THREAD_ALL_ACCESS,
  90. NULL,
  91. NtCurrentProcess(),
  92. NULL,
  93. ArpSReqThread,
  94. (PVOID)NULL);
  95. if (!NT_SUCCESS(Status))
  96. {
  97. DBGPRINT(DBG_LEVEL_ERROR,
  98. ("DriverEntry: Cannot create request thread %lx\n", Status));
  99. LOG_ERROR(Status);
  100. break;
  101. }
  102. else
  103. {
  104. //
  105. // Close the handle to the thread so that it goes away when the
  106. // thread terminates
  107. //
  108. NtClose(ThreadHandle);
  109. Status = PsCreateSystemThread(&ThreadHandle,
  110. THREAD_ALL_ACCESS,
  111. NULL,
  112. NtCurrentProcess(),
  113. NULL,
  114. MarsReqThread,
  115. (PVOID)NULL);
  116. if (!NT_SUCCESS(Status))
  117. {
  118. DBGPRINT(DBG_LEVEL_ERROR,
  119. ("DriverEntry: Cannot create MARS thread %lx\n", Status));
  120. LOG_ERROR(Status);
  121. }
  122. else
  123. {
  124. //
  125. // Close the handle to the thread so that it goes away when the
  126. // thread terminates
  127. //
  128. NtClose(ThreadHandle);
  129. }
  130. }
  131. //
  132. // Finally initialize the NDIS interface
  133. //
  134. if(NT_SUCCESS(Status))
  135. {
  136. Status = ArpSInitializeNdis();
  137. }
  138. if(!NT_SUCCESS(Status))
  139. {
  140. NTSTATUS Sts;
  141. DBGPRINT(DBG_LEVEL_INFO, ("DriverEntry: Error initializing NDIS\n"));
  142. //
  143. // Ask the request thread to die
  144. //
  145. KeInsertQueue(&ArpSReqQueue, &ArpSEntryOfDeath);
  146. //
  147. // Wait for it to die
  148. //
  149. WAIT_FOR_OBJECT(Sts, &ArpSReqThreadEvent, NULL);
  150. ArpSSleep(500);
  151. KeRundownQueue(&ArpSReqQueue);
  152. break;
  153. }
  154. } while (FALSE);
  155. if (!NT_SUCCESS(Status))
  156. {
  157. if (ArpSDeviceObject != NULL)
  158. {
  159. IoUnregisterShutdownNotification(ArpSDeviceObject);
  160. IoDeleteSymbolicLink(&SymbolicName);
  161. IoDeleteDevice(ArpSDeviceObject);
  162. }
  163. //
  164. // De-initialize the NDIS interface
  165. //
  166. ArpSDeinitializeNdis();
  167. ArpSFreeGlobalData();
  168. }
  169. return Status;
  170. }
  171. VOID
  172. ArpSUnload(
  173. IN PDRIVER_OBJECT DriverObject
  174. )
  175. /*++
  176. Routine Description:
  177. Called by the IO system to unload. This is a synchronous call and we block here till
  178. we finish all the cleanup before we unload.
  179. Arguments:
  180. DriverObject - The arp-server's driver object.
  181. Return Value:
  182. None
  183. --*/
  184. {
  185. ArpSShutDown();
  186. //
  187. // Finally delete the device
  188. //
  189. {
  190. UNICODE_STRING SymbolicName;
  191. RtlInitUnicodeString(&SymbolicName, ARP_SERVER_SYMBOLIC_NAME);
  192. IoUnregisterShutdownNotification(ArpSDeviceObject);
  193. IoDeleteSymbolicLink(&SymbolicName);
  194. IoDeleteDevice(ArpSDeviceObject);
  195. }
  196. }
  197. VOID
  198. ArpSShutDown(
  199. VOID
  200. )
  201. /*++
  202. Routine Description:
  203. Called by the IO system when the system is being shutdown.
  204. Arguments:
  205. None
  206. Return Value:
  207. None
  208. --*/
  209. {
  210. NTSTATUS Status;
  211. //
  212. // Take care of the NDIS layer. NDIS will tear down any existing
  213. // bindings when we deregister as a protocol.
  214. //
  215. ArpSDeinitializeNdis();
  216. //
  217. // Ask the request thread to quit and wait for its demise.
  218. //
  219. KeInsertQueue(&ArpSReqQueue, &ArpSEntryOfDeath);
  220. WAIT_FOR_OBJECT(Status, &ArpSReqThreadEvent, NULL);
  221. ArpSSleep(500);
  222. KeRundownQueue(&ArpSReqQueue);
  223. //
  224. // Ask the MARS thread to quit and wait for its demise.
  225. //
  226. KeInsertQueue(&MarsReqQueue, &ArpSEntryOfDeath);
  227. KeInitializeEvent(&ArpSReqThreadEvent, NotificationEvent, FALSE);
  228. WAIT_FOR_OBJECT(Status, &ArpSReqThreadEvent, NULL);
  229. ArpSSleep(500);
  230. KeRundownQueue(&MarsReqQueue);
  231. //
  232. // Now cleanup global data structures
  233. //
  234. ArpSFreeGlobalData();
  235. }
  236. PINTF
  237. ArpSCreateIntF(
  238. IN PNDIS_STRING DeviceName,
  239. IN PNDIS_STRING ConfigString,
  240. IN NDIS_HANDLE BindingContext
  241. )
  242. /*++
  243. Routine Description:
  244. Arguments:
  245. Return Value:
  246. --*/
  247. {
  248. NTSTATUS Status;
  249. HANDLE ThreadHandle;
  250. PINTF pIntF;
  251. UINT Size;
  252. UNICODE_STRING DevPrefix;
  253. UNICODE_STRING FilePrefix;
  254. UNICODE_STRING FileSuffix;
  255. UNICODE_STRING BaseName;
  256. NDIS_STRING AdapterFriendlyName;
  257. ARPS_PAGED_CODE( );
  258. //
  259. // Get the friendly name of the adapter we are bound to.
  260. //
  261. if (NdisQueryBindInstanceName(&AdapterFriendlyName, BindingContext) != NDIS_STATUS_SUCCESS)
  262. {
  263. return (NULL);
  264. }
  265. //
  266. // Extract the base-name of the device we are bound to
  267. //
  268. RtlInitUnicodeString(&DevPrefix, L"\\Device\\");
  269. RtlInitUnicodeString(&FilePrefix, L"\\SYSTEMROOT\\SYSTEM32\\");
  270. RtlInitUnicodeString(&FileSuffix, L".ARP");
  271. BaseName.Buffer = (PWSTR)((PUCHAR)DeviceName->Buffer + DevPrefix.Length);
  272. BaseName.Length = DeviceName->Length - DevPrefix.Length;
  273. BaseName.MaximumLength = DeviceName->MaximumLength - DevPrefix.Length;
  274. //
  275. // Start off by allocating an IntF block
  276. //
  277. Size = sizeof(INTF) + FilePrefix.Length + BaseName.Length + FileSuffix.Length + sizeof(WCHAR) +
  278. BaseName.Length + sizeof(WCHAR) +
  279. AdapterFriendlyName.MaximumLength + sizeof(WCHAR);
  280. Size += ConfigString->MaximumLength + sizeof(WCHAR);
  281. pIntF = (PINTF)ALLOC_NP_MEM(Size, POOL_TAG_INTF);
  282. if (pIntF != NULL)
  283. {
  284. ZERO_MEM(pIntF, Size);
  285. //
  286. // Fill in some defaults.
  287. //
  288. pIntF->MaxPacketSize = DEFAULT_MAX_PACKET_SIZE;
  289. pIntF->LinkSpeed.Inbound = pIntF->LinkSpeed.Outbound = DEFAULT_SEND_BANDWIDTH;
  290. pIntF->CCFlowSpec = DefaultCCFlowSpec;
  291. //
  292. // Start off with a refcount of 1 for the interface and one for the timer thread.
  293. // The timer thread derefs when asked to quit and the last reference
  294. // is removed when the interface is closed (ArpSCloseAdapterComplete).
  295. //
  296. pIntF->RefCount = 2;
  297. pIntF->LastVcId = 1; // Start off with 1 and wrap-around to 1. 0 and -1 are invalid
  298. pIntF->SupportedMedium = NdisMediumAtm;
  299. pIntF->CSN = 1;
  300. INITIALIZE_MUTEX(&pIntF->ArpCacheMutex);
  301. KeInitializeEvent(&pIntF->TimerThreadEvent, NotificationEvent, FALSE);
  302. InitializeListHead(&pIntF->InactiveVcHead);
  303. InitializeListHead(&pIntF->ActiveVcHead);
  304. InitializeListHead(&pIntF->CCPacketQueue);
  305. ArpSTimerInitialize(&pIntF->FlushTimer, ArpSWriteArpCache, ArpSFlushTime);
  306. ArpSTimerInitialize(&pIntF->MarsRedirectTimer, MarsSendRedirect, REDIRECT_INTERVAL);
  307. pIntF->InterfaceName.Buffer = (PWSTR)((PUCHAR)pIntF + sizeof(INTF));
  308. pIntF->InterfaceName.Length = 0;
  309. pIntF->InterfaceName.MaximumLength = BaseName.Length;
  310. pIntF->FileName.Buffer = (PWSTR)((PUCHAR)pIntF->InterfaceName.Buffer + BaseName.Length + sizeof(WCHAR));
  311. pIntF->FileName.Length = 0;
  312. pIntF->FileName.MaximumLength = FilePrefix.Length + BaseName.Length + FileSuffix.Length + sizeof(WCHAR);
  313. RtlUpcaseUnicodeString(&pIntF->InterfaceName,
  314. &BaseName,
  315. FALSE);
  316. RtlCopyUnicodeString(&pIntF->FileName, &FilePrefix);
  317. RtlAppendUnicodeStringToString(&pIntF->FileName, &pIntF->InterfaceName);
  318. RtlAppendUnicodeStringToString(&pIntF->FileName, &FileSuffix);
  319. //
  320. // Copy in the config string used to access registry for this interface.
  321. //
  322. pIntF->ConfigString.Buffer = (PWSTR)((ULONG_PTR)pIntF->FileName.Buffer + pIntF->FileName.MaximumLength);
  323. pIntF->ConfigString.Length = 0;
  324. pIntF->ConfigString.MaximumLength = ConfigString->MaximumLength;
  325. RtlCopyUnicodeString(&pIntF->ConfigString, ConfigString);
  326. //
  327. // Copy in the friendly name.
  328. //
  329. pIntF->FriendlyName.Buffer = (PWSTR)((ULONG_PTR)pIntF->ConfigString.Buffer + pIntF->ConfigString.MaximumLength);
  330. pIntF->FriendlyName.Length = 0;
  331. pIntF->FriendlyName.MaximumLength = AdapterFriendlyName.MaximumLength + sizeof(WCHAR);
  332. RtlCopyUnicodeString(&pIntF->FriendlyName, &AdapterFriendlyName);
  333. *(PWCHAR)((ULONG_PTR)pIntF->FriendlyName.Buffer + AdapterFriendlyName.MaximumLength) = L'\0';
  334. pIntF->FriendlyName.Length += sizeof(WCHAR);
  335. NdisFreeString(AdapterFriendlyName);
  336. //
  337. // Initialize the start timestamp value -- used for statistics reporting.
  338. //
  339. NdisGetCurrentSystemTime(&(pIntF->StatisticsStartTimeStamp));
  340. //
  341. // Create a timer-thread now.
  342. //
  343. Status = PsCreateSystemThread(&ThreadHandle,
  344. THREAD_ALL_ACCESS,
  345. NULL,
  346. NtCurrentProcess(),
  347. NULL,
  348. ArpSTimerThread,
  349. (PVOID)pIntF);
  350. if (!NT_SUCCESS(Status))
  351. {
  352. DBGPRINT(DBG_LEVEL_ERROR,
  353. ("ArpSCreateIntF: Cannot create timer thread %lx for device %Z\n",
  354. Status, DeviceName));
  355. LOG_ERROR(Status);
  356. FREE_MEM(pIntF);
  357. pIntF = NULL;
  358. }
  359. else
  360. {
  361. //
  362. // Close the handle to the thread so that it goes away when the
  363. // thread terminates
  364. //
  365. NtClose(ThreadHandle);
  366. DBGPRINT(DBG_LEVEL_INFO,
  367. ("ArpSCreateIntF: Device name %Z, InterfaceName %Z, FileName %Z, ConfigString %Z\n",
  368. DeviceName, &pIntF->InterfaceName, &pIntF->FileName, &pIntF->ConfigString));
  369. if (ArpSFlushTime != 0)
  370. ArpSTimerEnqueue(pIntF, &pIntF->FlushTimer);
  371. ArpSTimerEnqueue(pIntF, &pIntF->MarsRedirectTimer);
  372. }
  373. }
  374. return pIntF;
  375. }
  376. VOID
  377. ArpSReqThread(
  378. IN PVOID Context
  379. )
  380. /*++
  381. Routine Description:
  382. Handle all arp requests here.
  383. Arguments:
  384. None
  385. Return Value:
  386. None
  387. --*/
  388. {
  389. PARPS_HEADER Header;
  390. PARP_ENTRY ArpEntry;
  391. PNDIS_PACKET Pkt;
  392. PPROTOCOL_RESD Resd;
  393. PARP_VC Vc;
  394. PINTF pIntF;
  395. UINT PktLen;
  396. PLIST_ENTRY List;
  397. IPADDR SrcIpAddr, DstIpAddr;
  398. NTSTATUS Status;
  399. HW_ADDR SrcHwAddr, DstHwAddr;
  400. ATM_ADDRESS SrcSubAddr, DstSubAddr;
  401. PUCHAR p;
  402. BOOLEAN SendReply;
  403. BOOLEAN SendNAK = FALSE;
  404. ARPS_PAGED_CODE( );
  405. DBGPRINT(DBG_LEVEL_INFO,
  406. ("ArpSReqThread: Came to life\n"));
  407. do
  408. {
  409. List = KeRemoveQueue(&ArpSReqQueue, KernelMode, NULL);
  410. if (List == &ArpSEntryOfDeath)
  411. {
  412. //
  413. // Asked to terminate, do so.
  414. //
  415. break;
  416. }
  417. SendReply = FALSE;
  418. Resd = CONTAINING_RECORD(List, PROTOCOL_RESD, ReqList);
  419. Vc = Resd->Vc;
  420. Pkt = CONTAINING_RECORD(Resd, NDIS_PACKET, ProtocolReserved);
  421. pIntF = Vc->IntF;
  422. NdisQueryBuffer(Pkt->Private.Head, &Header, &PktLen);
  423. ASSERT (PktLen <= PKT_SPACE);
  424. p = (PUCHAR)Header + sizeof(ARPS_HEADER);
  425. //
  426. // Process arp request now. Since the Pkt is owned by us, we know that
  427. // the buffer that the packet points is contiguous and the integrity of
  428. // the packet has already been verified. There is also sufficient space
  429. // in the packet for the max. size reply that we can send.
  430. //
  431. // !!!!!!!!!! ALGORITHM FROM RFC 1577 !!!!!!!!!!
  432. //
  433. // Here is the algorithm for handling ARP requests from the RFC
  434. //
  435. // if (SrcIpAddr == DstIpAddr)
  436. // {
  437. // if ((ArpEntry(SrcIpAddr) != NULL) &&
  438. // (SrcAtmAddress != ArpEntry->AtmAddress) &&
  439. // (ArpEnrty->Vc != NULL) && (ArpEntry->Vc != Vc))
  440. // {
  441. // Respond with the information from the ArpEntry;
  442. // }
  443. // else if ((ArpEntry(SrcIpAddr) == NULL) ||
  444. // (ArpEntry->Vc == NULL) ||
  445. // (ArpEntry->Vc == Vc))
  446. // {
  447. // if (ArpEntry(SrcIpAddr) == NULL))
  448. // {
  449. // Create an arp entry for this IpAddr;
  450. // }
  451. // Update the arp entry with info from the request;
  452. //
  453. // Respond with the information from the ArpEntry;
  454. // }
  455. // }
  456. // else // if (SrcIpAddr != DstIpAddr)
  457. // {
  458. // if (ArpEntry(DstIpAddr) != NULL)
  459. // {
  460. // Respond with the information from the ArpEntry;
  461. // }
  462. // else
  463. // {
  464. // Respond with a NAK
  465. // }
  466. //
  467. // if (ArpEntry(SrcIpAddr) == NULL)
  468. // {
  469. // Create a new ArpEntry for the (SrcIpAddr, ArcAtmAddress) pair
  470. // }
  471. // else if ((ArpEntry->AtmAddress == SrcAtmAddress) &&
  472. // (ArpEntry->AtmAddress == Vc->AtmAddress))
  473. // {
  474. // Reset timer on this ArpEntry;
  475. // }
  476. // }
  477. //
  478. // !!!!!!!!!! ALGORITHM FROM RFC 1577 !!!!!!!!!!
  479. //
  480. //
  481. // Start off by extracting fields from the header
  482. // First the source hw address (incl. the sub-addr if any)
  483. //
  484. SrcHwAddr.Address.NumberOfDigits = TL_LEN(Header->SrcAddressTL);
  485. if (SrcHwAddr.Address.NumberOfDigits > 0)
  486. {
  487. SrcHwAddr.Address.AddressType = TL_TYPE(Header->SrcAddressTL);
  488. COPY_MEM(SrcHwAddr.Address.Address, p, SrcHwAddr.Address.NumberOfDigits);
  489. p += SrcHwAddr.Address.NumberOfDigits;
  490. }
  491. SrcHwAddr.SubAddress = NULL;
  492. if (TL_LEN(Header->SrcSubAddrTL) > 0)
  493. {
  494. SrcHwAddr.SubAddress = &SrcSubAddr;
  495. SrcSubAddr.NumberOfDigits = TL_LEN(Header->SrcSubAddrTL);
  496. SrcSubAddr.AddressType = TL_TYPE(Header->SrcSubAddrTL);
  497. COPY_MEM(&SrcSubAddr.Address, p, SrcSubAddr.NumberOfDigits);
  498. p += SrcSubAddr.NumberOfDigits;
  499. }
  500. //
  501. // Next get the source IP address
  502. //
  503. SrcIpAddr = 0;
  504. if (Header->SrcProtoAddrLen == IP_ADDR_LEN)
  505. {
  506. SrcIpAddr = *(UNALIGNED IPADDR *)p;
  507. p += IP_ADDR_LEN;
  508. }
  509. ArpSDumpAddress(SrcIpAddr, &SrcHwAddr, "Source");
  510. //
  511. // Now the destination hw address (incl. the sub-addr if any)
  512. //
  513. DstHwAddr.Address.NumberOfDigits = TL_LEN(Header->DstAddressTL);
  514. if (DstHwAddr.Address.NumberOfDigits > 0)
  515. {
  516. DstHwAddr.Address.AddressType = TL_TYPE(Header->DstAddressTL);
  517. COPY_MEM(DstHwAddr.Address.Address, p, DstHwAddr.Address.NumberOfDigits);
  518. p += DstHwAddr.Address.NumberOfDigits;
  519. }
  520. DstHwAddr.SubAddress = NULL;
  521. if (TL_LEN(Header->DstSubAddrTL) > 0)
  522. {
  523. DstHwAddr.SubAddress = &DstSubAddr;
  524. DstSubAddr.NumberOfDigits = TL_LEN(Header->DstSubAddrTL);
  525. DstSubAddr.AddressType = TL_TYPE(Header->DstSubAddrTL);
  526. COPY_MEM(&DstSubAddr.Address, p, DstSubAddr.NumberOfDigits);
  527. p += DstSubAddr.NumberOfDigits;
  528. }
  529. //
  530. // Finally the destination IP address
  531. //
  532. DstIpAddr = 0;
  533. if (Header->DstProtoAddrLen == IP_ADDR_LEN)
  534. {
  535. DstIpAddr = *(UNALIGNED IPADDR *)p;
  536. // p += IP_ADDR_LEN;
  537. }
  538. ArpSDumpAddress(DstIpAddr, &DstHwAddr, "Destination");
  539. do
  540. {
  541. //
  542. // Validate that the source and destination Ip addresses are not 0.0.0.0
  543. // NOTE: We can also check if they are within the same LIS (should we ?).
  544. //
  545. if ((SrcIpAddr == 0) || (DstIpAddr == 0))
  546. {
  547. DBGPRINT(DBG_LEVEL_ERROR,
  548. ("ArpSReqThread: Null IpAddress Src(%lx), Dst(%lx)\n",
  549. SrcIpAddr, DstIpAddr));
  550. SendReply = FALSE;
  551. break;
  552. }
  553. //
  554. // Take the lock on the Arp Cache now.
  555. //
  556. WAIT_FOR_OBJECT(Status, &pIntF->ArpCacheMutex, NULL);
  557. ASSERT (Status == STATUS_SUCCESS);
  558. if (SrcIpAddr == DstIpAddr)
  559. {
  560. //
  561. // Try to map the address to an arp cache entry
  562. //
  563. ArpEntry = ArpSLookupEntryByIpAddr(pIntF, SrcIpAddr);
  564. if ((ArpEntry != NULL) &&
  565. !COMP_HW_ADDR(&SrcHwAddr, &ArpEntry->HwAddr) &&
  566. (ArpEntry->Vc != NULL) && (ArpEntry->Vc != Vc))
  567. {
  568. //
  569. // Respond with the information from the ArpEntry
  570. // We have encountered a duplicate address.
  571. //
  572. ArpSBuildArpReply(pIntF, ArpEntry, Header, Pkt);
  573. SendReply = TRUE;
  574. LOG_ERROR(NDIS_STATUS_ALREADY_MAPPED);
  575. }
  576. else if ((ArpEntry == NULL) || (ArpEntry->Vc == NULL) || (ArpEntry->Vc == Vc))
  577. {
  578. if (ArpEntry == NULL)
  579. {
  580. //
  581. // Create an arp entry for this IpAddr
  582. //
  583. ArpEntry = ArpSAddArpEntry(pIntF, SrcIpAddr, &SrcHwAddr.Address, SrcHwAddr.SubAddress, Vc);
  584. }
  585. else
  586. {
  587. //
  588. // Update the arp entry with info from the request;
  589. //
  590. ArpSUpdateArpEntry(pIntF, ArpEntry, SrcIpAddr, &SrcHwAddr, Vc);
  591. }
  592. if (ArpEntry != NULL)
  593. {
  594. //
  595. // Respond with the information from the ArpEntry
  596. //
  597. ArpSBuildArpReply(pIntF, ArpEntry, Header, Pkt);
  598. SendReply = TRUE;
  599. }
  600. else
  601. {
  602. //
  603. // Failed to allocate an ARP entry
  604. //
  605. SendNAK = TRUE;
  606. SendReply = TRUE;
  607. }
  608. }
  609. else
  610. {
  611. DbgPrint("ATMARPS: pkt on wrong VC: ArpEntry %p, ArpEntry->Vc %p, Vc %p\n",
  612. ArpEntry,
  613. ((ArpEntry)? ArpEntry->Vc: NULL),
  614. Vc);
  615. }
  616. }
  617. else // i.e. (SrcIpAddr != DstIpAddr)
  618. {
  619. //
  620. // Try to map the dst address to an arp cache entry
  621. //
  622. ArpEntry = ArpSLookupEntryByIpAddr(pIntF, DstIpAddr);
  623. if (ArpEntry != NULL)
  624. {
  625. //
  626. // Respond with the information from the ArpEntry
  627. // for the destination IP Address
  628. //
  629. ArpSBuildArpReply(pIntF, ArpEntry, Header, Pkt);
  630. SendReply = TRUE;
  631. }
  632. else
  633. {
  634. //
  635. // Respond with a NAK
  636. //
  637. // ArpSBuildNakReply(pIntF, ArpEntry, Header, Pkt);
  638. DBGPRINT(DBG_LEVEL_INFO,
  639. ("ArpSThread: Naking for "));
  640. ArpSDumpIpAddr(DstIpAddr, "\n");
  641. Header->Opcode = ATMARP_Nak;
  642. SendReply = TRUE;
  643. SendNAK = TRUE; // for stats
  644. }
  645. //
  646. // Try to map the src address to an arp cache entry
  647. //
  648. ArpEntry = ArpSLookupEntryByIpAddr(pIntF, SrcIpAddr);
  649. if (ArpEntry == NULL)
  650. {
  651. //
  652. // Create a new ArpEntry for the (SrcIpAddr, ArcAtmAddress) pair
  653. //
  654. ArpEntry = ArpSAddArpEntry(pIntF, SrcIpAddr, &SrcHwAddr.Address, SrcHwAddr.SubAddress, Vc);
  655. }
  656. else if (COMP_HW_ADDR(&ArpEntry->HwAddr, &SrcHwAddr) &&
  657. COMP_HW_ADDR(&ArpEntry->HwAddr, &Vc->HwAddr))
  658. {
  659. //
  660. // Reset timer on this ArpEntry
  661. //
  662. ArpSTimerCancel(&ArpEntry->Timer);
  663. ArpEntry->Age = ARP_AGE;
  664. ArpSTimerEnqueue(pIntF, &ArpEntry->Timer);
  665. }
  666. }
  667. RELEASE_MUTEX(&pIntF->ArpCacheMutex);
  668. } while (FALSE);
  669. if (SendReply && (Vc->NdisVcHandle != NULL))
  670. {
  671. if (SendNAK)
  672. {
  673. pIntF->ArpStats.Naks++;
  674. }
  675. else
  676. {
  677. pIntF->ArpStats.Acks++;
  678. }
  679. NDIS_SET_PACKET_STATUS(Pkt, NDIS_STATUS_SUCCESS);
  680. NdisCoSendPackets(Vc->NdisVcHandle, &Pkt, 1);
  681. }
  682. else
  683. {
  684. pIntF->ArpStats.DiscardedRecvPkts++;
  685. ExInterlockedPushEntrySList(&ArpSPktList,
  686. &Resd->FreeList,
  687. &ArpSPktListLock);
  688. ArpSDereferenceVc(Vc, FALSE, TRUE);
  689. }
  690. } while (TRUE);
  691. KeSetEvent(&ArpSReqThreadEvent, 0, FALSE);
  692. DBGPRINT(DBG_LEVEL_WARN,
  693. ("ArpSReqThread: Terminating\n"));
  694. }
  695. UINT
  696. ArpSHandleArpRequest(
  697. IN NDIS_HANDLE ProtocolBindingContext,
  698. IN NDIS_HANDLE ProtocolVcContext,
  699. IN PNDIS_PACKET Packet
  700. )
  701. /*++
  702. Routine Description:
  703. Handle an incoming arp request from the network. Do minimal checks,
  704. make a copy of the packet and queue it up.
  705. Arguments:
  706. ProtocolBindingContext Pointer to the INTF
  707. ProtocolVcContext Pointer to the Vc
  708. Packet Pointer to the packet
  709. Return Value:
  710. Ref count on this received packet. This is 0 if we are done with
  711. the packet here, and 1 if we hang on to it (as for Multicast data
  712. that is forwarded).
  713. --*/
  714. {
  715. PARP_VC Vc = (PARP_VC)ProtocolVcContext;
  716. PINTF pIntF = (PINTF)ProtocolBindingContext;
  717. PARPS_HEADER Header;
  718. PMARS_HEADER MHdr;
  719. PNDIS_PACKET Pkt;
  720. PPROTOCOL_RESD Resd;
  721. UINT PktLen, Tmp;
  722. BOOLEAN ValidPkt, Mars;
  723. PSINGLE_LIST_ENTRY List;
  724. UINT ReturnValue;
  725. DBGPRINT(DBG_LEVEL_INFO,
  726. ("ArpSHandleArpRequest: Request on Vc %lx, Id %lx\n", Vc, Vc->VcId));
  727. ReturnValue = 0;
  728. do
  729. {
  730. //
  731. // Verify minimum packet length
  732. //
  733. NdisQueryPacket(Packet, NULL, NULL, NULL, &PktLen);
  734. if (PktLen < sizeof(ARPS_HEADER))
  735. {
  736. DBGPRINT(DBG_LEVEL_ERROR,
  737. ("ArpSHandleArpRequest: Invalid PktLen %d for received packet %lx\n",
  738. PktLen, Packet));
  739. //
  740. // For statistics purposes, we consider these to be discarded multicast data
  741. // packets.
  742. //
  743. pIntF->MarsStats.TotalMCDataPkts++;
  744. pIntF->MarsStats.DiscardedMCDataPkts++;
  745. break;
  746. }
  747. //
  748. // Check if this is Multicast data. If so, forward it
  749. // and quit.
  750. //
  751. NdisQueryBuffer(Packet->Private.Head, &Header, &Tmp);
  752. if (COMP_MEM(&Header->LlcSnapHdr, &MarsData1LlcSnapHdr, sizeof(LLC_SNAP_HDR)))
  753. {
  754. PNDIS_PACKET pNewPacket;
  755. pIntF->MarsStats.TotalMCDataPkts++;
  756. //
  757. // Check if the miniport wants this packet back immediately.
  758. // If so, don't reuse it.
  759. //
  760. if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES)
  761. {
  762. ReturnValue = 0;
  763. pIntF->MarsStats.DiscardedMCDataPkts++;
  764. break;
  765. }
  766. pNewPacket = MarsAllocPacketHdrCopy(Packet);
  767. if (pNewPacket != (PNDIS_PACKET)NULL)
  768. {
  769. pIntF->MarsStats.ReflectedMCDataPkts++;
  770. MarsSendOnClusterControlVc(pIntF, pNewPacket);
  771. ReturnValue = 1;
  772. }
  773. break;
  774. }
  775. //
  776. // This must be an ARP or MARS control packet. We make a copy and queue
  777. // this to the appropriate thread (ARPS or MARS).
  778. //
  779. pIntF->ArpStats.TotalRecvPkts++;
  780. //
  781. // Make sure that a larger packet wil not trash local packet after copy
  782. //
  783. if (PktLen > PKT_SPACE)
  784. {
  785. DBGPRINT(DBG_LEVEL_ERROR,
  786. ("ArpSHandleArpRequest: Incoming packet too large, truncating - %d, Vc %lx\n",
  787. PktLen, Vc));
  788. PktLen = PKT_SPACE;
  789. }
  790. //
  791. // Allocate a packet from our free pool. The contents from the packet from the adapter is copied into
  792. // this after verification and queued to the thread. If we fail to allocate, we simply drop the request.
  793. //
  794. List = ExInterlockedPopEntrySList(&ArpSPktList, &ArpSPktListLock);
  795. if (List == NULL)
  796. {
  797. DBGPRINT(DBG_LEVEL_ERROR,
  798. ("ArpSHandleArpRequest: Out of packets - interface %lx, Vc %lx\n",
  799. pIntF, Vc));
  800. pIntF->ArpStats.DiscardedRecvPkts++;
  801. break;
  802. }
  803. Resd = CONTAINING_RECORD(List, PROTOCOL_RESD, FreeList);
  804. Resd->Flags = 0;
  805. Pkt = CONTAINING_RECORD(Resd, NDIS_PACKET, ProtocolReserved);
  806. //
  807. // Adjust Length of packet to reflect the size of the received packet.
  808. // We adjust it again to size when we reply.
  809. //
  810. NdisAdjustBufferLength(Pkt->Private.Head, PktLen);
  811. Pkt->Private.ValidCounts = FALSE;
  812. NdisCopyFromPacketToPacket(Pkt,
  813. 0,
  814. PktLen,
  815. Packet,
  816. 0,
  817. &Tmp);
  818. ASSERT(Tmp == PktLen);
  819. ASSERT( PktLen < 65536);
  820. Resd->PktLen = (USHORT) PktLen;
  821. //
  822. // The incoming packet is now copied to our packet.
  823. // Examine and sanity check before queuing it.
  824. //
  825. NdisQueryBuffer(Pkt->Private.Head, &Header, &Tmp);
  826. Resd->PacketStart = (PUCHAR)Header;
  827. MHdr = (PMARS_HEADER)Header;
  828. do
  829. {
  830. ValidPkt = FALSE; // Assume the worst
  831. //
  832. // Check for the LLC SNAP Header
  833. //
  834. if (COMP_MEM(&Header->LlcSnapHdr, &ArpSLlcSnapHdr, sizeof(LLC_SNAP_HDR)))
  835. {
  836. Mars = FALSE;
  837. }
  838. else if (COMP_MEM(&Header->LlcSnapHdr, &MarsCntrlLlcSnapHdr, sizeof(LLC_SNAP_HDR)))
  839. {
  840. if ((MHdr->HwType == MARS_HWTYPE) &&
  841. (MHdr->Protocol == IP_PROTOCOL_TYPE) &&
  842. ArpSReferenceVc(Vc, TRUE))
  843. {
  844. Mars = TRUE;
  845. ValidPkt = TRUE;
  846. }
  847. break;
  848. }
  849. else
  850. {
  851. DBGPRINT(DBG_LEVEL_ERROR,
  852. ("ArpSHandleArpRequest: Invalid Llc Snap Hdr\n"));
  853. break;
  854. }
  855. Tmp = sizeof(ARPS_HEADER) +
  856. Header->SrcProtoAddrLen + TL_LEN(Header->SrcAddressTL) + TL_LEN(Header->SrcSubAddrTL) +
  857. Header->DstProtoAddrLen + TL_LEN(Header->DstAddressTL) + TL_LEN(Header->DstSubAddrTL);
  858. //
  859. // Make sure the address and sub-address formats are consistent.
  860. // The valid ones from the RFC:
  861. //
  862. // Adress Sub-Address
  863. // ------ -----------
  864. //
  865. // Structure 1 ATM Forum NSAP Null
  866. // Structure 2 E.164 Null
  867. // Structure 3 E.164 ATM Forum NSAP
  868. //
  869. if (TL_LEN(Header->SrcSubAddrTL) > 0)
  870. {
  871. //
  872. // Sub-address is present. Make sure that the Address is E.164 and Sub-Address is NSAP
  873. //
  874. if ((TL_TYPE(Header->SrcAddressTL) == ADDR_TYPE_NSAP) ||
  875. (TL_TYPE(Header->SrcSubAddrTL) == ADDR_TYPE_E164))
  876. {
  877. DBGPRINT(DBG_LEVEL_ERROR,
  878. ("ArpSHandleArpRequest: Src Address is NSAP and Src Sub Addr is E164\n"));
  879. break;
  880. }
  881. }
  882. if (TL_LEN(Header->DstSubAddrTL) > 0)
  883. {
  884. //
  885. // Sub-address is present. Make sure that the Address is E.164 and Sub-Address is NSAP
  886. //
  887. if ((TL_TYPE(Header->DstAddressTL) == ADDR_TYPE_NSAP) ||
  888. (TL_TYPE(Header->DstSubAddrTL) == ADDR_TYPE_E164))
  889. {
  890. DBGPRINT(DBG_LEVEL_ERROR,
  891. ("ArpSHandleArpRequest: Dst Address is NSAP and Dst Sub Addr is E164\n"));
  892. break;
  893. }
  894. }
  895. if ((Header->Opcode == ATMARP_Request) &&
  896. (Header->HwType == ATM_HWTYPE) &&
  897. (Header->Protocol == IP_PROTOCOL_TYPE) &&
  898. (PktLen >= Tmp) &&
  899. ArpSReferenceVc(Vc, TRUE))
  900. {
  901. ValidPkt = TRUE;
  902. break;
  903. }
  904. #if DBG
  905. else
  906. {
  907. if (Header->Opcode != ATMARP_Request)
  908. {
  909. DBGPRINT(DBG_LEVEL_ERROR,
  910. ("ArpSHandleArpRequest: Invalid OpCode %x\n", Header->Opcode));
  911. }
  912. else if (Header->HwType != ATM_HWTYPE)
  913. {
  914. DBGPRINT(DBG_LEVEL_ERROR,
  915. ("ArpSHandleArpRequest: Invalid HwType %x\n", Header->HwType));
  916. }
  917. else if (Header->Protocol == IP_PROTOCOL_TYPE)
  918. {
  919. DBGPRINT(DBG_LEVEL_ERROR,
  920. ("ArpSHandleArpRequest: Invalid Protocol %x\n", Header->Protocol));
  921. }
  922. else if (PktLen < Tmp)
  923. {
  924. DBGPRINT(DBG_LEVEL_ERROR,
  925. ("ArpSHandleArpRequest: Invalid Length %x - %x\n", PktLen, Tmp));
  926. }
  927. else
  928. {
  929. DBGPRINT(DBG_LEVEL_ERROR,
  930. ("ArpSHandleArpRequest: Cannot reference Vc\n"));
  931. }
  932. }
  933. #endif
  934. } while (FALSE);
  935. if (ValidPkt)
  936. {
  937. Resd->Vc = Vc;
  938. if (Mars)
  939. {
  940. Resd->Flags |= RESD_FLAG_MARS;
  941. KeInsertQueue(&MarsReqQueue, &Resd->ReqList);
  942. }
  943. else
  944. {
  945. Resd->Flags &= ~RESD_FLAG_MARS;
  946. KeInsertQueue(&ArpSReqQueue, &Resd->ReqList);
  947. }
  948. }
  949. else
  950. {
  951. //
  952. // Either a mal-formed packet or the Vc is closing
  953. //
  954. pIntF->ArpStats.DiscardedRecvPkts++;
  955. ArpSDumpPacket((PUCHAR)Header, PktLen);
  956. //
  957. // Move the packet back into the free list
  958. //
  959. ExInterlockedPushEntrySList(&ArpSPktList,
  960. &Resd->FreeList,
  961. &ArpSPktListLock);
  962. }
  963. } while (FALSE);
  964. return ReturnValue;
  965. }
  966. PARP_ENTRY
  967. ArpSLookupEntryByIpAddr(
  968. IN PINTF pIntF,
  969. IN IPADDR IpAddr
  970. )
  971. /*++
  972. Routine Description:
  973. Lookup the Arp table for the specified IP address. Called with the ArpCache mutex held.
  974. Arguments:
  975. pIntF Pointer to the IntF structure
  976. IpAddr IP address to look for
  977. Return Value:
  978. ArpEntry if found or NULL.
  979. --*/
  980. {
  981. PARP_ENTRY ArpEntry;
  982. UINT Hash = ARP_HASH(IpAddr);
  983. ARPS_PAGED_CODE( );
  984. DBGPRINT(DBG_LEVEL_INFO,
  985. ("ArpSLookupArpEntry: Lookup entry for IpAddr: "));
  986. ArpSDumpIpAddr(IpAddr, " ..... ");
  987. for (ArpEntry = pIntF->ArpCache[Hash];
  988. ArpEntry != NULL;
  989. ArpEntry = ArpEntry->Next)
  990. {
  991. if (ArpEntry->IpAddr == IpAddr)
  992. break;
  993. if (ArpEntry->IpAddr > IpAddr)
  994. {
  995. ArpEntry = NULL;
  996. break;
  997. }
  998. }
  999. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  1000. ("%sFound\n", (ArpEntry != NULL) ? "" : "Not"));
  1001. if (ArpEntry != NULL)
  1002. {
  1003. //
  1004. // Cleanup this entry if the Vc is no-longer active
  1005. //
  1006. CLEANUP_DEAD_VC(ArpEntry);
  1007. }
  1008. return ArpEntry;
  1009. }
  1010. PARP_ENTRY
  1011. ArpSLookupEntryByAtmAddr(
  1012. IN PINTF pIntF,
  1013. IN PATM_ADDRESS Address,
  1014. IN PATM_ADDRESS SubAddress OPTIONAL
  1015. )
  1016. /*++
  1017. Routine Description:
  1018. Lookup the Arp table for the specified IP address. Called with the ArpCache mutex held.
  1019. Arguments:
  1020. pIntF Pointer to the IntF structure
  1021. IpAddr IP address to look for
  1022. Return Value:
  1023. ArpEntry if found or NULL.
  1024. --*/
  1025. {
  1026. PARP_ENTRY ArpEntry;
  1027. UINT i;
  1028. ARPS_PAGED_CODE( );
  1029. DBGPRINT(DBG_LEVEL_INFO,
  1030. ("ArpSLookupArpEntry: Lookup entry for "));
  1031. ArpSDumpAtmAddr(Address, " ..... ");
  1032. if (SubAddress != NULL)
  1033. {
  1034. ArpSDumpAtmAddr(SubAddress, "\t Sub ");
  1035. }
  1036. for (i =0; i < ARP_TABLE_SIZE; i++)
  1037. {
  1038. for (ArpEntry = pIntF->ArpCache[i];
  1039. ArpEntry != NULL;
  1040. ArpEntry = ArpEntry->Next)
  1041. {
  1042. if (COMP_ATM_ADDR(Address, &ArpEntry->HwAddr.Address))
  1043. {
  1044. if (((SubAddress == NULL) && (ArpEntry->HwAddr.SubAddress == NULL)) ||
  1045. (((SubAddress != NULL) && (ArpEntry->HwAddr.SubAddress != NULL)) &&
  1046. COMP_ATM_ADDR(SubAddress, ArpEntry->HwAddr.SubAddress)))
  1047. {
  1048. break;
  1049. }
  1050. }
  1051. }
  1052. if (ArpEntry != NULL)
  1053. {
  1054. //
  1055. // Cleanup this entry if the Vc is no-longer active
  1056. //
  1057. CLEANUP_DEAD_VC(ArpEntry);
  1058. break;
  1059. }
  1060. }
  1061. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  1062. ("ArpSLookupArpEntry: %sFound\n", (ArpEntry != NULL) ? "" : "Not"));
  1063. return ArpEntry;
  1064. }
  1065. PARP_ENTRY
  1066. ArpSAddArpEntry(
  1067. IN PINTF pIntF,
  1068. IN IPADDR IpAddr,
  1069. IN PATM_ADDRESS Address,
  1070. IN PATM_ADDRESS SubAddress OPTIONAL,
  1071. IN PARP_VC Vc OPTIONAL
  1072. )
  1073. /*++
  1074. Routine Description:
  1075. Add the Arp table for the specified IP address. Called with the ArpCache mutex held.
  1076. Arguments:
  1077. pIntF Pointer to the IntF structure
  1078. IpAddr IP address to add
  1079. Address &
  1080. SubAddress Supplies the atm address and the sub-address
  1081. Vc The Vc associated with this ArpEntry, if any
  1082. Return Value:
  1083. ArpEntry if added successfully or NULL.
  1084. --*/
  1085. {
  1086. PARP_ENTRY ArpEntry, *ppEntry;
  1087. UINT Hash = ARP_HASH(IpAddr);
  1088. ENTRY_TYPE EntryType;
  1089. ARPS_PAGED_CODE( );
  1090. DBGPRINT(DBG_LEVEL_INFO,
  1091. ("ArpSAddArpEntry: Adding entry for IpAddr: "));
  1092. ArpSDumpIpAddr(IpAddr, " ..... ");
  1093. //
  1094. // Start off by allocating an arp-entry structure
  1095. //
  1096. EntryType = (SubAddress != NULL) ? ARP_BLOCK_SUBADDR : ARP_BLOCK_VANILA;
  1097. ArpEntry = (PARP_ENTRY)ArpSAllocBlock(pIntF, EntryType);
  1098. if (ArpEntry == NULL)
  1099. {
  1100. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1101. }
  1102. else
  1103. {
  1104. if (++(pIntF->ArpStats.CurrentArpEntries) > pIntF->ArpStats.MaxArpEntries)
  1105. {
  1106. pIntF->ArpStats.MaxArpEntries = pIntF->ArpStats.CurrentArpEntries;
  1107. }
  1108. ArpSTimerInitialize(&ArpEntry->Timer, ArpSAgeEntry, ARP_AGE);
  1109. ArpEntry->IpAddr = IpAddr;
  1110. COPY_ATM_ADDR(&ArpEntry->HwAddr.Address, Address);
  1111. if (SubAddress != NULL)
  1112. COPY_ATM_ADDR(ArpEntry->HwAddr.SubAddress, SubAddress);
  1113. if (ARGUMENT_PRESENT(Vc) && ArpSReferenceVc(Vc, FALSE))
  1114. {
  1115. ArpEntry->Vc = Vc;
  1116. Vc->ArpEntry = ArpEntry;
  1117. }
  1118. ArpEntry->Age = ARP_AGE;
  1119. //
  1120. // Keep the overflow list sorted in ascending order of Ip addresses
  1121. //
  1122. for (ppEntry = &pIntF->ArpCache[Hash];
  1123. *ppEntry != NULL;
  1124. ppEntry = (PARP_ENTRY *)(&(*ppEntry)->Next))
  1125. {
  1126. ASSERT ((*ppEntry)->IpAddr != IpAddr);
  1127. if ((*ppEntry)->IpAddr > IpAddr)
  1128. break;
  1129. }
  1130. ArpEntry->Next = *ppEntry;
  1131. ArpEntry->Prev = ppEntry;
  1132. if (*ppEntry != NULL)
  1133. {
  1134. (*ppEntry)->Prev = &ArpEntry->Next;
  1135. }
  1136. *ppEntry = ArpEntry;
  1137. pIntF->NumCacheEntries ++;
  1138. ArpSTimerEnqueue(pIntF, &ArpEntry->Timer);
  1139. }
  1140. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("%lx\n", ArpEntry));
  1141. return ArpEntry;
  1142. }
  1143. PARP_ENTRY
  1144. ArpSAddArpEntryFromDisk(
  1145. IN PINTF pIntF,
  1146. IN PDISK_ENTRY pDskEntry
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. Add the Arp table for the specified IP address. Called during intialization.
  1151. Arguments:
  1152. pIntF Pointer to the IntF structure
  1153. DiskEntry
  1154. Return Value:
  1155. ArpEntry if found or NULL.
  1156. --*/
  1157. {
  1158. PARP_ENTRY ArpEntry, *ppEntry;
  1159. UINT Hash = ARP_HASH(pDskEntry->IpAddr);
  1160. ENTRY_TYPE EntryType;
  1161. ARPS_PAGED_CODE( );
  1162. DBGPRINT(DBG_LEVEL_INFO,
  1163. ("ArpSAddArpEntryFromDisk: Adding entry for IpAddr: "));
  1164. ArpSDumpIpAddr(pDskEntry->IpAddr, " ..... ");
  1165. //
  1166. // Start off by allocating an arp-entry structure
  1167. //
  1168. EntryType = (pDskEntry->AtmAddr.SubAddrLen != 0) ? ARP_BLOCK_SUBADDR : ARP_BLOCK_VANILA;
  1169. ArpEntry = (PARP_ENTRY)ArpSAllocBlock(pIntF, EntryType);
  1170. if (ArpEntry == NULL)
  1171. {
  1172. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1173. }
  1174. else
  1175. {
  1176. ArpSTimerInitialize(&ArpEntry->Timer, ArpSAgeEntry, ARP_AGE);
  1177. ArpEntry->Age = ARP_AGE;
  1178. ArpEntry->IpAddr = pDskEntry->IpAddr;
  1179. ArpEntry->Vc = NULL;
  1180. //
  1181. // COPY_ATM_ADDR();
  1182. //
  1183. ArpEntry->HwAddr.Address.AddressType = pDskEntry->AtmAddr.AddrType;
  1184. ArpEntry->HwAddr.Address.NumberOfDigits = pDskEntry->AtmAddr.AddrLen;
  1185. COPY_MEM(ArpEntry->HwAddr.Address.Address, pDskEntry->AtmAddr.Address, pDskEntry->AtmAddr.AddrLen);
  1186. if (pDskEntry->AtmAddr.SubAddrLen != 0)
  1187. {
  1188. //
  1189. // COPY_ATM_ADDR();
  1190. //
  1191. ArpEntry->HwAddr.SubAddress->AddressType = pDskEntry->AtmAddr.SubAddrType;
  1192. ArpEntry->HwAddr.SubAddress->NumberOfDigits = pDskEntry->AtmAddr.SubAddrLen;
  1193. COPY_MEM(ArpEntry->HwAddr.SubAddress->Address,
  1194. (PUCHAR)pDskEntry + sizeof(DISK_ENTRY),
  1195. pDskEntry->AtmAddr.SubAddrLen);
  1196. }
  1197. //
  1198. // Keep the overflow list sorted in ascending order of Ip addresses
  1199. //
  1200. for (ppEntry = &pIntF->ArpCache[Hash];
  1201. *ppEntry != NULL;
  1202. ppEntry = (PARP_ENTRY *)(&(*ppEntry)->Next))
  1203. {
  1204. ASSERT ((*ppEntry)->IpAddr != pDskEntry->IpAddr);
  1205. if ((*ppEntry)->IpAddr > pDskEntry->IpAddr)
  1206. break;
  1207. }
  1208. ArpEntry->Next = *ppEntry;
  1209. ArpEntry->Prev = ppEntry;
  1210. if (*ppEntry != NULL)
  1211. {
  1212. (*ppEntry)->Prev = &ArpEntry->Next;
  1213. }
  1214. *ppEntry = ArpEntry;
  1215. pIntF->NumCacheEntries ++;
  1216. ArpSTimerEnqueue(pIntF, &ArpEntry->Timer);
  1217. }
  1218. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("%lx\n", ArpEntry));
  1219. return ArpEntry;
  1220. }
  1221. VOID
  1222. ArpSUpdateArpEntry(
  1223. IN PINTF pIntF,
  1224. IN PARP_ENTRY ArpEntry,
  1225. IN IPADDR IpAddr,
  1226. IN PHW_ADDR HwAddr,
  1227. IN PARP_VC Vc
  1228. )
  1229. /*++
  1230. Routine Description:
  1231. Update the ArpEntry with possibly new values.
  1232. Arguments:
  1233. ArpEntry ArpEntry to be updated
  1234. IpAddr IP Address
  1235. HwAddr Hw address (Atm Address and optionally Atm SubAddress)
  1236. Vc Vc associated with this entry
  1237. Return Value:
  1238. None
  1239. --*/
  1240. {
  1241. KIRQL OldIrql;
  1242. DBGPRINT(DBG_LEVEL_INFO,
  1243. ("ArpSUpdateArpEntry: Adding entry for IpAddr: "));
  1244. ArpSDumpIpAddr(IpAddr, " ..... ");
  1245. ASSERT ((ArpEntry->Vc == NULL) || (ArpEntry->Vc == Vc));
  1246. ASSERT (ArpEntry->IpAddr == IpAddr);
  1247. //
  1248. // If the Hw address changed, make sure that there is enough space there to copy the new address
  1249. //
  1250. if ((HwAddr->SubAddress != NULL) ^ (ArpEntry->HwAddr.SubAddress != NULL))
  1251. {
  1252. PARP_ENTRY *ppEntry, ArpEntryNew;
  1253. //
  1254. // Need to allocate a new ArpEntry. First de-queue the current
  1255. // entry from the list and cancel the timer.
  1256. //
  1257. ArpSTimerCancel(&ArpEntry->Timer);
  1258. *(ArpEntry->Prev) = ArpEntry->Next;
  1259. if (ArpEntry->Next != NULL)
  1260. ((PENTRY_HDR)(ArpEntry->Next))->Prev = ArpEntry->Prev;
  1261. pIntF->NumCacheEntries --;
  1262. //
  1263. // We create the new ArpEntry with a NULL Vc and then update it. This is to avoid
  1264. // de-ref and ref of the Vc again.
  1265. //
  1266. ArpEntryNew = ArpSAddArpEntry(pIntF, IpAddr, &HwAddr->Address, HwAddr->SubAddress, NULL);
  1267. if (ArpEntryNew == NULL)
  1268. {
  1269. //
  1270. // Allocation failure, link back the old entry and bail out.
  1271. //
  1272. if (ArpEntry->Next != NULL)
  1273. {
  1274. ((PENTRY_HDR)(ArpEntry->Next))->Prev = &ArpEntry;
  1275. }
  1276. *(ArpEntry->Prev) = ArpEntry;
  1277. ArpSTimerInitialize(&ArpEntry->Timer, ArpSAgeEntry, ARP_AGE);
  1278. pIntF->NumCacheEntries ++;
  1279. return;
  1280. }
  1281. //
  1282. // Update with the existing Vc for now.
  1283. //
  1284. ArpEntryNew->Vc = ArpEntry->Vc;
  1285. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1286. ASSERT((Vc->ArpEntry == ArpEntry) || (Vc->ArpEntry == NULL));
  1287. if (Vc->Flags & ARPVC_ACTIVE)
  1288. {
  1289. Vc->ArpEntry = ArpEntryNew;
  1290. }
  1291. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1292. ArpSFreeBlock(ArpEntry);
  1293. ArpEntry = ArpEntryNew;
  1294. }
  1295. else
  1296. {
  1297. ArpEntry->Age = ARP_AGE;
  1298. }
  1299. if (ArpEntry->Vc != Vc)
  1300. {
  1301. ASSERT(ArpEntry->Vc == NULL);
  1302. if (ArpSReferenceVc(Vc, FALSE))
  1303. {
  1304. ArpEntry->Vc = Vc;
  1305. }
  1306. }
  1307. COPY_HW_ADDR(&ArpEntry->HwAddr, HwAddr);
  1308. }
  1309. VOID
  1310. ArpSBuildArpReply(
  1311. IN PINTF pIntF,
  1312. IN PARP_ENTRY ArpEntry,
  1313. IN PARPS_HEADER Header,
  1314. IN PNDIS_PACKET Pkt
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. Arguments:
  1319. Return Value:
  1320. None
  1321. --*/
  1322. {
  1323. PUCHAR pSrc, pDst, pDstOld;
  1324. UINT Tmp, SrcLenOld, SrcLenNew, DstLenNew;
  1325. //
  1326. // Most of the fields are already valid (or else we will not be here)
  1327. //
  1328. Header->Opcode = ATMARP_Reply;
  1329. pSrc = (PUCHAR)Header + sizeof(ARPS_HEADER);
  1330. SrcLenOld = DstLenNew = IP_ADDR_LEN + TL_LEN(Header->SrcAddressTL) + TL_LEN(Header->SrcSubAddrTL);
  1331. SrcLenNew = IP_ADDR_LEN + ArpEntry->HwAddr.Address.NumberOfDigits;
  1332. if (ArpEntry->HwAddr.SubAddress != NULL)
  1333. SrcLenNew += ArpEntry->HwAddr.SubAddress->NumberOfDigits;
  1334. pDst = pSrc + SrcLenNew;
  1335. //
  1336. // Fill in the new destination fields from the source fields of the request
  1337. //
  1338. Header->DstAddressTL = Header->SrcAddressTL;
  1339. Header->DstSubAddrTL = Header->SrcSubAddrTL;
  1340. Header->DstProtoAddrLen = Header->SrcProtoAddrLen;
  1341. MOVE_MEM(pDst, pSrc, DstLenNew);
  1342. //
  1343. // Fill in the destination fields
  1344. //
  1345. Header->DstAddressTL = TL(ArpEntry->HwAddr.Address.AddressType, ArpEntry->HwAddr.Address.NumberOfDigits);
  1346. Header->DstSubAddrTL = 0;
  1347. if (ArpEntry->HwAddr.SubAddress != NULL)
  1348. {
  1349. Header->DstSubAddrTL =
  1350. TL(ArpEntry->HwAddr.SubAddress->AddressType, ArpEntry->HwAddr.SubAddress->NumberOfDigits);
  1351. }
  1352. Header->DstProtoAddrLen = IP_ADDR_LEN;
  1353. Tmp = ArpEntry->HwAddr.Address.NumberOfDigits;
  1354. COPY_MEM(pSrc, ArpEntry->HwAddr.Address.Address, Tmp);
  1355. if (ArpEntry->HwAddr.SubAddress != NULL)
  1356. {
  1357. COPY_MEM(pSrc + Tmp,
  1358. ArpEntry->HwAddr.SubAddress->Address,
  1359. ArpEntry->HwAddr.SubAddress->NumberOfDigits);
  1360. Tmp += ArpEntry->HwAddr.SubAddress->NumberOfDigits;
  1361. }
  1362. *(UNALIGNED IPADDR *)(pSrc + Tmp) = ArpEntry->IpAddr;
  1363. DBGPRINT(DBG_LEVEL_INFO,
  1364. ("BuildReply: Pkt=0x%lx MDL=0x%lx: sz=%lu bc=%lu bo=%lu new bc=%lu\n",
  1365. Pkt,
  1366. Pkt->Private.Head,
  1367. Pkt->Private.Head->Size,
  1368. Pkt->Private.Head->ByteCount,
  1369. Pkt->Private.Head->ByteOffset,
  1370. SrcLenNew + DstLenNew + sizeof(ARPS_HEADER)));
  1371. //
  1372. // Finally set the Pkt length correctly
  1373. //
  1374. NdisAdjustBufferLength(Pkt->Private.Head, SrcLenNew + DstLenNew + sizeof(ARPS_HEADER));
  1375. Pkt->Private.ValidCounts = FALSE;
  1376. }
  1377. BOOLEAN
  1378. ArpSAgeEntry(
  1379. IN PINTF pIntF,
  1380. IN PTIMER Timer,
  1381. IN BOOLEAN TimerShuttingDown
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. Check this ARP entry and if it ages out, free it.
  1386. Arguments:
  1387. Return Value:
  1388. --*/
  1389. {
  1390. PARP_ENTRY ArpEntry;
  1391. BOOLEAN rc;
  1392. ArpEntry = CONTAINING_RECORD(Timer, ARP_ENTRY, Timer);
  1393. ArpEntry->Age --;
  1394. if (TimerShuttingDown || (ArpEntry->Age == 0))
  1395. {
  1396. DBGPRINT(DBG_LEVEL_INFO,
  1397. ("ArpSAgeEntry: Aging out entry for IpAddr %lx\n", ArpEntry->IpAddr));
  1398. pIntF->ArpStats.CurrentArpEntries--;
  1399. if (ArpEntry->Next != NULL)
  1400. {
  1401. ((PENTRY_HDR)(ArpEntry->Next))->Prev = ArpEntry->Prev;
  1402. }
  1403. *(ArpEntry->Prev) = ArpEntry->Next;
  1404. pIntF->NumCacheEntries --;
  1405. //
  1406. // if there is an open Vc, make sure it is not pointing to this arpentry
  1407. //
  1408. CLEANUP_DEAD_VC(ArpEntry);
  1409. ArpSFreeBlock(ArpEntry);
  1410. rc = FALSE;
  1411. }
  1412. else
  1413. {
  1414. //
  1415. // Cleanup dead vcs
  1416. //
  1417. CLEANUP_DEAD_VC(ArpEntry);
  1418. rc = TRUE;
  1419. DBGPRINT(DBG_LEVEL_INFO,
  1420. ("ArpSAgeEntry: IpAddr %lx age %02d:%02d\n",
  1421. ArpEntry->IpAddr, ArpEntry->Age/4, (ArpEntry->Age % 4) * 15));
  1422. }
  1423. return rc;
  1424. }
  1425. BOOLEAN
  1426. ArpSDeleteIntFAddresses(
  1427. IN PINTF pIntF,
  1428. IN INT NumAddresses,
  1429. IN PATM_ADDRESS AddrList
  1430. )
  1431. //
  1432. // Return TRUE IFF the NdisCoRequest has been called EXACTLY NumAddresses times.
  1433. //
  1434. {
  1435. PNDIS_REQUEST NdisRequest;
  1436. NDIS_STATUS Status;
  1437. PCO_ADDRESS pCoAddr;
  1438. DBGPRINT(DBG_LEVEL_INFO,
  1439. ("ArpSDeleteIntFAddresses: pIntF %p: %Z, NumAddr %d\n", pIntF, &pIntF->InterfaceName, NumAddresses));
  1440. while (NumAddresses--)
  1441. {
  1442. NdisRequest = ALLOC_NP_MEM(sizeof(NDIS_REQUEST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS), POOL_TAG_REQ);
  1443. if (NdisRequest == NULL)
  1444. {
  1445. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1446. return FALSE;
  1447. }
  1448. ZERO_MEM(NdisRequest, sizeof(NDIS_REQUEST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS));
  1449. NdisRequest->RequestType = NdisRequestSetInformation;
  1450. NdisRequest->DATA.SET_INFORMATION.Oid = OID_CO_DELETE_ADDRESS;
  1451. NdisRequest->DATA.SET_INFORMATION.InformationBuffer = (PUCHAR)NdisRequest + sizeof(NDIS_REQUEST);
  1452. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  1453. //
  1454. // Copy the address into the request
  1455. //
  1456. pCoAddr = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
  1457. pCoAddr->AddressSize = sizeof(ATM_ADDRESS);
  1458. *(PATM_ADDRESS)(pCoAddr->Address) = *AddrList++;
  1459. Status = NdisCoRequest(pIntF->NdisBindingHandle,
  1460. pIntF->NdisAfHandle,
  1461. NULL,
  1462. NULL,
  1463. NdisRequest);
  1464. if (Status != NDIS_STATUS_PENDING)
  1465. {
  1466. ArpSCoRequestComplete(Status, pIntF, NULL, NULL, NdisRequest);
  1467. }
  1468. }
  1469. return TRUE;
  1470. }
  1471. VOID
  1472. ArpSQueryAndSetAddresses(
  1473. IN PINTF pIntF
  1474. )
  1475. {
  1476. PNDIS_REQUEST NdisRequest;
  1477. PCO_ADDRESS pCoAddr;
  1478. NDIS_STATUS Status;
  1479. UINT Size;
  1480. DBGPRINT(DBG_LEVEL_INFO, ("Querying current address\n"));
  1481. //
  1482. // Allocate a request to query the configured address
  1483. //
  1484. Size = sizeof(NDIS_REQUEST) + sizeof(CO_ADDRESS_LIST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  1485. NdisRequest = ALLOC_NP_MEM(Size, POOL_TAG_REQ);
  1486. if (NdisRequest == NULL)
  1487. {
  1488. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1489. return;
  1490. }
  1491. ZERO_MEM(NdisRequest, Size);
  1492. NdisRequest->RequestType = NdisRequestQueryInformation;
  1493. NdisRequest->DATA.QUERY_INFORMATION.Oid = OID_CO_GET_ADDRESSES;
  1494. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = ((PUCHAR)NdisRequest + sizeof(NDIS_REQUEST));
  1495. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size - sizeof(NDIS_REQUEST);
  1496. Status = NdisCoRequest(pIntF->NdisBindingHandle,
  1497. pIntF->NdisAfHandle,
  1498. NULL,
  1499. NULL,
  1500. NdisRequest);
  1501. if (Status != NDIS_STATUS_PENDING)
  1502. {
  1503. ArpSCoRequestComplete(Status, pIntF, NULL, NULL, NdisRequest);
  1504. }
  1505. }
  1506. VOID
  1507. ArpSValidateAndSetRegdAddresses(
  1508. IN PINTF pIntF, // LOCKIN NOLOCKOUT
  1509. IN KIRQL OldIrql
  1510. )
  1511. /*++
  1512. Initiate the 1st step of the following operations, which complete asynchronously
  1513. and in order:
  1514. - Validate 1st address to be registered (by making a call to the dest - if
  1515. it fails we consider the address validated).
  1516. - (on successful validation) Register the address with the call manager.
  1517. - Validate the 2nd address
  1518. - (on successful validation) Register the 2nd address
  1519. - etc..
  1520. --*/
  1521. {
  1522. PNDIS_REQUEST NdisRequest;
  1523. PCO_ADDRESS pCoAddr;
  1524. UINT Size;
  1525. INT fLockReleased;
  1526. PREG_ADDR_CTXT pRegAddrCtxt;
  1527. DBGPRINT(DBG_LEVEL_INFO, ("Validating and setting regd. addresses\n"));
  1528. pRegAddrCtxt = NULL;
  1529. fLockReleased = FALSE;
  1530. do
  1531. {
  1532. //
  1533. // The state on the ongoing validation and registration process is
  1534. // maintained in pIntF->pRegAddrCtxt, which we allocate and initialize
  1535. // here.
  1536. //
  1537. if (pIntF->pRegAddrCtxt != NULL)
  1538. {
  1539. //
  1540. // There is ongoing work relating to registering already!
  1541. // This could happen if we get an OID_CO_ADDRESS_CHANGE when we are
  1542. // either processing an earlier one, or are in the process of
  1543. // initializing. We get these cases during pnp stress
  1544. // ( 1c_reset script against an Olicom 616X) -- Whistler bug#102805
  1545. //
  1546. break;
  1547. }
  1548. if (pIntF->NumAddressesRegd >= pIntF->NumAllocedRegdAddresses)
  1549. {
  1550. ASSERT(pIntF->NumAddressesRegd == pIntF->NumAllocedRegdAddresses);
  1551. //
  1552. // No addresses to register.
  1553. //
  1554. DBGPRINT(DBG_LEVEL_INFO, ("ValAndSet: No addresses to register.\n"));
  1555. break;
  1556. }
  1557. pRegAddrCtxt = ALLOC_NP_MEM(sizeof(*pRegAddrCtxt), POOL_TAG_REQ);
  1558. if (pRegAddrCtxt == NULL)
  1559. {
  1560. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1561. break;
  1562. }
  1563. ZERO_MEM(pRegAddrCtxt, sizeof(*pRegAddrCtxt));
  1564. //
  1565. // Attach the context to the IF and add a reference.
  1566. // (Can't have the lock when adding the reference)
  1567. //
  1568. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1569. if (!ArpSReferenceIntF(pIntF))
  1570. {
  1571. DBGPRINT(DBG_LEVEL_INFO, ("ValAndSet: ERROR: Couldn't ref IntF. .\n"));
  1572. // Couldn't reference the IF. Fail.
  1573. //
  1574. fLockReleased = TRUE;
  1575. break;
  1576. }
  1577. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1578. if (pIntF->pRegAddrCtxt != NULL)
  1579. {
  1580. //
  1581. // Someone snuck in while we unlocked the IF above!
  1582. // We bail out.
  1583. //
  1584. ASSERT(FALSE);
  1585. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1586. ArpSDereferenceIntF(pIntF);
  1587. fLockReleased = TRUE;
  1588. break;
  1589. }
  1590. pIntF->pRegAddrCtxt = pRegAddrCtxt;
  1591. pRegAddrCtxt->pIntF = pIntF;
  1592. pRegAddrCtxt = NULL; // so that it is not deallocated in this function.
  1593. // Initiate the validation and registration of the first address.
  1594. //
  1595. ArpSValidateOneRegdAddress(pIntF, OldIrql);
  1596. //
  1597. // (Lock released by above call.)
  1598. fLockReleased = TRUE;
  1599. //
  1600. // The remainder of the validation and registration process happens
  1601. // asynchronously.
  1602. //
  1603. } while (FALSE);
  1604. if (pRegAddrCtxt != NULL)
  1605. {
  1606. FREE_MEM(pRegAddrCtxt);
  1607. }
  1608. if (!fLockReleased)
  1609. {
  1610. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1611. }
  1612. }
  1613. VOID
  1614. ArpSValidateOneRegdAddress(
  1615. IN PINTF pIntF, // LOCKIN NOLOCKOUT
  1616. IN KIRQL OldIrql
  1617. )
  1618. /*++
  1619. Routine Description:
  1620. Initiates the validation and registration of a single address.
  1621. "Initiate" consists of creating a vc and making a call to the address. The
  1622. next step in the process happens after the make call completes
  1623. (see 05/14/1999 notes.txt entry ("Rogue ARP server detection contd."))
  1624. for more details.
  1625. One more thing: If there are no addresses to be validated, then
  1626. this function will DEREF pIntF and FREE pIntF->pRegAddrCtxt (which
  1627. MUST be NON-NULL).
  1628. Arguments:
  1629. pIntF Pointer to the interface block.
  1630. OldIrql Irql before pIntF was locked.
  1631. --*/
  1632. {
  1633. NDIS_STATUS Status;
  1634. INT fLockReleased = FALSE;
  1635. INT fFreeContext = TRUE;
  1636. DBGPRINT(
  1637. DBG_LEVEL_INFO,
  1638. ("==>ValidateOneRegAddress(pIntF=0x%p; pCtxt=0x%p).\n",
  1639. pIntF,
  1640. pIntF->pRegAddrCtxt));
  1641. do
  1642. {
  1643. PREG_ADDR_CTXT pRegAddrCtxt;
  1644. PATM_ADDRESS pDestAtmAddress;
  1645. pRegAddrCtxt = pIntF->pRegAddrCtxt;
  1646. // We expect to be called only if there is a valid pRegAddrCtxt.
  1647. //
  1648. if (pRegAddrCtxt == NULL)
  1649. {
  1650. ASSERT(FALSE);
  1651. fFreeContext = FALSE;
  1652. break;
  1653. }
  1654. if (pIntF->Flags & INTF_STOPPING)
  1655. {
  1656. DBGPRINT(DBG_LEVEL_INFO, ("ValOneRA: IF stopping, quitting.\n"));
  1657. // Nothing left to do.
  1658. //
  1659. break;
  1660. }
  1661. if (pIntF->NumAddressesRegd >= pIntF->NumAllocedRegdAddresses)
  1662. {
  1663. DBGPRINT(DBG_LEVEL_INFO, ("ValOneRA: nothing left to do.\n"));
  1664. // Nothing left to do.
  1665. //
  1666. break;
  1667. }
  1668. if (pIntF->NumAddressesRegd > pRegAddrCtxt->RegAddrIndex)
  1669. {
  1670. // This should never happen.
  1671. //
  1672. ASSERT(FALSE);
  1673. break;
  1674. }
  1675. if (pIntF->NumAllocedRegdAddresses <= pRegAddrCtxt->RegAddrIndex)
  1676. {
  1677. ASSERT(pIntF->NumAllocedRegdAddresses == pRegAddrCtxt->RegAddrIndex);
  1678. DBGPRINT(DBG_LEVEL_INFO, ("ValOneRA: nothing left to do.\n"));
  1679. // Nothing left to do.
  1680. //
  1681. break;
  1682. }
  1683. if (pRegAddrCtxt->NdisVcHandle != NULL)
  1684. {
  1685. // We shouldn't be called with a non-null VcHandle.
  1686. //
  1687. fFreeContext = FALSE;
  1688. ASSERT(FALSE);
  1689. break;
  1690. }
  1691. // TODO: use the Flags field.
  1692. //
  1693. // There is at least one address to try to validate & register. It
  1694. // is pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex].
  1695. //
  1696. // Create VC
  1697. //
  1698. Status = NdisCoCreateVc(
  1699. pIntF->NdisBindingHandle,
  1700. pIntF->NdisAfHandle,
  1701. (NDIS_HANDLE)pRegAddrCtxt,
  1702. &pRegAddrCtxt->NdisVcHandle
  1703. );
  1704. if (Status != NDIS_STATUS_SUCCESS)
  1705. {
  1706. pRegAddrCtxt->NdisVcHandle = NULL;
  1707. break;
  1708. }
  1709. // Set the VC type.
  1710. //
  1711. pRegAddrCtxt->VcType = VC_TYPE_CHECK_REGADDR;
  1712. // Setup call params
  1713. //
  1714. pDestAtmAddress = &(pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex]);
  1715. ArpSSetupValidationCallParams(pRegAddrCtxt, pDestAtmAddress);
  1716. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1717. fLockReleased = TRUE;
  1718. fFreeContext = FALSE;
  1719. DBGPRINT(
  1720. DBG_LEVEL_INFO,
  1721. ("ValOneRA: Going to make call. pCallParams=0x%p\n",
  1722. &pRegAddrCtxt->CallParams));
  1723. //
  1724. // Make Call (in call complete handler we move on to the next step --
  1725. // see 05/14/1999 notes.txt entry for details.)
  1726. //
  1727. Status = NdisClMakeCall(
  1728. pRegAddrCtxt->NdisVcHandle,
  1729. &pRegAddrCtxt->CallParams,
  1730. NULL,
  1731. NULL
  1732. );
  1733. if (Status != NDIS_STATUS_PENDING)
  1734. {
  1735. ArpSMakeRegAddrCallComplete(
  1736. Status,
  1737. pRegAddrCtxt
  1738. );
  1739. Status = NDIS_STATUS_PENDING;
  1740. }
  1741. } while (FALSE);
  1742. if (fFreeContext)
  1743. {
  1744. ASSERT(!fLockReleased);
  1745. //
  1746. // If there is nothing more to be done, unlink the context.
  1747. //
  1748. ArpSUnlinkRegAddrCtxt(pIntF, OldIrql);
  1749. //
  1750. // IntF lock released in above call.
  1751. fLockReleased = TRUE;
  1752. }
  1753. if (!fLockReleased)
  1754. {
  1755. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1756. }
  1757. DBGPRINT(DBG_LEVEL_INFO, ("<==ValidateOneRegAddress.\n"));
  1758. }
  1759. BOOLEAN
  1760. ArpSReferenceIntF(
  1761. IN PINTF pIntF
  1762. )
  1763. /*++
  1764. Routine Description:
  1765. Reference the Interface object.
  1766. Arguments:
  1767. pIntF Pointer to the interface block.
  1768. Return Value:
  1769. TRUE Referenced
  1770. FALSE Interface is closing, cannot reference.
  1771. --*/
  1772. {
  1773. KIRQL OldIrql;
  1774. BOOLEAN rc = TRUE;
  1775. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1776. if (pIntF->Flags & INTF_CLOSING)
  1777. {
  1778. rc = FALSE;
  1779. }
  1780. else
  1781. {
  1782. pIntF->RefCount ++;
  1783. }
  1784. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1785. return rc;
  1786. }
  1787. PINTF
  1788. ArpSReferenceIntFByName(
  1789. IN PINTERFACE_NAME pInterface
  1790. )
  1791. /*++
  1792. Routine Description:
  1793. Reference the Interface object by base-name.
  1794. Arguments:
  1795. pIntF Pointer to the interface block.
  1796. Return Value:
  1797. TRUE Referenced
  1798. FALSE Interface is closing, cannot reference.
  1799. --*/
  1800. {
  1801. PINTF pIntF;
  1802. KIRQL OldIrql;
  1803. BOOLEAN Found = FALSE, ref = FALSE;
  1804. ULONG IfIndex;
  1805. ACQUIRE_SPIN_LOCK(&ArpSIfListLock, &OldIrql);
  1806. for (pIntF = ArpSIfList, IfIndex = 1;
  1807. pIntF != NULL;
  1808. pIntF = pIntF->Next, IfIndex++)
  1809. {
  1810. if (IfIndex > ArpSIfListSize)
  1811. {
  1812. DbgPrint("ATMARPS: RefIntByName: IF list at %p not consistent with list size %d\n",
  1813. ArpSIfList, ArpSIfListSize);
  1814. DbgBreakPoint();
  1815. break;
  1816. }
  1817. ACQUIRE_SPIN_LOCK_DPC(&pIntF->Lock);
  1818. if ((pIntF->FriendlyName.Length == pInterface->Length) &&
  1819. COMP_MEM(pIntF->FriendlyName.Buffer, pInterface->Buffer, pInterface->Length))
  1820. {
  1821. Found = TRUE;
  1822. if ((pIntF->Flags & INTF_CLOSING) == 0)
  1823. {
  1824. pIntF->RefCount ++;
  1825. ref = TRUE;
  1826. }
  1827. }
  1828. RELEASE_SPIN_LOCK_DPC(&pIntF->Lock);
  1829. if (Found)
  1830. break;
  1831. }
  1832. if (!ref)
  1833. {
  1834. pIntF = NULL;
  1835. }
  1836. RELEASE_SPIN_LOCK(&ArpSIfListLock, OldIrql);
  1837. DBGPRINT(DBG_LEVEL_INFO, ("ATMARPS: RefIntfByName:[%ws]: pIntF %p\n",
  1838. pInterface->Buffer, pIntF));
  1839. return pIntF;
  1840. }
  1841. VOID
  1842. ArpSDereferenceIntF(
  1843. IN PINTF pIntF
  1844. )
  1845. {
  1846. KIRQL OldIrql;
  1847. PINTF * ppIntF;
  1848. KIRQL EntryIrql;
  1849. ARPS_GET_IRQL(&EntryIrql);
  1850. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1851. ASSERT (pIntF->RefCount > 0);
  1852. pIntF->RefCount --;
  1853. if (pIntF->RefCount == 0)
  1854. {
  1855. BOOLEAN bFreeIntF = FALSE;
  1856. ASSERT (pIntF->Flags & INTF_CLOSING);
  1857. //
  1858. // We need to release and reacquire the lock to get the locks
  1859. // in the right order. In the meantime, we need to keep the
  1860. // refcount nonzero.
  1861. //
  1862. pIntF->RefCount = 1;
  1863. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1864. ACQUIRE_SPIN_LOCK(&ArpSIfListLock, &OldIrql);
  1865. ACQUIRE_SPIN_LOCK_DPC(&pIntF->Lock);
  1866. pIntF->RefCount--; // Remove tmp ref added just before.
  1867. if (pIntF->RefCount == 0)
  1868. {
  1869. //
  1870. // As expected, refcount is now back to zero. Also we have
  1871. // both list and IF lock held, so we can complete the deinit safely.
  1872. //
  1873. bFreeIntF = TRUE;
  1874. //
  1875. // Remove this Interface from the global list IF it is in the list.
  1876. //
  1877. for (ppIntF = &ArpSIfList; *ppIntF != NULL; ppIntF = &((*ppIntF)->Next))
  1878. {
  1879. if (*ppIntF == pIntF)
  1880. {
  1881. *ppIntF = pIntF->Next;
  1882. ArpSIfListSize--;
  1883. break;
  1884. }
  1885. }
  1886. //
  1887. // Signal anyone waiting for this to happen
  1888. //
  1889. if (pIntF->CleanupEvent != NULL)
  1890. {
  1891. KeSetEvent(pIntF->CleanupEvent, IO_NETWORK_INCREMENT, FALSE);
  1892. }
  1893. }
  1894. else
  1895. {
  1896. //
  1897. // Some other thread has snuck in and referenced the IF. We
  1898. // don't do anything here.
  1899. //
  1900. }
  1901. RELEASE_SPIN_LOCK_DPC(&pIntF->Lock);
  1902. RELEASE_SPIN_LOCK(&ArpSIfListLock, OldIrql);
  1903. if (bFreeIntF)
  1904. {
  1905. FREE_MEM(pIntF);
  1906. }
  1907. }
  1908. else
  1909. {
  1910. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1911. }
  1912. ARPS_CHECK_IRQL(EntryIrql);
  1913. }
  1914. BOOLEAN
  1915. ArpSReferenceVc(
  1916. IN PARP_VC Vc,
  1917. IN BOOLEAN bSendRef
  1918. )
  1919. /*++
  1920. Routine Description:
  1921. Reference the VC.
  1922. Arguments:
  1923. Vc Pointer to the VC.
  1924. bSendRef Is this a "pending send" reference?
  1925. Return Value:
  1926. TRUE Referenced
  1927. FALSE Interface or VC is closing, cannot reference.
  1928. --*/
  1929. {
  1930. PINTF pIntF = Vc->IntF;
  1931. KIRQL OldIrql;
  1932. BOOLEAN rc = TRUE;
  1933. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1934. if ((Vc->Flags & (ARPVC_CLOSING | ARPVC_CLOSE_PENDING)) != 0)
  1935. {
  1936. rc = FALSE;
  1937. }
  1938. else
  1939. {
  1940. Vc->RefCount ++;
  1941. if (bSendRef)
  1942. {
  1943. Vc->PendingSends ++;
  1944. }
  1945. }
  1946. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1947. return rc;
  1948. }
  1949. VOID
  1950. ArpSDereferenceVc(
  1951. IN PARP_VC Vc,
  1952. IN BOOLEAN KillArpEntry,
  1953. IN BOOLEAN bSendComplete
  1954. )
  1955. {
  1956. PINTF pIntF = Vc->IntF;
  1957. KIRQL OldIrql;
  1958. BOOLEAN bInitiateClose = FALSE;
  1959. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1960. if (bSendComplete)
  1961. {
  1962. Vc->PendingSends--;
  1963. }
  1964. ASSERT (Vc->RefCount > 0);
  1965. Vc->RefCount --;
  1966. if (Vc->RefCount == 0)
  1967. {
  1968. PINTF pIntF;
  1969. ASSERT ((Vc->Flags & ARPVC_ACTIVE) == 0);
  1970. ASSERT (Vc->ArpEntry == NULL);
  1971. //
  1972. // Do other cleanup here
  1973. //
  1974. pIntF = Vc->IntF;
  1975. RemoveEntryList(&Vc->List);
  1976. FREE_MEM(Vc);
  1977. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1978. ArpSDereferenceIntF(pIntF);
  1979. }
  1980. else
  1981. {
  1982. if (KillArpEntry)
  1983. {
  1984. DBGPRINT(DBG_LEVEL_WARN,
  1985. ("Cleaning dead vc from vc %lx, arpentry %lx\n", Vc, Vc->ArpEntry));
  1986. Vc->ArpEntry = NULL;
  1987. }
  1988. if ((Vc->PendingSends == 0) &&
  1989. (Vc->Flags & ARPVC_CLOSE_PENDING))
  1990. {
  1991. bInitiateClose = TRUE;
  1992. Vc->Flags |= ARPVC_CLOSING;
  1993. }
  1994. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1995. if (bInitiateClose)
  1996. {
  1997. ArpSInitiateCloseCall(Vc);
  1998. }
  1999. }
  2000. }
  2001. VOID
  2002. ArpSSleep(
  2003. IN UINT TimeInMs
  2004. )
  2005. {
  2006. #define NUM_100ns_PER_ms -10000L
  2007. KTIMER SleepTimer;
  2008. LARGE_INTEGER TimerValue;
  2009. NTSTATUS Status;
  2010. ARPS_PAGED_CODE( );
  2011. DBGPRINT(DBG_LEVEL_WARN,
  2012. ("=>ArpSSleep(%d)\n", TimeInMs));
  2013. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  2014. KeInitializeTimer(&SleepTimer);
  2015. TimerValue.QuadPart = Int32x32To64(TimeInMs, NUM_100ns_PER_ms);
  2016. KeSetTimer(&SleepTimer,
  2017. TimerValue,
  2018. NULL);
  2019. WAIT_FOR_OBJECT(Status, &SleepTimer, NULL);
  2020. DBGPRINT(DBG_LEVEL_WARN,
  2021. ("ArpSSleep: woken up, Status 0x%x\n", Status));
  2022. // ASSERT (Status == STATUS_TIMEOUT);
  2023. }
  2024. VOID
  2025. ArpSFreeGlobalData(
  2026. VOID
  2027. )
  2028. {
  2029. }
  2030. #if DBG
  2031. VOID
  2032. ArpSDumpPacket(
  2033. IN PUCHAR Packet,
  2034. IN UINT PktLen
  2035. )
  2036. {
  2037. UINT i;
  2038. DBGPRINT(DBG_LEVEL_INFO, (" PacketDump: "));
  2039. for (i = 0; i < PktLen; i++)
  2040. {
  2041. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  2042. ("%02x ", Packet[i]));
  2043. }
  2044. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("\n"));
  2045. }
  2046. VOID
  2047. ArpSDumpAddress(
  2048. IN IPADDR IpAddr,
  2049. IN PHW_ADDR HwAddr,
  2050. IN PCHAR String
  2051. )
  2052. {
  2053. UINT i;
  2054. DBGPRINT(DBG_LEVEL_INFO,
  2055. (" %s IpAddr: ", String));
  2056. ArpSDumpIpAddr(IpAddr, "");
  2057. ArpSDumpAtmAddr(&HwAddr->Address, ", ");
  2058. if (HwAddr->SubAddress != NULL)
  2059. {
  2060. ArpSDumpAtmAddr(HwAddr->SubAddress, "\tSub ");
  2061. }
  2062. }
  2063. VOID
  2064. ArpSDumpIpAddr(
  2065. IN IPADDR IpAddr,
  2066. IN PCHAR String
  2067. )
  2068. {
  2069. PUCHAR p = (PUCHAR)&IpAddr;
  2070. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  2071. ("%d.%d.%d.%d%s", p[0], p[1], p[2], p[3], String));
  2072. }
  2073. VOID
  2074. ArpSDumpAtmAddr(
  2075. IN PATM_ADDRESS AtmAddr,
  2076. IN PCHAR String
  2077. )
  2078. {
  2079. UINT i;
  2080. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("%sAtmAddr (%s, %d): ",
  2081. String,
  2082. (AtmAddr->AddressType == ATM_E164) ? "E164" : "NSAP",
  2083. AtmAddr->NumberOfDigits));
  2084. for (i = 0; i < AtmAddr->NumberOfDigits; i++)
  2085. {
  2086. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  2087. ("%02x ", AtmAddr->Address[i]));
  2088. }
  2089. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("\n"));
  2090. }
  2091. #endif
  2092. VOID
  2093. ArpSSetupValidationCallParams(
  2094. PREG_ADDR_CTXT pRegAddrCtxt, // LOCKIN LOCKOUT (pIntF lock)
  2095. PATM_ADDRESS pAtmAddr
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. Sets up the call parameters for a validation call (call to verify that
  2100. another server with the same address doesn't exist.).
  2101. Arguments:
  2102. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2103. pRegAddrCtxt->CallParams is filled with the call params.
  2104. pAtmAddr Destination address.
  2105. --*/
  2106. {
  2107. NDIS_STATUS Status;
  2108. PINTF pIntF;
  2109. //
  2110. // Set of parameters for a MakeCall
  2111. //
  2112. PCO_CALL_PARAMETERS pCallParameters;
  2113. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  2114. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  2115. //
  2116. // All Info Elements that we need to fill:
  2117. //
  2118. Q2931_IE UNALIGNED * pIe;
  2119. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  2120. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  2121. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  2122. ATM_BLLI_IE UNALIGNED * pBlli;
  2123. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  2124. //
  2125. // Total space requirements for the MakeCall
  2126. //
  2127. ULONG RequestSize;
  2128. pIntF = pRegAddrCtxt->pIntF;
  2129. ASSERT(pIntF->pRegAddrCtxt == pRegAddrCtxt);
  2130. //
  2131. // Zero out call params. Don't remove this!
  2132. //
  2133. ZERO_MEM(&pRegAddrCtxt->CallParams, sizeof(pRegAddrCtxt->CallParams));
  2134. ZERO_MEM(&pRegAddrCtxt->Buffer, sizeof(pRegAddrCtxt->Buffer));
  2135. //
  2136. // Distribute space amongst the various structures
  2137. //
  2138. pCallParameters = &pRegAddrCtxt->CallParams;
  2139. pCallMgrParameters = &pRegAddrCtxt->CmParams;
  2140. //
  2141. // Set pointers to link the above structures together
  2142. //
  2143. pCallParameters->CallMgrParameters = pCallMgrParameters;
  2144. pCallParameters->MediaParameters = NULL;
  2145. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  2146. pCallMgrParameters->CallMgrSpecific.Length =
  2147. sizeof(Q2931_CALLMGR_PARAMETERS) +
  2148. REGADDR_MAKE_CALL_IE_SPACE;
  2149. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  2150. pCallMgrParameters->CallMgrSpecific.Parameters;
  2151. //
  2152. // Call Manager generic flow parameters:
  2153. //
  2154. pCallMgrParameters->Transmit.TokenRate = QOS_NOT_SPECIFIED;
  2155. pCallMgrParameters->Transmit.TokenBucketSize = 9188;
  2156. pCallMgrParameters->Transmit.MaxSduSize = 9188;
  2157. pCallMgrParameters->Transmit.PeakBandwidth = QOS_NOT_SPECIFIED;
  2158. pCallMgrParameters->Transmit.ServiceType = SERVICETYPE_BESTEFFORT;
  2159. pCallMgrParameters->Receive.TokenRate = QOS_NOT_SPECIFIED;
  2160. pCallMgrParameters->Receive.TokenBucketSize = 9188;
  2161. pCallMgrParameters->Receive.MaxSduSize = 9188;
  2162. pCallMgrParameters->Receive.PeakBandwidth = QOS_NOT_SPECIFIED;
  2163. pCallMgrParameters->Receive.ServiceType = SERVICETYPE_BESTEFFORT;
  2164. //
  2165. // Q2931 Call Manager Parameters:
  2166. //
  2167. //
  2168. // Called address:
  2169. //
  2170. COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CalledParty),
  2171. (PUCHAR)pAtmAddr,
  2172. sizeof(ATM_ADDRESS));
  2173. //
  2174. // Calling address:
  2175. //
  2176. COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CallingParty),
  2177. (PUCHAR)&pIntF->ConfiguredAddress,
  2178. sizeof(ATM_ADDRESS));
  2179. //
  2180. // RFC 1755 (Sec 5) says that the following IEs MUST be present in the
  2181. // SETUP message, so fill them all.
  2182. //
  2183. // AAL Parameters
  2184. // Traffic Descriptor (only for MakeCall)
  2185. // Broadband Bearer Capability (only for MakeCall)
  2186. // Broadband Low Layer Info
  2187. // QoS (only for MakeCall)
  2188. //
  2189. //
  2190. // Initialize the Info Element list
  2191. //
  2192. pAtmCallMgrParameters->InfoElementCount = 0;
  2193. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  2194. //
  2195. // AAL Parameters:
  2196. //
  2197. {
  2198. UNALIGNED AAL5_PARAMETERS *pAal5;
  2199. pIe->IEType = IE_AALParameters;
  2200. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  2201. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  2202. pAalIe->AALType = AAL_TYPE_AAL5;
  2203. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  2204. pAal5->ForwardMaxCPCSSDUSize = 9188;
  2205. pAal5->BackwardMaxCPCSSDUSize = 9188;
  2206. }
  2207. pAtmCallMgrParameters->InfoElementCount++;
  2208. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  2209. //
  2210. // Broadband Lower Layer Information
  2211. //
  2212. pIe->IEType = IE_BLLI;
  2213. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  2214. pBlli = (PATM_BLLI_IE)pIe->IE;
  2215. COPY_MEM((PUCHAR)pBlli,
  2216. (PUCHAR)&ArpSDefaultBlli,
  2217. sizeof(ATM_BLLI_IE));
  2218. pAtmCallMgrParameters->InfoElementCount++;
  2219. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  2220. }
  2221. VOID
  2222. ArpSMakeRegAddrCallComplete(
  2223. NDIS_STATUS Status,
  2224. PREG_ADDR_CTXT pRegAddrCtxt
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. Completion handler for the validation call. On success we drop the call and
  2229. and move on to the next address. On failure we go on to register this address
  2230. with the switch. See 05/14/1999 notes.txt entry for the larger context.
  2231. Arguments:
  2232. Status MakeCall Completion status.
  2233. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2234. --*/
  2235. {
  2236. PINTF pIntF;
  2237. KIRQL OldIrql;
  2238. pIntF = pRegAddrCtxt->pIntF;
  2239. ASSERT(pIntF->pRegAddrCtxt == pRegAddrCtxt);
  2240. DBGPRINT(DBG_LEVEL_INFO,
  2241. ("==>ArpSMakeRegAddrCallComplete. Status=0x%lx, pIntF=0x%p, pCtxt=0x%p\n",
  2242. Status,
  2243. pRegAddrCtxt->pIntF,
  2244. pRegAddrCtxt
  2245. ));
  2246. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2247. if (Status == NDIS_STATUS_SUCCESS)
  2248. {
  2249. DBGPRINT(DBG_LEVEL_ERROR,
  2250. ("MakeRegAddrCallComplete: Successful call == failed validation; dropping call.\n"));
  2251. if (pIntF->Flags & INTF_STOPPING)
  2252. {
  2253. //
  2254. // When the IF is stopping, we can't rely on
  2255. // pIntF->RegAddresses to be still around...
  2256. //
  2257. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2258. }
  2259. else
  2260. {
  2261. ATM_ADDRESS AtmAddress;
  2262. //
  2263. // A successful make call is failed validation!
  2264. // We log the event, drop the call. The drop call complete handler will
  2265. // do the next thing, which is to move on to validating the next address.
  2266. //
  2267. AtmAddress = pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex]; // struct copy
  2268. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2269. ArpSLogFailedRegistration(&AtmAddress);
  2270. }
  2271. Status = NdisClCloseCall(pRegAddrCtxt->NdisVcHandle, NULL, NULL, 0);
  2272. if (Status != NDIS_STATUS_PENDING)
  2273. {
  2274. ArpSCloseRegAddrCallComplete(Status, pRegAddrCtxt);
  2275. }
  2276. }
  2277. else
  2278. {
  2279. //
  2280. // A failed make call is considered a successful validation!
  2281. // Delete VC and initiate registration of the address.
  2282. //
  2283. PNDIS_REQUEST pNdisRequest;
  2284. NDIS_HANDLE NdisVcHandle;
  2285. PATM_ADDRESS pValidatedAddress;
  2286. PCO_ADDRESS pCoAddr;
  2287. DBGPRINT(DBG_LEVEL_ERROR,
  2288. ("MakeRegAddrCallComplete: Failed call == successful validation; Adding address.\n"));
  2289. ASSERT(pRegAddrCtxt->NdisVcHandle != NULL);
  2290. NdisVcHandle = pRegAddrCtxt->NdisVcHandle;
  2291. pRegAddrCtxt->NdisVcHandle = NULL;
  2292. if (pIntF->Flags & INTF_STOPPING)
  2293. {
  2294. // Oh oh, the IF is stopping -- we clean up the VC and call
  2295. // ArpSValidateOneRegdAddress -- it will free pRegAddrCtxt.
  2296. //
  2297. //
  2298. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2299. if (NdisVcHandle != NULL)
  2300. {
  2301. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2302. }
  2303. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2304. ArpSValidateOneRegdAddress(
  2305. pIntF,
  2306. OldIrql
  2307. );
  2308. }
  2309. else
  2310. {
  2311. ASSERT(pRegAddrCtxt->RegAddrIndex < pIntF->NumAllocedRegdAddresses);
  2312. pValidatedAddress = &(pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex]);
  2313. pRegAddrCtxt->RegAddrIndex++;
  2314. pNdisRequest = &pRegAddrCtxt->Request.NdisRequest;
  2315. pNdisRequest->RequestType = NdisRequestSetInformation;
  2316. pNdisRequest->DATA.SET_INFORMATION.Oid = OID_CO_ADD_ADDRESS;
  2317. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer
  2318. = (PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST);
  2319. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength
  2320. = sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  2321. //
  2322. // Copy the address into the request
  2323. //
  2324. pCoAddr = pNdisRequest->DATA.SET_INFORMATION.InformationBuffer;
  2325. pCoAddr->AddressSize = sizeof(ATM_ADDRESS);
  2326. *(PATM_ADDRESS)(pCoAddr->Address) = *pValidatedAddress;
  2327. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2328. if (NdisVcHandle != NULL)
  2329. {
  2330. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2331. }
  2332. Status = NdisCoRequest(pIntF->NdisBindingHandle,
  2333. pIntF->NdisAfHandle,
  2334. NULL,
  2335. NULL,
  2336. pNdisRequest);
  2337. if (Status != NDIS_STATUS_PENDING)
  2338. {
  2339. ArpSCoRequestComplete(Status, pIntF, NULL, NULL, pNdisRequest);
  2340. }
  2341. }
  2342. }
  2343. DBGPRINT(DBG_LEVEL_INFO,
  2344. ("<==ArpSMakeRegAddrCallComplete.\n"));
  2345. }
  2346. VOID
  2347. ArpSCloseRegAddrCallComplete(
  2348. IN NDIS_STATUS Status,
  2349. IN PREG_ADDR_CTXT pRegAddrCtxt
  2350. )
  2351. /*++
  2352. Routine Description:
  2353. Completion handler for the NdisClCloseCall of validation call. Since this
  2354. is a failed validation, we move on to validating/registration of the next
  2355. address. See 05/14/1999 notes.txt entry for the larger context.
  2356. Arguments:
  2357. Status CloseCall Completion status (ignored).
  2358. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2359. --*/
  2360. {
  2361. KIRQL OldIrql;
  2362. PINTF pIntF;
  2363. NDIS_HANDLE NdisVcHandle;
  2364. DBGPRINT(DBG_LEVEL_INFO,
  2365. ("==>ArpSCloseRegAddrCallComplete. pIntF=0x%p, pCtxt=0x%p\n",
  2366. pRegAddrCtxt->pIntF,
  2367. pRegAddrCtxt
  2368. ));
  2369. pIntF = pRegAddrCtxt->pIntF;
  2370. ASSERT(pIntF->pRegAddrCtxt == pRegAddrCtxt);
  2371. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2372. if (!(pIntF->Flags & INTF_STOPPING))
  2373. {
  2374. ASSERT(pRegAddrCtxt->RegAddrIndex < pIntF->NumAllocedRegdAddresses);
  2375. pRegAddrCtxt->RegAddrIndex++;
  2376. }
  2377. ASSERT(pRegAddrCtxt->NdisVcHandle != NULL);
  2378. NdisVcHandle = pRegAddrCtxt->NdisVcHandle;
  2379. pRegAddrCtxt->NdisVcHandle = NULL;
  2380. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2381. if (NdisVcHandle != NULL)
  2382. {
  2383. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2384. }
  2385. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2386. ArpSValidateOneRegdAddress(
  2387. pIntF,
  2388. OldIrql
  2389. );
  2390. //
  2391. // Lock released above.
  2392. DBGPRINT(DBG_LEVEL_INFO, ("<==ArpSCloseRegAddrCallComplete\n"));
  2393. }
  2394. VOID
  2395. ArpSUnlinkRegAddrCtxt(
  2396. PINTF pIntF, // LOCKIN NOLOCKOUT
  2397. KIRQL OldIrql
  2398. )
  2399. /*++
  2400. Routine Description:
  2401. Deref pIntF, remove reference to pRegAddrCtxt = pIntF->pRegAddrCtxt, and
  2402. free pIntF->pRegAddrCtxt. See 05/14/1999 notes.txt entry for the larger context.
  2403. Must only be called AFTER all async activity relating to pRegAddrCtxt is
  2404. over and pRegAddrCtxt->NdisVcHandle is NULL.
  2405. Arguments:
  2406. Status CloseCall Completion status (ignored).
  2407. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2408. --*/
  2409. {
  2410. PREG_ADDR_CTXT pRegAddrCtxt;
  2411. DBGPRINT(DBG_LEVEL_INFO, ("==>ArpSUnlinkRegAddrCtxt\n"));
  2412. pRegAddrCtxt = pIntF->pRegAddrCtxt;
  2413. ASSERT(pRegAddrCtxt != NULL);
  2414. ASSERT(pRegAddrCtxt->pIntF == pIntF);
  2415. ASSERT(pRegAddrCtxt->NdisVcHandle == NULL);
  2416. // TODO: -- flags.
  2417. FREE_MEM(pRegAddrCtxt);
  2418. pIntF->pRegAddrCtxt = NULL;
  2419. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2420. ArpSDereferenceIntF(pIntF); // pRegAddrCtxt;
  2421. DBGPRINT(DBG_LEVEL_INFO, ("<==ArpSUnlinkRegAddrCtxt\n"));
  2422. }
  2423. VOID
  2424. ArpSIncomingRegAddrCloseCall(
  2425. IN NDIS_STATUS Status,
  2426. IN PREG_ADDR_CTXT pRegAddrCtxt
  2427. )
  2428. /*++
  2429. Routine Description:
  2430. Incoming close call handler for the validation call. Currently we do nothing
  2431. with this. I don't see the need to do anything, because we don't keep
  2432. the call up for an arbitrary length of time.
  2433. However, if/when we decide to keep the call up so that we can try to
  2434. re-validate after the call goes away, we'll need to do something here.
  2435. Arguments:
  2436. Status CloseCall Completion status (ignored).
  2437. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2438. --*/
  2439. {
  2440. DBGPRINT(DBG_LEVEL_INFO, ("<==>ArpSIncomingRegAddrCloseCall\n"));
  2441. }
  2442. VOID
  2443. ArpSLogFailedRegistration(
  2444. PATM_ADDRESS pAtmAddress
  2445. )
  2446. {
  2447. WCHAR TxtAddress[2*ATM_ADDRESS_LENGTH+1]; // 2 chars per address byte plus null
  2448. WCHAR *StringList[1];
  2449. static ULONG SequenceId;
  2450. //
  2451. // Convert atm address to unicode...
  2452. //
  2453. {
  2454. static PWSTR WHexChars = L"0123456789ABCDEF";
  2455. PWSTR StrBuf;
  2456. ULONG Index;
  2457. PWSTR pWStr;
  2458. PUCHAR pAddr;
  2459. UINT Max;
  2460. Max = pAtmAddress->NumberOfDigits;
  2461. if (Max > ATM_ADDRESS_LENGTH)
  2462. {
  2463. Max = ATM_ADDRESS_LENGTH;
  2464. }
  2465. for (Index = 0, pWStr = TxtAddress, pAddr = pAtmAddress->Address;
  2466. Index < Max;
  2467. Index++, pAddr++)
  2468. {
  2469. *pWStr++ = WHexChars[(*pAddr)>>4];
  2470. *pWStr++ = WHexChars[(*pAddr)&0xf];
  2471. }
  2472. *pWStr = L'\0';
  2473. }
  2474. StringList[0] = TxtAddress;
  2475. (VOID) NdisWriteEventLogEntry(
  2476. ArpSDriverObject,
  2477. EVENT_ATMARPS_ADDRESS_ALREADY_EXISTS,
  2478. SequenceId, // Sequence
  2479. 1, // NumStrings
  2480. &StringList, // String list
  2481. 0, // DataSize
  2482. NULL // Data
  2483. );
  2484. NdisInterlockedIncrement(&SequenceId);
  2485. }