www.pudn.com > DMBDRV.rar > SmsNdis.c
#include "SmsNdis.h"
#include "SmsGenDrv.h"
///////////////////////////////////////////////////////////////////////////////
#define ENABLED_DEBUG_ZONE ZONE_ERROR_SET | ZONE_WARNING_SET //| ZONE_INIT_SET | ZONE_INFO_SET
DBGPARAM dpCurSettings =
{
TEXT("Siano NDIS"),
{ /* Note: the order of the following must */
/* match the definitions in debug.h: */
TEXT("Errors"), TEXT("Warnings"), TEXT("Init"),
TEXT("Info"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Temporary"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined")
},
ENABLED_DEBUG_ZONE
};
///////////////////////////////////////////////////////////////////////////////
static UCHAR LocalMAC[] = {0x00,0x04,0x76,0x0D,0xAD,0x7A};
static UCHAR RemoteMAC[] = {0x00,0x01,0x01,0x03,0x04,0x40};
///////////////////////////////////////////////////////////////////////////////
/*****************************************************************************/
/* The SmsNdis Miniport device structure */
/*****************************************************************************/
typedef struct SMS_SMS_NDIS_S
{
NDIS_HANDLE hMiniportAdapter;
NDIS_HANDLE hWrapperConfigContext;
HANDLE hGenDrv;
UCHAR MulticastList[MAX_MULTICAST_LIST_SIZE][ETHERNET_ADDRESS_LEN];
UINT32 MulticastListCount;
ULONG CurrentPacketFilter;
ULONG CurrentLookahead;
ULONG RxPacketCount;
BYTE PrevPktPortion[MAX_IP_FRAME_LEN];
ULONG PrevPktPortionCount;
} SMS_SMS_NDIS_ST, *PSMS_SMS_NDIS_ST;
///////////////////////////////////////////////////////////////////////////////
void ReadIpCB(DWORD hContext, void* pBuffer, UINT32 BufSize);
BOOL RegisterReadIpCBFunc(PSMS_SMS_NDIS_ST pSmsNdis);
///////////////////////////////////////////////////////////////////////////////
#ifdef LOG_TO_FILE
#define LOG_FILE TEXT("\\Program Files\\SianoSmsUtils\\SmsNdisLog.txt")
HANDLE hLogFile = INVALID_HANDLE_VALUE;
CRITICAL_SECTION g_CriticalSection;
VOID LogStrToFile(TCHAR *pLogStr,...)
{
va_list argumentList;
int length;
CHAR charBuffer[500];
TCHAR tcharBuffer[500];
DWORD written;
INT i;
EnterCriticalSection(&g_CriticalSection);
va_start(argumentList, pLogStr);
do {
length = _vsntprintf(tcharBuffer,
(500 - 1),
pLogStr,
argumentList);
if (length < 0) {
break;
}
if (hLogFile == INVALID_HANDLE_VALUE) {
break;
}
for (i = 0; i < length; i++) {
if ((CHAR)tcharBuffer != '\n') {
charBuffer[i] = (CHAR)tcharBuffer[i];
} else {
charBuffer[i] = ' ';
}
}
WriteFile(hLogFile,charBuffer,length,&written,NULL);
} while (FALSE);
va_end(argumentList);
LeaveCriticalSection(&g_CriticalSection);
}
#endif
///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpreserved
)
{
BOOL bRc = TRUE;
UNREFERENCED_PARAMETER(hDllHandle);
UNREFERENCED_PARAMETER(lpreserved);
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
REGISTERZONES(hDllHandle);
#ifdef LOG_TO_FILE
hLogFile = CreateFile(LOG_FILE,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
0,
NULL);
if (hLogFile == INVALID_HANDLE_VALUE)
return FALSE;
InitializeCriticalSection(&g_CriticalSection);
#endif
DBGMSG(ZONE_INIT, (TEXT("SmsNdis: DLL_PROCESS_ATTACH\r\n")));
break;
case DLL_PROCESS_DETACH:
DBGMSG(ZONE_INIT, (TEXT("SmsNdis: DLL_PROCESS_DETACH\r\n")));
#ifdef LOG_TO_FILE
if (hLogFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hLogFile);
}
DeleteCriticalSection(&g_CriticalSection);
#endif
break;
default:
break;
}
return bRc;
}
//////////////////////////////////////////////////////////////////////////////
// SmsNdis_InitializeHandler - starts an adapter and registers resources with
// the wrapper
// Inputs: MediumArray - array of media types for the driver to choose from
// MediumArraySize - number of entries in the array
// MiniportAdapterHandle - handle for passing to the wrapper when
// referring to this adapter
// WrapperConfigurationContext - a handle to pass to NdisOpenConfiguration
// Outputs: pOpenErrorStatus - extra status bytes for opening token ring
// adapters
// pSelectedMediumIndex - index of the media type chosen by the
// driver
// Returns: NDIS_STATUS
// Notes:
//////////////////////////////////////////////////////////////////////////////
NDIS_STATUS SmsNdis_InitializeHandler( OUT PNDIS_STATUS pOpenErrorStatus,
PUINT pSelectedMediumIndex,
PNDIS_MEDIUM MediumArray,
UINT MediumArraySize,
NDIS_HANDLE MiniportAdapterHandle,
NDIS_HANDLE WrapperConfigurationContext)
{
NDIS_STATUS ndisStatus;
UINT mIdx;
PSMS_SMS_NDIS_ST pSmsNdis;
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +SmsNdis_InitializeHandler\r\n")));
// search for the medium type (802.3) in the given array.
for (mIdx = 0; mIdx < MediumArraySize; mIdx++)
{
if (MediumArray[mIdx] == NdisMedium802_3)
{
// found what we're looking for
break;
}
}
if (mIdx == MediumArraySize)
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: Unsupported mediums\r\n")));
}
*pSelectedMediumIndex = mIdx;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: Selected Medium Index %d\r\n"),mIdx));
// allocate device structure
ndisStatus = NdisAllocateMemory((PVOID*)&pSmsNdis,sizeof(SMS_SMS_NDIS_ST),0,HighestAcceptableMax);
if (ndisStatus == NDIS_STATUS_SUCCESS)
{
NdisZeroMemory(pSmsNdis,sizeof(SMS_SMS_NDIS_ST));
// register the allocated device as adapter context for use in SmsNdis_XXX
NdisMSetAttributesEx(MiniportAdapterHandle,(NDIS_HANDLE)pSmsNdis,0,0,NdisInterfaceInternal);
pSmsNdis->hMiniportAdapter = MiniportAdapterHandle;
pSmsNdis->hWrapperConfigContext = WrapperConfigurationContext;
pSmsNdis->CurrentPacketFilter = SUPPORTED_PACKET_FILTER;
pSmsNdis->CurrentLookahead = MAX_IP_PACKET_LEN;
if (RegisterReadIpCBFunc(pSmsNdis) == FALSE)
{
NdisFreeMemory(pSmsNdis,sizeof(SMS_SMS_NDIS_ST),0);
pSmsNdis = NULL;
ndisStatus = NDIS_STATUS_FAILURE;
}
}
else
{
pSmsNdis = NULL;
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: Failed to allocate SmsNdis device\r\n")));
}
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -SmsNdis_InitializeHandler\r\n")));
return ndisStatus;
}
/////////////////////////////////////////////////////////////////////////////
// SmsNdis_HaltHandler
// Inputs: MiniportAdapterContext - the device context (pointer to our
// adapter)
// Outputs:
// Returns:
// Notes:
/////////////////////////////////////////////////////////////////////////////
VOID SmsNdis_HaltHandler(NDIS_HANDLE MiniportAdapterContext)
{
PSMS_SMS_NDIS_ST pSmsNdis = (PSMS_SMS_NDIS_ST)MiniportAdapterContext;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +SmsNdis_HaltHandler\r\n")));
if (pSmsNdis)
{
if (pSmsNdis->hGenDrv)
{
CloseHandle(pSmsNdis->hGenDrv);
pSmsNdis->hGenDrv = NULL;
}
NdisTerminateWrapper(pSmsNdis->hWrapperConfigContext,NULL);
// freeing the SmsNdis device
NdisFreeMemory(pSmsNdis,sizeof(SMS_SMS_NDIS_ST),0);
}
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -SmsNdis_HaltHandler\r\n")));
}
//////////////////////////////////////////////////////////////////////////////
// SmsNdis_QueryInformationHandler -
// Inputs: MiniportAdapterContext - a pointer to the adapter
// Oid - the NDIS_OID to process
// pInfoBuffer - a pointer into the NdisRequest->InformationBuffer
// into which store the result of the query
// InfoBufferLen - the number of bytes at pInfoBuffer
// Outputs: pBytesWritten - a pointer to the number of bytes written into the
// InformationBuffer
// pBytesNeeded - if there is not enough room the information buffer
// then this will contathe number of bytes needed to complete the
// request
// Notes:
//////////////////////////////////////////////////////////////////////////////
NDIS_STATUS SmsNdis_QueryInformationHandler(NDIS_HANDLE MiniportAdapterContext,
NDIS_OID Oid,
PVOID pInfoBuffer,
ULONG InfoBufferLen,
PULONG pBytesWritten,
PULONG pBytesNeeded)
{
NDIS_STATUS ndisStatus;
PSMS_SMS_NDIS_ST pSmsNdis;
PVOID pReturnBuff;
ULONG returnBuffLen;
ULONG tmpULong;
USHORT tmpUshort;
NDIS_HARDWARE_STATUS hwStatus;
NDIS_MEDIUM ndisMedium;
const PCHAR strVendor = "Siano NDIS Miniport\0";
const UCHAR EmuEthernetAddr[] = {0x00,0x04,0x76,0x0D,0xAD,0x7A};
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +SmsNdis_QueryInformationHandler\r\n"),Oid));
pSmsNdis = (PSMS_SMS_NDIS_ST)MiniportAdapterContext;
*pBytesWritten = 0;
*pBytesNeeded = 0;
ndisStatus = NDIS_STATUS_SUCCESS;
pReturnBuff = NULL;
returnBuffLen = 0;
#define CASE_OID(Oid) \
case Oid: \
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: Query 0x%08X ") TEXT(#Oid) TEXT("\r\n"),Oid));
#define CASE_OID_NOT_SUPPORTED(Oid) \
case Oid: \
DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: Query 0x%08X ") TEXT(#Oid) TEXT(" not supported\r\n"),Oid)); \
ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
switch(Oid)
{
CASE_OID(OID_GEN_HARDWARE_STATUS)
hwStatus = NdisHardwareStatusReady;
pReturnBuff = (PVOID)&hwStatus;
returnBuffLen = sizeof(hwStatus);
break;
CASE_OID(OID_GEN_MEDIA_SUPPORTED)
ndisMedium = NdisMedium802_3;
pReturnBuff = (PVOID)&ndisMedium;
returnBuffLen = sizeof(ndisMedium);
break;
CASE_OID(OID_GEN_MEDIA_IN_USE)
ndisMedium = NdisMedium802_3;
pReturnBuff = (PVOID)&ndisMedium;
returnBuffLen = sizeof(ndisMedium);
break;
CASE_OID(OID_GEN_MAXIMUM_LOOKAHEAD)
tmpULong = MAX_IP_PACKET_LEN;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_MAXIMUM_FRAME_SIZE)
tmpULong = MAX_IP_PACKET_LEN;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_LINK_SPEED)
tmpULong = 100000;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_TRANSMIT_BUFFER_SPACE)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_RECEIVE_BUFFER_SPACE)
tmpULong = MAX_IP_PACKET_LEN;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_TRANSMIT_BLOCK_SIZE)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_RECEIVE_BLOCK_SIZE)
tmpULong = MAX_IP_PACKET_LEN;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_VENDOR_DESCRIPTION)
pReturnBuff = (PVOID)strVendor;
returnBuffLen = strlen(strVendor) + 1;
break;
CASE_OID(OID_GEN_VENDOR_DRIVER_VERSION)
tmpUshort = 0x0001;
pReturnBuff = (PVOID)&tmpUshort;
returnBuffLen = sizeof(tmpUshort);
break;
CASE_OID(OID_GEN_DRIVER_VERSION)
tmpUshort = 0x0001;
pReturnBuff = (PVOID)&tmpUshort;
returnBuffLen = sizeof(tmpUshort);
break;
CASE_OID(OID_GEN_CURRENT_PACKET_FILTER)
tmpULong = pSmsNdis->CurrentPacketFilter;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_CURRENT_LOOKAHEAD)
tmpULong = pSmsNdis->CurrentLookahead;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_MAXIMUM_TOTAL_SIZE)
tmpULong = MAX_IP_PACKET_LEN;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_MAC_OPTIONS)
tmpULong = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
NDIS_MAC_OPTION_NO_LOOPBACK;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_MAXIMUM_SEND_PACKETS)
tmpULong = 1;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_XMIT_OK)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_RCV_OK)
tmpULong = pSmsNdis->RxPacketCount;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_XMIT_ERROR)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_RCV_ERROR)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_RCV_NO_BUFFER)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_GEN_INIT_TIME_MS)
tmpULong = 0;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_802_3_PERMANENT_ADDRESS)
pReturnBuff = (PVOID)EmuEthernetAddr;
returnBuffLen = sizeof(EmuEthernetAddr);
break;
CASE_OID(OID_802_3_CURRENT_ADDRESS)
pReturnBuff = (PVOID)EmuEthernetAddr;
returnBuffLen = sizeof(EmuEthernetAddr);
break;
CASE_OID(OID_802_3_MAXIMUM_LIST_SIZE)
tmpULong = MAX_MULTICAST_LIST_SIZE;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID(OID_802_3_MULTICAST_LIST)
pReturnBuff = (PVOID)pSmsNdis->MulticastList;
returnBuffLen = pSmsNdis->MulticastListCount * ETHERNET_ADDRESS_LEN;
break;
CASE_OID(OID_GEN_MEDIA_CONNECT_STATUS)
tmpULong = NdisMediaStateConnected;
pReturnBuff = (PVOID)&tmpULong;
returnBuffLen = sizeof(tmpULong);
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_SUPPORTED_LIST)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_VENDOR_ID)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_PHYSICAL_MEDIUM)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_MEDIA_CAPABILITIES)
break;
CASE_OID_NOT_SUPPORTED(OID_PNP_CAPABILITIES)
break;
CASE_OID_NOT_SUPPORTED(OID_TCP_TASK_OFFLOAD)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_DIRECTED_BYTES_XMIT)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_DIRECTED_FRAMES_XMIT)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_MULTICAST_BYTES_XMIT)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_MULTICAST_FRAMES_XMIT)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_BROADCAST_BYTES_XMIT)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_BROADCAST_FRAMES_XMIT)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_DIRECTED_BYTES_RCV)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_DIRECTED_FRAMES_RCV)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_MULTICAST_BYTES_RCV)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_MULTICAST_FRAMES_RCV)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_BROADCAST_BYTES_RCV)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_BROADCAST_FRAMES_RCV)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_RCV_CRC_ERROR)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_TRANSMIT_QUEUE_LENGTH)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_GET_TIME_CAPS)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_GET_NETCARD_TIME)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_NETCARD_LOAD)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_DEVICE_PROFILE)
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_MEDIA_SENSE_COUNTS)
break;
default:
DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: Query Oid 0x%08X invalid or not supported\r\n"),Oid));
ndisStatus = NDIS_STATUS_INVALID_OID;
break;
}
#undef CASE_OID
#undef CASE_OID_NOT_SUPPORTED
if (ndisStatus == NDIS_STATUS_SUCCESS)
{
if (returnBuffLen > InfoBufferLen)
{
*pBytesNeeded = returnBuffLen;
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: pInfoBuffer len too small. Len %d Need %d\r\n"),InfoBufferLen,returnBuffLen));
}
else
{
if (pReturnBuff)
{
NdisMoveMemory(pInfoBuffer, pReturnBuff, returnBuffLen);
*pBytesWritten = returnBuffLen;
*pBytesNeeded = 0;
}
else
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: Wrong handling of OID\r\n")));
ndisStatus = NDIS_STATUS_INVALID_OID;
}
}
}
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -SmsNdis_QueryInformationHandler. status 0x%X\r\n"),ndisStatus));
return ndisStatus;
}
/////////////////////////////////////////////////////////////////////////////
// SmsNdis_SetInformationHandler -
// Inputs: pMiniportAdapterContext - a pointer to the adapter
// Oid - the NDIS_OID to process
// pInfoBuffer - data to be set
// InfoBufferLen - length of information buffer
// Outputs: pBytesRead - If the call is successful, returns the number
// of bytes read from InformationBuffer
// pBytesNeeded - If there is not enough data InformationBuffer
// to satisfy the OID, returns the amount of storage needed
// Returns: NDIS_STATUS_SUCCESS on success
// Notes:
/////////////////////////////////////////////////////////////////////////////
NDIS_STATUS SmsNdis_SetInformationHandler( NDIS_HANDLE MiniportAdapterContext,
NDIS_OID Oid,
PVOID pInfoBuffer,
ULONG InfoBufferLen,
PULONG pBytesRead,
PULONG pBytesNeeded)
{
NDIS_STATUS ndisStatus;
PSMS_SMS_NDIS_ST pSmsNdis;
UINT32 i;
ULONG tmpULong;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +SmsNdis_SetInformationHandler\r\n")));
pSmsNdis = (PSMS_SMS_NDIS_ST)MiniportAdapterContext;
ndisStatus = NDIS_STATUS_SUCCESS;
*pBytesRead = 0;
*pBytesNeeded = 0;
#define CASE_OID(Oid) \
case Oid: \
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: Set 0x%08X ") TEXT(#Oid) TEXT("\r\n"),Oid));
#define CASE_OID_NOT_SUPPORTED(Oid) \
case Oid: \
DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: Set 0x%08X ") TEXT(#Oid) TEXT(" not supported\r\n"),Oid)); \
ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
switch(Oid)
{
CASE_OID(OID_GEN_CURRENT_PACKET_FILTER)
if (InfoBufferLen != sizeof(ULONG))
{
*pBytesNeeded = ETHERNET_ADDRESS_LEN;
ndisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
tmpULong = *((ULONG*)pInfoBuffer);
//if (tmpULong & SUPPORTED_PACKET_FILTER)
//{
// *pBytesRead = InfoBufferLen;
// *pBytesNeeded = 0;
// ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
//}
//else
{
pSmsNdis->CurrentPacketFilter = tmpULong;
}
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: Set Current packet filter 0x%X\r\n"),tmpULong));
break;
CASE_OID(OID_GEN_CURRENT_LOOKAHEAD)
if (InfoBufferLen != sizeof(ULONG))
{
*pBytesNeeded = sizeof(ULONG);
ndisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
pSmsNdis->CurrentLookahead = *((ULONG*)pInfoBuffer);
*pBytesRead = InfoBufferLen;
*pBytesNeeded = 0;
break;
CASE_OID(OID_802_3_MULTICAST_LIST)
if (((InfoBufferLen % ETHERNET_ADDRESS_LEN) != 0) ||
(InfoBufferLen > (ETHERNET_ADDRESS_LEN * MAX_MULTICAST_LIST_SIZE)))
{
*pBytesNeeded = ETHERNET_ADDRESS_LEN;
ndisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
NdisZeroMemory(pSmsNdis->MulticastList,ETHERNET_ADDRESS_LEN * MAX_MULTICAST_LIST_SIZE);
if (InfoBufferLen > 0)
{
NdisMoveMemory(pSmsNdis->MulticastList,pInfoBuffer,InfoBufferLen);
}
pSmsNdis->MulticastListCount = InfoBufferLen / ETHERNET_ADDRESS_LEN;
*pBytesRead = InfoBufferLen;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: Multicast Address List :\r\n")));
for (i = 0;i < pSmsNdis->MulticastListCount;i++)
{
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: %02x:%02x:%02x:%02x:%02x:%02x\r\n"),
pSmsNdis->MulticastList[i][0],pSmsNdis->MulticastList[i][1],
pSmsNdis->MulticastList[i][2],pSmsNdis->MulticastList[i][3],
pSmsNdis->MulticastList[i][4],pSmsNdis->MulticastList[i][5]));
}
break;
CASE_OID(OID_GEN_NETWORK_LAYER_ADDRESSES)
*pBytesRead = InfoBufferLen;
*pBytesNeeded = 0;
break;
CASE_OID(OID_GEN_TRANSPORT_HEADER_OFFSET)
*pBytesRead = InfoBufferLen;
*pBytesNeeded = 0;
break;
CASE_OID_NOT_SUPPORTED(OID_GEN_PROTOCOL_OPTIONS)
break;
CASE_OID_NOT_SUPPORTED(OID_PNP_ADD_WAKE_UP_PATTERN)
break;
default:
DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: Set Oid 0x%08X invalid or not supported\r\n"),Oid));
ndisStatus = NDIS_STATUS_INVALID_OID;
break;
}
#undef CASE_OID
#undef CASE_OID_NOT_SUPPORTED
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -SmsNdis_SetInformationHandler. status 0x%X\r\n"),ndisStatus));
return ndisStatus;
}
/////////////////////////////////////////////////////////////////////////////
// SmsNdis_SendHandler -
// Inputs: MiniportAdapterContext - device context
// pPacket - descriptor for the packet that is to be transmitted
// Flags - optional send flags
// Outputs:
// Returns: NDIS_STATUS
// Notes:
/////////////////////////////////////////////////////////////////////////////
NDIS_STATUS SmsNdis_SendHandler(NDIS_HANDLE MiniportAdapterContext,
PNDIS_PACKET pPacket,
UINT Flags)
{
//PSMS_SMS_NDIS_ST pSmsNdis = (PSMS_SMS_NDIS_ST)MiniportAdapterContext;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +SmsNdis_SendHandler\r\n")));
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -SmsNdis_SendHandler\n")));
return NDIS_STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////////
// DriverEntry - initial driver entry point for Ndis driver
// Input: pDriverObject - NT driver object
// pRegistryPath - path to this drivers registry entries
// Output:
// Returns: NDIS_STATUS
// Notes:
//////////////////////////////////////////////////////////////////////////////
NDIS_STATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
NDIS_STATUS ndisStatus;
NDIS_HANDLE hNdisWrapper;
NDIS_MINIPORT_CHARACTERISTICS mChars;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +DriverEntry\r\n")));
NdisMInitializeWrapper (&hNdisWrapper,pDriverObject,pRegistryPath,NULL);
NdisZeroMemory(&mChars,sizeof(mChars));
mChars.MajorNdisVersion = 0x04;
mChars.MinorNdisVersion = 0x00;
mChars.HaltHandler = SmsNdis_HaltHandler;
mChars.InitializeHandler = SmsNdis_InitializeHandler;
mChars.QueryInformationHandler = SmsNdis_QueryInformationHandler;
mChars.SendHandler = SmsNdis_SendHandler;
mChars.SetInformationHandler = SmsNdis_SetInformationHandler;
// register NIC entry point
ndisStatus = NdisMRegisterMiniport(hNdisWrapper,&mChars,sizeof(mChars));
if (ndisStatus != NDIS_STATUS_SUCCESS)
{
NdisTerminateWrapper(hNdisWrapper,NULL);
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: Failed to register miniport. status 0x%X\r\n"),ndisStatus));
}
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -DriverEntry\r\n")));
return ndisStatus;
}
///////////////////////////////////////////////////////////////////////////////
BOOL RegisterReadIpCBFunc(PSMS_SMS_NDIS_ST pSmsNdis)
{
GEN_IOCTL_REGISTER_READ_IP_PARAMS_ST readIpParams;
pSmsNdis->hGenDrv = CreateFile(TEXT("SGD1:"),GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,0,NULL);
if (pSmsNdis->hGenDrv == NULL)
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: Failed to open connection to GenDrv\r\n")));
return FALSE;
}
readIpParams.pReadIpCBFunc = ReadIpCB;
readIpParams.hContext = (DWORD)pSmsNdis;
if (DeviceIoControl(pSmsNdis->hGenDrv,SIANO_GEN_IOCTL_REGISTER_READ_IP_CB,
&readIpParams,sizeof(readIpParams),NULL,0,NULL,NULL) == FALSE)
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: Failed to register ReadIpCB\r\n")));
CloseHandle(pSmsNdis->hGenDrv);
pSmsNdis->hGenDrv = NULL;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
/*
* MulticastEthAddrFromIpAddr
* Populate the ethAddr ethernet address with the
* IANA multicast address from the IP multicast group in ipAddr
*/
void MulticastEthAddrFromIpAddr(
ULONG ipAddr,
UCHAR *ethAddr)
{
ethAddr[0] = 0x01;
ethAddr[1] = 0x00;
ethAddr[2] = 0x5E;
ethAddr[3] = (UCHAR)((ipAddr & 0x00ff00)>>8) & 0x7f;
ethAddr[4] = (UCHAR)((ipAddr & 0x00ff0000)>>16);
ethAddr[5] = (UCHAR)((ipAddr & 0xff000000)>>24);
}
///////////////////////////////////////////////////////////////////////////////
/*
* Return true if the IP address is in the multicast range (class D)
* of 224.0.0.0 to 239.255.255.255
* !!Address should be in network byte order!!
*/
static BOOL IsAnIPMulticastGroup(
ULONG IpAddr
)
{
UCHAR *AddrArray = (PUCHAR)&IpAddr;
if (AddrArray[3] >= 224 && AddrArray[3] < 240) {
return TRUE;
} else {
return FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////
BOOL IsAnIPv6MulticastGroup(UCHAR *ipAddr)
{
if(ipAddr[0]==IPV6_MULTICAST_INDICATOR)
{
return TRUE;
}
else
{
return FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////
void MulticastEthAddrFromIPv6Addr(UCHAR *ipAddr/*destanattion address*/,UCHAR *ethAddr)
{
/*
For IPv6 Multicast addresses,
the Ethernet MAC is derived by the four low-order octets
OR'ed with the MAC 33:33:00:00:00:00,
so for example the IPv6 address FF02:DEAD:BEEF:1:3
would map to the Ethernet MAC address 33:33:00:01:00:03
*/
ethAddr[0] = 0x33;
ethAddr[1] = 0x33;
ethAddr[2] = ipAddr[12];
ethAddr[3] = ipAddr[13];
ethAddr[4] = ipAddr[14];
ethAddr[5] = ipAddr[15];
}
///////////////////////////////////////////////////////////////////////////////
void IndicateIpPacketReceive(PSMS_SMS_NDIS_ST pSmsNdis,PBYTE pPacket,UINT32 PacketLen)
{
ETHERNETHEADER_ST EthHdr;
ULONG u32;
if ((pPacket[0] & 0xF0) == 0x60)
{
// fill ethernet header
if (IsAnIPv6MulticastGroup( pPacket + 24 /*DstAddress*/ ))
{
MulticastEthAddrFromIPv6Addr(pPacket + 24 /*DstAddress*/ , EthHdr.DestAdd);
}
else
{
memcpy(EthHdr.DestAdd, LocalMAC, 6);
}
memcpy(EthHdr.SrcAdd,RemoteMAC,6);
EthHdr.PacketType = htons(PACKET_TYPE_IPV6);
}
else // v4
{
// fill ethernet header
u32 = (pPacket[16] << 24) | (pPacket[17] << 16) | (pPacket[18] << 8) | pPacket[19]; /* DestAdd */
if (IsAnIPMulticastGroup( ntohl(u32) ))
{
MulticastEthAddrFromIpAddr(u32, EthHdr.DestAdd);
}
else
{
memcpy(EthHdr.DestAdd, LocalMAC, 6);
}
memcpy(EthHdr.SrcAdd,RemoteMAC,6);
EthHdr.PacketType = htons(PACKET_TYPE_IP);
}
#if 0 // to print RTP sequence num. and check it, enable this line
{
PBYTE pUdpHdr;
UINT16 curSeq,destPort;
static UINT16 basePort = 0xFFFF;
if ((pPacket[0] & 0xF0) == 0x60)
pUdpHdr = pPacket + 40;
else
pUdpHdr = pPacket + 20;
destPort = (pUdpHdr[2] << 8) + pUdpHdr[3]; /* Udp DestinationPort */
curSeq = (pUdpHdr[10] << 8) + pUdpHdr[11]; /* seq num */
//DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: %u %u\r\n"),destPort,curSeq));
if (basePort == 0xFFFF)
{
// get the port that will be checked. assumption: the audio port is bigger by 2 from the video
basePort = destPort & 0xFFFC;
}
if (destPort == basePort)
{
static UINT16 prevSeq = 0xFFFF;
if (prevSeq == 0xFFFF)
{
DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: checking vd seq port %d\r\n"),destPort));
}
if ((prevSeq < curSeq) && ((prevSeq+1) != curSeq))
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: miss vd t %d %d %d miss %d\r\n"),GetTickCount(),prevSeq,curSeq,curSeq-prevSeq-1));
MessageBeep(0xFFFFFFFF);
}
prevSeq = curSeq;
}
else if (destPort == (basePort+2))
{
static UINT16 prevSeq = 0xFFFF;
if (prevSeq == 0xFFFF)
{
DBGMSG(ZONE_WARNING, (TEXT("SmsNdis: checking au seq port %d\r\n"),destPort));
}
if ((prevSeq < curSeq) && ((prevSeq+1) != curSeq))
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: miss au t %d %d %d miss %d\r\n"),GetTickCount(),prevSeq,curSeq,curSeq-prevSeq-1));
MessageBeep(0xFFFFFFFF);
}
prevSeq = curSeq;
}
}
#endif
// insert ip to ip stack
NdisMEthIndicateReceive(pSmsNdis->hMiniportAdapter,
NULL, // TransferData will not be called
(PCHAR)&EthHdr, // pointer to header
ETHERNET_HEADER_LEN, // header size
pPacket, // pointer to buffer
PacketLen, // lookahead buffer size
PacketLen); // packet size
// update statistics counter
pSmsNdis->RxPacketCount++;
}
///////////////////////////////////////////////////////////////////////////////
void ReadIpCB(DWORD hContext, void* pBuffer, UINT32 BufSize)
{
PSMS_SMS_NDIS_ST pSmsNdis = (PSMS_SMS_NDIS_ST)hContext;
NDIS_HANDLE SwitchHandle;
ULONG validIpCount = 0;
ULONG u32;
ULONG PktLen;
PBYTE pBuff = (PBYTE)pBuffer;
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: +ReadIpCB 0x08%X %d\r\n"),pBuffer,BufSize));
NdisIMSwitchToMiniport(pSmsNdis->hMiniportAdapter,&SwitchHandle);
if (pSmsNdis->PrevPktPortionCount > 0)
{
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: Handle split packet. PrevPktPortionCount %d\r\n"),pSmsNdis->PrevPktPortionCount));
// handle prev partial packet
if (pSmsNdis->PrevPktPortionCount < (sizeof(UINT32) * 2))
{
// can't extract ip len form prev packet bytes.
u32 = (sizeof(UINT32) * 2) - pSmsNdis->PrevPktPortionCount;
if (u32 > BufSize)
{
// append to prev
NdisMoveMappedMemory(pSmsNdis->PrevPktPortion + pSmsNdis->PrevPktPortionCount,pBuff,BufSize);
pSmsNdis->PrevPktPortionCount += BufSize;
NdisIMRevertBack(pSmsNdis->hMiniportAdapter,&SwitchHandle);
return;
}
// append to prev
NdisMoveMappedMemory(pSmsNdis->PrevPktPortion + pSmsNdis->PrevPktPortionCount,pBuff,u32);
pSmsNdis->PrevPktPortionCount += u32;
pBuff += u32;
BufSize -= u32;
}
if ((pSmsNdis->PrevPktPortion[0] & 0xF0) == 0x60)
{
PktLen = ((pSmsNdis->PrevPktPortion[4] << 8) + pSmsNdis->PrevPktPortion[5]); /* PayloadLen */
PktLen += IPV6_HEADER_LEN;
}
else if ((pSmsNdis->PrevPktPortion[0] & 0xF0) == 0x40)
{
PktLen = (pSmsNdis->PrevPktPortion[2] << 8) + pSmsNdis->PrevPktPortion[3]; /* TotalLen */
}
else
{
PktLen = 0;
}
u32 = PktLen - pSmsNdis->PrevPktPortionCount; // bytes needed from pBuff
if (PktLen > pSmsNdis->PrevPktPortionCount && PktLen < MAX_IP_FRAME_LEN && // is valid ip len
(pSmsNdis->PrevPktPortionCount + u32 <= MAX_IP_FRAME_LEN)) // there is enough space in buff
{
if (u32 > BufSize)
{
// append to prev
NdisMoveMappedMemory(pSmsNdis->PrevPktPortion + pSmsNdis->PrevPktPortionCount,pBuff,BufSize);
pSmsNdis->PrevPktPortionCount += BufSize;
NdisIMRevertBack(pSmsNdis->hMiniportAdapter,&SwitchHandle);
return;
}
// concatenate the two portion and update pBuff pointer
NdisMoveMappedMemory(pSmsNdis->PrevPktPortion + pSmsNdis->PrevPktPortionCount,pBuff,u32);
pBuff += u32;
BufSize -= u32;
// insert ip to stack
IndicateIpPacketReceive(pSmsNdis,pSmsNdis->PrevPktPortion,PktLen);
validIpCount++;
}
else
{
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: IP concatenation failed. %d\r\n"),PktLen));
}
pSmsNdis->PrevPktPortionCount = 0;
}
while (BufSize >= (sizeof(UINT32) * 2)) // atleast part of header include len
{
if ((pBuff[0] & 0xF0) == 0x60)
{
PktLen = ((pBuff[4] << 8) + pBuff[5]); /* PayloadLen */
PktLen += IPV6_HEADER_LEN;
}
else if ((pBuff[0] & 0xF0) == 0x40)
{
PktLen = (pBuff[2] << 8) + pBuff[3]; /* TotalLen */
}
else
{
PktLen = 0;
}
if (PktLen == 0 || PktLen > MAX_IP_FRAME_LEN)
{
// search for sync bytes
pBuff++;
BufSize--;
if (BufSize < (sizeof(UINT32) * 2))
{
// no chance to find sync bytes
BufSize = 0;
break;
}
DBGMSG(ZONE_ERROR, (TEXT("SmsNdis: resync %02X %d %d\r\n"),pBuff[0],PktLen,BufSize));
continue;
}
if (PktLen > BufSize)
{
// partial packet
break;
}
// insert ip to stack
IndicateIpPacketReceive(pSmsNdis,pBuff,PktLen);
validIpCount++;
pBuff += PktLen;
BufSize -= PktLen;
}
if (BufSize > 0)
{
// save partial packet
NdisMoveMappedMemory(pSmsNdis->PrevPktPortion,pBuff,BufSize);
pSmsNdis->PrevPktPortionCount = BufSize;
}
if (validIpCount > 0)
{
// flush ip stack
NdisMEthIndicateReceiveComplete(pSmsNdis->hMiniportAdapter);
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: %d valid packets\r\n"),validIpCount));
}
NdisIMRevertBack(pSmsNdis->hMiniportAdapter,&SwitchHandle);
DBGMSG(ZONE_INFO, (TEXT("SmsNdis: -ReadIpCB\r\n")));
}
///////////////////////////////////////////////////////////////////////////////