Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1292 lines
27 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. ioctl.c
  6. Abstract:
  7. IOCTL Handler functions
  8. Author:
  9. Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
  10. Notes:
  11. --*/
  12. #include <precomp.h>
  13. PATMLANE_ADAPTER
  14. AtmLaneIoctlNameToAdapter(
  15. IN PUNICODE_STRING pDeviceName
  16. )
  17. /*++
  18. Routine Description:
  19. Given the name of an adapter, return a pointer to the corresponding
  20. adapter structure if one exists, else NULL.
  21. This routine also references the adapter.
  22. Arguments:
  23. pDeviceName - Pointer to Device name we are searching for.
  24. Return Value:
  25. See above.
  26. --*/
  27. {
  28. PLIST_ENTRY pListEntry;
  29. PATMLANE_ADAPTER pAdapter;
  30. PATMLANE_ADAPTER pAdapterToReturn = NULL_PATMLANE_ADAPTER;
  31. BOOLEAN bReferenced = FALSE;
  32. TRACEIN(IoctlNameToAdapter);
  33. // fixup the Buffer pointer
  34. pDeviceName->Buffer = (PWSTR)((PUCHAR)pDeviceName + sizeof(UNICODE_STRING));
  35. // loop thru the adapters looking for the ELAN
  36. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  37. for (pListEntry = pAtmLaneGlobalInfo->AdapterList.Flink;
  38. pListEntry != &(pAtmLaneGlobalInfo->AdapterList);
  39. pListEntry = pListEntry->Flink)
  40. {
  41. // get pointer to Adapter
  42. pAdapter = CONTAINING_RECORD(pListEntry, ATMLANE_ADAPTER, Link);
  43. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  44. // compare length first and then actual names
  45. if ((pDeviceName->Length == pAdapter->DeviceName.Length) &&
  46. (memcmp(pDeviceName->Buffer,
  47. pAdapter->DeviceName.Buffer,
  48. pDeviceName->Length) == 0))
  49. {
  50. // match - return this adapter
  51. pAdapterToReturn = pAdapter;
  52. ACQUIRE_ADAPTER_LOCK_DPC(pAdapter);
  53. bReferenced = AtmLaneReferenceAdapter(pAdapter, "ioctl");
  54. RELEASE_ADAPTER_LOCK_DPC(pAdapter);
  55. break;
  56. }
  57. }
  58. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  59. TRACEOUT(IoctlNameToAdapter);
  60. return (bReferenced? pAdapterToReturn: NULL);
  61. }
  62. PATMLANE_ELAN
  63. AtmLaneIoctlNameToElan(
  64. IN PATMLANE_ADAPTER pAdapter,
  65. IN PUNICODE_STRING pDeviceName
  66. )
  67. /*++
  68. Routine Description:
  69. Given a pointer to an adapter data structure and an
  70. ELAN device name, return a pointer to the corresponding
  71. ELAN structure if one exists, else NULL.
  72. This also references the ELAN structure.
  73. Arguments:
  74. pAdapter - Pointer to Adapter data structure.
  75. pDeviceName - Pointer to Device name we are searching for.
  76. Return Value:
  77. See above.
  78. --*/
  79. {
  80. PLIST_ENTRY pListEntry;
  81. PATMLANE_ELAN pElan;
  82. PATMLANE_ELAN pElanToReturn = NULL_PATMLANE_ELAN;
  83. TRACEIN(IoctlNameToElan);
  84. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  85. // fixup the Buffer pointer
  86. pDeviceName->Buffer = (PWSTR)((PUCHAR)pDeviceName + sizeof(UNICODE_STRING));
  87. ACQUIRE_ADAPTER_LOCK(pAdapter);
  88. // loop thru the ELANs looking for the given name
  89. for (pListEntry = pAdapter->ElanList.Flink;
  90. pListEntry != &(pAdapter->ElanList);
  91. pListEntry = pListEntry->Flink)
  92. {
  93. // get pointer to ELAN
  94. pElan = CONTAINING_RECORD(pListEntry, ATMLANE_ELAN, Link);
  95. STRUCT_ASSERT(pElan, atmlane_elan);
  96. // compare length first and then actual names
  97. if ((pDeviceName->Length == pElan->CfgDeviceName.Length) &&
  98. (memcmp(pDeviceName->Buffer,
  99. pElan->CfgDeviceName.Buffer,
  100. pDeviceName->Length) == 0))
  101. {
  102. // match - return this ELAN
  103. pElanToReturn = pElan;
  104. ACQUIRE_ELAN_LOCK(pElan);
  105. AtmLaneReferenceElan(pElan, "iocnametoelan");
  106. RELEASE_ELAN_LOCK(pElan);
  107. break;
  108. }
  109. }
  110. RELEASE_ADAPTER_LOCK(pAdapter);
  111. TRACEOUT(IoctlNameToElan);
  112. return (pElanToReturn);
  113. }
  114. NTSTATUS
  115. AtmLaneIoctlGetInfoVersion (
  116. IN PUCHAR pBuffer,
  117. IN UINT InputBufferLength,
  118. IN UINT OutputBufferLength,
  119. IN OUT UINT_PTR * pBytesWritten
  120. )
  121. /*++
  122. Routine Description:
  123. Return the version number of the information exported by
  124. these ioctl codes.
  125. Arguments:
  126. pBuffer - Space for input/output
  127. InputBufferLength - Length of input parameters
  128. OutputBufferLength - Space available for output
  129. pBytesWritten - Where we return the amount we actually used up
  130. Return Value:
  131. Status code
  132. --*/
  133. {
  134. NTSTATUS Status;
  135. TRACEIN(IoctlGetInfoVersion);
  136. // init
  137. *pBytesWritten = 0;
  138. Status = STATUS_SUCCESS;
  139. do
  140. {
  141. // check for enough output space
  142. if (OutputBufferLength < sizeof(ULONG))
  143. {
  144. Status = STATUS_BUFFER_OVERFLOW;
  145. break;
  146. }
  147. // output the version
  148. *((PULONG)pBuffer) = ATMLANE_INFO_VERSION;
  149. *pBytesWritten = sizeof(ULONG);
  150. }
  151. while (FALSE);
  152. TRACEOUT(IoctlGetInfoVersion);
  153. return STATUS_SUCCESS;
  154. }
  155. NTSTATUS
  156. AtmLaneIoctlEnumerateAdapters (
  157. IN PUCHAR pBuffer,
  158. IN UINT InputBufferLength,
  159. IN UINT OutputBufferLength,
  160. IN OUT UINT_PTR * pBytesWritten
  161. )
  162. /*++
  163. Routine Description:
  164. Return a list of adapters bound to the AtmLane protocol.
  165. We go through the list of Adapter structures and concatenate the
  166. device names stored in each into the output buffer.
  167. Arguments:
  168. pBuffer - Space for input/output
  169. InputBufferLength - Length of input parameters
  170. OutputBufferLength - Space available for output
  171. pBytesWritten - Where we return the amount we actually used up
  172. Return Value:
  173. Status code
  174. --*/
  175. {
  176. PATMLANE_ADAPTER pAdapter;
  177. UINT Remaining;
  178. PATMLANE_ADAPTER_LIST pAdapterList;
  179. PUNICODE_STRING pAdapterName;
  180. NTSTATUS Status;
  181. PLIST_ENTRY pListEntry;
  182. TRACEIN(IoctlEnumAdapters);
  183. // init
  184. *pBytesWritten = 0;
  185. Status = STATUS_SUCCESS;
  186. do
  187. {
  188. // check for minimal output space
  189. Remaining = OutputBufferLength;
  190. if (Remaining < sizeof(ATMLANE_ADAPTER_LIST))
  191. {
  192. Status = STATUS_BUFFER_OVERFLOW;
  193. break;
  194. }
  195. pAdapterList = (PATMLANE_ADAPTER_LIST)pBuffer;
  196. // setup to return empty list
  197. pAdapterList->AdapterCountReturned = 0;
  198. *pBytesWritten = FIELD_OFFSET(ATMLANE_ADAPTER_LIST, AdapterList);
  199. pAdapterName = &pAdapterList->AdapterList;
  200. // adjust space for output
  201. Remaining -= FIELD_OFFSET (ATMLANE_ADAPTER_LIST, AdapterList);
  202. // loop thru the adapters
  203. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  204. for (pListEntry = pAtmLaneGlobalInfo->AdapterList.Flink;
  205. pListEntry != &(pAtmLaneGlobalInfo->AdapterList);
  206. pListEntry = pListEntry->Flink)
  207. {
  208. // get pointer to adapter struct
  209. pAdapter = CONTAINING_RECORD(pListEntry, ATMLANE_ADAPTER, Link);
  210. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  211. // quit loop if no more space
  212. if (Remaining < sizeof(NDIS_STRING) + pAdapter->DeviceName.Length)
  213. {
  214. Status = STATUS_BUFFER_OVERFLOW;
  215. break;
  216. }
  217. // count and copy the adapter name
  218. pAdapterList->AdapterCountReturned++;
  219. pAdapterName->Buffer = (PWSTR)((PUCHAR)pAdapterName + sizeof(UNICODE_STRING));
  220. memcpy(pAdapterName->Buffer, pAdapter->DeviceName.Buffer, pAdapter->DeviceName.Length);
  221. pAdapterName->MaximumLength = pAdapterName->Length = pAdapter->DeviceName.Length;
  222. // convert the Buffer pointer to an offset - caller expects it
  223. pAdapterName->Buffer = (PWSTR)((PUCHAR)pAdapterName->Buffer - (PUCHAR)pAdapterList);
  224. // move ptr past the name we just copied
  225. pAdapterName = (PUNICODE_STRING)((PUCHAR)pAdapterName + sizeof(UNICODE_STRING)
  226. + pAdapter->DeviceName.Length);
  227. // update bytes written and remaining space
  228. *pBytesWritten += sizeof(UNICODE_STRING) + pAdapter->DeviceName.Length;
  229. Remaining -= sizeof(UNICODE_STRING) + pAdapter->DeviceName.Length;
  230. }
  231. // check count available same as count returned
  232. pAdapterList->AdapterCountAvailable = pAdapterList->AdapterCountReturned;
  233. // count any remaining adapters that there wasn't space for
  234. while (pListEntry != &(pAtmLaneGlobalInfo->AdapterList))
  235. {
  236. pAdapterList->AdapterCountAvailable++;
  237. pListEntry = pListEntry->Flink;
  238. }
  239. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  240. } while (FALSE);
  241. TRACEOUT(IoctlEnumerateAdapters);
  242. return (Status);
  243. }
  244. NTSTATUS
  245. AtmLaneIoctlEnumerateElans(
  246. IN PUCHAR pBuffer,
  247. IN UINT InputBufferLength,
  248. IN UINT OutputBufferLength,
  249. IN OUT UINT_PTR * pBytesWritten
  250. )
  251. /*++
  252. Routine Description:
  253. Return a list of adapters bound to the AtmLane protocol.
  254. We go through the list of Adapter structures and concatenate the
  255. device names stored in each into the output buffer.
  256. Arguments:
  257. pBuffer - Space for input/output
  258. InputBufferLength - Length of input parameters
  259. OutputBufferLength - Space available for output
  260. pBytesWritten - Where we return the amount we actually used up
  261. Return Value:
  262. Status code
  263. --*/
  264. {
  265. PATMLANE_ADAPTER pAdapter;
  266. UINT Remaining;
  267. PATMLANE_ELAN_LIST pElanList;
  268. PUNICODE_STRING pElanName;
  269. NTSTATUS Status;
  270. PATMLANE_ELAN pElan;
  271. PLIST_ENTRY pListEntry;
  272. ULONG rc;
  273. TRACEIN(IoctlEnumerateElans);
  274. // init
  275. *pBytesWritten = 0;
  276. Status = STATUS_SUCCESS;
  277. pAdapter = NULL;
  278. do
  279. {
  280. // check if adapter string passed in
  281. if (InputBufferLength < sizeof(UNICODE_STRING))
  282. {
  283. Status = STATUS_BUFFER_OVERFLOW;
  284. break;
  285. }
  286. if (InputBufferLength < sizeof(UNICODE_STRING) + ((PUNICODE_STRING)pBuffer)->MaximumLength)
  287. {
  288. Status = STATUS_BUFFER_OVERFLOW;
  289. break;
  290. }
  291. // sanity check
  292. if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length)
  293. {
  294. Status = STATUS_BUFFER_OVERFLOW;
  295. break;
  296. }
  297. // get the adapter struct from the name
  298. pAdapter = AtmLaneIoctlNameToAdapter((PUNICODE_STRING)pBuffer);
  299. if (pAdapter == NULL_PATMLANE_ADAPTER)
  300. {
  301. Status = STATUS_UNSUCCESSFUL;
  302. break;
  303. }
  304. // check for minimal output space
  305. Remaining = OutputBufferLength;
  306. if (Remaining < sizeof(ATMLANE_ELAN_LIST))
  307. {
  308. Status = STATUS_BUFFER_OVERFLOW;
  309. break;
  310. }
  311. pElanList = (PATMLANE_ELAN_LIST)pBuffer;
  312. // setup to return empty list
  313. pElanList->ElanCountReturned = 0;
  314. *pBytesWritten = FIELD_OFFSET(ATMLANE_ELAN_LIST, ElanList);
  315. Remaining -= FIELD_OFFSET(ATMLANE_ELAN_LIST, ElanList);
  316. pElanName = &pElanList->ElanList;
  317. // loop thru the Elans
  318. ACQUIRE_ADAPTER_LOCK(pAdapter);
  319. for (pListEntry = pAdapter->ElanList.Flink;
  320. pListEntry != &(pAdapter->ElanList);
  321. pListEntry = pListEntry->Flink)
  322. {
  323. // get pointer to adapter struct
  324. pElan = CONTAINING_RECORD(pListEntry, ATMLANE_ELAN, Link);
  325. STRUCT_ASSERT(pElan, atmlane_elan);
  326. // quit loop if no more space
  327. if (Remaining < sizeof(NDIS_STRING) + pElan->CfgDeviceName.Length)
  328. {
  329. Status = STATUS_BUFFER_OVERFLOW;
  330. break;
  331. }
  332. // count and copy the adapter name
  333. pElanList->ElanCountReturned++;
  334. pElanName->Buffer = (PWSTR)((PUCHAR)pElanName + sizeof(UNICODE_STRING));
  335. memcpy(pElanName->Buffer, pElan->CfgDeviceName.Buffer, pElan->CfgDeviceName.Length);
  336. pElanName->MaximumLength = pElanName->Length = pElan->CfgDeviceName.Length;
  337. // convert the Buffer pointer to an offset - caller expects it
  338. pElanName->Buffer = (PWSTR)((PUCHAR)pElanName->Buffer - (PUCHAR)pElanList);
  339. // move ptr past the name we just copied
  340. pElanName = (PUNICODE_STRING)((PUCHAR)pElanName + sizeof(UNICODE_STRING)
  341. + pElan->CfgDeviceName.Length);
  342. // update bytes written and remaining space
  343. *pBytesWritten += (sizeof(UNICODE_STRING) + pElan->CfgDeviceName.Length);
  344. Remaining -= sizeof(UNICODE_STRING) + pElan->CfgDeviceName.Length;
  345. }
  346. // set count available same as count returned
  347. pElanList->ElanCountAvailable = pElanList->ElanCountReturned;
  348. // count any remaining adapters that there wasn't space for
  349. while (pListEntry != &(pAdapter->ElanList))
  350. {
  351. pElanList->ElanCountAvailable++;
  352. pListEntry = pListEntry->Flink;
  353. }
  354. RELEASE_ADAPTER_LOCK(pAdapter);
  355. } while (FALSE);
  356. if (pAdapter != NULL)
  357. {
  358. ACQUIRE_ADAPTER_LOCK(pAdapter);
  359. rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: enumelans");
  360. if (rc != 0)
  361. {
  362. RELEASE_ADAPTER_LOCK(pAdapter);
  363. }
  364. }
  365. TRACEOUT(IoctlEnumerateElans);
  366. return (Status);
  367. }
  368. NTSTATUS
  369. AtmLaneIoctlGetElanInfo(
  370. IN PUCHAR pBuffer,
  371. IN UINT InputBufferLength,
  372. IN UINT OutputBufferLength,
  373. OUT UINT_PTR * pBytesWritten
  374. )
  375. /*++
  376. Routine Description:
  377. Return the state information about a specific Elan.
  378. Arguments:
  379. pBuffer - Space for input/output
  380. InputBufferLength - Length of input parameters
  381. OutputBufferLength - Space available for output
  382. pBytesWritten - Where we return the amount we actually used up
  383. Return Value:
  384. Status Code
  385. --*/
  386. {
  387. PATMLANE_ADAPTER pAdapter;
  388. PATMLANE_ELAN pElan;
  389. PUNICODE_STRING pAdapterNameIn;
  390. PUNICODE_STRING pElanNameIn;
  391. PATMLANE_ELANINFO pElanInfo;
  392. NTSTATUS Status;
  393. ULONG rc;
  394. TRACEIN(IoctlGetElanInfo);
  395. // init
  396. *pBytesWritten = 0;
  397. Status = STATUS_SUCCESS;
  398. pAdapter = NULL;
  399. pElan = NULL;
  400. do
  401. {
  402. // check if adapter string passed in
  403. if (InputBufferLength < sizeof(UNICODE_STRING))
  404. {
  405. Status = STATUS_BUFFER_OVERFLOW;
  406. break;
  407. }
  408. // check if elan string passed in
  409. if (InputBufferLength < ((sizeof(UNICODE_STRING) * 2) +
  410. ((PUNICODE_STRING)pBuffer)->MaximumLength))
  411. {
  412. Status = STATUS_BUFFER_OVERFLOW;
  413. break;
  414. }
  415. // sanity check
  416. if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length)
  417. {
  418. Status = STATUS_BUFFER_OVERFLOW;
  419. break;
  420. }
  421. // check if minimal output space
  422. if (OutputBufferLength < sizeof(ATMLANE_ELANINFO))
  423. {
  424. Status = STATUS_BUFFER_OVERFLOW;
  425. break;
  426. }
  427. // setup ptrs to input names
  428. pAdapterNameIn = (PUNICODE_STRING)pBuffer;
  429. pElanNameIn = (PUNICODE_STRING)(pBuffer + sizeof(UNICODE_STRING) +
  430. pAdapterNameIn->MaximumLength);
  431. // find adapter struct
  432. pAdapter = AtmLaneIoctlNameToAdapter(pAdapterNameIn);
  433. if (pAdapter == NULL_PATMLANE_ADAPTER)
  434. {
  435. Status = STATUS_UNSUCCESSFUL;
  436. break;
  437. }
  438. // find elan struct - check the lengths passed in first.
  439. InputBufferLength -= (sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
  440. if (InputBufferLength < sizeof(UNICODE_STRING))
  441. {
  442. Status = STATUS_BUFFER_OVERFLOW;
  443. break;
  444. }
  445. if (InputBufferLength < sizeof(UNICODE_STRING) + pElanNameIn->MaximumLength)
  446. {
  447. Status = STATUS_BUFFER_OVERFLOW;
  448. break;
  449. }
  450. if (pElanNameIn->MaximumLength < pElanNameIn->Length)
  451. {
  452. Status = STATUS_BUFFER_OVERFLOW;
  453. break;
  454. }
  455. pElan = AtmLaneIoctlNameToElan(pAdapter, pElanNameIn);
  456. if (pElan == NULL_PATMLANE_ELAN)
  457. {
  458. Status = STATUS_UNSUCCESSFUL;
  459. break;
  460. }
  461. // setup to fill in ELAN info
  462. pElanInfo = (PATMLANE_ELANINFO)pBuffer;
  463. NdisZeroMemory(pElanInfo, sizeof(ATMLANE_ELANINFO));
  464. ACQUIRE_ELAN_LOCK(pElan);
  465. pElanInfo->ElanNumber = pElan->ElanNumber;
  466. pElanInfo->ElanState = pElan->State;
  467. NdisMoveMemory(
  468. &pElanInfo->AtmAddress,
  469. &pElan->AtmAddress.Address,
  470. ATM_ADDRESS_LENGTH);
  471. NdisMoveMemory(
  472. &pElanInfo->LecsAddress,
  473. &pElan->LecsAddress.Address,
  474. ATM_ADDRESS_LENGTH);
  475. NdisMoveMemory(
  476. &pElanInfo->LesAddress,
  477. &pElan->LesAddress.Address,
  478. ATM_ADDRESS_LENGTH);
  479. NdisMoveMemory(
  480. &pElanInfo->BusAddress,
  481. &pElan->BusAddress.Address,
  482. ATM_ADDRESS_LENGTH);
  483. pElanInfo->LanType = pElan->LanType;
  484. pElanInfo->MaxFrameSizeCode = pElan->MaxFrameSizeCode;
  485. pElanInfo->LecId = SWAPUSHORT(pElan->LecId);
  486. NdisMoveMemory(
  487. pElanInfo->ElanName,
  488. pElan->ElanName,
  489. pElan->ElanNameSize);
  490. if (pElan->LanType == LANE_LANTYPE_TR)
  491. {
  492. NdisMoveMemory(
  493. &pElanInfo->MacAddress,
  494. &pElan->MacAddressTr,
  495. sizeof(MAC_ADDRESS));
  496. }
  497. else
  498. {
  499. NdisMoveMemory(
  500. &pElanInfo->MacAddress,
  501. &pElan->MacAddressEth,
  502. sizeof(MAC_ADDRESS));
  503. }
  504. pElanInfo->ControlTimeout = pElan->ControlTimeout;
  505. pElanInfo->MaxUnkFrameCount = pElan->MaxUnkFrameCount;
  506. pElanInfo->MaxUnkFrameTime = pElan->MaxUnkFrameTime;
  507. pElanInfo->VccTimeout = pElan->VccTimeout;
  508. pElanInfo->MaxRetryCount = pElan->MaxRetryCount;
  509. pElanInfo->AgingTime = pElan->AgingTime;
  510. pElanInfo->ForwardDelayTime = pElan->ForwardDelayTime;
  511. pElanInfo->TopologyChange = pElan->TopologyChange;
  512. pElanInfo->ArpResponseTime = pElan->ArpResponseTime;
  513. pElanInfo->FlushTimeout = pElan->FlushTimeout;
  514. pElanInfo->PathSwitchingDelay = pElan->PathSwitchingDelay;
  515. pElanInfo->LocalSegmentId = pElan->LocalSegmentId;
  516. pElanInfo->McastSendVcType = pElan->McastSendVcType;
  517. pElanInfo->McastSendVcAvgRate = pElan->McastSendVcAvgRate;
  518. pElanInfo->McastSendVcPeakRate = pElan->McastSendVcPeakRate;
  519. pElanInfo->ConnComplTimer = pElan->ConnComplTimer;
  520. RELEASE_ELAN_LOCK(pElan);
  521. *pBytesWritten = sizeof(ATMLANE_ELANINFO);
  522. } while (FALSE);
  523. if (pElan != NULL)
  524. {
  525. ACQUIRE_ELAN_LOCK(pElan);
  526. rc = AtmLaneDereferenceElan(pElan, "ioctl: getelaninfo");
  527. if (rc != 0)
  528. {
  529. RELEASE_ELAN_LOCK(pElan);
  530. }
  531. }
  532. if (pAdapter != NULL)
  533. {
  534. ACQUIRE_ADAPTER_LOCK(pAdapter);
  535. rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: getelaninfo");
  536. if (rc != 0)
  537. {
  538. RELEASE_ADAPTER_LOCK(pAdapter);
  539. }
  540. }
  541. TRACEOUT(IoctlGetElanInfo);
  542. return (Status);
  543. }
  544. NTSTATUS
  545. AtmLaneIoctlGetElanArpTable(
  546. IN PUCHAR pBuffer,
  547. IN UINT InputBufferLength,
  548. IN UINT OutputBufferLength,
  549. OUT UINT_PTR * pBytesWritten
  550. )
  551. /*++
  552. Routine Description:
  553. Return the ARP table for the specified ELAN.
  554. Arguments:
  555. pBuffer - Space for input/output
  556. InputBufferLength - Length of input parameters
  557. OutputBufferLength - Space available for output
  558. pBytesWritten - Where we return the amount we actually used up
  559. Return Value:
  560. Status code
  561. --*/
  562. {
  563. PATMLANE_ADAPTER pAdapter;
  564. PATMLANE_ELAN pElan;
  565. PUNICODE_STRING pAdapterNameIn;
  566. PUNICODE_STRING pElanNameIn;
  567. PATMLANE_ARPTABLE pArpTable;
  568. PATMLANE_ARPENTRY pArpEntry;
  569. UINT Remaining;
  570. PATMLANE_MAC_ENTRY pMacEntry;
  571. NTSTATUS Status;
  572. UINT i;
  573. ULONG rc;
  574. TRACEIN(IoctlGetElanArpTable);
  575. // init
  576. *pBytesWritten = 0;
  577. Status = STATUS_SUCCESS;
  578. pAdapter = NULL;
  579. pElan = NULL;
  580. do
  581. {
  582. // check if adapter string passed in
  583. if (InputBufferLength < sizeof(UNICODE_STRING))
  584. {
  585. Status = STATUS_BUFFER_OVERFLOW;
  586. break;
  587. }
  588. // sanity check the unicode string fields.
  589. if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length)
  590. {
  591. Status = STATUS_BUFFER_OVERFLOW;
  592. break;
  593. }
  594. // check if elan string passed in
  595. if (InputBufferLength < (((sizeof(UNICODE_STRING) * 2) +
  596. ((PUNICODE_STRING)pBuffer)->MaximumLength)))
  597. {
  598. Status = STATUS_BUFFER_OVERFLOW;
  599. break;
  600. }
  601. // check if minimum output space
  602. if (OutputBufferLength < sizeof(ATMLANE_ARPTABLE))
  603. {
  604. Status = STATUS_BUFFER_OVERFLOW;
  605. break;
  606. }
  607. // setup ptrs to input names
  608. pAdapterNameIn = (PUNICODE_STRING)pBuffer;
  609. pElanNameIn = (PUNICODE_STRING)(pBuffer + sizeof(UNICODE_STRING) +
  610. pAdapterNameIn->MaximumLength);
  611. // find adapter struct
  612. pAdapter = AtmLaneIoctlNameToAdapter(pAdapterNameIn);
  613. if (pAdapter == NULL_PATMLANE_ADAPTER)
  614. {
  615. Status = STATUS_UNSUCCESSFUL;
  616. break;
  617. }
  618. // find elan struct
  619. pElan = AtmLaneIoctlNameToElan(pAdapter, pElanNameIn);
  620. if (pElan == NULL_PATMLANE_ELAN)
  621. {
  622. Status = STATUS_UNSUCCESSFUL;
  623. break;
  624. }
  625. // setup to return empty list
  626. pArpTable = (PATMLANE_ARPTABLE)pBuffer;
  627. pArpTable->ArpEntriesAvailable = pElan->NumMacEntries;
  628. pArpTable->ArpEntriesReturned = 0;
  629. *pBytesWritten = sizeof(ATMLANE_ARPTABLE);
  630. Remaining = OutputBufferLength - sizeof(ATMLANE_ARPTABLE);
  631. pArpEntry = (PATMLANE_ARPENTRY)(pBuffer + sizeof(ATMLANE_ARPTABLE));
  632. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  633. // loop thru array of lists
  634. for (i = 0; i < ATMLANE_MAC_TABLE_SIZE; i++)
  635. {
  636. pMacEntry = pElan->pMacTable[i];
  637. while (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  638. {
  639. // check if enough space remaining
  640. if (Remaining < sizeof(ATMLANE_ARPENTRY))
  641. {
  642. Status = STATUS_BUFFER_OVERFLOW;
  643. break;
  644. }
  645. // output the entry
  646. NdisZeroMemory(pArpEntry, sizeof(ATMLANE_ARPENTRY));
  647. NdisMoveMemory(
  648. pArpEntry->MacAddress,
  649. &pMacEntry->MacAddress,
  650. sizeof(MAC_ADDRESS));
  651. if (pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  652. {
  653. NdisMoveMemory(
  654. pArpEntry->AtmAddress,
  655. pMacEntry->pAtmEntry->AtmAddress.Address,
  656. ATM_ADDRESS_LENGTH);
  657. }
  658. // update space used and space remaining
  659. *pBytesWritten += sizeof(ATMLANE_ARPENTRY);
  660. Remaining -= sizeof(ATMLANE_ARPENTRY);
  661. // increment in and out pointers
  662. pArpEntry++;
  663. pMacEntry = pMacEntry->pNextEntry;
  664. // add one to EntriesReturned
  665. pArpTable->ArpEntriesReturned++;
  666. }
  667. }
  668. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  669. } while (FALSE);
  670. if (pElan != NULL)
  671. {
  672. ACQUIRE_ELAN_LOCK(pElan);
  673. rc = AtmLaneDereferenceElan(pElan, "ioctl: getelanarp");
  674. if (rc != 0)
  675. {
  676. RELEASE_ELAN_LOCK(pElan);
  677. }
  678. }
  679. if (pAdapter != NULL)
  680. {
  681. ACQUIRE_ADAPTER_LOCK(pAdapter);
  682. rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: getelanarp");
  683. if (rc != 0)
  684. {
  685. RELEASE_ADAPTER_LOCK(pAdapter);
  686. }
  687. }
  688. TRACEOUT(IoctlGetElanArpTable);
  689. return (Status);
  690. }
  691. NTSTATUS
  692. AtmLaneIoctlGetElanConnectTable(
  693. IN PUCHAR pBuffer,
  694. IN UINT InputBufferLength,
  695. IN UINT OutputBufferLength,
  696. OUT UINT_PTR * pBytesWritten
  697. )
  698. /*++
  699. Routine Description:
  700. Return the Connection table for the specified ELAN.
  701. Arguments:
  702. pBuffer - Space for input/output
  703. InputBufferLength - Length of input parameters
  704. OutputBufferLength - Space available for output
  705. pBytesWritten - Where we return the amount we actually used up
  706. Return Value:
  707. Status code
  708. --*/
  709. {
  710. PATMLANE_ADAPTER pAdapter;
  711. PATMLANE_ELAN pElan;
  712. PUNICODE_STRING pAdapterNameIn;
  713. PUNICODE_STRING pElanNameIn;
  714. PATMLANE_CONNECTTABLE pConnTable;
  715. PATMLANE_CONNECTENTRY pConnEntry;
  716. UINT Remaining;
  717. PATMLANE_ATM_ENTRY pAtmEntry;
  718. NTSTATUS Status;
  719. ULONG rc;
  720. TRACEIN(IoctlGetElanConnectTable);
  721. // init
  722. *pBytesWritten = 0;
  723. Status = STATUS_SUCCESS;
  724. pAdapter = NULL;
  725. pElan = NULL;
  726. do
  727. {
  728. // check if adapter string passed in
  729. if (InputBufferLength < sizeof(UNICODE_STRING))
  730. {
  731. Status = STATUS_BUFFER_OVERFLOW;
  732. break;
  733. }
  734. // check if elan string passed in
  735. if (InputBufferLength < (((sizeof(UNICODE_STRING) * 2) +
  736. ((PUNICODE_STRING)pBuffer)->MaximumLength)))
  737. {
  738. Status = STATUS_BUFFER_OVERFLOW;
  739. break;
  740. }
  741. // sanity check
  742. if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length)
  743. {
  744. Status = STATUS_BUFFER_OVERFLOW;
  745. break;
  746. }
  747. // check if minimum output space
  748. if (OutputBufferLength < sizeof(ATMLANE_CONNECTTABLE))
  749. {
  750. Status = STATUS_BUFFER_OVERFLOW;
  751. break;
  752. }
  753. // setup ptrs to input names
  754. pAdapterNameIn = (PUNICODE_STRING)pBuffer;
  755. pElanNameIn = (PUNICODE_STRING)(pBuffer + sizeof(UNICODE_STRING) +
  756. pAdapterNameIn->MaximumLength);
  757. // How much of the input buffer do we have left?
  758. InputBufferLength -= (sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
  759. // validate the ELAN name buffer
  760. if (pElanNameIn->MaximumLength < pElanNameIn->Length)
  761. {
  762. Status = STATUS_BUFFER_OVERFLOW;
  763. break;
  764. }
  765. if (InputBufferLength < sizeof(UNICODE_STRING) + pElanNameIn->MaximumLength)
  766. {
  767. Status = STATUS_BUFFER_OVERFLOW;
  768. break;
  769. }
  770. // find adapter struct
  771. pAdapter = AtmLaneIoctlNameToAdapter(pAdapterNameIn);
  772. if (pAdapter == NULL_PATMLANE_ADAPTER)
  773. {
  774. Status = STATUS_UNSUCCESSFUL;
  775. break;
  776. }
  777. // find elan struct
  778. pElan = AtmLaneIoctlNameToElan(pAdapter, pElanNameIn);
  779. if (pElan == NULL_PATMLANE_ELAN)
  780. {
  781. Status = STATUS_UNSUCCESSFUL;
  782. break;
  783. }
  784. // setup to return empty list
  785. pConnTable = (PATMLANE_CONNECTTABLE)pBuffer;
  786. pConnTable->ConnectEntriesAvailable = pElan->NumAtmEntries;
  787. pConnTable->ConnectEntriesReturned = 0;
  788. *pBytesWritten = sizeof(ATMLANE_CONNECTTABLE);
  789. Remaining = OutputBufferLength - sizeof(ATMLANE_CONNECTTABLE);
  790. pConnEntry =
  791. (PATMLANE_CONNECTENTRY)(pBuffer + sizeof(ATMLANE_CONNECTTABLE));
  792. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  793. // loop thru the list
  794. pAtmEntry = pElan->pAtmEntryList;
  795. while (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  796. {
  797. // check if enough space for another entry
  798. if (Remaining < sizeof(ATMLANE_CONNECTENTRY))
  799. {
  800. Status = STATUS_BUFFER_OVERFLOW;
  801. break;
  802. }
  803. // fill in entry
  804. NdisMoveMemory(
  805. pConnEntry->AtmAddress,
  806. &pAtmEntry->AtmAddress.Address,
  807. ATM_ADDRESS_LENGTH
  808. );
  809. pConnEntry->Type = pAtmEntry->Type;
  810. pConnEntry->Vc = (pAtmEntry->pVcList!=NULL_PATMLANE_VC);
  811. pConnEntry->VcIncoming = (pAtmEntry->pVcIncoming!=NULL_PATMLANE_VC);
  812. // update space used and space remaining
  813. *pBytesWritten += sizeof(ATMLANE_CONNECTENTRY);
  814. Remaining -= sizeof(ATMLANE_CONNECTENTRY);
  815. // increment in and out pointers
  816. pConnEntry++;
  817. pAtmEntry = pAtmEntry->pNext;
  818. // add one to EntriesReturned
  819. pConnTable->ConnectEntriesReturned++;
  820. }
  821. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  822. } while (FALSE);
  823. if (pElan != NULL)
  824. {
  825. ACQUIRE_ELAN_LOCK(pElan);
  826. rc = AtmLaneDereferenceElan(pElan, "ioctl: getelanconntab");
  827. if (rc != 0)
  828. {
  829. RELEASE_ELAN_LOCK(pElan);
  830. }
  831. }
  832. if (pAdapter != NULL)
  833. {
  834. ACQUIRE_ADAPTER_LOCK(pAdapter);
  835. rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: getelanconntab");
  836. if (rc != 0)
  837. {
  838. RELEASE_ADAPTER_LOCK(pAdapter);
  839. }
  840. }
  841. TRACEOUT(IoctlGetElanConnectTable);
  842. return (Status);
  843. }
  844. NTSTATUS
  845. AtmLaneIoctlRequest(
  846. IN PIRP pIrp
  847. )
  848. /*++
  849. Routine Description:
  850. Starting point for all IOCTL Requests.
  851. Arguments:
  852. pIrp : Pointer to the IRP
  853. pHandled : If request handled TRUE otherwise FALSE
  854. Return Value:
  855. Status of the request
  856. --*/
  857. {
  858. NTSTATUS Status = STATUS_SUCCESS;
  859. PUCHAR pBuf;
  860. UINT BufLen;
  861. UINT OutBufLen;
  862. UNICODE_STRING IfName;
  863. PIO_STACK_LOCATION pIrpSp;
  864. TRACEIN(IoctlRequest);
  865. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  866. pBuf = pIrp->AssociatedIrp.SystemBuffer;
  867. BufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  868. OutBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  869. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  870. {
  871. case ATMLANE_IOCTL_GET_INFO_VERSION:
  872. DBGP((3, "IoctlRequest: Get Info Version\n"));
  873. Status = AtmLaneIoctlGetInfoVersion(
  874. pBuf,
  875. BufLen,
  876. OutBufLen,
  877. &pIrp->IoStatus.Information
  878. );
  879. break;
  880. case ATMLANE_IOCTL_ENUM_ADAPTERS:
  881. DBGP((3, "IoctlRequest: Enum Adapters\n"));
  882. Status = AtmLaneIoctlEnumerateAdapters(
  883. pBuf,
  884. BufLen,
  885. OutBufLen,
  886. &pIrp->IoStatus.Information
  887. );
  888. break;
  889. case ATMLANE_IOCTL_ENUM_ELANS:
  890. DBGP((3, "IoctlRequest: Enum ELANs\n"));
  891. Status = AtmLaneIoctlEnumerateElans(
  892. pBuf,
  893. BufLen,
  894. OutBufLen,
  895. &pIrp->IoStatus.Information
  896. );
  897. break;
  898. case ATMLANE_IOCTL_GET_ELAN_INFO:
  899. DBGP((3, "IoctlRequest: Get ELAN Info\n"));
  900. Status = AtmLaneIoctlGetElanInfo(
  901. pBuf,
  902. BufLen,
  903. OutBufLen,
  904. &pIrp->IoStatus.Information
  905. );
  906. break;
  907. case ATMLANE_IOCTL_GET_ELAN_ARP_TABLE:
  908. DBGP((3, "IoctlRequest: Getl ELAN ARP table\n"));
  909. Status = AtmLaneIoctlGetElanArpTable(
  910. pBuf,
  911. BufLen,
  912. OutBufLen,
  913. &pIrp->IoStatus.Information
  914. );
  915. break;
  916. case ATMLANE_IOCTL_GET_ELAN_CONNECT_TABLE:
  917. DBGP((3, "IoctlRequest: Get ELAN Connection table\n"));
  918. Status = AtmLaneIoctlGetElanConnectTable(
  919. pBuf,
  920. BufLen,
  921. OutBufLen,
  922. &pIrp->IoStatus.Information
  923. );
  924. break;
  925. default:
  926. DBGP((0, "IoctlRequest: Unknown control code %x\n",
  927. pIrpSp->Parameters.DeviceIoControl.IoControlCode));
  928. break;
  929. }
  930. TRACEOUT(IoctlRequest);
  931. return (Status);
  932. }