📄 vmini.c
字号:
NextLoop:
//
// Return the buffer to kernel.
//
if (bConvert)
BufferAddress |= 0x20000000;
KernelIoControl(
IOCTL_VBRIDGE_GET_RX_PACKET_COMPLETE,
(LPVOID)BufferAddress,
sizeof(DWORD),
NULL,
0x00,
&dwReturnedBytes);
} // while()
//
// Time to quit..
//
if (VMini.vm_bHalt)
{
DEBUGMSG (ZONE_WARNING,
(TEXT("VMini:: RX Thread quiting..\r\n")));
return;
}
} // while (1)
} // VirtMiniISR()
////////////////////////////////////////////////////////////////////////////////
// GetXBytesOffsetYBytes()
//
// Routine description:
//
// Given an NDIS packet, get the first X bytes after offset Y bytes.
// If the X Bytes are all in one NdisBuffer then that's fine.
// otherwise copy that into the given buffer.
//
// Arguments:
//
// ppbData :: [i/o] If all X Bytes are in one buffer, ppbData will
// point to this buffer on return or otherwise it will
// point to the pTransitBuffer..
//
// pTransitBuffer :: If X bytes spans across NdisBuffer, then copy them
// to this given buffer.
// ** Caller ** must allocate the buffer.
//
// uiXBytes :: X number of bytes required.
//
// uiYBytes :: Y number of bytes offset from the very beginning..
//
// pPacket :: The NDIS_PACKET
//
// return values:
//
// FALSE :: Unable to get the required bytes.
//
// TRUE :: The required info is either pointed to by ppbData or
// copied to pTransitBuffer.
//
BOOL
GetXBytesOffsetYBytes(
BYTE **ppbData,
BYTE *pTransitBuffer,
UINT uiXBytes,
UINT uiYBytes,
PNDIS_PACKET pPacket)
{
UINT NdisBufferCount;
PNDIS_BUFFER CurrentNdisBuffer;
UINT TotalPacketLength;
UINT CurrentBufferLength = 0x00;
PVOID VirtualAddress = 0x00;
UINT TotalCopiedLength = 0x00;
UINT TotalParsedLength = 0x00;
BOOL bStarted = FALSE;
NdisRecalculatePacketCounts(pPacket);
NdisQueryPacket(
pPacket,
NULL,
&NdisBufferCount,
&CurrentNdisBuffer,
&TotalPacketLength
);
DEBUGMSG (0, (TEXT("GetFirstXBytes: Packet Length = %d\r\n"),
TotalPacketLength));
if (TotalPacketLength < uiXBytes)
{
//
// Impossible to get, total length is less than X bytes.
//
*ppbData = NULL;
return FALSE;
}
//
// Now, loop through the Total buffer count, and break out once our goal
// has been achieved.
//
while (NdisBufferCount--)
{
NdisQueryBuffer(
CurrentNdisBuffer,
&VirtualAddress,
&CurrentBufferLength
);
NdisGetNextBuffer(
CurrentNdisBuffer,
&CurrentNdisBuffer);
if (!bStarted)
{
if ((TotalParsedLength + CurrentBufferLength) >= uiYBytes)
{
bStarted = TRUE;
if ((TotalParsedLength + CurrentBufferLength) >= (uiYBytes + uiXBytes))
{
//
// All data available in one buffer, simply point the
// ppbData to this VA, and our job is done!
//
*ppbData = ((PBYTE) VirtualAddress) +
(uiYBytes - TotalParsedLength);
return TRUE;
}
else
{
//
// Now, the X bytes we want span across different
// NDIS_BUFFER, start copying from this buffer onwards.
//
if (pTransitBuffer == NULL)
return FALSE;
*ppbData = pTransitBuffer;
memcpy(
pTransitBuffer + TotalCopiedLength,
(PBYTE)VirtualAddress + (uiYBytes - TotalParsedLength),
CurrentBufferLength - (uiYBytes - TotalParsedLength));
TotalCopiedLength +=
(CurrentBufferLength - (uiYBytes - TotalParsedLength));
}
}
TotalParsedLength += CurrentBufferLength;
}
else
{
//
// By the time we get here, it will always be a straight copy.
//
if ((CurrentBufferLength + TotalCopiedLength) > uiXBytes)
{
memcpy(
pTransitBuffer + TotalCopiedLength,
VirtualAddress,
uiXBytes - TotalCopiedLength);
return TRUE;
}
//
// If we get here, it means we need more buffer!!
//
memcpy(
pTransitBuffer + TotalCopiedLength,
VirtualAddress,
CurrentBufferLength);
TotalCopiedLength += CurrentBufferLength;
}
} // while()
//
// We should never get here.
// If we do it means that total number of bytes in the packet is less
// than what we expect.
//
DEBUGMSG (1,
(TEXT("VMini:: GetX... Not enough! Need:[%d] - Copied So Far:[%d]\r\n"),
uiXBytes,
TotalCopiedLength));
return FALSE;
} // GetXBytesOffsetYBytes()
////////////////////////////////////////////////////////////////////////////////
// IsDhcpRelease()
//
// Routine description:
//
// This function determines whether a given NDIS_PACKET is dhcp release
// packet.
//
// Arguments:
//
// pPacket :: The NDIS_PACKET
//
// return values:
//
// FALSE :: Not DHCP release packet.
//
// TRUE :: Oh ya...
//
BOOL
IsDhcpRelease(PNDIS_PACKET pPacket)
{
#define MIN_ETYPE 0x0600 // Minimum valid Ethertype
#define IP_TYPE 0x0800 // IP frame.
#define PROTOCOL_UDP 0x11
#define DHCP_SERVER_PORT 0x0043
#define DHCP_CLIENT_PORT 0x0044
#define DHCP_MSG_TYPE_OP 53
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNACK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8
#define DHCP_MINUS_OPTION_SIZE (sizeof(DHCP_PACKET) - OPTIONS_LEN)
#define MIN_LENGTH sizeof(ENetHeaderFormat) + \
sizeof(IPHeaderFormat) + \
sizeof(UDPHeaderFormat) + \
DHCP_MINUS_OPTION_SIZE
UCHAR ucScrapBuffer[512];
DWORD dwOffset;
DWORD dwPacketLength;
USHORT usEType;
ENetHeaderFormat UNALIGNED *pEnetHeader;
IPHeaderFormat UNALIGNED *pIPHeader;
UDPHeaderFormat UNALIGNED *pUDPHeader;
PUCHAR pucType, pucTargetEnd;
DWORD dwOptionLength;
//
// Quick check that it is DHCP packet..
//
NdisQueryPacket(
pPacket,
NULL,
NULL,
NULL,
&dwPacketLength);
if (dwPacketLength < MIN_LENGTH)
return FALSE;
//
// Get the ethernet header..
//
if (!GetXBytesOffsetYBytes(
(BYTE **)&pEnetHeader,
&ucScrapBuffer[0],
sizeof(ENetHeaderFormat),
0,
pPacket))
{
//
// Can't even get ethernet header... Should never happen..
// Well, just pass it..
//
return FALSE;
}
usEType = net_short(pEnetHeader->eh_type);
//
// Bail if not IP packet..
//
if (usEType != IP_TYPE)
return FALSE;
//
// Get the IP header..
//
if (usEType < MIN_ETYPE)
dwOffset = sizeof(SNAPHeaderFormat);
else
dwOffset = sizeof(ENetHeaderFormat);
if (!GetXBytesOffsetYBytes(
(BYTE **)&pIPHeader,
&ucScrapBuffer[0],
sizeof(IPHeaderFormat),
dwOffset,
pPacket))
{
//
// Should never happen.. Well, just pass it..
//
return FALSE;
}
//
// Bail if not UDP
//
if (pIPHeader->bProtocol != PROTOCOL_UDP)
return FALSE;
//
// Get the UDP header..
//
dwOffset += (pIPHeader->bVersionLength & 0x0f) * 4;
if (!GetXBytesOffsetYBytes(
(BYTE **)&pUDPHeader,
&ucScrapBuffer[0],
sizeof(UDPHeaderFormat),
dwOffset,
pPacket))
{
//
// Should never happen.. Well, just pass it..
//
return FALSE;
}
//
// If destination is DHCP server port then it can potentially
// be DHCP Release..
//
if (net_short(pUDPHeader->wDestPort) != DHCP_SERVER_PORT)
return FALSE;
//
// Definitely DHCP packet, bypass all of it and get the option
// field..
//
dwOffset += sizeof(UDPHeaderFormat) + DHCP_MINUS_OPTION_SIZE;
dwOptionLength = dwPacketLength - dwOffset;
if (!GetXBytesOffsetYBytes(
(BYTE **)&pucType,
&ucScrapBuffer[0],
dwOptionLength,
dwOffset,
pPacket))
{
//
// Should not happen..
//
ASSERT(0);
return FALSE;
}
pucTargetEnd = pucType + dwOptionLength;
//
// Skip the magic cookie..
//
pucType += 4;
//
// Okay, parse the option field looking for DHCPRELEASE
// in DHCP_MSG_TYPE_OP type.
//
while (pucType < pucTargetEnd)
{
if (*pucType == DHCP_MSG_TYPE_OP)
{
DEBUGMSG (1, (TEXT("VMini:: Detected DHCP [%s]\r\n"),
(pucType[2] == DHCPDISCOVER) ? TEXT("DISCOVER") :
(pucType[2] == DHCPOFFER) ? TEXT("OFFER") :
(pucType[2] == DHCPREQUEST) ? TEXT("REQUEST") :
(pucType[2] == DHCPDECLINE) ? TEXT("DECLINE") :
(pucType[2] == DHCPACK) ? TEXT("ACK") :
(pucType[2] == DHCPNACK) ? TEXT("NACK") :
(pucType[2] == DHCPRELEASE) ? TEXT("RELEASE") :
(pucType[2] == DHCPINFORM) ? TEXT("INFORM") :
TEXT("UNKNOWN!")));
if (pucType[2] == DHCPRELEASE)
{
RETAILMSG (1,
(TEXT("VMini:: is doing the right thing, block DHCP_RELEASE..\r\n")));
return TRUE;
}
else
return FALSE;
}
//
// Next type please...
// Type is followed by length (1 byte), add two
// for the type and the length fields..
//
pucType += pucType[1] + 2;
}
return FALSE;
} // IsDhcpRelease()
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Start of all the normal MiniportXXX functions.
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// VMiniInitialize()
//
// Routine description:
//
// Called by NDIS after we call: NdisMRegisterMiniport().
//
// Arguments:
//
// Look at MSDN MiniportInitialize() description.
//
// return values:
//
// NDIS_STATUS_XXX
//
NDIS_STATUS
VMiniMInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE VMiniportHandle,
IN NDIS_HANDLE ConfigurationHandle
)
{
DWORD dwReturnedBytes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -