|
|
/*++
Copyright (c) 1997 FORE Systems, Inc. Copyright (c) 1997 Microsoft Corporation
Module Name:
ioctl.c
Abstract:
IOCTL Handler functions
Author:
Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
Notes:
--*/ #include <precomp.h>
PATMLANE_ADAPTER AtmLaneIoctlNameToAdapter( IN PUNICODE_STRING pDeviceName ) /*++
Routine Description:
Given the name of an adapter, return a pointer to the corresponding adapter structure if one exists, else NULL.
This routine also references the adapter.
Arguments:
pDeviceName - Pointer to Device name we are searching for.
Return Value:
See above.
--*/ { PLIST_ENTRY pListEntry; PATMLANE_ADAPTER pAdapter; PATMLANE_ADAPTER pAdapterToReturn = NULL_PATMLANE_ADAPTER; BOOLEAN bReferenced = FALSE;
TRACEIN(IoctlNameToAdapter);
// fixup the Buffer pointer
pDeviceName->Buffer = (PWSTR)((PUCHAR)pDeviceName + sizeof(UNICODE_STRING));
// loop thru the adapters looking for the ELAN
ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo); for (pListEntry = pAtmLaneGlobalInfo->AdapterList.Flink; pListEntry != &(pAtmLaneGlobalInfo->AdapterList); pListEntry = pListEntry->Flink) { // get pointer to Adapter
pAdapter = CONTAINING_RECORD(pListEntry, ATMLANE_ADAPTER, Link); STRUCT_ASSERT(pAdapter, atmlane_adapter); // compare length first and then actual names
if ((pDeviceName->Length == pAdapter->DeviceName.Length) && (memcmp(pDeviceName->Buffer, pAdapter->DeviceName.Buffer, pDeviceName->Length) == 0)) { // match - return this adapter
pAdapterToReturn = pAdapter;
ACQUIRE_ADAPTER_LOCK_DPC(pAdapter); bReferenced = AtmLaneReferenceAdapter(pAdapter, "ioctl"); RELEASE_ADAPTER_LOCK_DPC(pAdapter);
break; } }
RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
TRACEOUT(IoctlNameToAdapter); return (bReferenced? pAdapterToReturn: NULL); }
PATMLANE_ELAN AtmLaneIoctlNameToElan( IN PATMLANE_ADAPTER pAdapter, IN PUNICODE_STRING pDeviceName ) /*++
Routine Description:
Given a pointer to an adapter data structure and an ELAN device name, return a pointer to the corresponding ELAN structure if one exists, else NULL.
This also references the ELAN structure.
Arguments: pAdapter - Pointer to Adapter data structure. pDeviceName - Pointer to Device name we are searching for.
Return Value:
See above.
--*/ { PLIST_ENTRY pListEntry; PATMLANE_ELAN pElan; PATMLANE_ELAN pElanToReturn = NULL_PATMLANE_ELAN;
TRACEIN(IoctlNameToElan);
STRUCT_ASSERT(pAdapter, atmlane_adapter);
// fixup the Buffer pointer
pDeviceName->Buffer = (PWSTR)((PUCHAR)pDeviceName + sizeof(UNICODE_STRING)); ACQUIRE_ADAPTER_LOCK(pAdapter);
// loop thru the ELANs looking for the given name
for (pListEntry = pAdapter->ElanList.Flink; pListEntry != &(pAdapter->ElanList); pListEntry = pListEntry->Flink) { // get pointer to ELAN
pElan = CONTAINING_RECORD(pListEntry, ATMLANE_ELAN, Link); STRUCT_ASSERT(pElan, atmlane_elan);
// compare length first and then actual names
if ((pDeviceName->Length == pElan->CfgDeviceName.Length) && (memcmp(pDeviceName->Buffer, pElan->CfgDeviceName.Buffer, pDeviceName->Length) == 0)) { // match - return this ELAN
pElanToReturn = pElan;
ACQUIRE_ELAN_LOCK(pElan); AtmLaneReferenceElan(pElan, "iocnametoelan"); RELEASE_ELAN_LOCK(pElan);
break; } } RELEASE_ADAPTER_LOCK(pAdapter);
TRACEOUT(IoctlNameToElan);
return (pElanToReturn); }
NTSTATUS AtmLaneIoctlGetInfoVersion ( IN PUCHAR pBuffer, IN UINT InputBufferLength, IN UINT OutputBufferLength, IN OUT UINT_PTR * pBytesWritten ) /*++
Routine Description:
Return the version number of the information exported by these ioctl codes. Arguments:
pBuffer - Space for input/output InputBufferLength - Length of input parameters OutputBufferLength - Space available for output pBytesWritten - Where we return the amount we actually used up
Return Value:
Status code
--*/ { NTSTATUS Status; TRACEIN(IoctlGetInfoVersion);
// init
*pBytesWritten = 0; Status = STATUS_SUCCESS;
do { // check for enough output space
if (OutputBufferLength < sizeof(ULONG)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// output the version
*((PULONG)pBuffer) = ATMLANE_INFO_VERSION; *pBytesWritten = sizeof(ULONG); } while (FALSE);
TRACEOUT(IoctlGetInfoVersion);
return STATUS_SUCCESS; }
NTSTATUS AtmLaneIoctlEnumerateAdapters ( IN PUCHAR pBuffer, IN UINT InputBufferLength, IN UINT OutputBufferLength, IN OUT UINT_PTR * pBytesWritten ) /*++
Routine Description:
Return a list of adapters bound to the AtmLane protocol. We go through the list of Adapter structures and concatenate the device names stored in each into the output buffer.
Arguments:
pBuffer - Space for input/output InputBufferLength - Length of input parameters OutputBufferLength - Space available for output pBytesWritten - Where we return the amount we actually used up
Return Value:
Status code
--*/ { PATMLANE_ADAPTER pAdapter; UINT Remaining; PATMLANE_ADAPTER_LIST pAdapterList; PUNICODE_STRING pAdapterName; NTSTATUS Status; PLIST_ENTRY pListEntry;
TRACEIN(IoctlEnumAdapters);
// init
*pBytesWritten = 0; Status = STATUS_SUCCESS;
do { // check for minimal output space
Remaining = OutputBufferLength; if (Remaining < sizeof(ATMLANE_ADAPTER_LIST)) { Status = STATUS_BUFFER_OVERFLOW; break; }
pAdapterList = (PATMLANE_ADAPTER_LIST)pBuffer;
// setup to return empty list
pAdapterList->AdapterCountReturned = 0; *pBytesWritten = FIELD_OFFSET(ATMLANE_ADAPTER_LIST, AdapterList); pAdapterName = &pAdapterList->AdapterList;
// adjust space for output
Remaining -= FIELD_OFFSET (ATMLANE_ADAPTER_LIST, AdapterList);
// loop thru the adapters
ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo); for (pListEntry = pAtmLaneGlobalInfo->AdapterList.Flink; pListEntry != &(pAtmLaneGlobalInfo->AdapterList); pListEntry = pListEntry->Flink) { // get pointer to adapter struct
pAdapter = CONTAINING_RECORD(pListEntry, ATMLANE_ADAPTER, Link); STRUCT_ASSERT(pAdapter, atmlane_adapter);
// quit loop if no more space
if (Remaining < sizeof(NDIS_STRING) + pAdapter->DeviceName.Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
// count and copy the adapter name
pAdapterList->AdapterCountReturned++; pAdapterName->Buffer = (PWSTR)((PUCHAR)pAdapterName + sizeof(UNICODE_STRING)); memcpy(pAdapterName->Buffer, pAdapter->DeviceName.Buffer, pAdapter->DeviceName.Length); pAdapterName->MaximumLength = pAdapterName->Length = pAdapter->DeviceName.Length;
// convert the Buffer pointer to an offset - caller expects it
pAdapterName->Buffer = (PWSTR)((PUCHAR)pAdapterName->Buffer - (PUCHAR)pAdapterList);
// move ptr past the name we just copied
pAdapterName = (PUNICODE_STRING)((PUCHAR)pAdapterName + sizeof(UNICODE_STRING) + pAdapter->DeviceName.Length);
// update bytes written and remaining space
*pBytesWritten += sizeof(UNICODE_STRING) + pAdapter->DeviceName.Length; Remaining -= sizeof(UNICODE_STRING) + pAdapter->DeviceName.Length; }
// check count available same as count returned
pAdapterList->AdapterCountAvailable = pAdapterList->AdapterCountReturned;
// count any remaining adapters that there wasn't space for
while (pListEntry != &(pAtmLaneGlobalInfo->AdapterList)) { pAdapterList->AdapterCountAvailable++; pListEntry = pListEntry->Flink; }
RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
} while (FALSE); TRACEOUT(IoctlEnumerateAdapters); return (Status);
}
NTSTATUS AtmLaneIoctlEnumerateElans( IN PUCHAR pBuffer, IN UINT InputBufferLength, IN UINT OutputBufferLength, IN OUT UINT_PTR * pBytesWritten ) /*++
Routine Description:
Return a list of adapters bound to the AtmLane protocol. We go through the list of Adapter structures and concatenate the device names stored in each into the output buffer.
Arguments:
pBuffer - Space for input/output InputBufferLength - Length of input parameters OutputBufferLength - Space available for output pBytesWritten - Where we return the amount we actually used up
Return Value:
Status code
--*/ { PATMLANE_ADAPTER pAdapter; UINT Remaining; PATMLANE_ELAN_LIST pElanList; PUNICODE_STRING pElanName; NTSTATUS Status; PATMLANE_ELAN pElan; PLIST_ENTRY pListEntry; ULONG rc;
TRACEIN(IoctlEnumerateElans);
// init
*pBytesWritten = 0; Status = STATUS_SUCCESS; pAdapter = NULL;
do { // check if adapter string passed in
if (InputBufferLength < sizeof(UNICODE_STRING)) { Status = STATUS_BUFFER_OVERFLOW; break; }
if (InputBufferLength < sizeof(UNICODE_STRING) + ((PUNICODE_STRING)pBuffer)->MaximumLength) { Status = STATUS_BUFFER_OVERFLOW; break; }
// sanity check
if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
// get the adapter struct from the name
pAdapter = AtmLaneIoctlNameToAdapter((PUNICODE_STRING)pBuffer);
if (pAdapter == NULL_PATMLANE_ADAPTER) { Status = STATUS_UNSUCCESSFUL; break; }
// check for minimal output space
Remaining = OutputBufferLength; if (Remaining < sizeof(ATMLANE_ELAN_LIST)) { Status = STATUS_BUFFER_OVERFLOW; break; }
pElanList = (PATMLANE_ELAN_LIST)pBuffer;
// setup to return empty list
pElanList->ElanCountReturned = 0; *pBytesWritten = FIELD_OFFSET(ATMLANE_ELAN_LIST, ElanList); Remaining -= FIELD_OFFSET(ATMLANE_ELAN_LIST, ElanList);
pElanName = &pElanList->ElanList;
// loop thru the Elans
ACQUIRE_ADAPTER_LOCK(pAdapter); for (pListEntry = pAdapter->ElanList.Flink; pListEntry != &(pAdapter->ElanList); pListEntry = pListEntry->Flink) { // get pointer to adapter struct
pElan = CONTAINING_RECORD(pListEntry, ATMLANE_ELAN, Link); STRUCT_ASSERT(pElan, atmlane_elan);
// quit loop if no more space
if (Remaining < sizeof(NDIS_STRING) + pElan->CfgDeviceName.Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
// count and copy the adapter name
pElanList->ElanCountReturned++; pElanName->Buffer = (PWSTR)((PUCHAR)pElanName + sizeof(UNICODE_STRING)); memcpy(pElanName->Buffer, pElan->CfgDeviceName.Buffer, pElan->CfgDeviceName.Length); pElanName->MaximumLength = pElanName->Length = pElan->CfgDeviceName.Length;
// convert the Buffer pointer to an offset - caller expects it
pElanName->Buffer = (PWSTR)((PUCHAR)pElanName->Buffer - (PUCHAR)pElanList);
// move ptr past the name we just copied
pElanName = (PUNICODE_STRING)((PUCHAR)pElanName + sizeof(UNICODE_STRING) + pElan->CfgDeviceName.Length);
// update bytes written and remaining space
*pBytesWritten += (sizeof(UNICODE_STRING) + pElan->CfgDeviceName.Length); Remaining -= sizeof(UNICODE_STRING) + pElan->CfgDeviceName.Length; }
// set count available same as count returned
pElanList->ElanCountAvailable = pElanList->ElanCountReturned;
// count any remaining adapters that there wasn't space for
while (pListEntry != &(pAdapter->ElanList)) { pElanList->ElanCountAvailable++; pListEntry = pListEntry->Flink; }
RELEASE_ADAPTER_LOCK(pAdapter);
} while (FALSE); if (pAdapter != NULL) { ACQUIRE_ADAPTER_LOCK(pAdapter); rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: enumelans"); if (rc != 0) { RELEASE_ADAPTER_LOCK(pAdapter); } }
TRACEOUT(IoctlEnumerateElans);
return (Status); }
NTSTATUS AtmLaneIoctlGetElanInfo( IN PUCHAR pBuffer, IN UINT InputBufferLength, IN UINT OutputBufferLength, OUT UINT_PTR * pBytesWritten ) /*++
Routine Description:
Return the state information about a specific Elan.
Arguments:
pBuffer - Space for input/output InputBufferLength - Length of input parameters OutputBufferLength - Space available for output pBytesWritten - Where we return the amount we actually used up
Return Value:
Status Code
--*/ { PATMLANE_ADAPTER pAdapter; PATMLANE_ELAN pElan; PUNICODE_STRING pAdapterNameIn; PUNICODE_STRING pElanNameIn; PATMLANE_ELANINFO pElanInfo; NTSTATUS Status; ULONG rc;
TRACEIN(IoctlGetElanInfo);
// init
*pBytesWritten = 0; Status = STATUS_SUCCESS; pAdapter = NULL; pElan = NULL;
do { // check if adapter string passed in
if (InputBufferLength < sizeof(UNICODE_STRING)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// check if elan string passed in
if (InputBufferLength < ((sizeof(UNICODE_STRING) * 2) + ((PUNICODE_STRING)pBuffer)->MaximumLength)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// sanity check
if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
// check if minimal output space
if (OutputBufferLength < sizeof(ATMLANE_ELANINFO)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// setup ptrs to input names
pAdapterNameIn = (PUNICODE_STRING)pBuffer; pElanNameIn = (PUNICODE_STRING)(pBuffer + sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
// find adapter struct
pAdapter = AtmLaneIoctlNameToAdapter(pAdapterNameIn);
if (pAdapter == NULL_PATMLANE_ADAPTER) { Status = STATUS_UNSUCCESSFUL; break; }
// find elan struct - check the lengths passed in first.
InputBufferLength -= (sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
if (InputBufferLength < sizeof(UNICODE_STRING)) { Status = STATUS_BUFFER_OVERFLOW; break; }
if (InputBufferLength < sizeof(UNICODE_STRING) + pElanNameIn->MaximumLength) { Status = STATUS_BUFFER_OVERFLOW; break; }
if (pElanNameIn->MaximumLength < pElanNameIn->Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
pElan = AtmLaneIoctlNameToElan(pAdapter, pElanNameIn);
if (pElan == NULL_PATMLANE_ELAN) { Status = STATUS_UNSUCCESSFUL; break; }
// setup to fill in ELAN info
pElanInfo = (PATMLANE_ELANINFO)pBuffer; NdisZeroMemory(pElanInfo, sizeof(ATMLANE_ELANINFO)); ACQUIRE_ELAN_LOCK(pElan);
pElanInfo->ElanNumber = pElan->ElanNumber; pElanInfo->ElanState = pElan->State; NdisMoveMemory( &pElanInfo->AtmAddress, &pElan->AtmAddress.Address, ATM_ADDRESS_LENGTH); NdisMoveMemory( &pElanInfo->LecsAddress, &pElan->LecsAddress.Address, ATM_ADDRESS_LENGTH); NdisMoveMemory( &pElanInfo->LesAddress, &pElan->LesAddress.Address, ATM_ADDRESS_LENGTH); NdisMoveMemory( &pElanInfo->BusAddress, &pElan->BusAddress.Address, ATM_ADDRESS_LENGTH); pElanInfo->LanType = pElan->LanType; pElanInfo->MaxFrameSizeCode = pElan->MaxFrameSizeCode; pElanInfo->LecId = SWAPUSHORT(pElan->LecId); NdisMoveMemory( pElanInfo->ElanName, pElan->ElanName, pElan->ElanNameSize); if (pElan->LanType == LANE_LANTYPE_TR) { NdisMoveMemory( &pElanInfo->MacAddress, &pElan->MacAddressTr, sizeof(MAC_ADDRESS)); } else { NdisMoveMemory( &pElanInfo->MacAddress, &pElan->MacAddressEth, sizeof(MAC_ADDRESS)); } pElanInfo->ControlTimeout = pElan->ControlTimeout; pElanInfo->MaxUnkFrameCount = pElan->MaxUnkFrameCount; pElanInfo->MaxUnkFrameTime = pElan->MaxUnkFrameTime; pElanInfo->VccTimeout = pElan->VccTimeout; pElanInfo->MaxRetryCount = pElan->MaxRetryCount; pElanInfo->AgingTime = pElan->AgingTime; pElanInfo->ForwardDelayTime = pElan->ForwardDelayTime; pElanInfo->TopologyChange = pElan->TopologyChange; pElanInfo->ArpResponseTime = pElan->ArpResponseTime; pElanInfo->FlushTimeout = pElan->FlushTimeout; pElanInfo->PathSwitchingDelay = pElan->PathSwitchingDelay; pElanInfo->LocalSegmentId = pElan->LocalSegmentId; pElanInfo->McastSendVcType = pElan->McastSendVcType; pElanInfo->McastSendVcAvgRate = pElan->McastSendVcAvgRate; pElanInfo->McastSendVcPeakRate = pElan->McastSendVcPeakRate; pElanInfo->ConnComplTimer = pElan->ConnComplTimer; RELEASE_ELAN_LOCK(pElan);
*pBytesWritten = sizeof(ATMLANE_ELANINFO);
} while (FALSE);
if (pElan != NULL) { ACQUIRE_ELAN_LOCK(pElan); rc = AtmLaneDereferenceElan(pElan, "ioctl: getelaninfo");
if (rc != 0) { RELEASE_ELAN_LOCK(pElan); } }
if (pAdapter != NULL) { ACQUIRE_ADAPTER_LOCK(pAdapter); rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: getelaninfo"); if (rc != 0) { RELEASE_ADAPTER_LOCK(pAdapter); } }
TRACEOUT(IoctlGetElanInfo); return (Status); }
NTSTATUS AtmLaneIoctlGetElanArpTable( IN PUCHAR pBuffer, IN UINT InputBufferLength, IN UINT OutputBufferLength, OUT UINT_PTR * pBytesWritten ) /*++
Routine Description:
Return the ARP table for the specified ELAN.
Arguments:
pBuffer - Space for input/output InputBufferLength - Length of input parameters OutputBufferLength - Space available for output pBytesWritten - Where we return the amount we actually used up
Return Value: Status code
--*/ { PATMLANE_ADAPTER pAdapter; PATMLANE_ELAN pElan; PUNICODE_STRING pAdapterNameIn; PUNICODE_STRING pElanNameIn; PATMLANE_ARPTABLE pArpTable; PATMLANE_ARPENTRY pArpEntry; UINT Remaining; PATMLANE_MAC_ENTRY pMacEntry; NTSTATUS Status; UINT i; ULONG rc;
TRACEIN(IoctlGetElanArpTable);
// init
*pBytesWritten = 0; Status = STATUS_SUCCESS; pAdapter = NULL; pElan = NULL;
do { // check if adapter string passed in
if (InputBufferLength < sizeof(UNICODE_STRING)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// sanity check the unicode string fields.
if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
// check if elan string passed in
if (InputBufferLength < (((sizeof(UNICODE_STRING) * 2) + ((PUNICODE_STRING)pBuffer)->MaximumLength))) { Status = STATUS_BUFFER_OVERFLOW; break; }
// check if minimum output space
if (OutputBufferLength < sizeof(ATMLANE_ARPTABLE)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// setup ptrs to input names
pAdapterNameIn = (PUNICODE_STRING)pBuffer; pElanNameIn = (PUNICODE_STRING)(pBuffer + sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
// find adapter struct
pAdapter = AtmLaneIoctlNameToAdapter(pAdapterNameIn);
if (pAdapter == NULL_PATMLANE_ADAPTER) { Status = STATUS_UNSUCCESSFUL; break; }
// find elan struct
pElan = AtmLaneIoctlNameToElan(pAdapter, pElanNameIn);
if (pElan == NULL_PATMLANE_ELAN) { Status = STATUS_UNSUCCESSFUL; break; }
// setup to return empty list
pArpTable = (PATMLANE_ARPTABLE)pBuffer; pArpTable->ArpEntriesAvailable = pElan->NumMacEntries; pArpTable->ArpEntriesReturned = 0; *pBytesWritten = sizeof(ATMLANE_ARPTABLE); Remaining = OutputBufferLength - sizeof(ATMLANE_ARPTABLE); pArpEntry = (PATMLANE_ARPENTRY)(pBuffer + sizeof(ATMLANE_ARPTABLE)); ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
// loop thru array of lists
for (i = 0; i < ATMLANE_MAC_TABLE_SIZE; i++) { pMacEntry = pElan->pMacTable[i];
while (pMacEntry != NULL_PATMLANE_MAC_ENTRY) {
// check if enough space remaining
if (Remaining < sizeof(ATMLANE_ARPENTRY)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// output the entry
NdisZeroMemory(pArpEntry, sizeof(ATMLANE_ARPENTRY));
NdisMoveMemory( pArpEntry->MacAddress, &pMacEntry->MacAddress, sizeof(MAC_ADDRESS));
if (pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY) { NdisMoveMemory( pArpEntry->AtmAddress, pMacEntry->pAtmEntry->AtmAddress.Address, ATM_ADDRESS_LENGTH); }
// update space used and space remaining
*pBytesWritten += sizeof(ATMLANE_ARPENTRY); Remaining -= sizeof(ATMLANE_ARPENTRY);
// increment in and out pointers
pArpEntry++; pMacEntry = pMacEntry->pNextEntry;
// add one to EntriesReturned
pArpTable->ArpEntriesReturned++; } } RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
} while (FALSE);
if (pElan != NULL) { ACQUIRE_ELAN_LOCK(pElan); rc = AtmLaneDereferenceElan(pElan, "ioctl: getelanarp");
if (rc != 0) { RELEASE_ELAN_LOCK(pElan); } }
if (pAdapter != NULL) { ACQUIRE_ADAPTER_LOCK(pAdapter); rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: getelanarp"); if (rc != 0) { RELEASE_ADAPTER_LOCK(pAdapter); } }
TRACEOUT(IoctlGetElanArpTable);
return (Status); }
NTSTATUS AtmLaneIoctlGetElanConnectTable( IN PUCHAR pBuffer, IN UINT InputBufferLength, IN UINT OutputBufferLength, OUT UINT_PTR * pBytesWritten ) /*++
Routine Description:
Return the Connection table for the specified ELAN.
Arguments:
pBuffer - Space for input/output InputBufferLength - Length of input parameters OutputBufferLength - Space available for output pBytesWritten - Where we return the amount we actually used up
Return Value: Status code
--*/ { PATMLANE_ADAPTER pAdapter; PATMLANE_ELAN pElan; PUNICODE_STRING pAdapterNameIn; PUNICODE_STRING pElanNameIn; PATMLANE_CONNECTTABLE pConnTable; PATMLANE_CONNECTENTRY pConnEntry; UINT Remaining; PATMLANE_ATM_ENTRY pAtmEntry; NTSTATUS Status; ULONG rc;
TRACEIN(IoctlGetElanConnectTable);
// init
*pBytesWritten = 0; Status = STATUS_SUCCESS; pAdapter = NULL; pElan = NULL;
do { // check if adapter string passed in
if (InputBufferLength < sizeof(UNICODE_STRING)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// check if elan string passed in
if (InputBufferLength < (((sizeof(UNICODE_STRING) * 2) + ((PUNICODE_STRING)pBuffer)->MaximumLength))) { Status = STATUS_BUFFER_OVERFLOW; break; }
// sanity check
if (((PUNICODE_STRING)pBuffer)->MaximumLength < ((PUNICODE_STRING)pBuffer)->Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
// check if minimum output space
if (OutputBufferLength < sizeof(ATMLANE_CONNECTTABLE)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// setup ptrs to input names
pAdapterNameIn = (PUNICODE_STRING)pBuffer; pElanNameIn = (PUNICODE_STRING)(pBuffer + sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
// How much of the input buffer do we have left?
InputBufferLength -= (sizeof(UNICODE_STRING) + pAdapterNameIn->MaximumLength);
// validate the ELAN name buffer
if (pElanNameIn->MaximumLength < pElanNameIn->Length) { Status = STATUS_BUFFER_OVERFLOW; break; }
if (InputBufferLength < sizeof(UNICODE_STRING) + pElanNameIn->MaximumLength) { Status = STATUS_BUFFER_OVERFLOW; break; }
// find adapter struct
pAdapter = AtmLaneIoctlNameToAdapter(pAdapterNameIn);
if (pAdapter == NULL_PATMLANE_ADAPTER) { Status = STATUS_UNSUCCESSFUL; break; }
// find elan struct
pElan = AtmLaneIoctlNameToElan(pAdapter, pElanNameIn);
if (pElan == NULL_PATMLANE_ELAN) { Status = STATUS_UNSUCCESSFUL; break; }
// setup to return empty list
pConnTable = (PATMLANE_CONNECTTABLE)pBuffer; pConnTable->ConnectEntriesAvailable = pElan->NumAtmEntries; pConnTable->ConnectEntriesReturned = 0; *pBytesWritten = sizeof(ATMLANE_CONNECTTABLE); Remaining = OutputBufferLength - sizeof(ATMLANE_CONNECTTABLE); pConnEntry = (PATMLANE_CONNECTENTRY)(pBuffer + sizeof(ATMLANE_CONNECTTABLE)); ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
// loop thru the list
pAtmEntry = pElan->pAtmEntryList;
while (pAtmEntry != NULL_PATMLANE_ATM_ENTRY) {
// check if enough space for another entry
if (Remaining < sizeof(ATMLANE_CONNECTENTRY)) { Status = STATUS_BUFFER_OVERFLOW; break; }
// fill in entry
NdisMoveMemory( pConnEntry->AtmAddress, &pAtmEntry->AtmAddress.Address, ATM_ADDRESS_LENGTH ); pConnEntry->Type = pAtmEntry->Type; pConnEntry->Vc = (pAtmEntry->pVcList!=NULL_PATMLANE_VC); pConnEntry->VcIncoming = (pAtmEntry->pVcIncoming!=NULL_PATMLANE_VC);
// update space used and space remaining
*pBytesWritten += sizeof(ATMLANE_CONNECTENTRY); Remaining -= sizeof(ATMLANE_CONNECTENTRY); // increment in and out pointers
pConnEntry++; pAtmEntry = pAtmEntry->pNext;
// add one to EntriesReturned
pConnTable->ConnectEntriesReturned++; }
RELEASE_ELAN_ATM_LIST_LOCK(pElan);
} while (FALSE);
if (pElan != NULL) { ACQUIRE_ELAN_LOCK(pElan); rc = AtmLaneDereferenceElan(pElan, "ioctl: getelanconntab");
if (rc != 0) { RELEASE_ELAN_LOCK(pElan); } }
if (pAdapter != NULL) { ACQUIRE_ADAPTER_LOCK(pAdapter); rc = AtmLaneDereferenceAdapter(pAdapter, "ioctl: getelanconntab"); if (rc != 0) { RELEASE_ADAPTER_LOCK(pAdapter); } }
TRACEOUT(IoctlGetElanConnectTable);
return (Status); }
NTSTATUS AtmLaneIoctlRequest( IN PIRP pIrp ) /*++
Routine Description:
Starting point for all IOCTL Requests.
Arguments:
pIrp : Pointer to the IRP pHandled : If request handled TRUE otherwise FALSE
Return Value:
Status of the request
--*/ { NTSTATUS Status = STATUS_SUCCESS; PUCHAR pBuf; UINT BufLen; UINT OutBufLen; UNICODE_STRING IfName; PIO_STACK_LOCATION pIrpSp;
TRACEIN(IoctlRequest); pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
pBuf = pIrp->AssociatedIrp.SystemBuffer; BufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength; OutBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode) { case ATMLANE_IOCTL_GET_INFO_VERSION: DBGP((3, "IoctlRequest: Get Info Version\n"));
Status = AtmLaneIoctlGetInfoVersion( pBuf, BufLen, OutBufLen, &pIrp->IoStatus.Information ); break; case ATMLANE_IOCTL_ENUM_ADAPTERS:
DBGP((3, "IoctlRequest: Enum Adapters\n")); Status = AtmLaneIoctlEnumerateAdapters( pBuf, BufLen, OutBufLen, &pIrp->IoStatus.Information ); break; case ATMLANE_IOCTL_ENUM_ELANS:
DBGP((3, "IoctlRequest: Enum ELANs\n")); Status = AtmLaneIoctlEnumerateElans( pBuf, BufLen, OutBufLen, &pIrp->IoStatus.Information ); break; case ATMLANE_IOCTL_GET_ELAN_INFO:
DBGP((3, "IoctlRequest: Get ELAN Info\n")); Status = AtmLaneIoctlGetElanInfo( pBuf, BufLen, OutBufLen, &pIrp->IoStatus.Information ); break; case ATMLANE_IOCTL_GET_ELAN_ARP_TABLE:
DBGP((3, "IoctlRequest: Getl ELAN ARP table\n")); Status = AtmLaneIoctlGetElanArpTable( pBuf, BufLen, OutBufLen, &pIrp->IoStatus.Information ); break; case ATMLANE_IOCTL_GET_ELAN_CONNECT_TABLE:
DBGP((3, "IoctlRequest: Get ELAN Connection table\n")); Status = AtmLaneIoctlGetElanConnectTable( pBuf, BufLen, OutBufLen, &pIrp->IoStatus.Information ); break; default: DBGP((0, "IoctlRequest: Unknown control code %x\n", pIrpSp->Parameters.DeviceIoControl.IoControlCode)); break; } TRACEOUT(IoctlRequest);
return (Status);
}
|