📄 kitleth.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
// File: kitleth.c
//
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <kitl.h>
#include <ethdbg.h>
#include <oal.h>
#include "kitleth.h"
//------------------------------------------------------------------------------
// Local variable
static struct {
OAL_KITL_ETH_DRIVER *pDriver;
UINT32 flags;
UINT8 deviceMAC[6];
UINT32 deviceIP;
UINT8 kitlServerMAC[6];
UINT32 kitlServerIP;
UINT16 kitlServerPort;
UINT32 dhcpState;
UINT32 dhcpServerIP;
UINT32 dhcpXId;
PFN_SENDFRAME pfnSend;
PFN_RECVFRAME pfnRecv;
BOOL updateFilter;
UINT32 deviceFilter;
BOOL updateMCast;
UINT32 deviceMCastSize;
UINT8 deviceMCast[32 * 6];
UINT8 packet[1516];
} g_kitlEthState;
//------------------------------------------------------------------------------
static UINT8* KitlEthDecode(UINT8 *pFrame, UINT16 *pLength);
//------------------------------------------------------------------------------
static UINT16 Sum(UINT16 seed, VOID *pData, UINT32 size)
{
UINT32 sum;
UINT16 *p;
// There is no need to swap for network ordering during calculation
// because of the end around carry used in 1's complement addition
sum = seed;
p = (UINT16*)pData;
while (size >= sizeof(UINT16)) {
sum += *p++;
size -= sizeof(UINT16);
}
if (size > 0) sum += *((UINT8*)p);
while ((sum & 0xFFFF0000) != 0) {
sum = (sum & 0x0000FFFF) + (sum >> 16);
}
return (UINT16)sum;
}
//------------------------------------------------------------------------------
static VOID SendARP(UINT16 op, UINT8 mac[], UINT32 ip)
{
UINT8 *pFrame = g_kitlEthState.packet;
ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
ARP_MESSAGE *pARP = (ARP_MESSAGE*)((UINT8*)pEth + sizeof(ETH_HEADER));
memcpy(pEth->destmac, mac, sizeof(pEth->destmac));
memcpy(pEth->srcmac, g_kitlEthState.deviceMAC, sizeof(pEth->srcmac));
pEth->ftype = htons(ARP_FRAME);
pARP->htype = htons(1); // Ethernet
pARP->ptype = htons(IP_FRAME); // IP4 addresses
pARP->hsize = 6; // MAC address is 6 bytes long
pARP->psize = 4; // IP4 addresses are 4 bytes long
pARP->op = htons(op); // Specify an ARP op
// Fill in the source side information
memcpy(pARP->srcmac, g_kitlEthState.deviceMAC, sizeof(pARP->srcmac));
pARP->srcip = g_kitlEthState.deviceIP;
// Fill in the destination information
memcpy(pARP->destmac, mac, sizeof(pARP->destmac));
pARP->destip = ip;
// Send packet
g_kitlEthState.pfnSend(pFrame, sizeof(ETH_HEADER) + sizeof(ARP_MESSAGE));
}
//------------------------------------------------------------------------------
static UINT16 GetOpARP(UINT8 *pFrame, UINT16 length)
{
ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
ARP_MESSAGE *pARP = (ARP_MESSAGE*)((UINT8*)pEth + sizeof(ETH_HEADER));
if (pEth->ftype != htons(ARP_FRAME)) return 0;
return htons(pARP->op);
}
//------------------------------------------------------------------------------
static VOID DecodeARP(UINT8 *pFrame, UINT16 length, BOOL *pUsed)
{
ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
ARP_MESSAGE *pARP = (ARP_MESSAGE*)((UINT8*)pEth + sizeof(ETH_HEADER));
// Check to see that they were requesting the ARP response from us,
// send reply to ARP request, but ignore other ops
if (
pARP->destip == g_kitlEthState.deviceIP &&
pARP->op == htons(ARP_REQUEST)
) {
SendARP(ARP_RESPONSE, pARP->srcmac, pARP->srcip);
*pUsed = TRUE;
} else {
*pUsed = FALSE;
}
}
//------------------------------------------------------------------------------
static UINT16 EncodeIP(
UINT8 *pFrame, UINT16 length, UINT8 *pDestMAC, UINT32 srcIP, UINT32 destIP,
UINT8 protocol
) {
static UINT16 ipId = 0;
ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
IP4_HEADER *pIP = (IP4_HEADER*)((UINT8*)pEth + sizeof(ETH_HEADER));
UINT16 ipLength, ethLength;
// Get final length
ipLength = sizeof(IP4_HEADER) + length;
ethLength = sizeof(ETH_HEADER) + ipLength;
// Fill in Ethernet header
if (pDestMAC != NULL) {
memcpy(pEth->destmac, pDestMAC, sizeof(pEth->destmac));
} else {
memset(pEth->destmac, 0xFF, sizeof(pEth->destmac));
}
memcpy(pEth->srcmac, g_kitlEthState.deviceMAC, sizeof(pEth->srcmac));
pEth->ftype = htons(IP_FRAME);
// Fill in IP4 header
pIP->verlen = 0x45;
pIP->tos = 0;
pIP->length = htons(ipLength);
pIP->id = ipId++;
pIP->fragment = 0;
pIP->ttl = 64;
pIP->protocol = protocol;
pIP->sum = 0;
pIP->srcip = srcIP;
pIP->destip = destIP;
// Compute IP4 header checksum
pIP->sum = ~ Sum(0, pIP, sizeof(IP4_HEADER));
// We are done
return ethLength;
}
//------------------------------------------------------------------------------
static UINT16 EncodeUDP(
UINT8 *pFrame, UINT16 length, UINT8 *pDestMAC, UINT32 srcIP, UINT32 destIP,
UINT16 srcPort, UINT16 destPort
) {
UDP_HEADER *pUDP;
UINT16 xsum, udpLength;
// First calculate UDP length
udpLength = sizeof(UDP_HEADER) + length;
// Fill in UDP header
pUDP = (UDP_HEADER*)(pFrame + sizeof(ETH_HEADER) + sizeof(IP4_HEADER));
pUDP->srcPort = srcPort;
pUDP->dstPort = destPort;
pUDP->length = htons(udpLength);
pUDP->sum = 0;
// Compute UDP header checksum
xsum = htons(UDP_PROTOCOL);
xsum = Sum(xsum, &srcIP, sizeof(UINT32));
xsum = Sum(xsum, &destIP, sizeof(UINT32));
xsum = Sum(xsum, &pUDP->length, sizeof(UINT32));
xsum = Sum(xsum, pUDP, udpLength);
pUDP->sum = ~xsum;
// And now do IP encode
return EncodeIP(pFrame, udpLength, pDestMAC, srcIP, destIP, UDP_PROTOCOL);
}
//------------------------------------------------------------------------------
static UINT8* FindDHCPOption(BOOTP_MESSAGE *pDHCP, DHCP_OPTIONS option)
{
UINT8 *p;
p = &pDHCP->options[4];
while (*p != DHCP_END) {
if (*p == option) break;
p += p[1] + 2;
}
if (*p == DHCP_END) p = NULL;
return p;
}
//------------------------------------------------------------------------------
static VOID AddDHCPOption(
BOOTP_MESSAGE *pDHCP, DHCP_OPTIONS option, UINT32 *pOffset,
VOID *pData, UINT32 size
) {
pDHCP->options[(*pOffset)++] = option;
pDHCP->options[(*pOffset)++] = size;
memcpy(&pDHCP->options[*pOffset], pData, size);
*pOffset += size;
}
//------------------------------------------------------------------------------
static VOID SendDHCP(DHCP_MESSAGE_TYPE msgType, UINT32 requestIP)
{
UINT8 *pFrame = g_kitlEthState.packet;
BOOTP_MESSAGE *pDHCP;
UINT32 offset;
UINT16 size;
UINT8 clientId[7];
// Get pointer to BOOTP/DHCP message
pDHCP = (BOOTP_MESSAGE*)(
pFrame + sizeof(ETH_HEADER) + sizeof(IP4_HEADER) + sizeof(UDP_HEADER)
);
// Clear all fields
memset(pDHCP, 0, sizeof(BOOTP_MESSAGE));
// BOOTP header
pDHCP->op = 1; // BOOTREQUEST
pDHCP->htype = 1; // 10 Mbps Ethernet
pDHCP->hlen = 6; // Ethernet address size
pDHCP->secs = 0; // Who care?
pDHCP->xid = g_kitlEthState.dhcpXId;
// Device MAC address
memcpy(
pDHCP->chaddr, g_kitlEthState.deviceMAC,
sizeof(g_kitlEthState.deviceMAC)
);
// Start with options
offset = 0;
// DHCP cookie
pDHCP->options[offset++] = 0x63;
pDHCP->options[offset++] = 0x82;
pDHCP->options[offset++] = 0x53;
pDHCP->options[offset++] = 0x63;
// DHCP message type
AddDHCPOption(pDHCP, DHCP_MSGTYPE, &offset, &msgType, 1);
// Add client id
clientId[0] = 1;
memcpy(&clientId[1], g_kitlEthState.deviceMAC, 6);
AddDHCPOption(pDHCP, DHCP_CLIENT_ID, &offset, clientId, 7);
switch (msgType) {
case DHCP_REQUEST:
if (requestIP != 0) {
AddDHCPOption(
pDHCP, DHCP_IP_ADDR_REQ, &offset, &requestIP, sizeof(requestIP)
);
AddDHCPOption(
pDHCP, DHCP_SERVER_ID, &offset, &g_kitlEthState.dhcpServerIP,
sizeof(g_kitlEthState.dhcpServerIP)
);
} else {
pDHCP->ciaddr = g_kitlEthState.deviceIP;
}
break;
case DHCP_DECLINE:
AddDHCPOption(
pDHCP, DHCP_IP_ADDR_REQ, &offset, &requestIP, sizeof(requestIP)
);
AddDHCPOption(
pDHCP, DHCP_SERVER_ID, &offset, &g_kitlEthState.dhcpServerIP,
sizeof(g_kitlEthState.dhcpServerIP)
);
break;
}
// DHCP message end
pDHCP->options[offset++] = DHCP_END;
// Add MAC/IP/UDP header and checksum
size = EncodeUDP(
pFrame, sizeof(BOOTP_MESSAGE) + offset, NULL, requestIP, 0xFFFFFFFF,
htons(DHCP_CLIENT_PORT), htons(DHCP_SERVER_PORT)
);
// Send packet on wire
g_kitlEthState.pfnSend(pFrame, size);
}
//------------------------------------------------------------------------------
static VOID RenewDHCP(VOID *pParam)
{
KITL_RETAILMSG(ZONE_WARNING, ("KITL: Start DHCP RENEW process\r\n"));
// Change transaction id (ok, not too random)
g_kitlEthState.dhcpXId += 0x01080217;
// Send request
SendDHCP(DHCP_REQUEST, 0);
g_kitlEthState.dhcpState = DHCP_REQUESTING;
}
//------------------------------------------------------------------------------
static VOID GetAddressDHCP(UINT32 ip)
{
UINT32 startTime, attempts;
UINT16 size;
UINT8 mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// If there is already IP adress, try first renew it
if (ip != 0) {
// Send request
SendDHCP(DHCP_REQUEST, 0);
g_kitlEthState.dhcpState = DHCP_REQUESTING;
// Wait until DHCP gets address or timeout
startTime = OALGetTickCount();
while ((OALGetTickCount() - startTime) < DHCP_TIMEOUT) {
size = sizeof(g_kitlEthState.packet);
if (!g_kitlEthState.pfnRecv(g_kitlEthState.packet, &size)) continue;
KitlEthDecode(g_kitlEthState.packet, &size);
if (g_kitlEthState.dhcpState == DHCP_BOUND) break;
}
// If we end in BOUND state we renew it...
if (g_kitlEthState.dhcpState == DHCP_BOUND) goto cleanUp;
}
// Allocate new IP address
attempts = 0;
while (attempts++ < 3) {
// Reset device and server IP
g_kitlEthState.deviceIP = 0;
g_kitlEthState.dhcpServerIP = 0;
// Send DHCP discover message
SendDHCP(DHCP_DISCOVER, 0);
g_kitlEthState.dhcpState = DHCP_SELECTING;
// Wait until DHCP gets address or timeout
startTime = OALGetTickCount();
while ((OALGetTickCount() - startTime) < DHCP_TIMEOUT) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -