⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kitleth.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -