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

📄 kitleth.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 3 页
字号:
            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 there was timeout try start DHCP againg with new transaction id
        if (g_kitlEthState.dhcpState != DHCP_BOUND) {
            g_kitlEthState.dhcpXId += 0x00080000;
            continue;
        }

        // We get address, verify if it isn't used by somebody else...
        SendARP(ARP_REQUEST, mac, g_kitlEthState.deviceIP);
        startTime = OALGetTickCount();
        while ((OALGetTickCount() - startTime) < ARP_TIMEOUT) {
            size = sizeof(g_kitlEthState.packet);
            if (g_kitlEthState.pfnRecv(g_kitlEthState.packet, &size)) {
                if (GetOpARP(g_kitlEthState.packet, size) == ARP_RESPONSE) {
                    // Oops, somebody is using assigned address, decline...
                    SendDHCP(DHCP_DECLINE, g_kitlEthState.deviceIP);
                    g_kitlEthState.deviceIP = 0;
                    break;
                }
            }
        }

        // If we get with valid address we are done
        if (g_kitlEthState.deviceIP != 0) break;

        // Let try new DHCP transaction
        g_kitlEthState.dhcpXId += 0x01080000;

    }

cleanUp:
    if(g_kitlEthState.deviceIP != 0)
    KITL_RETAILMSG(ZONE_INIT, ("KITL: DHCP get/renew device IP: %s\r\n",
        OALKitlIPtoString(g_kitlEthState.deviceIP)
    ));
}

//------------------------------------------------------------------------------

static VOID DecodeDHCP(UINT8* pFrame, UINT16 *pSize, BOOL *pUsed)
{
    BOOTP_MESSAGE *pDHCP;
    UINT8 *pOption, msgType;
    UINT32 value;
    BOOL rc;

    // Be pesimistic
    *pUsed = FALSE;

    // Get pointers to BOOTP/DHCP message
    pDHCP = (BOOTP_MESSAGE*)(
        pFrame + sizeof(ETH_HEADER) + sizeof(IP4_HEADER) + sizeof(UDP_HEADER)
    );

    // Check magic DHCP cookie & transaction id
    if (
        pDHCP->options[0] != 0x63 || pDHCP->options[1] != 0x82 ||
        pDHCP->options[2] != 0x53 || pDHCP->options[3] != 0x63 ||
        pDHCP->xid != g_kitlEthState.dhcpXId
    ) goto cleanUp;

    // This is our DHCP transaction
    *pUsed = TRUE;

    // Then find DHCP message type
    pOption = FindDHCPOption(pDHCP, DHCP_MSGTYPE);
    if (pOption == NULL) return;
    msgType = pOption[2];

    // Message processing depend on DHCP client state
    switch (g_kitlEthState.dhcpState) {
    case DHCP_SELECTING:
        // Ignore anything other then offer
        if (msgType != DHCP_OFFER) break;
        // Find server IP address
        pOption = FindDHCPOption(pDHCP, DHCP_SERVER_ID);
        if (pOption == NULL) break;
        memcpy(&g_kitlEthState.dhcpServerIP, &pOption[2], sizeof(UINT32));
        // Request offered IP address
        SendDHCP(DHCP_REQUEST, pDHCP->yiaddr);
        // We moved to new state
        g_kitlEthState.dhcpState = DHCP_REQUESTING;
        break;
    case DHCP_REQUESTING:
        if (msgType == DHCP_ACK) {
            // Set assigned address
            g_kitlEthState.deviceIP = pDHCP->yiaddr;
            // Find renew period & set timer callback
            pOption = FindDHCPOption(pDHCP, DHCP_RENEW_TIME);
            if (pOption != NULL) {
                memcpy(&value, &pOption[2], sizeof(UINT32));
                rc = KitlSetTimerCallback(ntohl(value), RenewDHCP, NULL);
            } else {
                // If there isn't renew period select 30 minutes
                KitlSetTimerCallback(30*60, RenewDHCP, NULL);
            }
            // We get address, let check it...
            g_kitlEthState.dhcpState = DHCP_BOUND;
        } else if (msgType == DHCP_NAK) {
            g_kitlEthState.deviceIP = 0;
            // Discover DHCP servers
            SendDHCP(DHCP_DISCOVER, 0);
            // Start with discover again
            g_kitlEthState.dhcpState = DHCP_SELECTING;
        }
        break;
    }

cleanUp:
    return;
}

//------------------------------------------------------------------------------

static VOID DecodeICMP(UINT8 *pFrame, UINT16 length, BOOL *pUsed)
{
    ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
    IP4_HEADER *pIP = (IP4_HEADER*)((UINT8*)pEth + sizeof(ETH_HEADER));
    ICMP_HEADER *pICMP = (ICMP_HEADER*)((UINT8*)pIP + sizeof(IP4_HEADER));
    UINT16 icmpLength;

    // Be pesimistic
    *pUsed = FALSE;

    // Get ICMP message size & verify checksum
    icmpLength = ntohs(pIP->length) - sizeof(IP4_HEADER);
    if (Sum(0, pICMP, icmpLength) != 0xFFFF) goto cleanUp;

    // Reply to ping only
    if (pICMP->op != ICMP_ECHOREQ) goto cleanUp;

    // We now know that packet is used
    *pUsed = TRUE;

    // Encode reply & do checksum
    pICMP->op = 0;
    pICMP->code = 0;
    pICMP->sum = 0;
    pICMP->sum = ~ Sum(0, pICMP, icmpLength);

    // Add IP header
    EncodeIP(
        pFrame, icmpLength, pEth->srcmac, pIP->destip, pIP->srcip, ICMP_PROTOCOL
    );

    // Send packet
    g_kitlEthState.pfnSend(pFrame, length);

cleanUp:
    return;
}

//------------------------------------------------------------------------------

static UINT8* DecodeUDP(UINT8 *pFrame, UINT16 *pLength, BOOL *pUsed)
{
    UINT8 *pData = NULL;
    ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
    IP4_HEADER *pIP = (IP4_HEADER*)((UINT8*)pEth + sizeof(ETH_HEADER));
    UDP_HEADER *pUDP = (UDP_HEADER*)((UINT8*)pIP + sizeof(IP4_HEADER));
    UINT16 xsum;
    UINT32 ipLength, udpLength;

    // Be pesimistic
    *pUsed = FALSE;

    // Get IP and UDP lengths from packet
    ipLength = ntohs(pIP->length);
    udpLength = ntohs(pUDP->length);

    // UPD length must be in sync with IP length
    if (ipLength < sizeof(IP4_HEADER) + udpLength) goto cleanUp;

    // Verify UDP header checksum
    if (pUDP->sum != 0) {    
       xsum = htons(UDP_PROTOCOL);
       xsum = Sum(xsum, &pIP->srcip, sizeof(UINT32));
       xsum = Sum(xsum, &pIP->destip, sizeof(UINT32));
       xsum = Sum(xsum, &pUDP->length, sizeof(UINT32));
       xsum = Sum(xsum, pUDP, udpLength);
       if (xsum != pUDP->sum) goto cleanUp;
    }

    switch (ntohs(pUDP->dstPort)) {
    case DHCP_CLIENT_PORT:
        DecodeDHCP(pFrame, pLength, pUsed);
        break;
    case KITL_CLIENT_PORT:
        // Message must be for us and client must have an address
        if (
            g_kitlEthState.deviceIP != pIP->destip ||
            g_kitlEthState.deviceIP == 0
        ) break;
        // Initialize KITL server address
        if (g_kitlEthState.kitlServerIP == 0xFFFFFFFF) {
            memcpy(
                g_kitlEthState.kitlServerMAC, pEth->srcmac,
                sizeof(g_kitlEthState.kitlServerMAC)
            );
            g_kitlEthState.kitlServerIP = pIP->srcip;
            g_kitlEthState.kitlServerPort = pUDP->srcPort;
            KITL_RETAILMSG(ZONE_INIT, (
                "KITL: Connected host  IP: %s  Port: %d\r\n",
                OALKitlIPtoString(g_kitlEthState.kitlServerIP),
                ntohs(g_kitlEthState.kitlServerPort)
            ));
        }
        *pUsed = TRUE;
        pData = (UINT8*)pUDP + sizeof(UDP_HEADER);
        *pLength = udpLength - sizeof(UDP_HEADER);
        break;
    }

cleanUp:
    return pData;
}

//------------------------------------------------------------------------------

UINT8* DecodeIP(UINT8 *pFrame, UINT16 *pLength, BOOL *pUsed)
{
    UINT8 *pData = NULL;
    ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
    IP4_HEADER *pIP = (IP4_HEADER*)((UINT8*)pEth + sizeof(ETH_HEADER));

    // Be pesimistic
    *pUsed = FALSE;

    // We support only IP4 with standard IP4 header (no options...)
    if (pIP->verlen != 0x45) goto cleanUp;

    // First check if packet is for us
    if (
        pIP->destip != g_kitlEthState.deviceIP &&
        pIP->destip != 0xFFFFFFFF &&
        g_kitlEthState.deviceIP != 0
    ) goto cleanUp;

    // Verify IP4 header checksum
    if (Sum(0, pIP, sizeof(IP4_HEADER)) != 0xFFFF) goto cleanUp;

    // Then decode protocol
    switch (pIP->protocol) {
    case UDP_PROTOCOL:
        pData = DecodeUDP(pFrame, pLength, pUsed);
        break;
    case ICMP_PROTOCOL:
        DecodeICMP(pFrame, *pLength, pUsed);
        break;
    }

cleanUp:
    return pData;
}


//------------------------------------------------------------------------------
//
//  Function:  KitlEthDecode
//
//  This function is called by KITL to decode data for transport. For KITL
//  ethernet it means process packet if it belongs to any supporting protocol
//  (currently ARP, ICMP and DHCP) and send any reply packet. For KITL packets
//  function returns (after checksums pass) pointer to data and its size.
//  For any other packet function return NULL.
//
static UINT8* KitlEthDecode(UINT8 *pFrame, UINT16 *pLength)
{
    ETH_HEADER *pEth = (ETH_HEADER*)pFrame;
    UINT8 *pData = NULL;
    BOOL used = FALSE;


    KITL_RETAILMSG(ZONE_RECV, (
        "+KitlEthDecode(0x%08x, 0x%08x->%d)\r\n", pFrame, pLength, *pLength
    ));

    // Process received packet
    switch (ntohs(pEth->ftype)) {
    case ARP_FRAME:
        DecodeARP(pFrame, *pLength, &used);
        break;
    case IP_FRAME:
        pData = DecodeIP(pFrame, pLength, &used);
        break;
    }

    // If packet wasn't used, indicate it to VMINI
    if (!used && (g_kitlEthState.flags & OAL_KITL_FLAGS_VMINI) != 0) {
        VBridgeKIndicateOneRxBuffer(pFrame, *pLength, FALSE, &used);
    }

    KITL_RETAILMSG(ZONE_RECV, (
        "-KitlEthDecode(pData = 0x%08x, length = %d)\r\n", pData, *pLength
    ));
    return pData;
}

//------------------------------------------------------------------------------
//
//  Function:  KitlEthEncode
//
//  This function is called by KITL to encode data for transport. For KITL
//  ethernet it means adding MAC/IP4/UDP headers and checksums.
//
static BOOL KitlEthEncode(UINT8 *pFrame, UINT16 length)
{
    KITL_RETAILMSG(ZONE_SEND, (
        "+KitlEthEncode(%08x, %d)\r\n", pFrame, length
    ));

    // Encode packets
    EncodeUDP(
        pFrame, length,
        g_kitlEthState.kitlServerMAC, g_kitlEthState.deviceIP,
        g_kitlEthState.kitlServerIP, htons(KITL_CLIENT_PORT),
        g_kitlEthState.kitlServerPort
    );

    KITL_RETAILMSG(ZONE_SEND, ("-KitlEthEncode(rc = 1)\r\n"));
    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  KitlEthGetFrameHdrSize
//
//  This function is called by KITL to get information about transport header
//  size. It allows to allocate packet structure with room for it.
//
static UCHAR KitlEthGetFrameHdrSize()
{
    return sizeof(ETH_HEADER) + sizeof(IP4_HEADER) + sizeof(UDP_HEADER);
}

//------------------------------------------------------------------------------
//
//  Function:  KitlEthSetHostCfg
//
//  This function is called by KITL to with information sent by host in
//  negotiation. There is nothing useful for KITL on Ethernet.
//
static BOOL KitlEthSetHostCfg(UINT8 *pData, UINT16 size)
{
     return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  KitlEthGetDevCfg
//
//  This function is called by KITL to get information about transport layer.
//  For ethernet device should return its IP address, MAC address and UDP port.
//
static BOOL KitlEthGetDevCfg(UINT8 *pData, UINT16 *pSize)
{
    BOOL rc = FALSE;
    UINT16 port = htons(KITL_CLIENT_PORT);

    KITL_RETAILMSG(ZONE_KITL_OAL,  (
        "+KitlEthGetDevCfg(0x%08x, 0x%08x->%d)\r\n", pData, pSize, *pSize
    ));

    // Is there space in buffer?
    if (*pSize < (sizeof(UINT32) + 4 * sizeof(UINT16))) goto cleanUp;

    *pSize = 0;
    memcpy(pData, &g_kitlEthState.deviceIP, sizeof(UINT32));
    pData += sizeof(UINT32);
    *pSize += sizeof(UINT32);
    memcpy(pData, g_kitlEthState.deviceMAC, 3*sizeof(UINT16));
    pData += 3*sizeof(UINT16);
    *pSize += 3*sizeof(UINT16);
    memcpy(pData, &port, sizeof(UINT16));
    pData += sizeof(UINT16);
    *pSize += sizeof(UINT16);

    // We are done
    rc = TRUE;

cleanUp:
    KITL_RETAILMSG(ZONE_KITL_OAL, ("-KitlEthGetDevCfg(rc = %d)\r\n", rc));
    return rc;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -