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

3083 lines
71 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. PSLIST_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. if (Pkt->Private.Head == NULL)
  811. {
  812. DbgPrint("ATMARPS: HandleArpReq: Pkt %p has NULL head!\n", Pkt);
  813. DbgBreakPoint();
  814. }
  815. if ((Pkt->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS) == 0)
  816. {
  817. DbgPrint("ATMARPS: HandleArpReq: Pkt %p is freed?\n", Pkt);
  818. DbgBreakPoint();
  819. }
  820. NdisAdjustBufferLength(Pkt->Private.Head, PktLen);
  821. Pkt->Private.ValidCounts = FALSE;
  822. NdisCopyFromPacketToPacket(Pkt,
  823. 0,
  824. PktLen,
  825. Packet,
  826. 0,
  827. &Tmp);
  828. ASSERT(Tmp == PktLen);
  829. ASSERT( PktLen < 65536);
  830. Resd->PktLen = (USHORT) PktLen;
  831. //
  832. // The incoming packet is now copied to our packet.
  833. // Examine and sanity check before queuing it.
  834. //
  835. NdisQueryBuffer(Pkt->Private.Head, &Header, &Tmp);
  836. Resd->PacketStart = (PUCHAR)Header;
  837. MHdr = (PMARS_HEADER)Header;
  838. do
  839. {
  840. ValidPkt = FALSE; // Assume the worst
  841. //
  842. // Check for the LLC SNAP Header
  843. //
  844. if (COMP_MEM(&Header->LlcSnapHdr, &ArpSLlcSnapHdr, sizeof(LLC_SNAP_HDR)))
  845. {
  846. Mars = FALSE;
  847. }
  848. else if (COMP_MEM(&Header->LlcSnapHdr, &MarsCntrlLlcSnapHdr, sizeof(LLC_SNAP_HDR)))
  849. {
  850. if ((MHdr->HwType == MARS_HWTYPE) &&
  851. (MHdr->Protocol == IP_PROTOCOL_TYPE) &&
  852. ArpSReferenceVc(Vc, TRUE))
  853. {
  854. Mars = TRUE;
  855. ValidPkt = TRUE;
  856. }
  857. break;
  858. }
  859. else
  860. {
  861. DBGPRINT(DBG_LEVEL_ERROR,
  862. ("ArpSHandleArpRequest: Invalid Llc Snap Hdr\n"));
  863. break;
  864. }
  865. Tmp = sizeof(ARPS_HEADER) +
  866. Header->SrcProtoAddrLen + TL_LEN(Header->SrcAddressTL) + TL_LEN(Header->SrcSubAddrTL) +
  867. Header->DstProtoAddrLen + TL_LEN(Header->DstAddressTL) + TL_LEN(Header->DstSubAddrTL);
  868. //
  869. // Make sure the address and sub-address formats are consistent.
  870. // The valid ones from the RFC:
  871. //
  872. // Adress Sub-Address
  873. // ------ -----------
  874. //
  875. // Structure 1 ATM Forum NSAP Null
  876. // Structure 2 E.164 Null
  877. // Structure 3 E.164 ATM Forum NSAP
  878. //
  879. if (TL_LEN(Header->SrcSubAddrTL) > 0)
  880. {
  881. //
  882. // Sub-address is present. Make sure that the Address is E.164 and Sub-Address is NSAP
  883. //
  884. if ((TL_TYPE(Header->SrcAddressTL) == ADDR_TYPE_NSAP) ||
  885. (TL_TYPE(Header->SrcSubAddrTL) == ADDR_TYPE_E164))
  886. {
  887. DBGPRINT(DBG_LEVEL_ERROR,
  888. ("ArpSHandleArpRequest: Src Address is NSAP and Src Sub Addr is E164\n"));
  889. break;
  890. }
  891. }
  892. if (TL_LEN(Header->DstSubAddrTL) > 0)
  893. {
  894. //
  895. // Sub-address is present. Make sure that the Address is E.164 and Sub-Address is NSAP
  896. //
  897. if ((TL_TYPE(Header->DstAddressTL) == ADDR_TYPE_NSAP) ||
  898. (TL_TYPE(Header->DstSubAddrTL) == ADDR_TYPE_E164))
  899. {
  900. DBGPRINT(DBG_LEVEL_ERROR,
  901. ("ArpSHandleArpRequest: Dst Address is NSAP and Dst Sub Addr is E164\n"));
  902. break;
  903. }
  904. }
  905. if ((Header->Opcode == ATMARP_Request) &&
  906. (Header->HwType == ATM_HWTYPE) &&
  907. (Header->Protocol == IP_PROTOCOL_TYPE) &&
  908. (PktLen >= Tmp) &&
  909. ArpSReferenceVc(Vc, TRUE))
  910. {
  911. ValidPkt = TRUE;
  912. break;
  913. }
  914. #if DBG
  915. else
  916. {
  917. if (Header->Opcode != ATMARP_Request)
  918. {
  919. DBGPRINT(DBG_LEVEL_ERROR,
  920. ("ArpSHandleArpRequest: Invalid OpCode %x\n", Header->Opcode));
  921. }
  922. else if (Header->HwType != ATM_HWTYPE)
  923. {
  924. DBGPRINT(DBG_LEVEL_ERROR,
  925. ("ArpSHandleArpRequest: Invalid HwType %x\n", Header->HwType));
  926. }
  927. else if (Header->Protocol == IP_PROTOCOL_TYPE)
  928. {
  929. DBGPRINT(DBG_LEVEL_ERROR,
  930. ("ArpSHandleArpRequest: Invalid Protocol %x\n", Header->Protocol));
  931. }
  932. else if (PktLen < Tmp)
  933. {
  934. DBGPRINT(DBG_LEVEL_ERROR,
  935. ("ArpSHandleArpRequest: Invalid Length %x - %x\n", PktLen, Tmp));
  936. }
  937. else
  938. {
  939. DBGPRINT(DBG_LEVEL_ERROR,
  940. ("ArpSHandleArpRequest: Cannot reference Vc\n"));
  941. }
  942. }
  943. #endif
  944. } while (FALSE);
  945. if (ValidPkt)
  946. {
  947. Resd->Vc = Vc;
  948. if (Mars)
  949. {
  950. Resd->Flags |= RESD_FLAG_MARS;
  951. KeInsertQueue(&MarsReqQueue, &Resd->ReqList);
  952. }
  953. else
  954. {
  955. Resd->Flags &= ~RESD_FLAG_MARS;
  956. KeInsertQueue(&ArpSReqQueue, &Resd->ReqList);
  957. }
  958. }
  959. else
  960. {
  961. //
  962. // Either a mal-formed packet or the Vc is closing
  963. //
  964. pIntF->ArpStats.DiscardedRecvPkts++;
  965. ArpSDumpPacket((PUCHAR)Header, PktLen);
  966. //
  967. // Move the packet back into the free list
  968. //
  969. ExInterlockedPushEntrySList(&ArpSPktList,
  970. &Resd->FreeList,
  971. &ArpSPktListLock);
  972. }
  973. } while (FALSE);
  974. return ReturnValue;
  975. }
  976. PARP_ENTRY
  977. ArpSLookupEntryByIpAddr(
  978. IN PINTF pIntF,
  979. IN IPADDR IpAddr
  980. )
  981. /*++
  982. Routine Description:
  983. Lookup the Arp table for the specified IP address. Called with the ArpCache mutex held.
  984. Arguments:
  985. pIntF Pointer to the IntF structure
  986. IpAddr IP address to look for
  987. Return Value:
  988. ArpEntry if found or NULL.
  989. --*/
  990. {
  991. PARP_ENTRY ArpEntry;
  992. UINT Hash = ARP_HASH(IpAddr);
  993. ARPS_PAGED_CODE( );
  994. DBGPRINT(DBG_LEVEL_INFO,
  995. ("ArpSLookupArpEntry: Lookup entry for IpAddr: "));
  996. ArpSDumpIpAddr(IpAddr, " ..... ");
  997. for (ArpEntry = pIntF->ArpCache[Hash];
  998. ArpEntry != NULL;
  999. ArpEntry = ArpEntry->Next)
  1000. {
  1001. if (ArpEntry->IpAddr == IpAddr)
  1002. break;
  1003. if (ArpEntry->IpAddr > IpAddr)
  1004. {
  1005. ArpEntry = NULL;
  1006. break;
  1007. }
  1008. }
  1009. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  1010. ("%sFound\n", (ArpEntry != NULL) ? "" : "Not"));
  1011. if (ArpEntry != NULL)
  1012. {
  1013. //
  1014. // Cleanup this entry if the Vc is no-longer active
  1015. //
  1016. CLEANUP_DEAD_VC(ArpEntry);
  1017. }
  1018. return ArpEntry;
  1019. }
  1020. PARP_ENTRY
  1021. ArpSLookupEntryByAtmAddr(
  1022. IN PINTF pIntF,
  1023. IN PATM_ADDRESS Address,
  1024. IN PATM_ADDRESS SubAddress OPTIONAL
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. Lookup the Arp table for the specified IP address. Called with the ArpCache mutex held.
  1029. Arguments:
  1030. pIntF Pointer to the IntF structure
  1031. IpAddr IP address to look for
  1032. Return Value:
  1033. ArpEntry if found or NULL.
  1034. --*/
  1035. {
  1036. PARP_ENTRY ArpEntry;
  1037. UINT i;
  1038. ARPS_PAGED_CODE( );
  1039. DBGPRINT(DBG_LEVEL_INFO,
  1040. ("ArpSLookupArpEntry: Lookup entry for "));
  1041. ArpSDumpAtmAddr(Address, " ..... ");
  1042. if (SubAddress != NULL)
  1043. {
  1044. ArpSDumpAtmAddr(SubAddress, "\t Sub ");
  1045. }
  1046. for (i =0; i < ARP_TABLE_SIZE; i++)
  1047. {
  1048. for (ArpEntry = pIntF->ArpCache[i];
  1049. ArpEntry != NULL;
  1050. ArpEntry = ArpEntry->Next)
  1051. {
  1052. if (COMP_ATM_ADDR(Address, &ArpEntry->HwAddr.Address))
  1053. {
  1054. if (((SubAddress == NULL) && (ArpEntry->HwAddr.SubAddress == NULL)) ||
  1055. (((SubAddress != NULL) && (ArpEntry->HwAddr.SubAddress != NULL)) &&
  1056. COMP_ATM_ADDR(SubAddress, ArpEntry->HwAddr.SubAddress)))
  1057. {
  1058. break;
  1059. }
  1060. }
  1061. }
  1062. if (ArpEntry != NULL)
  1063. {
  1064. //
  1065. // Cleanup this entry if the Vc is no-longer active
  1066. //
  1067. CLEANUP_DEAD_VC(ArpEntry);
  1068. break;
  1069. }
  1070. }
  1071. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  1072. ("ArpSLookupArpEntry: %sFound\n", (ArpEntry != NULL) ? "" : "Not"));
  1073. return ArpEntry;
  1074. }
  1075. PARP_ENTRY
  1076. ArpSAddArpEntry(
  1077. IN PINTF pIntF,
  1078. IN IPADDR IpAddr,
  1079. IN PATM_ADDRESS Address,
  1080. IN PATM_ADDRESS SubAddress OPTIONAL,
  1081. IN PARP_VC Vc OPTIONAL
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. Add the Arp table for the specified IP address. Called with the ArpCache mutex held.
  1086. Arguments:
  1087. pIntF Pointer to the IntF structure
  1088. IpAddr IP address to add
  1089. Address &
  1090. SubAddress Supplies the atm address and the sub-address
  1091. Vc The Vc associated with this ArpEntry, if any
  1092. Return Value:
  1093. ArpEntry if added successfully or NULL.
  1094. --*/
  1095. {
  1096. PARP_ENTRY ArpEntry, *ppEntry;
  1097. UINT Hash = ARP_HASH(IpAddr);
  1098. ENTRY_TYPE EntryType;
  1099. ARPS_PAGED_CODE( );
  1100. DBGPRINT(DBG_LEVEL_INFO,
  1101. ("ArpSAddArpEntry: Adding entry for IpAddr: "));
  1102. ArpSDumpIpAddr(IpAddr, " ..... ");
  1103. //
  1104. // Start off by allocating an arp-entry structure
  1105. //
  1106. EntryType = (SubAddress != NULL) ? ARP_BLOCK_SUBADDR : ARP_BLOCK_VANILA;
  1107. ArpEntry = (PARP_ENTRY)ArpSAllocBlock(pIntF, EntryType);
  1108. if (ArpEntry == NULL)
  1109. {
  1110. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1111. }
  1112. else
  1113. {
  1114. if (++(pIntF->ArpStats.CurrentArpEntries) > pIntF->ArpStats.MaxArpEntries)
  1115. {
  1116. pIntF->ArpStats.MaxArpEntries = pIntF->ArpStats.CurrentArpEntries;
  1117. }
  1118. ArpSTimerInitialize(&ArpEntry->Timer, ArpSAgeEntry, ARP_AGE);
  1119. ArpEntry->IpAddr = IpAddr;
  1120. COPY_ATM_ADDR(&ArpEntry->HwAddr.Address, Address);
  1121. if (SubAddress != NULL)
  1122. COPY_ATM_ADDR(ArpEntry->HwAddr.SubAddress, SubAddress);
  1123. if (ARGUMENT_PRESENT(Vc) && ArpSReferenceVc(Vc, FALSE))
  1124. {
  1125. ArpEntry->Vc = Vc;
  1126. Vc->ArpEntry = ArpEntry;
  1127. }
  1128. ArpEntry->Age = ARP_AGE;
  1129. //
  1130. // Keep the overflow list sorted in ascending order of Ip addresses
  1131. //
  1132. for (ppEntry = &pIntF->ArpCache[Hash];
  1133. *ppEntry != NULL;
  1134. ppEntry = (PARP_ENTRY *)(&(*ppEntry)->Next))
  1135. {
  1136. ASSERT ((*ppEntry)->IpAddr != IpAddr);
  1137. if ((*ppEntry)->IpAddr > IpAddr)
  1138. break;
  1139. }
  1140. ArpEntry->Next = *ppEntry;
  1141. ArpEntry->Prev = ppEntry;
  1142. if (*ppEntry != NULL)
  1143. {
  1144. (*ppEntry)->Prev = &ArpEntry->Next;
  1145. }
  1146. *ppEntry = ArpEntry;
  1147. pIntF->NumCacheEntries ++;
  1148. ArpSTimerEnqueue(pIntF, &ArpEntry->Timer);
  1149. }
  1150. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("%lx\n", ArpEntry));
  1151. return ArpEntry;
  1152. }
  1153. PARP_ENTRY
  1154. ArpSAddArpEntryFromDisk(
  1155. IN PINTF pIntF,
  1156. IN PDISK_ENTRY pDskEntry
  1157. )
  1158. /*++
  1159. Routine Description:
  1160. Add the Arp table for the specified IP address. Called during intialization.
  1161. Arguments:
  1162. pIntF Pointer to the IntF structure
  1163. DiskEntry
  1164. Return Value:
  1165. ArpEntry if found or NULL.
  1166. --*/
  1167. {
  1168. PARP_ENTRY ArpEntry, *ppEntry;
  1169. UINT Hash = ARP_HASH(pDskEntry->IpAddr);
  1170. ENTRY_TYPE EntryType;
  1171. ARPS_PAGED_CODE( );
  1172. DBGPRINT(DBG_LEVEL_INFO,
  1173. ("ArpSAddArpEntryFromDisk: Adding entry for IpAddr: "));
  1174. ArpSDumpIpAddr(pDskEntry->IpAddr, " ..... ");
  1175. //
  1176. // Start off by allocating an arp-entry structure
  1177. //
  1178. EntryType = (pDskEntry->AtmAddr.SubAddrLen != 0) ? ARP_BLOCK_SUBADDR : ARP_BLOCK_VANILA;
  1179. ArpEntry = (PARP_ENTRY)ArpSAllocBlock(pIntF, EntryType);
  1180. if (ArpEntry == NULL)
  1181. {
  1182. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1183. }
  1184. else
  1185. {
  1186. ArpSTimerInitialize(&ArpEntry->Timer, ArpSAgeEntry, ARP_AGE);
  1187. ArpEntry->Age = ARP_AGE;
  1188. ArpEntry->IpAddr = pDskEntry->IpAddr;
  1189. ArpEntry->Vc = NULL;
  1190. //
  1191. // COPY_ATM_ADDR();
  1192. //
  1193. ArpEntry->HwAddr.Address.AddressType = pDskEntry->AtmAddr.AddrType;
  1194. ArpEntry->HwAddr.Address.NumberOfDigits = pDskEntry->AtmAddr.AddrLen;
  1195. COPY_MEM(ArpEntry->HwAddr.Address.Address, pDskEntry->AtmAddr.Address, pDskEntry->AtmAddr.AddrLen);
  1196. if (pDskEntry->AtmAddr.SubAddrLen != 0)
  1197. {
  1198. //
  1199. // COPY_ATM_ADDR();
  1200. //
  1201. ArpEntry->HwAddr.SubAddress->AddressType = pDskEntry->AtmAddr.SubAddrType;
  1202. ArpEntry->HwAddr.SubAddress->NumberOfDigits = pDskEntry->AtmAddr.SubAddrLen;
  1203. COPY_MEM(ArpEntry->HwAddr.SubAddress->Address,
  1204. (PUCHAR)pDskEntry + sizeof(DISK_ENTRY),
  1205. pDskEntry->AtmAddr.SubAddrLen);
  1206. }
  1207. //
  1208. // Keep the overflow list sorted in ascending order of Ip addresses
  1209. //
  1210. for (ppEntry = &pIntF->ArpCache[Hash];
  1211. *ppEntry != NULL;
  1212. ppEntry = (PARP_ENTRY *)(&(*ppEntry)->Next))
  1213. {
  1214. ASSERT ((*ppEntry)->IpAddr != pDskEntry->IpAddr);
  1215. if ((*ppEntry)->IpAddr > pDskEntry->IpAddr)
  1216. break;
  1217. }
  1218. ArpEntry->Next = *ppEntry;
  1219. ArpEntry->Prev = ppEntry;
  1220. if (*ppEntry != NULL)
  1221. {
  1222. (*ppEntry)->Prev = &ArpEntry->Next;
  1223. }
  1224. *ppEntry = ArpEntry;
  1225. pIntF->NumCacheEntries ++;
  1226. ArpSTimerEnqueue(pIntF, &ArpEntry->Timer);
  1227. }
  1228. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("%lx\n", ArpEntry));
  1229. return ArpEntry;
  1230. }
  1231. VOID
  1232. ArpSUpdateArpEntry(
  1233. IN PINTF pIntF,
  1234. IN PARP_ENTRY ArpEntry,
  1235. IN IPADDR IpAddr,
  1236. IN PHW_ADDR HwAddr,
  1237. IN PARP_VC Vc
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. Update the ArpEntry with possibly new values.
  1242. Arguments:
  1243. ArpEntry ArpEntry to be updated
  1244. IpAddr IP Address
  1245. HwAddr Hw address (Atm Address and optionally Atm SubAddress)
  1246. Vc Vc associated with this entry
  1247. Return Value:
  1248. None
  1249. --*/
  1250. {
  1251. KIRQL OldIrql;
  1252. DBGPRINT(DBG_LEVEL_INFO,
  1253. ("ArpSUpdateArpEntry: Adding entry for IpAddr: "));
  1254. ArpSDumpIpAddr(IpAddr, " ..... ");
  1255. ASSERT ((ArpEntry->Vc == NULL) || (ArpEntry->Vc == Vc));
  1256. ASSERT (ArpEntry->IpAddr == IpAddr);
  1257. //
  1258. // If the Hw address changed, make sure that there is enough space there to copy the new address
  1259. //
  1260. if ((HwAddr->SubAddress != NULL) ^ (ArpEntry->HwAddr.SubAddress != NULL))
  1261. {
  1262. PARP_ENTRY *ppEntry, ArpEntryNew;
  1263. //
  1264. // Need to allocate a new ArpEntry. First de-queue the current
  1265. // entry from the list and cancel the timer.
  1266. //
  1267. ArpSTimerCancel(&ArpEntry->Timer);
  1268. *(ArpEntry->Prev) = ArpEntry->Next;
  1269. if (ArpEntry->Next != NULL)
  1270. ((PENTRY_HDR)(ArpEntry->Next))->Prev = ArpEntry->Prev;
  1271. pIntF->NumCacheEntries --;
  1272. //
  1273. // We create the new ArpEntry with a NULL Vc and then update it. This is to avoid
  1274. // de-ref and ref of the Vc again.
  1275. //
  1276. ArpEntryNew = ArpSAddArpEntry(pIntF, IpAddr, &HwAddr->Address, HwAddr->SubAddress, NULL);
  1277. if (ArpEntryNew == NULL)
  1278. {
  1279. //
  1280. // Allocation failure, link back the old entry and bail out.
  1281. //
  1282. if (ArpEntry->Next != NULL)
  1283. {
  1284. ((PENTRY_HDR)(ArpEntry->Next))->Prev = &ArpEntry;
  1285. }
  1286. *(ArpEntry->Prev) = ArpEntry;
  1287. ArpSTimerInitialize(&ArpEntry->Timer, ArpSAgeEntry, ARP_AGE);
  1288. pIntF->NumCacheEntries ++;
  1289. return;
  1290. }
  1291. //
  1292. // Update with the existing Vc for now.
  1293. //
  1294. ArpEntryNew->Vc = ArpEntry->Vc;
  1295. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1296. ASSERT((Vc->ArpEntry == ArpEntry) || (Vc->ArpEntry == NULL));
  1297. if (Vc->Flags & ARPVC_ACTIVE)
  1298. {
  1299. Vc->ArpEntry = ArpEntryNew;
  1300. }
  1301. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1302. ArpSFreeBlock(ArpEntry);
  1303. ArpEntry = ArpEntryNew;
  1304. }
  1305. else
  1306. {
  1307. ArpEntry->Age = ARP_AGE;
  1308. }
  1309. if (ArpEntry->Vc != Vc)
  1310. {
  1311. ASSERT(ArpEntry->Vc == NULL);
  1312. if (ArpSReferenceVc(Vc, FALSE))
  1313. {
  1314. ArpEntry->Vc = Vc;
  1315. }
  1316. }
  1317. COPY_HW_ADDR(&ArpEntry->HwAddr, HwAddr);
  1318. }
  1319. VOID
  1320. ArpSBuildArpReply(
  1321. IN PINTF pIntF,
  1322. IN PARP_ENTRY ArpEntry,
  1323. IN PARPS_HEADER Header,
  1324. IN PNDIS_PACKET Pkt
  1325. )
  1326. /*++
  1327. Routine Description:
  1328. Arguments:
  1329. Return Value:
  1330. None
  1331. --*/
  1332. {
  1333. PUCHAR pSrc, pDst, pDstOld;
  1334. UINT Tmp, SrcLenOld, SrcLenNew, DstLenNew;
  1335. //
  1336. // Most of the fields are already valid (or else we will not be here)
  1337. //
  1338. Header->Opcode = ATMARP_Reply;
  1339. pSrc = (PUCHAR)Header + sizeof(ARPS_HEADER);
  1340. SrcLenOld = DstLenNew = IP_ADDR_LEN + TL_LEN(Header->SrcAddressTL) + TL_LEN(Header->SrcSubAddrTL);
  1341. SrcLenNew = IP_ADDR_LEN + ArpEntry->HwAddr.Address.NumberOfDigits;
  1342. if (ArpEntry->HwAddr.SubAddress != NULL)
  1343. SrcLenNew += ArpEntry->HwAddr.SubAddress->NumberOfDigits;
  1344. pDst = pSrc + SrcLenNew;
  1345. //
  1346. // Fill in the new destination fields from the source fields of the request
  1347. //
  1348. Header->DstAddressTL = Header->SrcAddressTL;
  1349. Header->DstSubAddrTL = Header->SrcSubAddrTL;
  1350. Header->DstProtoAddrLen = Header->SrcProtoAddrLen;
  1351. MOVE_MEM(pDst, pSrc, DstLenNew);
  1352. //
  1353. // Fill in the destination fields
  1354. //
  1355. Header->DstAddressTL = TL(ArpEntry->HwAddr.Address.AddressType, ArpEntry->HwAddr.Address.NumberOfDigits);
  1356. Header->DstSubAddrTL = 0;
  1357. if (ArpEntry->HwAddr.SubAddress != NULL)
  1358. {
  1359. Header->DstSubAddrTL =
  1360. TL(ArpEntry->HwAddr.SubAddress->AddressType, ArpEntry->HwAddr.SubAddress->NumberOfDigits);
  1361. }
  1362. Header->DstProtoAddrLen = IP_ADDR_LEN;
  1363. Tmp = ArpEntry->HwAddr.Address.NumberOfDigits;
  1364. COPY_MEM(pSrc, ArpEntry->HwAddr.Address.Address, Tmp);
  1365. if (ArpEntry->HwAddr.SubAddress != NULL)
  1366. {
  1367. COPY_MEM(pSrc + Tmp,
  1368. ArpEntry->HwAddr.SubAddress->Address,
  1369. ArpEntry->HwAddr.SubAddress->NumberOfDigits);
  1370. Tmp += ArpEntry->HwAddr.SubAddress->NumberOfDigits;
  1371. }
  1372. *(UNALIGNED IPADDR *)(pSrc + Tmp) = ArpEntry->IpAddr;
  1373. DBGPRINT(DBG_LEVEL_INFO,
  1374. ("BuildReply: Pkt=0x%lx MDL=0x%lx: sz=%lu bc=%lu bo=%lu new bc=%lu\n",
  1375. Pkt,
  1376. Pkt->Private.Head,
  1377. Pkt->Private.Head->Size,
  1378. Pkt->Private.Head->ByteCount,
  1379. Pkt->Private.Head->ByteOffset,
  1380. SrcLenNew + DstLenNew + sizeof(ARPS_HEADER)));
  1381. //
  1382. // Finally set the Pkt length correctly
  1383. //
  1384. NdisAdjustBufferLength(Pkt->Private.Head, SrcLenNew + DstLenNew + sizeof(ARPS_HEADER));
  1385. Pkt->Private.ValidCounts = FALSE;
  1386. }
  1387. BOOLEAN
  1388. ArpSAgeEntry(
  1389. IN PINTF pIntF,
  1390. IN PTIMER Timer,
  1391. IN BOOLEAN TimerShuttingDown
  1392. )
  1393. /*++
  1394. Routine Description:
  1395. Check this ARP entry and if it ages out, free it.
  1396. Arguments:
  1397. Return Value:
  1398. --*/
  1399. {
  1400. PARP_ENTRY ArpEntry;
  1401. BOOLEAN rc;
  1402. ArpEntry = CONTAINING_RECORD(Timer, ARP_ENTRY, Timer);
  1403. ArpEntry->Age --;
  1404. if (TimerShuttingDown || (ArpEntry->Age == 0))
  1405. {
  1406. DBGPRINT(DBG_LEVEL_INFO,
  1407. ("ArpSAgeEntry: Aging out entry for IpAddr %lx\n", ArpEntry->IpAddr));
  1408. pIntF->ArpStats.CurrentArpEntries--;
  1409. if (ArpEntry->Next != NULL)
  1410. {
  1411. ((PENTRY_HDR)(ArpEntry->Next))->Prev = ArpEntry->Prev;
  1412. }
  1413. *(ArpEntry->Prev) = ArpEntry->Next;
  1414. pIntF->NumCacheEntries --;
  1415. //
  1416. // if there is an open Vc, make sure it is not pointing to this arpentry
  1417. //
  1418. CLEANUP_DEAD_VC(ArpEntry);
  1419. ArpSFreeBlock(ArpEntry);
  1420. rc = FALSE;
  1421. }
  1422. else
  1423. {
  1424. //
  1425. // Cleanup dead vcs
  1426. //
  1427. CLEANUP_DEAD_VC(ArpEntry);
  1428. rc = TRUE;
  1429. DBGPRINT(DBG_LEVEL_INFO,
  1430. ("ArpSAgeEntry: IpAddr %lx age %02d:%02d\n",
  1431. ArpEntry->IpAddr, ArpEntry->Age/4, (ArpEntry->Age % 4) * 15));
  1432. }
  1433. return rc;
  1434. }
  1435. BOOLEAN
  1436. ArpSDeleteIntFAddresses(
  1437. IN PINTF pIntF,
  1438. IN INT NumAddresses,
  1439. IN PATM_ADDRESS AddrList
  1440. )
  1441. //
  1442. // Return TRUE IFF the NdisCoRequest has been called EXACTLY NumAddresses times.
  1443. //
  1444. {
  1445. PNDIS_REQUEST NdisRequest;
  1446. NDIS_STATUS Status;
  1447. PCO_ADDRESS pCoAddr;
  1448. DBGPRINT(DBG_LEVEL_INFO,
  1449. ("ArpSDeleteIntFAddresses: pIntF %p: %Z, NumAddr %d\n", pIntF, &pIntF->InterfaceName, NumAddresses));
  1450. while (NumAddresses--)
  1451. {
  1452. NdisRequest = ALLOC_NP_MEM(sizeof(NDIS_REQUEST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS), POOL_TAG_REQ);
  1453. if (NdisRequest == NULL)
  1454. {
  1455. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1456. return FALSE;
  1457. }
  1458. ZERO_MEM(NdisRequest, sizeof(NDIS_REQUEST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS));
  1459. NdisRequest->RequestType = NdisRequestSetInformation;
  1460. NdisRequest->DATA.SET_INFORMATION.Oid = OID_CO_DELETE_ADDRESS;
  1461. NdisRequest->DATA.SET_INFORMATION.InformationBuffer = (PUCHAR)NdisRequest + sizeof(NDIS_REQUEST);
  1462. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  1463. //
  1464. // Copy the address into the request
  1465. //
  1466. pCoAddr = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
  1467. pCoAddr->AddressSize = sizeof(ATM_ADDRESS);
  1468. *(PATM_ADDRESS)(pCoAddr->Address) = *AddrList++;
  1469. if (pIntF->NdisAfHandle == NULL)
  1470. {
  1471. //
  1472. // Can happen if ATMUNI was unbound and we closed the AF handle
  1473. // on receiving an OID_CO_AF_CLOSE.
  1474. //
  1475. Status = NDIS_STATUS_SUCCESS;
  1476. }
  1477. else
  1478. {
  1479. Status = NdisCoRequest(pIntF->NdisBindingHandle,
  1480. pIntF->NdisAfHandle,
  1481. NULL,
  1482. NULL,
  1483. NdisRequest);
  1484. }
  1485. if (Status != NDIS_STATUS_PENDING)
  1486. {
  1487. ArpSCoRequestComplete(Status, pIntF, NULL, NULL, NdisRequest);
  1488. }
  1489. }
  1490. return TRUE;
  1491. }
  1492. VOID
  1493. ArpSQueryAndSetAddresses(
  1494. IN PINTF pIntF
  1495. )
  1496. {
  1497. PNDIS_REQUEST NdisRequest;
  1498. PCO_ADDRESS pCoAddr;
  1499. NDIS_STATUS Status;
  1500. UINT Size;
  1501. DBGPRINT(DBG_LEVEL_INFO, ("Querying current address\n"));
  1502. //
  1503. // Allocate a request to query the configured address
  1504. //
  1505. Size = sizeof(NDIS_REQUEST) + sizeof(CO_ADDRESS_LIST) + sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  1506. NdisRequest = ALLOC_NP_MEM(Size, POOL_TAG_REQ);
  1507. if (NdisRequest == NULL)
  1508. {
  1509. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1510. return;
  1511. }
  1512. ZERO_MEM(NdisRequest, Size);
  1513. NdisRequest->RequestType = NdisRequestQueryInformation;
  1514. NdisRequest->DATA.QUERY_INFORMATION.Oid = OID_CO_GET_ADDRESSES;
  1515. NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = ((PUCHAR)NdisRequest + sizeof(NDIS_REQUEST));
  1516. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size - sizeof(NDIS_REQUEST);
  1517. if (pIntF->NdisAfHandle == NULL)
  1518. {
  1519. Status = NDIS_STATUS_FAILURE;
  1520. }
  1521. else
  1522. {
  1523. Status = NdisCoRequest(pIntF->NdisBindingHandle,
  1524. pIntF->NdisAfHandle,
  1525. NULL,
  1526. NULL,
  1527. NdisRequest);
  1528. }
  1529. if (Status != NDIS_STATUS_PENDING)
  1530. {
  1531. ArpSCoRequestComplete(Status, pIntF, NULL, NULL, NdisRequest);
  1532. }
  1533. }
  1534. VOID
  1535. ArpSValidateAndSetRegdAddresses(
  1536. IN PINTF pIntF, // LOCKIN NOLOCKOUT
  1537. IN KIRQL OldIrql
  1538. )
  1539. /*++
  1540. Initiate the 1st step of the following operations, which complete asynchronously
  1541. and in order:
  1542. - Validate 1st address to be registered (by making a call to the dest - if
  1543. it fails we consider the address validated).
  1544. - (on successful validation) Register the address with the call manager.
  1545. - Validate the 2nd address
  1546. - (on successful validation) Register the 2nd address
  1547. - etc..
  1548. --*/
  1549. {
  1550. PNDIS_REQUEST NdisRequest;
  1551. PCO_ADDRESS pCoAddr;
  1552. UINT Size;
  1553. INT fLockReleased;
  1554. PREG_ADDR_CTXT pRegAddrCtxt;
  1555. DBGPRINT(DBG_LEVEL_INFO, ("Validating and setting regd. addresses\n"));
  1556. pRegAddrCtxt = NULL;
  1557. fLockReleased = FALSE;
  1558. do
  1559. {
  1560. //
  1561. // The state on the ongoing validation and registration process is
  1562. // maintained in pIntF->pRegAddrCtxt, which we allocate and initialize
  1563. // here.
  1564. //
  1565. if (pIntF->pRegAddrCtxt != NULL)
  1566. {
  1567. //
  1568. // There is ongoing work relating to registering already!
  1569. // This could happen if we get an OID_CO_ADDRESS_CHANGE when we are
  1570. // either processing an earlier one, or are in the process of
  1571. // initializing. We get these cases during pnp stress
  1572. // ( 1c_reset script against an Olicom 616X) -- Whistler bug#102805
  1573. //
  1574. break;
  1575. }
  1576. if (pIntF->NumAddressesRegd >= pIntF->NumAllocedRegdAddresses)
  1577. {
  1578. ASSERT(pIntF->NumAddressesRegd == pIntF->NumAllocedRegdAddresses);
  1579. //
  1580. // No addresses to register.
  1581. //
  1582. DBGPRINT(DBG_LEVEL_INFO, ("ValAndSet: No addresses to register.\n"));
  1583. break;
  1584. }
  1585. pRegAddrCtxt = ALLOC_NP_MEM(sizeof(*pRegAddrCtxt), POOL_TAG_REQ);
  1586. if (pRegAddrCtxt == NULL)
  1587. {
  1588. LOG_ERROR(NDIS_STATUS_RESOURCES);
  1589. break;
  1590. }
  1591. ZERO_MEM(pRegAddrCtxt, sizeof(*pRegAddrCtxt));
  1592. //
  1593. // Attach the context to the IF and add a reference.
  1594. // (Can't have the lock when adding the reference)
  1595. //
  1596. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1597. if (!ArpSReferenceIntF(pIntF))
  1598. {
  1599. DBGPRINT(DBG_LEVEL_INFO, ("ValAndSet: ERROR: Couldn't ref IntF. .\n"));
  1600. // Couldn't reference the IF. Fail.
  1601. //
  1602. fLockReleased = TRUE;
  1603. break;
  1604. }
  1605. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1606. if (pIntF->pRegAddrCtxt != NULL)
  1607. {
  1608. //
  1609. // Someone snuck in while we unlocked the IF above!
  1610. // We bail out.
  1611. //
  1612. ASSERT(FALSE);
  1613. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1614. ArpSDereferenceIntF(pIntF);
  1615. fLockReleased = TRUE;
  1616. break;
  1617. }
  1618. pIntF->pRegAddrCtxt = pRegAddrCtxt;
  1619. pRegAddrCtxt->pIntF = pIntF;
  1620. pRegAddrCtxt = NULL; // so that it is not deallocated in this function.
  1621. // Initiate the validation and registration of the first address.
  1622. //
  1623. ArpSValidateOneRegdAddress(pIntF, OldIrql);
  1624. //
  1625. // (Lock released by above call.)
  1626. fLockReleased = TRUE;
  1627. //
  1628. // The remainder of the validation and registration process happens
  1629. // asynchronously.
  1630. //
  1631. } while (FALSE);
  1632. if (pRegAddrCtxt != NULL)
  1633. {
  1634. FREE_MEM(pRegAddrCtxt);
  1635. }
  1636. if (!fLockReleased)
  1637. {
  1638. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1639. }
  1640. }
  1641. VOID
  1642. ArpSValidateOneRegdAddress(
  1643. IN PINTF pIntF, // LOCKIN NOLOCKOUT
  1644. IN KIRQL OldIrql
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. Initiates the validation and registration of a single address.
  1649. "Initiate" consists of creating a vc and making a call to the address. The
  1650. next step in the process happens after the make call completes
  1651. (see 05/14/1999 notes.txt entry ("Rogue ARP server detection contd."))
  1652. for more details.
  1653. One more thing: If there are no addresses to be validated, then
  1654. this function will DEREF pIntF and FREE pIntF->pRegAddrCtxt (which
  1655. MUST be NON-NULL).
  1656. Arguments:
  1657. pIntF Pointer to the interface block.
  1658. OldIrql Irql before pIntF was locked.
  1659. --*/
  1660. {
  1661. NDIS_STATUS Status;
  1662. INT fLockReleased = FALSE;
  1663. INT fFreeContext = TRUE;
  1664. DBGPRINT(
  1665. DBG_LEVEL_INFO,
  1666. ("==>ValidateOneRegAddress(pIntF=0x%p; pCtxt=0x%p).\n",
  1667. pIntF,
  1668. pIntF->pRegAddrCtxt));
  1669. do
  1670. {
  1671. PREG_ADDR_CTXT pRegAddrCtxt;
  1672. PATM_ADDRESS pDestAtmAddress;
  1673. pRegAddrCtxt = pIntF->pRegAddrCtxt;
  1674. // We expect to be called only if there is a valid pRegAddrCtxt.
  1675. //
  1676. if (pRegAddrCtxt == NULL)
  1677. {
  1678. ASSERT(FALSE);
  1679. fFreeContext = FALSE;
  1680. break;
  1681. }
  1682. if (pIntF->Flags & INTF_STOPPING)
  1683. {
  1684. DBGPRINT(DBG_LEVEL_INFO, ("ValOneRA: IF stopping, quitting.\n"));
  1685. // Nothing left to do.
  1686. //
  1687. break;
  1688. }
  1689. if (pIntF->NumAddressesRegd >= pIntF->NumAllocedRegdAddresses)
  1690. {
  1691. DBGPRINT(DBG_LEVEL_INFO, ("ValOneRA: nothing left to do.\n"));
  1692. // Nothing left to do.
  1693. //
  1694. break;
  1695. }
  1696. if (pIntF->NumAddressesRegd > pRegAddrCtxt->RegAddrIndex)
  1697. {
  1698. // This should never happen.
  1699. //
  1700. ASSERT(FALSE);
  1701. break;
  1702. }
  1703. if (pIntF->NumAllocedRegdAddresses <= pRegAddrCtxt->RegAddrIndex)
  1704. {
  1705. ASSERT(pIntF->NumAllocedRegdAddresses == pRegAddrCtxt->RegAddrIndex);
  1706. DBGPRINT(DBG_LEVEL_INFO, ("ValOneRA: nothing left to do.\n"));
  1707. // Nothing left to do.
  1708. //
  1709. break;
  1710. }
  1711. if (pRegAddrCtxt->NdisVcHandle != NULL)
  1712. {
  1713. // We shouldn't be called with a non-null VcHandle.
  1714. //
  1715. fFreeContext = FALSE;
  1716. ASSERT(FALSE);
  1717. break;
  1718. }
  1719. // TODO: use the Flags field.
  1720. //
  1721. // There is at least one address to try to validate & register. It
  1722. // is pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex].
  1723. //
  1724. // Create VC
  1725. //
  1726. Status = NdisCoCreateVc(
  1727. pIntF->NdisBindingHandle,
  1728. pIntF->NdisAfHandle,
  1729. (NDIS_HANDLE)pRegAddrCtxt,
  1730. &pRegAddrCtxt->NdisVcHandle
  1731. );
  1732. if (Status != NDIS_STATUS_SUCCESS)
  1733. {
  1734. pRegAddrCtxt->NdisVcHandle = NULL;
  1735. break;
  1736. }
  1737. // Set the VC type.
  1738. //
  1739. pRegAddrCtxt->VcType = VC_TYPE_CHECK_REGADDR;
  1740. // Setup call params
  1741. //
  1742. pDestAtmAddress = &(pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex]);
  1743. ArpSSetupValidationCallParams(pRegAddrCtxt, pDestAtmAddress);
  1744. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1745. fLockReleased = TRUE;
  1746. fFreeContext = FALSE;
  1747. DBGPRINT(
  1748. DBG_LEVEL_INFO,
  1749. ("ValOneRA: Going to make call. pCallParams=0x%p\n",
  1750. &pRegAddrCtxt->CallParams));
  1751. //
  1752. // Make Call (in call complete handler we move on to the next step --
  1753. // see 05/14/1999 notes.txt entry for details.)
  1754. //
  1755. Status = NdisClMakeCall(
  1756. pRegAddrCtxt->NdisVcHandle,
  1757. &pRegAddrCtxt->CallParams,
  1758. NULL,
  1759. NULL
  1760. );
  1761. if (Status != NDIS_STATUS_PENDING)
  1762. {
  1763. ArpSMakeRegAddrCallComplete(
  1764. Status,
  1765. pRegAddrCtxt
  1766. );
  1767. Status = NDIS_STATUS_PENDING;
  1768. }
  1769. } while (FALSE);
  1770. if (fFreeContext)
  1771. {
  1772. ASSERT(!fLockReleased);
  1773. //
  1774. // If there is nothing more to be done, unlink the context.
  1775. //
  1776. ArpSUnlinkRegAddrCtxt(pIntF, OldIrql);
  1777. //
  1778. // IntF lock released in above call.
  1779. fLockReleased = TRUE;
  1780. }
  1781. if (!fLockReleased)
  1782. {
  1783. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1784. }
  1785. DBGPRINT(DBG_LEVEL_INFO, ("<==ValidateOneRegAddress.\n"));
  1786. }
  1787. BOOLEAN
  1788. ArpSReferenceIntF(
  1789. IN PINTF pIntF
  1790. )
  1791. /*++
  1792. Routine Description:
  1793. Reference the Interface object.
  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. KIRQL OldIrql;
  1802. BOOLEAN rc = TRUE;
  1803. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1804. if (pIntF->Flags & INTF_CLOSING)
  1805. {
  1806. rc = FALSE;
  1807. }
  1808. else
  1809. {
  1810. pIntF->RefCount ++;
  1811. }
  1812. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1813. return rc;
  1814. }
  1815. PINTF
  1816. ArpSReferenceIntFByName(
  1817. IN PINTERFACE_NAME pInterface
  1818. )
  1819. /*++
  1820. Routine Description:
  1821. Reference the Interface object by base-name.
  1822. Arguments:
  1823. pIntF Pointer to the interface block.
  1824. Return Value:
  1825. TRUE Referenced
  1826. FALSE Interface is closing, cannot reference.
  1827. --*/
  1828. {
  1829. PINTF pIntF;
  1830. KIRQL OldIrql;
  1831. BOOLEAN Found = FALSE, ref = FALSE;
  1832. ULONG IfIndex;
  1833. ACQUIRE_SPIN_LOCK(&ArpSIfListLock, &OldIrql);
  1834. for (pIntF = ArpSIfList, IfIndex = 1;
  1835. pIntF != NULL;
  1836. pIntF = pIntF->Next, IfIndex++)
  1837. {
  1838. if (IfIndex > ArpSIfListSize)
  1839. {
  1840. DbgPrint("ATMARPS: RefIntByName: IF list at %p not consistent with list size %d\n",
  1841. ArpSIfList, ArpSIfListSize);
  1842. DbgBreakPoint();
  1843. break;
  1844. }
  1845. ACQUIRE_SPIN_LOCK_DPC(&pIntF->Lock);
  1846. if ((pIntF->FriendlyName.Length == pInterface->Length) &&
  1847. COMP_MEM(pIntF->FriendlyName.Buffer, pInterface->Buffer, pInterface->Length))
  1848. {
  1849. Found = TRUE;
  1850. if ((pIntF->Flags & INTF_CLOSING) == 0)
  1851. {
  1852. pIntF->RefCount ++;
  1853. ref = TRUE;
  1854. }
  1855. }
  1856. RELEASE_SPIN_LOCK_DPC(&pIntF->Lock);
  1857. if (Found)
  1858. break;
  1859. }
  1860. if (!ref)
  1861. {
  1862. pIntF = NULL;
  1863. }
  1864. RELEASE_SPIN_LOCK(&ArpSIfListLock, OldIrql);
  1865. DBGPRINT(DBG_LEVEL_INFO, ("ATMARPS: RefIntfByName:[%ws]: pIntF %p\n",
  1866. pInterface->Buffer, pIntF));
  1867. return pIntF;
  1868. }
  1869. VOID
  1870. ArpSDereferenceIntF(
  1871. IN PINTF pIntF
  1872. )
  1873. {
  1874. KIRQL OldIrql;
  1875. PINTF * ppIntF;
  1876. KIRQL EntryIrql;
  1877. ARPS_GET_IRQL(&EntryIrql);
  1878. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1879. ASSERT (pIntF->RefCount > 0);
  1880. pIntF->RefCount --;
  1881. if (pIntF->RefCount == 0)
  1882. {
  1883. BOOLEAN bFreeIntF = FALSE;
  1884. ASSERT (pIntF->Flags & INTF_CLOSING);
  1885. //
  1886. // We need to release and reacquire the lock to get the locks
  1887. // in the right order. In the meantime, we need to keep the
  1888. // refcount nonzero.
  1889. //
  1890. pIntF->RefCount = 1;
  1891. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1892. ACQUIRE_SPIN_LOCK(&ArpSIfListLock, &OldIrql);
  1893. ACQUIRE_SPIN_LOCK_DPC(&pIntF->Lock);
  1894. pIntF->RefCount--; // Remove tmp ref added just before.
  1895. if (pIntF->RefCount == 0)
  1896. {
  1897. //
  1898. // As expected, refcount is now back to zero. Also we have
  1899. // both list and IF lock held, so we can complete the deinit safely.
  1900. //
  1901. bFreeIntF = TRUE;
  1902. //
  1903. // Remove this Interface from the global list IF it is in the list.
  1904. //
  1905. for (ppIntF = &ArpSIfList; *ppIntF != NULL; ppIntF = &((*ppIntF)->Next))
  1906. {
  1907. if (*ppIntF == pIntF)
  1908. {
  1909. *ppIntF = pIntF->Next;
  1910. ArpSIfListSize--;
  1911. break;
  1912. }
  1913. }
  1914. //
  1915. // Signal anyone waiting for this to happen
  1916. //
  1917. if (pIntF->CleanupEvent != NULL)
  1918. {
  1919. KeSetEvent(pIntF->CleanupEvent, IO_NETWORK_INCREMENT, FALSE);
  1920. }
  1921. }
  1922. else
  1923. {
  1924. //
  1925. // Some other thread has snuck in and referenced the IF. We
  1926. // don't do anything here.
  1927. //
  1928. }
  1929. RELEASE_SPIN_LOCK_DPC(&pIntF->Lock);
  1930. RELEASE_SPIN_LOCK(&ArpSIfListLock, OldIrql);
  1931. if (bFreeIntF)
  1932. {
  1933. FREE_MEM(pIntF);
  1934. }
  1935. }
  1936. else
  1937. {
  1938. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1939. }
  1940. ARPS_CHECK_IRQL(EntryIrql);
  1941. }
  1942. BOOLEAN
  1943. ArpSReferenceVc(
  1944. IN PARP_VC Vc,
  1945. IN BOOLEAN bSendRef
  1946. )
  1947. /*++
  1948. Routine Description:
  1949. Reference the VC.
  1950. Arguments:
  1951. Vc Pointer to the VC.
  1952. bSendRef Is this a "pending send" reference?
  1953. Return Value:
  1954. TRUE Referenced
  1955. FALSE Interface or VC is closing, cannot reference.
  1956. --*/
  1957. {
  1958. PINTF pIntF = Vc->IntF;
  1959. KIRQL OldIrql;
  1960. BOOLEAN rc = TRUE;
  1961. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1962. if ((Vc->Flags & (ARPVC_CLOSING | ARPVC_CLOSE_PENDING)) != 0)
  1963. {
  1964. rc = FALSE;
  1965. }
  1966. else
  1967. {
  1968. Vc->RefCount ++;
  1969. if (bSendRef)
  1970. {
  1971. Vc->PendingSends ++;
  1972. }
  1973. }
  1974. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  1975. return rc;
  1976. }
  1977. VOID
  1978. ArpSDereferenceVc(
  1979. IN PARP_VC Vc,
  1980. IN BOOLEAN KillArpEntry,
  1981. IN BOOLEAN bSendComplete
  1982. )
  1983. {
  1984. PINTF pIntF = Vc->IntF;
  1985. KIRQL OldIrql;
  1986. BOOLEAN bInitiateClose = FALSE;
  1987. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  1988. if (bSendComplete)
  1989. {
  1990. Vc->PendingSends--;
  1991. }
  1992. ASSERT (Vc->RefCount > 0);
  1993. Vc->RefCount --;
  1994. if (Vc->RefCount == 0)
  1995. {
  1996. ASSERT ((Vc->Flags & ARPVC_ACTIVE) == 0);
  1997. ASSERT (Vc->ArpEntry == NULL);
  1998. //
  1999. // Do other cleanup here
  2000. //
  2001. RemoveEntryList(&Vc->List);
  2002. FREE_MEM(Vc);
  2003. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2004. ArpSDereferenceIntF(pIntF);
  2005. }
  2006. else
  2007. {
  2008. if (KillArpEntry)
  2009. {
  2010. DBGPRINT(DBG_LEVEL_WARN,
  2011. ("Cleaning dead vc from vc %lx, arpentry %lx\n", Vc, Vc->ArpEntry));
  2012. Vc->ArpEntry = NULL;
  2013. }
  2014. if ((Vc->PendingSends == 0) &&
  2015. (Vc->Flags & ARPVC_CLOSE_PENDING))
  2016. {
  2017. bInitiateClose = TRUE;
  2018. Vc->Flags |= ARPVC_CLOSING;
  2019. }
  2020. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2021. if (bInitiateClose)
  2022. {
  2023. ArpSInitiateCloseCall(Vc);
  2024. }
  2025. }
  2026. }
  2027. VOID
  2028. ArpSSleep(
  2029. IN UINT TimeInMs
  2030. )
  2031. {
  2032. #define NUM_100ns_PER_ms -10000L
  2033. KTIMER SleepTimer;
  2034. LARGE_INTEGER TimerValue;
  2035. NTSTATUS Status;
  2036. ARPS_PAGED_CODE( );
  2037. DBGPRINT(DBG_LEVEL_WARN,
  2038. ("=>ArpSSleep(%d)\n", TimeInMs));
  2039. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  2040. KeInitializeTimer(&SleepTimer);
  2041. TimerValue.QuadPart = Int32x32To64(TimeInMs, NUM_100ns_PER_ms);
  2042. KeSetTimer(&SleepTimer,
  2043. TimerValue,
  2044. NULL);
  2045. WAIT_FOR_OBJECT(Status, &SleepTimer, NULL);
  2046. DBGPRINT(DBG_LEVEL_WARN,
  2047. ("ArpSSleep: woken up, Status 0x%x\n", Status));
  2048. // ASSERT (Status == STATUS_TIMEOUT);
  2049. }
  2050. VOID
  2051. ArpSFreeGlobalData(
  2052. VOID
  2053. )
  2054. {
  2055. }
  2056. #if DBG
  2057. VOID
  2058. ArpSDumpPacket(
  2059. IN PUCHAR Packet,
  2060. IN UINT PktLen
  2061. )
  2062. {
  2063. UINT i;
  2064. DBGPRINT(DBG_LEVEL_INFO, (" PacketDump: "));
  2065. for (i = 0; i < PktLen; i++)
  2066. {
  2067. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  2068. ("%02x ", Packet[i]));
  2069. }
  2070. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("\n"));
  2071. }
  2072. VOID
  2073. ArpSDumpAddress(
  2074. IN IPADDR IpAddr,
  2075. IN PHW_ADDR HwAddr,
  2076. IN PCHAR String
  2077. )
  2078. {
  2079. UINT i;
  2080. DBGPRINT(DBG_LEVEL_INFO,
  2081. (" %s IpAddr: ", String));
  2082. ArpSDumpIpAddr(IpAddr, "");
  2083. ArpSDumpAtmAddr(&HwAddr->Address, ", ");
  2084. if (HwAddr->SubAddress != NULL)
  2085. {
  2086. ArpSDumpAtmAddr(HwAddr->SubAddress, "\tSub ");
  2087. }
  2088. }
  2089. VOID
  2090. ArpSDumpIpAddr(
  2091. IN IPADDR IpAddr,
  2092. IN PCHAR String
  2093. )
  2094. {
  2095. PUCHAR p = (PUCHAR)&IpAddr;
  2096. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  2097. ("%d.%d.%d.%d%s", p[0], p[1], p[2], p[3], String));
  2098. }
  2099. VOID
  2100. ArpSDumpAtmAddr(
  2101. IN PATM_ADDRESS AtmAddr,
  2102. IN PCHAR String
  2103. )
  2104. {
  2105. UINT i;
  2106. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("%sAtmAddr (%s, %d): ",
  2107. String,
  2108. (AtmAddr->AddressType == ATM_E164) ? "E164" : "NSAP",
  2109. AtmAddr->NumberOfDigits));
  2110. for (i = 0; i < AtmAddr->NumberOfDigits; i++)
  2111. {
  2112. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR,
  2113. ("%02x ", AtmAddr->Address[i]));
  2114. }
  2115. DBGPRINT(DBG_LEVEL_INFO+DBG_NO_HDR, ("\n"));
  2116. }
  2117. #endif
  2118. VOID
  2119. ArpSSetupValidationCallParams(
  2120. PREG_ADDR_CTXT pRegAddrCtxt, // LOCKIN LOCKOUT (pIntF lock)
  2121. PATM_ADDRESS pAtmAddr
  2122. )
  2123. /*++
  2124. Routine Description:
  2125. Sets up the call parameters for a validation call (call to verify that
  2126. another server with the same address doesn't exist.).
  2127. Arguments:
  2128. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2129. pRegAddrCtxt->CallParams is filled with the call params.
  2130. pAtmAddr Destination address.
  2131. --*/
  2132. {
  2133. NDIS_STATUS Status;
  2134. PINTF pIntF;
  2135. //
  2136. // Set of parameters for a MakeCall
  2137. //
  2138. PCO_CALL_PARAMETERS pCallParameters;
  2139. PCO_CALL_MANAGER_PARAMETERS pCallMgrParameters;
  2140. PQ2931_CALLMGR_PARAMETERS pAtmCallMgrParameters;
  2141. //
  2142. // All Info Elements that we need to fill:
  2143. //
  2144. Q2931_IE UNALIGNED * pIe;
  2145. AAL_PARAMETERS_IE UNALIGNED * pAalIe;
  2146. ATM_TRAFFIC_DESCRIPTOR_IE UNALIGNED * pTrafficDescriptor;
  2147. ATM_BROADBAND_BEARER_CAPABILITY_IE UNALIGNED * pBbc;
  2148. ATM_BLLI_IE UNALIGNED * pBlli;
  2149. ATM_QOS_CLASS_IE UNALIGNED * pQos;
  2150. //
  2151. // Total space requirements for the MakeCall
  2152. //
  2153. ULONG RequestSize;
  2154. pIntF = pRegAddrCtxt->pIntF;
  2155. ASSERT(pIntF->pRegAddrCtxt == pRegAddrCtxt);
  2156. //
  2157. // Zero out call params. Don't remove this!
  2158. //
  2159. ZERO_MEM(&pRegAddrCtxt->CallParams, sizeof(pRegAddrCtxt->CallParams));
  2160. ZERO_MEM(&pRegAddrCtxt->Buffer, sizeof(pRegAddrCtxt->Buffer));
  2161. //
  2162. // Distribute space amongst the various structures
  2163. //
  2164. pCallParameters = &pRegAddrCtxt->CallParams;
  2165. pCallMgrParameters = &pRegAddrCtxt->CmParams;
  2166. //
  2167. // Set pointers to link the above structures together
  2168. //
  2169. pCallParameters->CallMgrParameters = pCallMgrParameters;
  2170. pCallParameters->MediaParameters = NULL;
  2171. pCallMgrParameters->CallMgrSpecific.ParamType = 0;
  2172. pCallMgrParameters->CallMgrSpecific.Length =
  2173. sizeof(Q2931_CALLMGR_PARAMETERS) +
  2174. REGADDR_MAKE_CALL_IE_SPACE;
  2175. pAtmCallMgrParameters = (PQ2931_CALLMGR_PARAMETERS)
  2176. pCallMgrParameters->CallMgrSpecific.Parameters;
  2177. //
  2178. // Call Manager generic flow parameters:
  2179. //
  2180. pCallMgrParameters->Transmit.TokenRate = QOS_NOT_SPECIFIED;
  2181. pCallMgrParameters->Transmit.TokenBucketSize = 9188;
  2182. pCallMgrParameters->Transmit.MaxSduSize = 9188;
  2183. pCallMgrParameters->Transmit.PeakBandwidth = QOS_NOT_SPECIFIED;
  2184. pCallMgrParameters->Transmit.ServiceType = SERVICETYPE_BESTEFFORT;
  2185. pCallMgrParameters->Receive.TokenRate = QOS_NOT_SPECIFIED;
  2186. pCallMgrParameters->Receive.TokenBucketSize = 9188;
  2187. pCallMgrParameters->Receive.MaxSduSize = 9188;
  2188. pCallMgrParameters->Receive.PeakBandwidth = QOS_NOT_SPECIFIED;
  2189. pCallMgrParameters->Receive.ServiceType = SERVICETYPE_BESTEFFORT;
  2190. //
  2191. // Q2931 Call Manager Parameters:
  2192. //
  2193. //
  2194. // Called address:
  2195. //
  2196. COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CalledParty),
  2197. (PUCHAR)pAtmAddr,
  2198. sizeof(ATM_ADDRESS));
  2199. //
  2200. // Calling address:
  2201. //
  2202. COPY_MEM((PUCHAR)&(pAtmCallMgrParameters->CallingParty),
  2203. (PUCHAR)&pIntF->ConfiguredAddress,
  2204. sizeof(ATM_ADDRESS));
  2205. //
  2206. // RFC 1755 (Sec 5) says that the following IEs MUST be present in the
  2207. // SETUP message, so fill them all.
  2208. //
  2209. // AAL Parameters
  2210. // Traffic Descriptor (only for MakeCall)
  2211. // Broadband Bearer Capability (only for MakeCall)
  2212. // Broadband Low Layer Info
  2213. // QoS (only for MakeCall)
  2214. //
  2215. //
  2216. // Initialize the Info Element list
  2217. //
  2218. pAtmCallMgrParameters->InfoElementCount = 0;
  2219. pIe = (PQ2931_IE)(pAtmCallMgrParameters->InfoElements);
  2220. //
  2221. // AAL Parameters:
  2222. //
  2223. {
  2224. UNALIGNED AAL5_PARAMETERS *pAal5;
  2225. pIe->IEType = IE_AALParameters;
  2226. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_AAL_PARAMETERS_IE;
  2227. pAalIe = (PAAL_PARAMETERS_IE)pIe->IE;
  2228. pAalIe->AALType = AAL_TYPE_AAL5;
  2229. pAal5 = &(pAalIe->AALSpecificParameters.AAL5Parameters);
  2230. pAal5->ForwardMaxCPCSSDUSize = 9188;
  2231. pAal5->BackwardMaxCPCSSDUSize = 9188;
  2232. }
  2233. pAtmCallMgrParameters->InfoElementCount++;
  2234. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  2235. //
  2236. // Broadband Lower Layer Information
  2237. //
  2238. pIe->IEType = IE_BLLI;
  2239. pIe->IELength = SIZEOF_Q2931_IE + SIZEOF_ATM_BLLI_IE;
  2240. pBlli = (PATM_BLLI_IE)pIe->IE;
  2241. COPY_MEM((PUCHAR)pBlli,
  2242. (PUCHAR)&ArpSDefaultBlli,
  2243. sizeof(ATM_BLLI_IE));
  2244. pAtmCallMgrParameters->InfoElementCount++;
  2245. pIe = (PQ2931_IE)((PUCHAR)pIe + pIe->IELength);
  2246. }
  2247. VOID
  2248. ArpSMakeRegAddrCallComplete(
  2249. NDIS_STATUS Status,
  2250. PREG_ADDR_CTXT pRegAddrCtxt
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. Completion handler for the validation call. On success we drop the call and
  2255. and move on to the next address. On failure we go on to register this address
  2256. with the switch. See 05/14/1999 notes.txt entry for the larger context.
  2257. Arguments:
  2258. Status MakeCall Completion status.
  2259. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2260. --*/
  2261. {
  2262. PINTF pIntF;
  2263. KIRQL OldIrql;
  2264. pIntF = pRegAddrCtxt->pIntF;
  2265. ASSERT(pIntF->pRegAddrCtxt == pRegAddrCtxt);
  2266. DBGPRINT(DBG_LEVEL_INFO,
  2267. ("==>ArpSMakeRegAddrCallComplete. Status=0x%lx, pIntF=0x%p, pCtxt=0x%p\n",
  2268. Status,
  2269. pRegAddrCtxt->pIntF,
  2270. pRegAddrCtxt
  2271. ));
  2272. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2273. if (Status == NDIS_STATUS_SUCCESS)
  2274. {
  2275. DBGPRINT(DBG_LEVEL_ERROR,
  2276. ("MakeRegAddrCallComplete: Successful call == failed validation; dropping call.\n"));
  2277. if (pIntF->Flags & INTF_STOPPING)
  2278. {
  2279. //
  2280. // When the IF is stopping, we can't rely on
  2281. // pIntF->RegAddresses to be still around...
  2282. //
  2283. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2284. }
  2285. else
  2286. {
  2287. ATM_ADDRESS AtmAddress;
  2288. //
  2289. // A successful make call is failed validation!
  2290. // We log the event, drop the call. The drop call complete handler will
  2291. // do the next thing, which is to move on to validating the next address.
  2292. //
  2293. AtmAddress = pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex]; // struct copy
  2294. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2295. ArpSLogFailedRegistration(&AtmAddress);
  2296. }
  2297. Status = NdisClCloseCall(pRegAddrCtxt->NdisVcHandle, NULL, NULL, 0);
  2298. if (Status != NDIS_STATUS_PENDING)
  2299. {
  2300. ArpSCloseRegAddrCallComplete(Status, pRegAddrCtxt);
  2301. }
  2302. }
  2303. else
  2304. {
  2305. //
  2306. // A failed make call is considered a successful validation!
  2307. // Delete VC and initiate registration of the address.
  2308. //
  2309. PNDIS_REQUEST pNdisRequest;
  2310. NDIS_HANDLE NdisVcHandle;
  2311. PATM_ADDRESS pValidatedAddress;
  2312. PCO_ADDRESS pCoAddr;
  2313. DBGPRINT(DBG_LEVEL_ERROR,
  2314. ("MakeRegAddrCallComplete: Failed call == successful validation; Adding address.\n"));
  2315. ASSERT(pRegAddrCtxt->NdisVcHandle != NULL);
  2316. NdisVcHandle = pRegAddrCtxt->NdisVcHandle;
  2317. pRegAddrCtxt->NdisVcHandle = NULL;
  2318. if (pIntF->Flags & INTF_STOPPING)
  2319. {
  2320. // Oh oh, the IF is stopping -- we clean up the VC and call
  2321. // ArpSValidateOneRegdAddress -- it will free pRegAddrCtxt.
  2322. //
  2323. //
  2324. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2325. if (NdisVcHandle != NULL)
  2326. {
  2327. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2328. }
  2329. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2330. ArpSValidateOneRegdAddress(
  2331. pIntF,
  2332. OldIrql
  2333. );
  2334. }
  2335. else
  2336. {
  2337. ASSERT(pRegAddrCtxt->RegAddrIndex < pIntF->NumAllocedRegdAddresses);
  2338. pValidatedAddress = &(pIntF->RegAddresses[pRegAddrCtxt->RegAddrIndex]);
  2339. pRegAddrCtxt->RegAddrIndex++;
  2340. pNdisRequest = &pRegAddrCtxt->Request.NdisRequest;
  2341. pNdisRequest->RequestType = NdisRequestSetInformation;
  2342. pNdisRequest->DATA.SET_INFORMATION.Oid = OID_CO_ADD_ADDRESS;
  2343. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer
  2344. = (PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST);
  2345. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength
  2346. = sizeof(CO_ADDRESS) + sizeof(ATM_ADDRESS);
  2347. //
  2348. // Copy the address into the request
  2349. //
  2350. pCoAddr = pNdisRequest->DATA.SET_INFORMATION.InformationBuffer;
  2351. pCoAddr->AddressSize = sizeof(ATM_ADDRESS);
  2352. *(PATM_ADDRESS)(pCoAddr->Address) = *pValidatedAddress;
  2353. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2354. if (NdisVcHandle != NULL)
  2355. {
  2356. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2357. }
  2358. if (pIntF->NdisAfHandle == NULL)
  2359. {
  2360. Status = NDIS_STATUS_FAILURE;
  2361. }
  2362. else
  2363. {
  2364. Status = NdisCoRequest(pIntF->NdisBindingHandle,
  2365. pIntF->NdisAfHandle,
  2366. NULL,
  2367. NULL,
  2368. pNdisRequest);
  2369. }
  2370. if (Status != NDIS_STATUS_PENDING)
  2371. {
  2372. ArpSCoRequestComplete(Status, pIntF, NULL, NULL, pNdisRequest);
  2373. }
  2374. }
  2375. }
  2376. DBGPRINT(DBG_LEVEL_INFO,
  2377. ("<==ArpSMakeRegAddrCallComplete.\n"));
  2378. }
  2379. VOID
  2380. ArpSCloseRegAddrCallComplete(
  2381. IN NDIS_STATUS Status,
  2382. IN PREG_ADDR_CTXT pRegAddrCtxt
  2383. )
  2384. /*++
  2385. Routine Description:
  2386. Completion handler for the NdisClCloseCall of validation call. Since this
  2387. is a failed validation, we move on to validating/registration of the next
  2388. address. See 05/14/1999 notes.txt entry for the larger context.
  2389. Arguments:
  2390. Status CloseCall Completion status (ignored).
  2391. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2392. --*/
  2393. {
  2394. KIRQL OldIrql;
  2395. PINTF pIntF;
  2396. NDIS_HANDLE NdisVcHandle;
  2397. DBGPRINT(DBG_LEVEL_INFO,
  2398. ("==>ArpSCloseRegAddrCallComplete. pIntF=0x%p, pCtxt=0x%p\n",
  2399. pRegAddrCtxt->pIntF,
  2400. pRegAddrCtxt
  2401. ));
  2402. pIntF = pRegAddrCtxt->pIntF;
  2403. ASSERT(pIntF->pRegAddrCtxt == pRegAddrCtxt);
  2404. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2405. if (!(pIntF->Flags & INTF_STOPPING))
  2406. {
  2407. ASSERT(pRegAddrCtxt->RegAddrIndex < pIntF->NumAllocedRegdAddresses);
  2408. pRegAddrCtxt->RegAddrIndex++;
  2409. }
  2410. ASSERT(pRegAddrCtxt->NdisVcHandle != NULL);
  2411. NdisVcHandle = pRegAddrCtxt->NdisVcHandle;
  2412. pRegAddrCtxt->NdisVcHandle = NULL;
  2413. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2414. if (NdisVcHandle != NULL)
  2415. {
  2416. (VOID)NdisCoDeleteVc(NdisVcHandle);
  2417. }
  2418. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  2419. ArpSValidateOneRegdAddress(
  2420. pIntF,
  2421. OldIrql
  2422. );
  2423. //
  2424. // Lock released above.
  2425. DBGPRINT(DBG_LEVEL_INFO, ("<==ArpSCloseRegAddrCallComplete\n"));
  2426. }
  2427. VOID
  2428. ArpSUnlinkRegAddrCtxt(
  2429. PINTF pIntF, // LOCKIN NOLOCKOUT
  2430. KIRQL OldIrql
  2431. )
  2432. /*++
  2433. Routine Description:
  2434. Deref pIntF, remove reference to pRegAddrCtxt = pIntF->pRegAddrCtxt, and
  2435. free pIntF->pRegAddrCtxt. See 05/14/1999 notes.txt entry for the larger context.
  2436. Must only be called AFTER all async activity relating to pRegAddrCtxt is
  2437. over and pRegAddrCtxt->NdisVcHandle is NULL.
  2438. Arguments:
  2439. Status CloseCall Completion status (ignored).
  2440. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2441. --*/
  2442. {
  2443. PREG_ADDR_CTXT pRegAddrCtxt;
  2444. DBGPRINT(DBG_LEVEL_INFO, ("==>ArpSUnlinkRegAddrCtxt\n"));
  2445. pRegAddrCtxt = pIntF->pRegAddrCtxt;
  2446. ASSERT(pRegAddrCtxt != NULL);
  2447. ASSERT(pRegAddrCtxt->pIntF == pIntF);
  2448. ASSERT(pRegAddrCtxt->NdisVcHandle == NULL);
  2449. // TODO: -- flags.
  2450. FREE_MEM(pRegAddrCtxt);
  2451. pIntF->pRegAddrCtxt = NULL;
  2452. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  2453. ArpSDereferenceIntF(pIntF); // pRegAddrCtxt;
  2454. DBGPRINT(DBG_LEVEL_INFO, ("<==ArpSUnlinkRegAddrCtxt\n"));
  2455. }
  2456. VOID
  2457. ArpSIncomingRegAddrCloseCall(
  2458. IN NDIS_STATUS Status,
  2459. IN PREG_ADDR_CTXT pRegAddrCtxt
  2460. )
  2461. /*++
  2462. Routine Description:
  2463. Incoming close call handler for the validation call. Currently we do nothing
  2464. with this. I don't see the need to do anything, because we don't keep
  2465. the call up for an arbitrary length of time.
  2466. However, if/when we decide to keep the call up so that we can try to
  2467. re-validate after the call goes away, we'll need to do something here.
  2468. Arguments:
  2469. Status CloseCall Completion status (ignored).
  2470. pRegAddrCtxt Pointer to the context used to validate and register the address.
  2471. --*/
  2472. {
  2473. DBGPRINT(DBG_LEVEL_INFO, ("<==>ArpSIncomingRegAddrCloseCall\n"));
  2474. }
  2475. VOID
  2476. ArpSLogFailedRegistration(
  2477. PATM_ADDRESS pAtmAddress
  2478. )
  2479. {
  2480. WCHAR TxtAddress[2*ATM_ADDRESS_LENGTH+1]; // 2 chars per address byte plus null
  2481. WCHAR *StringList[1];
  2482. static ULONG SequenceId;
  2483. //
  2484. // Convert atm address to unicode...
  2485. //
  2486. {
  2487. static PWSTR WHexChars = L"0123456789ABCDEF";
  2488. PWSTR StrBuf;
  2489. ULONG Index;
  2490. PWSTR pWStr;
  2491. PUCHAR pAddr;
  2492. UINT Max;
  2493. Max = pAtmAddress->NumberOfDigits;
  2494. if (Max > ATM_ADDRESS_LENGTH)
  2495. {
  2496. Max = ATM_ADDRESS_LENGTH;
  2497. }
  2498. for (Index = 0, pWStr = TxtAddress, pAddr = pAtmAddress->Address;
  2499. Index < Max;
  2500. Index++, pAddr++)
  2501. {
  2502. *pWStr++ = WHexChars[(*pAddr)>>4];
  2503. *pWStr++ = WHexChars[(*pAddr)&0xf];
  2504. }
  2505. *pWStr = L'\0';
  2506. }
  2507. StringList[0] = TxtAddress;
  2508. (VOID) NdisWriteEventLogEntry(
  2509. ArpSDriverObject,
  2510. EVENT_ATMARPS_ADDRESS_ALREADY_EXISTS,
  2511. SequenceId, // Sequence
  2512. 1, // NumStrings
  2513. &StringList[0], // String list
  2514. 0, // DataSize
  2515. NULL // Data
  2516. );
  2517. NdisInterlockedIncrement(&SequenceId);
  2518. }