📄 kitleth.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name: kitleth.c
Abstract:
This module contains the KITL Ethernet transport exported functions
Functions:
Notes:
--*/
#include <windows.h>
#include <Kitl.h>
#include <halether.h>
#include "kitlethp.h"
static EDBG_ADDR DevAddr;
// initialize host address to be a limit-broadcast to Service port
static EDBG_ADDR HostAddr = { 0xffffffff, 0xffff, 0xffff, 0xffff, htons(EDBG_SVC_PORT) };
static UINT16 CRC (UINT16 *pwRegion1, UINT16 wLength1, UINT16 *pwRegion2, UINT16 wLength2);
BOOL KitlEtherInit (EDBG_ADDR *pAddr, DWORD dwDHCPLeaseTime)
{
// validate the parameters
if (!pAddr || !pAddr->dwIP || !pAddr->wPort)
return FALSE;
// keep a local copy of the addresses
memcpy (&DevAddr, pAddr, sizeof (EDBG_ADDR));
KITLOutputDebugString ("Calling EdbgInitDHCP\r\n");
// initialized DHCP renew process
return EdbgInitDHCP (pAddr, dwDHCPLeaseTime);
}
BOOL EncodeUDP (LPBYTE pbFrame, USHORT cbData, EDBG_ADDR *pSrcAddr, EDBG_ADDR *pDestAddr)
{
EthernetFrameHeader *pFrameHeader;
IPHeaderFormat *pIPHeader;
UDPPseudoHeaderFormat UDPPseudoHeader;
UDPHeaderFormat *pUDPHeader;
LPBYTE pData = pbFrame + UDP_DATA_FRAME_OFFSET;
static UINT16 wIndentification = 0;
// the frame buffer MUST be WORD aligned
if (!pbFrame || !cbData || ((DWORD) pbFrame & 3)) {
EdbgOutputDebugString ("!EncodeUDP: frame buffer must be DWORD aligned\r\n");
return FALSE;
}
// Fill in destination and source MAC addresses and the IP frame type
pFrameHeader = (EthernetFrameHeader *) pbFrame;
pFrameHeader->wDestMAC[0] = pDestAddr->wMAC[0];
pFrameHeader->wDestMAC[1] = pDestAddr->wMAC[1];
pFrameHeader->wDestMAC[2] = pDestAddr->wMAC[2];
pFrameHeader->wSrcMAC[0] = pSrcAddr->wMAC[0];
pFrameHeader->wSrcMAC[1] = pSrcAddr->wMAC[1];
pFrameHeader->wSrcMAC[2] = pSrcAddr->wMAC[2];
pFrameHeader->wFrameType = htons(IP_FRAME);
// The field information comes from page 34 of TCP/IP Illustrated by W. Richard Stevens
pIPHeader = (IPHeaderFormat *) (pbFrame + sizeof(EthernetFrameHeader));
pIPHeader->bVersionLength = 0x45; // IP Version 4, No option IP header (5 32 bit words)
pIPHeader->bTypeOfService = 0; // No special transport options
// Total length of the IP datagram
pIPHeader->cwTotalLength = htons(sizeof(IPHeaderFormat) + sizeof(UDPHeaderFormat) + cbData);
// Unique packet identification
pIPHeader->wIdentification = wIndentification++;
pIPHeader->wFragment = 0; // No fragmentation
pIPHeader->bTimeToLive = 64; // We can go through 64 routers
pIPHeader->bProtocol = UDP_PROTOCOL;// Specify the UDP protocol
pIPHeader->wCRC = 0; // Set the CRC to 0 while it is being computed
pIPHeader->dwSrcIP = pSrcAddr->dwIP;
pIPHeader->dwDestIP = pDestAddr->dwIP;
// Compute the CRC and we're done with the IP header
pIPHeader->wCRC = CRC ((UINT16 *)pIPHeader, sizeof(IPHeaderFormat), NULL, 0);
// The field information comes from page 145 of TCP/IP Illustrated by W. Richard Stevens
// Construct the UDP pseudo header
UDPPseudoHeader.dwSrcIP = pSrcAddr->dwIP;
UDPPseudoHeader.dwDestIP = pDestAddr->dwIP;
UDPPseudoHeader.bZero = 0;
UDPPseudoHeader.bProtocol = UDP_PROTOCOL; // This is the code for the UDP protocol
UDPPseudoHeader.cwTotalUDPLength = htons(sizeof(UDPHeaderFormat) + cbData);
// Construct the real UDP header
pUDPHeader = (UDPHeaderFormat *)((BYTE *)pIPHeader + sizeof(IPHeaderFormat));
pUDPHeader->wSrcPort = pSrcAddr->wPort;
pUDPHeader->wDestPort = pDestAddr->wPort;
// The total length of the UDP datagram
pUDPHeader->cwTotalUDPLength = UDPPseudoHeader.cwTotalUDPLength;
pUDPHeader->wCRC = 0; // Set the CRC to 0 while it is being computed
// Compute the CRC for the UDP datagram. The pad 0 will automatically be added if there are an odd number of bytes
pUDPHeader->wCRC = CRC ((UINT16 *)(&UDPPseudoHeader), sizeof(UDPPseudoHeader), (UINT16 *)pUDPHeader, ntohs(pUDPHeader->cwTotalUDPLength));
if (pUDPHeader->wCRC == 0)
pUDPHeader->wCRC = ~(pUDPHeader->wCRC);
return TRUE;
}
BOOL KitlEtherEncodeUDP (LPBYTE pbFrame, USHORT cbData)
{
return EncodeUDP (pbFrame, cbData, &DevAddr, &HostAddr);
}
LPBYTE KitlEtherDecodeUDP (LPBYTE pbFrame, PUSHORT pcbData)
{
EthernetFrameHeader *pFrameHeader = (EthernetFrameHeader *) pbFrame;
IPHeaderFormat *pIPHeader;
UDPPseudoHeaderFormat UDPPseudoHeader;
UDPHeaderFormat *pUDPHeader;
// the frame buffer MUST be WORD aligned
if (!pbFrame || !*pcbData || ((DWORD) pbFrame & 1)) {
return NULL;
}
switch (ntohs(pFrameHeader->wFrameType)) {
case ARP_FRAME:
HandleARPPacket (&DevAddr, (LPBYTE) pbFrame);
return NULL; // ARP packet, KITL don't want any part of it
case IP_FRAME:
break;
default:
return NULL; // not ARP, not IP, forget about it
}
pIPHeader = (IPHeaderFormat *) (pbFrame + sizeof(EthernetFrameHeader));
// Make sure that it was for our IP address
if (pIPHeader->dwDestIP != DevAddr.dwIP) {
return NULL; // the frame not for us
}
// Make sure that it is a UDP packet
if (pIPHeader->bProtocol != UDP_PROTOCOL) {
KITLOutputDebugString("!CheckUDP: Not UDP (proto = 0x%X)\n",pIPHeader->bProtocol);
return NULL;
}
// Check the IP header checksum
if (CRC ((UINT16 *) pIPHeader, sizeof(IPHeaderFormat), NULL, 0) != 0) {
KITLOutputDebugString("!CheckUDP: IP header checksum failure\n");
return NULL;
}
// Build the UDP Pseudo Header
UDPPseudoHeader.dwSrcIP = pIPHeader->dwSrcIP;
UDPPseudoHeader.dwDestIP = pIPHeader->dwDestIP;
UDPPseudoHeader.bZero = 0;
UDPPseudoHeader.bProtocol = UDP_PROTOCOL; // This is the code for the UDP protocol
UDPPseudoHeader.cwTotalUDPLength = htons(ntohs(pIPHeader->cwTotalLength) - sizeof(IPHeaderFormat));
// Check the UDP checksum, I'm using the cwTotalUDPLength calculated from the IP header info because
// we know that it's not corrupted and won't give an outrageous length for the packet
pUDPHeader = (UDPHeaderFormat *) ((BYTE *)pIPHeader + sizeof(IPHeaderFormat));
if (CRC ((UINT16 *)(&UDPPseudoHeader), sizeof(UDPPseudoHeader), (UINT16 *)pUDPHeader, ntohs(UDPPseudoHeader.cwTotalUDPLength)) != 0) {
KITLOutputDebugString("!CheckUDP: UDP header checksum failure\n");
return NULL;
}
// update host address if it's sending to our service port
if (htons (EDBG_SVC_PORT) == pUDPHeader->wDestPort) {
// update host address
if (HostAddr.dwIP == 0xffffffff) {
EdbgOutputDebugString ("Host connected\r\n");
HostAddr.wMAC[0] = pFrameHeader->wSrcMAC[0];
HostAddr.wMAC[1] = pFrameHeader->wSrcMAC[1];
HostAddr.wMAC[2] = pFrameHeader->wSrcMAC[2];
HostAddr.dwIP = pIPHeader->dwSrcIP;
HostAddr.wPort = pUDPHeader->wSrcPort;
EdbgOutputDebugString ("Host IP: %s, port %d\r\n", inet_ntoa (HostAddr.dwIP), htons (HostAddr.wPort));
}
}
// check if it's DHCP packet
if (HandleDHCPPacket (&DevAddr, pUDPHeader)) {
return NULL; // DHCP messages, KITL don't want any part of it
}
// update get the data and lenght
*pcbData = htons (pUDPHeader->cwTotalUDPLength) - sizeof(UDPHeaderFormat);
return (LPBYTE) pUDPHeader + sizeof(UDPHeaderFormat);
}
UCHAR KitlEtherGetFrameHdrSize (void)
{
return UDP_DATA_FRAME_OFFSET;
}
// This routine will calculation the complemented 16-bit 1's complement sum required to compute
// network CRCs. The CRC can be calculated over two different memory regions. If only one
// region is desired, then the other's length can be set to 0. Also, if an odd number of bytes
// are specified, the routine will add a 0 to the end of the data before doing the CRC and will
// include that 0 in the calculation.
static UINT16 CRC (UINT16 *pwRegion1, UINT16 wLength1, UINT16 *pwRegion2, UINT16 wLength2)
{
DWORD dwSum, dwCarryOut;
UINT16 wCRC;
UINT16 i;
// There is no need to swap for network ordering during calculation because of the end around
// carry used in 1's complement addition
dwSum = 0;
if (wLength1 & 1) {
*((BYTE *)pwRegion1 + wLength1) = 0;
wLength1++;
}
wLength1 >>= 1;
for (i = 0; i < wLength1; i++)
dwSum += *pwRegion1++;
if (wLength2 & 1) {
*((BYTE *)pwRegion2 + wLength2) = 0;
wLength2++;
}
wLength2 >>= 1;
for (i = 0; i < wLength2; i++)
dwSum += *pwRegion2++;
// Now, we have to add back in all the carry out's from the lower 16 bits
// because this is 1's complement
while (dwSum & 0xFFFF0000UL) {
dwCarryOut = dwSum >> 16;
dwSum &= 0x0000FFFFUL;
dwSum += dwCarryOut;
}
wCRC = (UINT16)dwSum;
// There is no need to flip for network byte order because we did all the sums backwards
// already.
wCRC = ~wCRC;
return wCRC;
}
BOOL EdbgSendUDP(
BYTE *pFrameBuffer, // @parm [IN] - Formatting buffer (must be at least 42 + cwLength bytes)
EDBG_ADDR *pDestAddr, // @parm [IN] - Address of destination
USHORT wSrcPort, // @parm [IN] - Source UDP port number
BYTE *pData, // @parm [IN] - User data buffer
UINT16 cwLength ) // @parm [IN] - # of bytes of data in user buffer
{
EDBG_ADDR srcAddr;
// construct source address
memcpy (&srcAddr, &DevAddr, sizeof (EDBG_ADDR));
srcAddr.wPort = htons (wSrcPort);
// Copy user data if necessary
if ((pData - pFrameBuffer) != UDP_DATA_FRAME_OFFSET)
memcpy (pFrameBuffer + UDP_DATA_FRAME_OFFSET, pData, cwLength);
// UDP encoding
if (!EncodeUDP (pFrameBuffer, cwLength, &srcAddr, pDestAddr)) {
return FALSE;
}
return KitlSendRawData (pFrameBuffer, (USHORT) (cwLength + UDP_DATA_FRAME_OFFSET));
}
BOOL KitlEthGetInfo (DWORD dwCode, LPVOID lpData, LPDWORD pcbData)
{
if (!lpData || !pcbData || ((DWORD)lpData & 3) || (sizeof(DWORD) != *pcbData)) {
return FALSE;
}
switch (dwCode) {
case KGI_HOSTADDR:
*(LPDWORD)lpData = HostAddr.dwIP;
break;
case KGI_DEVADDR:
*(LPDWORD)lpData = DevAddr.dwIP;
break;
case KGI_BAUDRATE:
*(LPDWORD)lpData = 10*1024*1024; // 10MB per second
break;
case KGI_PORT:
*(LPDWORD)lpData = htons (HostAddr.wPort);
break;
default:
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -