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.

1105 lines
24 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. This file contains the code to implement the IOCTL interface to the atmarp server.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com) July 1996
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include <precomp.h>
  14. #define _FILENUM_ FILENUM_IOCTL
  15. NTSTATUS
  16. ArpSDispatch(
  17. IN PDEVICE_OBJECT pDeviceObject,
  18. IN PIRP pIrp
  19. )
  20. /*++
  21. Routine Description:
  22. Handler for the ioctl interface - not implemented yet.
  23. Arguments:
  24. pDeviceObject ARP Server device object
  25. pIrp IRP
  26. Return Value:
  27. STATUS_NOT_IMPLEMENTED currently
  28. --*/
  29. {
  30. PIO_STACK_LOCATION pIrpSp;
  31. NTSTATUS Status;
  32. static ULONG OpenCount = 0;
  33. ARPS_PAGED_CODE( );
  34. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  35. pIrp->IoStatus.Information = 0;
  36. switch (pIrpSp->MajorFunction)
  37. {
  38. case IRP_MJ_CREATE:
  39. DBGPRINT(DBG_LEVEL_INFO,
  40. ("ArpSDispatch: Open Handle\n"));
  41. InterlockedIncrement(&OpenCount);
  42. Status = STATUS_SUCCESS;
  43. break;
  44. case IRP_MJ_CLOSE:
  45. DBGPRINT(DBG_LEVEL_INFO,
  46. ("ArpSDispatch: Close Handle\n"));
  47. Status = STATUS_SUCCESS;
  48. break;
  49. case IRP_MJ_DEVICE_CONTROL:
  50. Status = ArpSHandleIoctlRequest(pIrp, pIrpSp);
  51. break;
  52. case IRP_MJ_FILE_SYSTEM_CONTROL:
  53. Status = STATUS_NOT_IMPLEMENTED;
  54. break;
  55. case IRP_MJ_CLEANUP:
  56. DBGPRINT(DBG_LEVEL_INFO,
  57. ("ArpSDispatch: Cleanup Handle\n"));
  58. Status = STATUS_SUCCESS;
  59. InterlockedDecrement(&OpenCount);
  60. break;
  61. case IRP_MJ_SHUTDOWN:
  62. DBGPRINT(DBG_LEVEL_INFO,
  63. ("ArpSDispatch: Shutdown\n"));
  64. ArpSShutDown();
  65. Status = STATUS_SUCCESS;
  66. break;
  67. default:
  68. Status = STATUS_NOT_IMPLEMENTED;
  69. break;
  70. }
  71. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  72. if (Status != STATUS_PENDING)
  73. {
  74. pIrp->IoStatus.Status = Status;
  75. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  76. }
  77. else
  78. {
  79. IoMarkIrpPending(pIrp);
  80. }
  81. return Status;
  82. }
  83. NTSTATUS
  84. ArpSHandleIoctlRequest(
  85. IN PIRP pIrp,
  86. IN PIO_STACK_LOCATION pIrpSp
  87. )
  88. /*++
  89. Routine Description:
  90. Arguments:
  91. Return Value:
  92. --*/
  93. {
  94. NTSTATUS Status = STATUS_SUCCESS;
  95. PUCHAR pBuf;
  96. UINT BufLen;
  97. PINTF pIntF = NULL;
  98. pIrp->IoStatus.Information = 0;
  99. pBuf = pIrp->AssociatedIrp.SystemBuffer;
  100. BufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  101. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  102. {
  103. case ARPS_IOCTL_FLUSH_ARPCACHE:
  104. case ARPS_IOCTL_QUERY_ARPCACHE:
  105. case ARPS_IOCTL_ADD_ARPENTRY:
  106. case ARPS_IOCTL_QUERY_IP_FROM_ATM:
  107. case ARPS_IOCTL_QUERY_ATM_FROM_IP:
  108. case ARPS_IOCTL_QUERY_ARP_STATISTICS:
  109. case ARPS_IOCTL_QUERY_MARSCACHE:
  110. case ARPS_IOCTL_QUERY_MARS_STATISTICS:
  111. case ARPS_IOCTL_RESET_STATISTICS:
  112. {
  113. INTERFACE_NAME RawName;
  114. UINT Offset;
  115. if (pIrpSp->Parameters.DeviceIoControl.IoControlCode == ARPS_IOCTL_QUERY_ARPCACHE)
  116. {
  117. Offset = FIELD_OFFSET(IOCTL_QUERY_CACHE, Name);
  118. }
  119. else if (pIrpSp->Parameters.DeviceIoControl.IoControlCode == ARPS_IOCTL_QUERY_MARSCACHE)
  120. {
  121. Offset = FIELD_OFFSET(IOCTL_QUERY_MARS_CACHE, Name);
  122. }
  123. else
  124. {
  125. Offset = 0;
  126. }
  127. if (BufLen < sizeof(INTERFACE_NAME) + Offset)
  128. {
  129. return STATUS_INVALID_PARAMETER;
  130. }
  131. RawName = *(PINTERFACE_NAME)((PUCHAR)pBuf + Offset);
  132. RawName.Buffer = (PWSTR)(pBuf + Offset + (ULONG_PTR)RawName.Buffer); // fixup ptr
  133. //
  134. // Probe away...
  135. //
  136. if ( (PUCHAR)RawName.Buffer < (pBuf+sizeof(INTERFACE_NAME))
  137. || (PUCHAR)RawName.Buffer >= (pBuf+BufLen)
  138. || ((PUCHAR)RawName.Buffer + RawName.Length) > (pBuf+BufLen))
  139. {
  140. return STATUS_INVALID_PARAMETER;
  141. }
  142. pIntF = ArpSReferenceIntFByName(&RawName);
  143. if (pIntF == NULL)
  144. {
  145. return STATUS_NOT_FOUND;
  146. }
  147. }
  148. break;
  149. default:
  150. break; // FALL THROUGH
  151. }
  152. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  153. {
  154. case ARPS_IOCTL_QUERY_INTERFACES:
  155. DBGPRINT(DBG_LEVEL_NOTICE,
  156. ("ArpSHandleIoctlRequest: QUERY_INTERFACES\n"));
  157. BufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  158. Status = ArpSEnumerateInterfaces(pBuf, &BufLen);
  159. if (NT_SUCCESS(Status))
  160. {
  161. pIrp->IoStatus.Information = BufLen;
  162. }
  163. else
  164. {
  165. pIrp->IoStatus.Information = 0;
  166. }
  167. break;
  168. case ARPS_IOCTL_FLUSH_ARPCACHE:
  169. ASSERT (pIntF);
  170. DBGPRINT(DBG_LEVEL_NOTICE,
  171. ("ArpSHandleIoctlRequest: FLUSH_ARPCACHE on %Z\n",
  172. &pIntF->FriendlyName));
  173. Status = ArpSFlushArpCache(pIntF);
  174. pIrp->IoStatus.Information = 0;
  175. break;
  176. case ARPS_IOCTL_QUERY_ARPCACHE:
  177. ASSERT (pIntF);
  178. DBGPRINT(DBG_LEVEL_NOTICE,
  179. ("ArpSHandleIoctlRequest: QUERY_ARPCACHE on %Z\n",
  180. &pIntF->FriendlyName));
  181. pIrp->IoStatus.Information = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  182. Status = ArpSQueryArpCache(pIntF, pBuf, &pIrp->IoStatus.Information);
  183. break;
  184. #if 0
  185. //
  186. // These need more work - commented out as they aren't critical.
  187. //
  188. case ARPS_IOCTL_ADD_ARPENTRY:
  189. ASSERT (pIntF);
  190. DBGPRINT(DBG_LEVEL_NOTICE,
  191. ("ArpSHandleIoctlRequest: QUERY_ADD_ARPENTRY on %Z\n",
  192. &pIntF->FriendlyName));
  193. Status = ArpSQueryOrAddArpEntry(pIntF, (PIOCTL_QA_ENTRY)pBuf, ADD_ARP_ENTRY);
  194. break;
  195. case ARPS_IOCTL_QUERY_IP_FROM_ATM:
  196. ASSERT (pIntF);
  197. DBGPRINT(DBG_LEVEL_NOTICE,
  198. ("ArpSHandleIoctlRequest: QUERY_IP_ADDR on %Z\n",
  199. &pIntF->FriendlyName));
  200. Status = ArpSQueryOrAddArpEntry(pIntF, (PIOCTL_QA_ENTRY)pBuf, QUERY_IP_FROM_ATM);
  201. if (Status == STATUS_SUCCESS)
  202. {
  203. pIrp->IoStatus.Information = sizeof(IOCTL_QA_ENTRY);
  204. }
  205. break;
  206. case ARPS_IOCTL_QUERY_ATM_FROM_IP:
  207. ASSERT (pIntF);
  208. DBGPRINT(DBG_LEVEL_NOTICE,
  209. ("ArpSHandleIoctlRequest: QUERY_ATM_ADDR on %Z\n",
  210. pIntF->FriendlyName));
  211. Status = ArpSQueryOrAddArpEntry( pIntF, (PIOCTL_QA_ENTRY)pBuf, QUERY_ATM_FROM_IP );
  212. if (Status == STATUS_SUCCESS)
  213. {
  214. pIrp->IoStatus.Information = sizeof(IOCTL_QA_ENTRY);
  215. }
  216. break;
  217. #endif // 0
  218. case ARPS_IOCTL_QUERY_ARP_STATISTICS:
  219. ASSERT (pIntF);
  220. DBGPRINT(DBG_LEVEL_NOTICE,
  221. ("ArpSHandleIoctlRequest: QUERY_ARP_STATS on %Z\n",
  222. pIntF->FriendlyName));
  223. if (BufLen<sizeof(ARP_SERVER_STATISTICS))
  224. {
  225. Status = STATUS_BUFFER_TOO_SMALL;
  226. break;
  227. }
  228. Status = ArpSQueryArpStats( pIntF, (PARP_SERVER_STATISTICS)pBuf);
  229. if (Status == STATUS_SUCCESS)
  230. {
  231. pIrp->IoStatus.Information = sizeof(ARP_SERVER_STATISTICS);
  232. }
  233. break;
  234. case ARPS_IOCTL_QUERY_MARSCACHE:
  235. ASSERT (pIntF);
  236. DBGPRINT(DBG_LEVEL_NOTICE,
  237. ("ArpSHandleIoctlRequest: QUERY_MARSCACHE on %Z\n",
  238. &pIntF->FriendlyName));
  239. pIrp->IoStatus.Information = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  240. Status = ArpSQueryMarsCache(pIntF, pBuf, &pIrp->IoStatus.Information);
  241. break;
  242. case ARPS_IOCTL_QUERY_MARS_STATISTICS:
  243. ASSERT (pIntF);
  244. DBGPRINT(DBG_LEVEL_NOTICE,
  245. ("ArpSHandleIoctlRequest: QUERY_MARS_STATS on %Z\n",
  246. pIntF->FriendlyName));
  247. if (BufLen<sizeof(MARS_SERVER_STATISTICS))
  248. {
  249. Status = STATUS_BUFFER_TOO_SMALL;
  250. break;
  251. }
  252. Status = ArpSQueryMarsStats( pIntF, (PMARS_SERVER_STATISTICS)pBuf);
  253. if (Status == STATUS_SUCCESS)
  254. {
  255. pIrp->IoStatus.Information = sizeof(MARS_SERVER_STATISTICS);
  256. }
  257. break;
  258. case ARPS_IOCTL_RESET_STATISTICS:
  259. ASSERT (pIntF);
  260. DBGPRINT(DBG_LEVEL_NOTICE,
  261. ("ArpSHandleIoctlRequest: RESET_STATISTICS on %Z\n",
  262. pIntF->FriendlyName));
  263. ArpSResetStats(pIntF);
  264. pIrp->IoStatus.Information = 0;
  265. break;
  266. default:
  267. Status = STATUS_NOT_SUPPORTED;
  268. DBGPRINT(DBG_LEVEL_NOTICE,
  269. ("ArpSHandleIoctlRequest: Unknown request %lx\n",
  270. pIrpSp->Parameters.DeviceIoControl.IoControlCode));
  271. break;
  272. }
  273. if (pIntF != NULL)
  274. {
  275. ArpSDereferenceIntF(pIntF);
  276. }
  277. return Status;
  278. }
  279. NTSTATUS
  280. ArpSEnumerateInterfaces(
  281. IN PUCHAR pBuffer,
  282. IN OUT PULONG pSize
  283. )
  284. /*++
  285. Routine Description:
  286. Arguments:
  287. Return Value:
  288. --*/
  289. {
  290. PINTERFACES pInterfaces = (PINTERFACES)pBuffer;
  291. PINTERFACE_NAME pInterface;
  292. NTSTATUS Status = STATUS_SUCCESS;
  293. PINTF pIntF;
  294. KIRQL OldIrql;
  295. UINT Size, Total, Remaining;
  296. PUCHAR pBuf;
  297. UINT InputSize = (UINT) *pSize;
  298. ULONG IfIndex;
  299. if (InputSize < sizeof(INTERFACES))
  300. {
  301. return STATUS_BUFFER_TOO_SMALL;
  302. }
  303. pInterfaces->NumberOfInterfaces = 0;
  304. pBuf = (PUCHAR)pInterfaces + InputSize;
  305. ACQUIRE_SPIN_LOCK(&ArpSIfListLock, &OldIrql);
  306. pInterface = &pInterfaces->Interfaces[0];
  307. for (pIntF = ArpSIfList, Total = 0, Remaining = InputSize, IfIndex = 1;
  308. pIntF != NULL;
  309. pIntF = pIntF->Next, pInterface++, IfIndex++)
  310. {
  311. if (IfIndex > ArpSIfListSize)
  312. {
  313. DbgPrint("ATMARPS: EnumInt: IF list at %p not consistent with list size %d\n",
  314. ArpSIfList, ArpSIfListSize);
  315. DbgBreakPoint();
  316. break;
  317. }
  318. Size = sizeof(INTERFACE_NAME) + pIntF->FriendlyName.Length;
  319. if (Size > Remaining)
  320. {
  321. Status = STATUS_BUFFER_OVERFLOW;
  322. break;
  323. }
  324. pInterfaces->NumberOfInterfaces ++;
  325. pInterface->MaximumLength = pInterface->Length = pIntF->FriendlyName.Length;
  326. pInterface->Buffer = (PWSTR)(pBuf - pIntF->FriendlyName.Length);
  327. COPY_MEM(pInterface->Buffer, pIntF->FriendlyName.Buffer, pIntF->FriendlyName.Length);
  328. pBuf -= pIntF->FriendlyName.Length;
  329. Total += Size;
  330. Remaining -= Size;
  331. //
  332. // Convert the ptr now to an offset
  333. //
  334. pInterface->Buffer = (PWSTR)((ULONG_PTR)pInterface->Buffer - (ULONG_PTR)pInterface);
  335. }
  336. RELEASE_SPIN_LOCK(&ArpSIfListLock, OldIrql);
  337. //
  338. // Note: leave *pSize as is, because we write at the end of the
  339. // passed-in buffer.
  340. //
  341. return Status;
  342. }
  343. NTSTATUS
  344. ArpSFlushArpCache(
  345. IN PINTF pIntF
  346. )
  347. /*++
  348. Routine Description:
  349. Arguments:
  350. Return Value:
  351. --*/
  352. {
  353. NTSTATUS Status = STATUS_SUCCESS;
  354. PARP_ENTRY ArpEntry, NextArpEntry;
  355. KIRQL OldIrql;
  356. UINT i;
  357. //
  358. // Acquire the ArpCache mutex now.
  359. //
  360. WAIT_FOR_OBJECT(Status, &pIntF->ArpCacheMutex, NULL);
  361. ASSERT (Status == STATUS_SUCCESS);
  362. for (i = 0; i < ARP_TABLE_SIZE; i++)
  363. {
  364. for (ArpEntry = pIntF->ArpCache[i];
  365. ArpEntry != NULL;
  366. ArpEntry = NextArpEntry)
  367. {
  368. NextArpEntry = ArpEntry->Next;
  369. if (ArpEntry->Vc != NULL)
  370. {
  371. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  372. ArpEntry->Vc->ArpEntry = NULL;
  373. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  374. }
  375. if (ArpEntry->Next != NULL)
  376. {
  377. ((PENTRY_HDR)(ArpEntry->Next))->Prev = ArpEntry->Prev;
  378. }
  379. *(ArpEntry->Prev) = ArpEntry->Next;
  380. ArpSFreeBlock(ArpEntry);
  381. pIntF->NumCacheEntries --;
  382. }
  383. }
  384. RELEASE_MUTEX(&pIntF->ArpCacheMutex);
  385. return Status;
  386. }
  387. NTSTATUS
  388. ArpSQueryOrAddArpEntry(
  389. IN PINTF pIntF,
  390. IN OUT PIOCTL_QA_ENTRY pQaBuf,
  391. IN OPERATION Operation
  392. )
  393. /*++
  394. Routine Description:
  395. Arguments:
  396. Return Value:
  397. --*/
  398. {
  399. NTSTATUS Status = STATUS_SUCCESS;
  400. PARP_ENTRY ArpEntry;
  401. //
  402. // Acquire the ArpCache mutex now.
  403. //
  404. WAIT_FOR_OBJECT(Status, &pIntF->ArpCacheMutex, NULL);
  405. ASSERT (Status == STATUS_SUCCESS);
  406. switch (Operation)
  407. {
  408. case QUERY_IP_FROM_ATM:
  409. if ( !ArpSValidAtmAddress(&pQaBuf->ArpEntry.AtmAddress, 0) // TODO
  410. || !ArpSValidAtmAddress(&pQaBuf->ArpEntry.SubAddress, 0)) // TODO
  411. {
  412. DBGPRINT(DBG_LEVEL_ERROR,
  413. ("QueryIpAddress: Invalid address or subaddress\n"));
  414. Status = STATUS_INVALID_PARAMETER;
  415. break;
  416. }
  417. DBGPRINT(DBG_LEVEL_NOTICE,
  418. ("QueryIpAddress for "));
  419. ArpSDumpAtmAddr(&pQaBuf->ArpEntry.AtmAddress, "");
  420. if (pQaBuf->ArpEntry.SubAddress.NumberOfDigits != 0)
  421. ArpSDumpAtmAddr(&pQaBuf->ArpEntry.SubAddress, "\tSub");
  422. ArpEntry = ArpSLookupEntryByAtmAddr(pIntF,
  423. &pQaBuf->ArpEntry.AtmAddress,
  424. (pQaBuf->ArpEntry.SubAddress.NumberOfDigits != 0) ?
  425. &pQaBuf->ArpEntry.SubAddress : NULL);
  426. Status = STATUS_NOT_FOUND;
  427. if (ArpEntry != NULL)
  428. {
  429. pQaBuf->ArpEntry.IpAddr = ArpEntry->IpAddr;
  430. Status = STATUS_SUCCESS;
  431. }
  432. break;
  433. case QUERY_ATM_FROM_IP:
  434. DBGPRINT(DBG_LEVEL_NOTICE,
  435. ("QueryAtmAddress for "));
  436. ArpSDumpIpAddr(pQaBuf->ArpEntry.IpAddr, "");
  437. ArpEntry = ArpSLookupEntryByIpAddr(pIntF, pQaBuf->ArpEntry.IpAddr);
  438. Status = STATUS_NOT_FOUND;
  439. if (ArpEntry != NULL)
  440. {
  441. COPY_ATM_ADDR(&pQaBuf->ArpEntry.AtmAddress, &ArpEntry->HwAddr.Address);
  442. Status = STATUS_SUCCESS;
  443. }
  444. break;
  445. #if 0
  446. case ADD_ARP_ENTRY:
  447. if ( !ArpSValidAtmAddress(&pQaBuf->ArpEntry.AtmAddress, 0) // TODO
  448. || !ArpSValidAtmAddress(&pQaBuf->ArpEntry.SubAddress, 0)) // TODO
  449. {
  450. DBGPRINT(DBG_LEVEL_ERROR,
  451. ("AddArpEntry: Invalid address or subaddress\n"));
  452. Status = STATUS_INVALID_PARAMETER;
  453. break;
  454. }
  455. DBGPRINT(DBG_LEVEL_NOTICE, ("AddArpEntry: IpAddr "));
  456. ArpSDumpIpAddr(pQaBuf->ArpEntry.IpAddr, "");
  457. ArpSDumpAtmAddr(&pQaBuf->ArpEntry.AtmAddress, "");
  458. if (pQaBuf->ArpEntry.SubAddress.NumberOfDigits != 0)
  459. ArpSDumpAtmAddr(&pQaBuf->ArpEntry.SubAddress, "\tSub");
  460. ArpEntry = ArpSAddArpEntry(pIntF,
  461. pQaBuf->ArpEntry.IpAddr,
  462. &pQaBuf->ArpEntry.AtmAddress,
  463. (pQaBuf->ArpEntry.SubAddress.NumberOfDigits != 0) ?
  464. &pQaBuf->ArpEntry.SubAddress : NULL,
  465. NULL);
  466. #endif // 0
  467. break;
  468. default:
  469. Status = STATUS_NOT_SUPPORTED;
  470. break;
  471. }
  472. RELEASE_MUTEX(&pIntF->ArpCacheMutex);
  473. return Status;
  474. }
  475. NTSTATUS
  476. ArpSQueryArpCache(
  477. IN PINTF pIntF,
  478. IN PUCHAR pBuf,
  479. IN OUT PULONG_PTR pSize
  480. )
  481. {
  482. NTSTATUS Status = STATUS_SUCCESS;
  483. PIOCTL_QUERY_CACHE pQCache = (PIOCTL_QUERY_CACHE)pBuf;
  484. PARP_ENTRY ArpEntry;
  485. PARPENTRY Entry;
  486. UINT i, Total, Remaining;
  487. UINT InputSize = (UINT) *pSize;
  488. UINT StartIndex;
  489. #define HEADERSIZE (UINT)FIELD_OFFSET(IOCTL_QUERY_CACHE, Entries.Entries)
  490. if (InputSize < HEADERSIZE)
  491. {
  492. //
  493. // We don't even have enough space to store the
  494. // IOCTL_QUERY_CACHE.Entries structure!
  495. //
  496. return STATUS_BUFFER_TOO_SMALL;
  497. }
  498. //
  499. // Acquire the ArpCache mutex now.
  500. //
  501. WAIT_FOR_OBJECT(Status, &pIntF->ArpCacheMutex, NULL);
  502. ASSERT (Status == STATUS_SUCCESS);
  503. StartIndex = pQCache->StartEntryIndex;
  504. pQCache->Entries.TotalNumberOfEntries = pIntF->NumCacheEntries;
  505. pQCache->Entries.NumberOfEntriesInBuffer = 0;
  506. Entry = &pQCache->Entries.Entries[0];
  507. for (i = 0, Total = 0, Remaining = InputSize - HEADERSIZE;
  508. i < ARP_TABLE_SIZE;
  509. i++)
  510. {
  511. for (ArpEntry = pIntF->ArpCache[i];
  512. ArpEntry != NULL;
  513. ArpEntry = ArpEntry->Next)
  514. {
  515. //
  516. // Skip entries until we reach entry # StartIndex
  517. //
  518. if (StartIndex != 0)
  519. {
  520. StartIndex--;
  521. continue;
  522. }
  523. if (sizeof(*Entry) > Remaining)
  524. {
  525. break;
  526. }
  527. Remaining -= sizeof(ARPENTRY);
  528. Entry->IpAddr = ArpEntry->IpAddr;
  529. Entry->AtmAddress = ArpEntry->HwAddr.Address;
  530. Entry->SubAddress.NumberOfDigits = 0;
  531. if (ArpEntry->HwAddr.SubAddress != NULL)
  532. Entry->SubAddress = *ArpEntry->HwAddr.SubAddress;
  533. pQCache->Entries.NumberOfEntriesInBuffer ++;
  534. Entry ++;
  535. }
  536. if (Status == STATUS_BUFFER_OVERFLOW)
  537. break;
  538. }
  539. RELEASE_MUTEX(&pIntF->ArpCacheMutex);
  540. return Status;
  541. }
  542. NTSTATUS
  543. ArpSQueryMarsCache(
  544. IN PINTF pIntF,
  545. IN PUCHAR pBuf,
  546. IN OUT PULONG_PTR pSize
  547. )
  548. /*++
  549. Routine Description:
  550. Dump the mars cache into pBuf. The structure is QUERY_MARS_CACHE.MarsCache.
  551. The atm addresses are all placed together at the end of the supplied buffer,
  552. so the full size, *pSize, is used.
  553. Arguments:
  554. pIntF - The interface on which the MARS_REQUEST arrived
  555. Vc - The VC on which the packet arrived
  556. Header - Points to the request packet
  557. Packet - Packet where the incoming information is copied
  558. Return Value:
  559. None
  560. --*/
  561. {
  562. NTSTATUS Status = STATUS_SUCCESS;
  563. PMARS_ENTRY pMarsEntry;
  564. PMARSENTRY pEntry;
  565. UINT i, Total, Remaining;
  566. KIRQL OldIrql;
  567. ATM_ADDRESS *pAtmAddr;
  568. UINT InputSize;
  569. UINT StartIndex;
  570. PIOCTL_QUERY_MARS_CACHE pQCache = (PIOCTL_QUERY_MARS_CACHE)pBuf;
  571. #define MCHEADERSIZE \
  572. ((UINT)FIELD_OFFSET(IOCTL_QUERY_MARS_CACHE, MarsCache.Entries))
  573. //
  574. // Since we put stuff at the end of the buffer, let's force the
  575. // size to be a multiple of ULONG_PTR size.
  576. //
  577. InputSize = (UINT)(*pSize) & ~ ((UINT) (sizeof(ULONG_PTR)-1));
  578. DBGPRINT(DBG_LEVEL_NOTICE,
  579. ("QueryMarsCache: pBuf=0x%lx Size=%lu. pBuf+Size=0x%lx\n",
  580. pBuf,
  581. InputSize,
  582. pBuf+InputSize
  583. ));
  584. if (InputSize < MCHEADERSIZE)
  585. {
  586. DBGPRINT(DBG_LEVEL_NOTICE,
  587. ("QueryMarsCache: Size %lu too small. Want %lu\n",
  588. InputSize,
  589. MCHEADERSIZE
  590. ));
  591. //
  592. // We don't even have enough space to store the
  593. // IOCTL_QUERY_CACHE.Entries structure!
  594. //
  595. return STATUS_BUFFER_TOO_SMALL;
  596. }
  597. StartIndex = pQCache->StartEntryIndex;
  598. // Acquire the lock on the interface now
  599. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  600. pQCache->MarsCache.TotalNumberOfEntries = 0;
  601. pQCache->MarsCache.Sig = SIG_MARSENTRY;
  602. pQCache->MarsCache.NumberOfEntriesInBuffer = 0;
  603. pEntry = &pQCache->MarsCache.Entries[0];
  604. //
  605. // We'll go through the entire cache, but only pick up as many
  606. // as we have space for. pAtmAddr contains the next location to
  607. // put an atm address -- it starts out at the end of the buffer and
  608. // works it's way backwards. Meanwhile, the mars entries are growing
  609. // forward, starting with pQCache->MarseCache.Entries[1].
  610. // Needless to say, we must keep track of how much space is left.
  611. //
  612. pAtmAddr = ((PATM_ADDRESS) (pBuf + InputSize));
  613. for (i = 0, Total = 0, Remaining = InputSize-MCHEADERSIZE;
  614. i < MARS_TABLE_SIZE && Status == STATUS_SUCCESS;
  615. i++)
  616. {
  617. for (pMarsEntry = pIntF->MarsCache[i];
  618. pMarsEntry != NULL && Status == STATUS_SUCCESS;
  619. pMarsEntry = pMarsEntry->Next)
  620. {
  621. PGROUP_MEMBER pGroup;
  622. UINT NumMembersPickedUp=0;
  623. //
  624. // Skip entries until we reach entry # StartIndex
  625. //
  626. if (StartIndex != 0)
  627. {
  628. StartIndex--;
  629. continue;
  630. }
  631. if (sizeof(*pEntry) > Remaining)
  632. {
  633. DBGPRINT(
  634. DBG_LEVEL_NOTICE,
  635. ("QueryMarsCache: \tOut of space. Remaining=%lu\n", Remaining));
  636. break;
  637. }
  638. DBGPRINT(
  639. DBG_LEVEL_NOTICE,
  640. ("QueryMarsCache: \tPicking up Group 0x%x. IP=0x%08lx NumAddr=%lu pE=0x%x Remaining=%lu\n",
  641. pMarsEntry,
  642. pMarsEntry->IPAddress,
  643. pMarsEntry->NumMembers,
  644. pEntry,
  645. Remaining));
  646. Remaining -= sizeof(*pEntry);
  647. pQCache->MarsCache.NumberOfEntriesInBuffer ++;
  648. GETULONG2ULONG(&(pEntry->IpAddr), &(pMarsEntry->IPAddress));
  649. pEntry->Flags = 0;
  650. pEntry->NumAtmAddresses = pMarsEntry->NumMembers;
  651. pEntry->OffsetAtmAddresses = 0;
  652. if (MarsIsAddressMcsServed(pIntF, pMarsEntry->IPAddress))
  653. {
  654. pEntry->Flags |= MARSENTRY_MCS_SERVED;
  655. }
  656. //
  657. // Pick up the HW addresses of all the members of this group.
  658. // (TODO: We don't pick up the subaddress).
  659. //
  660. for (
  661. pGroup = pMarsEntry->pMembers, NumMembersPickedUp=0;
  662. pGroup != NULL;
  663. pGroup = pGroup->Next, NumMembersPickedUp++)
  664. {
  665. ARPS_ASSERT(pGroup != NULL_PGROUP_MEMBER);
  666. //
  667. // Check that we have enough space.
  668. //
  669. if (Remaining < sizeof(*pAtmAddr))
  670. {
  671. //
  672. // If there is not enough space to store all atm addresses
  673. // of a particular group, we return none, this is indicated
  674. // by setting pEntry->OffsetAtmAdresses to 0.
  675. //
  676. DBGPRINT(
  677. DBG_LEVEL_NOTICE,
  678. ("QueryMarsCache: \t\tOut of space adding addreses. Remaining=%lu\n", Remaining));
  679. Status = STATUS_BUFFER_OVERFLOW;
  680. break;
  681. }
  682. ARPS_ASSERT( (PUCHAR)(pAtmAddr-1) >= (PUCHAR)(pEntry+1));
  683. //
  684. // Copy over the atm address
  685. //
  686. DBGPRINT(
  687. DBG_LEVEL_NOTICE,
  688. ("QueryMarsCache: \t\tPicking up Addr. pDestAddr=%x. Remaining=%lu\n",
  689. pAtmAddr-1,
  690. Remaining));
  691. *--pAtmAddr = pGroup->pClusterMember->HwAddr.Address;
  692. Remaining -= sizeof(*pAtmAddr);
  693. }
  694. if (Status == STATUS_SUCCESS && NumMembersPickedUp)
  695. {
  696. //
  697. // There are non-zero members of this entry and they were
  698. // all copied successfully. Let's set the offset to these
  699. // addresses.
  700. //
  701. pEntry->OffsetAtmAddresses =
  702. (UINT) ((PUCHAR)pAtmAddr - (PUCHAR) pEntry);
  703. //
  704. // We expect NumMembersPickedUp to be equal to
  705. // pMarsEntry->NumMembers.
  706. //
  707. ARPS_ASSERT(pMarsEntry->NumMembers == NumMembersPickedUp);
  708. if (pMarsEntry->NumMembers != NumMembersPickedUp)
  709. {
  710. pEntry->NumAtmAddresses = NumMembersPickedUp;
  711. }
  712. DBGPRINT(
  713. DBG_LEVEL_NOTICE,
  714. ("QueryMarsCache: \t Picked up all addresses. OffsetAtmAddresses = %lu\n",
  715. pEntry->OffsetAtmAddresses));
  716. pEntry++;
  717. }
  718. }
  719. }
  720. pQCache->MarsCache.TotalNumberOfEntries =
  721. pQCache->MarsCache.NumberOfEntriesInBuffer; // TODO
  722. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  723. return Status;
  724. }
  725. UINT
  726. ArpSElapsedSeconds(
  727. IN PLARGE_INTEGER pStatisticsStartTimeStamp
  728. )
  729. /*++
  730. Routine Description:
  731. Return the elapsed time, in seconds, relative to *pStatisticsStartTimeStamp
  732. Arguments:
  733. pStatisticsStartTimeStamp ptr to the start time.
  734. Return Value:
  735. None
  736. --*/
  737. {
  738. UINT Ret;
  739. LARGE_INTEGER Current;
  740. NdisGetCurrentSystemTime(&Current);
  741. //
  742. // Current is in units of 100-nanoseconds so we must convert the difference
  743. // to seconds. Note we use implicit large-arithmetic operators here.
  744. //
  745. Ret = (UINT) ((Current.QuadPart - pStatisticsStartTimeStamp->QuadPart)/10000000);
  746. return Ret;
  747. }
  748. extern
  749. NTSTATUS
  750. ArpSQueryArpStats(
  751. IN PINTF pIntF,
  752. OUT PARP_SERVER_STATISTICS pArpStats
  753. )
  754. /*++
  755. Routine Description:
  756. Fill in the current arp statistics. Also set the ElapsedSeconds field
  757. to the time in seconds since statistics computation started.
  758. Arguments:
  759. pIntF - The interface applicable to the request
  760. pArpStats - Arp statistics to fill out
  761. Return Value:
  762. STATUS_SUCCESS
  763. --*/
  764. {
  765. KIRQL OldIrql;
  766. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  767. *pArpStats = pIntF->ArpStats; // big structure copy.
  768. pArpStats->ElapsedSeconds = ArpSElapsedSeconds(
  769. &(pIntF->StatisticsStartTimeStamp)
  770. );
  771. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  772. return STATUS_SUCCESS;
  773. }
  774. extern
  775. NTSTATUS
  776. ArpSQueryMarsStats(
  777. IN PINTF pIntF,
  778. OUT PMARS_SERVER_STATISTICS pMarsStats
  779. )
  780. /*++
  781. Routine Description:
  782. Fill in the current mars statistics. Also set the ElapsedSeconds field
  783. to the time in seconds since statistics computation started.
  784. Arguments:
  785. pIntF - The interface applicable to the request
  786. pMarsStats - Mars statistics to fill out.
  787. Return Value:
  788. STATUS_SUCCESS
  789. --*/
  790. {
  791. KIRQL OldIrql;
  792. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  793. *pMarsStats = pIntF->MarsStats; // big structure copy.
  794. pMarsStats->ElapsedSeconds = ArpSElapsedSeconds(
  795. &(pIntF->StatisticsStartTimeStamp)
  796. );
  797. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  798. return STATUS_SUCCESS;
  799. }
  800. extern
  801. VOID
  802. ArpSResetStats(
  803. IN PINTF pIntF
  804. )
  805. /*++
  806. Routine Description:
  807. Reset all arp and mars statistics. Update the statistics start timestamp.
  808. Arguments:
  809. pIntF - The interface on which the MARS_REQUEST arrived
  810. Return Value:
  811. None
  812. --*/
  813. {
  814. KIRQL OldIrql;
  815. ACQUIRE_SPIN_LOCK(&pIntF->Lock, &OldIrql);
  816. ZERO_MEM(&(pIntF->ArpStats), sizeof(pIntF->ArpStats));
  817. ZERO_MEM(&(pIntF->MarsStats), sizeof(pIntF->MarsStats));
  818. NdisGetCurrentSystemTime(&(pIntF->StatisticsStartTimeStamp));
  819. //
  820. // Now recompute the "current" and "max" values...
  821. //
  822. //
  823. // Arp cache entries
  824. //
  825. pIntF->ArpStats.CurrentArpEntries
  826. = pIntF->ArpStats.MaxArpEntries
  827. = pIntF->NumCacheEntries;
  828. //
  829. // Cluster member count
  830. //
  831. {
  832. pIntF->MarsStats.CurrentClusterMembers
  833. = pIntF->MarsStats.MaxClusterMembers
  834. = pIntF->NumClusterMembers;
  835. }
  836. //
  837. // MCast group count and max group-size - we have to go through the entire
  838. // mars cache to get this information.
  839. //
  840. {
  841. UINT u;
  842. UINT MaxGroupSize;
  843. UINT NumGroups;
  844. for (u = 0, MaxGroupSize = 0, NumGroups = 0;
  845. u < MARS_TABLE_SIZE;
  846. u++)
  847. {
  848. PMARS_ENTRY pMarsEntry;
  849. for (pMarsEntry = pIntF->MarsCache[u];
  850. pMarsEntry != NULL;
  851. pMarsEntry = pMarsEntry->Next)
  852. {
  853. if (MaxGroupSize < pMarsEntry->NumMembers)
  854. {
  855. MaxGroupSize = pMarsEntry->NumMembers;
  856. }
  857. NumGroups++;
  858. }
  859. }
  860. pIntF->MarsStats.CurrentGroups
  861. = pIntF->MarsStats.MaxGroups
  862. = NumGroups;
  863. pIntF->MarsStats.MaxAddressesPerGroup = MaxGroupSize;
  864. }
  865. RELEASE_SPIN_LOCK(&pIntF->Lock, OldIrql);
  866. }