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

📄 dhcp.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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:   dhcp.c

Abstract:  
    This contains the DHCP protocol IP address resolution
    routines for the ethernet debug system.
Functions:


Notes: 

--*/

#include <windows.h>
#include <Kitl.h>
#include <halether.h>
#include "Kitlethp.h"
#include "dhcp.h"

#define DHCP_ACK_TIMEOUT   120         // 2 minutes
#define ARP_WAIT_TIMEOUT   120         // 2 minutes

// This is used to broadcast things to the DHCP servers
static EDBG_ADDR BroadCastAddr = { 0xFFFFFFFFUL, { 0xFFFF, 0xFFFF, 0xFFFF }, DHCP_SERVER_PORT };
static DWORD DHCPLeaseTime;
static DWORD dwXID;
static DWORD DHCPState = DHCP_BOUND;

static void RenewDHCP (LPVOID lpParam);
static void EdbgDHCPError (void);
static BOOL EdbgSendDHCPRenew (EDBG_ADDR *pMyAddr, DWORD *dwXID);
static BOOL SendGratuitousARP (EDBG_ADDR *pMyAddr);

// setup a timer callback to renew DHCP half way through our DHCP lease period
BOOL EdbgInitDHCP (EDBG_ADDR *pMyAddr, DWORD dwDHCPLeaseTime)
{
    static EDBG_ADDR MyAddr;
    // make a local copy, update port number
    memcpy (&MyAddr, pMyAddr, sizeof (EDBG_ADDR));
    MyAddr.wPort = DHCP_CLIENT_PORT;

    if (!(DHCPLeaseTime = dwDHCPLeaseTime)) {
        // use static IP, don't bother DHCP server, just ARP it every now and then
        DHCPLeaseTime = DEFAULT_DHCP_LEASE;
        DHCPState = DHCP_ARPED;
    }

    // set timer to renew DHCP half way through the renew period
    KitlSetTimerCallback (DHCPLeaseTime >> 1, RenewDHCP, &MyAddr);
    return TRUE;
}

// function to handle ARP packets received
void HandleARPPacket (EDBG_ADDR *pMyAddr, LPBYTE pbFrame)
{
    EthernetFrameHeader *pFrameHeader;
    ARPPacketFormat *pARP;

    pARP = (ARPPacketFormat *) (pbFrame + sizeof(EthernetFrameHeader));

    // Check to see that they were requesting the ARP response from us
    if (pARP->dwDestIP != pMyAddr->dwIP)
        return;     // not for us

    // Make sure this is an ARP request
    switch (htons(pARP->wOperation)) {
    case 1: // ARP request
        break;

    case 2: 
        // ARP response -- we shared an IP address as others, FATAL
        // spin forever
        EdbgDHCPError ();
        return;

    case 3: // RARP request
    case 4: // RARP response
    default:
        // just ignore it
        return;
    }

    // Fill in destination and source MAC addresses and the ARP frame type
    pFrameHeader = (EthernetFrameHeader *) pbFrame;
    pFrameHeader->wDestMAC[0] = pARP->wSrcMAC[0];
    pFrameHeader->wDestMAC[1] = pARP->wSrcMAC[1];
    pFrameHeader->wDestMAC[2] = pARP->wSrcMAC[2];
    pFrameHeader->wSrcMAC[0] = pMyAddr->wMAC[0];
    pFrameHeader->wSrcMAC[1] = pMyAddr->wMAC[1];
    pFrameHeader->wSrcMAC[2] = pMyAddr->wMAC[2];
    pFrameHeader->wFrameType = htons(ARP_FRAME);

    // The field information comes from page 57 of TCP/IP Illustrated by W. Richard Stevens
    pARP->wHardwareType = htons(1);         // Specifies Ethernet
    pARP->wProtocolType = htons(IP_FRAME);  // Specifies that IP addresses are being mapped
    pARP->bHardwareAddrSize = 6;            // Ethernet MAC addresses are 6 bytes long
    pARP->bProtocolAddrSize = 4;            // IP addresses are 4 bytes long
    pARP->wOperation = htons(2);            // Specify an ARP reply

    // Fill in the destination information
    pARP->wDestMAC[0] = pARP->wSrcMAC[0];
    pARP->wDestMAC[1] = pARP->wSrcMAC[1];
    pARP->wDestMAC[2] = pARP->wSrcMAC[2];
    pARP->dwDestIP = pARP->dwSrcIP;
    // Fill in the source side information
    pARP->wSrcMAC[0] = pMyAddr->wMAC[0];
    pARP->wSrcMAC[1] = pMyAddr->wMAC[1];
    pARP->wSrcMAC[2] = pMyAddr->wMAC[2];
    pARP->dwSrcIP = pMyAddr->dwIP;

    KitlSendRawData (pbFrame, sizeof(EthernetFrameHeader) + sizeof(ARPPacketFormat));
}

BOOL HandleDHCPPacket (EDBG_ADDR *pMyAddr, UDPHeaderFormat *pUdpHdr)
{
    DHCPMsgFormat *pDHCPMsg = (DHCPMsgFormat *) ((LPBYTE) pUdpHdr + sizeof (UDPHeaderFormat));

    // check if this is a DHCP message
    if ((pUdpHdr->wDestPort != DHCP_CLIENT_PORT)
        || (pUdpHdr->wSrcPort != DHCP_SERVER_PORT))
        return FALSE;

    // ignore all DHCP messages if we're not renewing
    if (DHCPState != DHCP_RENEWING) {
        return TRUE;
    }

    // ignore messages not for our renewing request
    if (pDHCPMsg->dwXID != dwXID) {
        return TRUE;    
    }

    // If the server says to discard the offer, we're toast
    if (pDHCPMsg->bOptions[6] == DHCP_NAK) {
        EdbgDHCPError();    // doesn't return
        return TRUE;
    }

    // signal we've got an valid IP address if we got an ACK
    if (pDHCPMsg->bOptions[6] == DHCP_ACK) {
        LPBYTE pbParse = EdbgDHCPFindOption (DHCP_LEASE_TIME, pDHCPMsg);
        if (pbParse == NULL) {
            KITLOutputDebugString ("ProcessDHCP()::DHCP_REQUESTING::DHCPFindOption() Got DHCP_ACK without DHCP_LEASE_TIME\r\n");
            return TRUE;
        }
        DHCPState = DHCP_ACKED;
        DHCPLeaseTime = ((DWORD)(pbParse[5])) | (((DWORD)(pbParse[4])) <<  8)
              | (((DWORD)(pbParse[3])) << 16) | (((DWORD)(pbParse[2])) << 24);
        KITLOutputDebugString ("\r\nProcessDHCP()::DHCP IP Address Resolved as %s\r\n",
                            inet_ntoa(pMyAddr->dwIP));
        KITLOutputDebugString("Lease time: %d seconds\r\n",DHCPLeaseTime);

    }
    return TRUE;
}

//
// callback from timer to renew DHCP
//
static void RenewDHCP (LPVOID lpParam)
{
    EDBG_ADDR *pMyAddr = (EDBG_ADDR *) lpParam;

    switch (DHCPState) {
    // states for using DHCP
    case DHCP_BOUND:    // lease just expired, renew
        DHCPState = DHCP_RENEWING;
        // fall through
    case DHCP_RENEWING: // in the process of renewing
        EdbgSendDHCPRenew (pMyAddr, &dwXID);
        KitlSetTimerCallback (DHCP_ACK_TIMEOUT, RenewDHCP, pMyAddr);
        break;
    case DHCP_ACKED:    // got ack'd for our renewal
        DHCPState = DHCP_BOUND;
        // next renewal will be half way through our lease time
        KitlSetTimerCallback (DHCPLeaseTime >> 1, RenewDHCP, pMyAddr);
        break;

    // states for using static IP
    case DHCP_ARPED:
        DHCPState = DHCP_ARPING;
        // send Gratuitous ARP, hoping no one respond
        SendGratuitousARP (pMyAddr);
        KitlSetTimerCallback (ARP_WAIT_TIMEOUT, RenewDHCP, pMyAddr);
        break;
    case DHCP_ARPING:   // didn't received ARP response for gratituous ARP
        DHCPState = DHCP_ARPED;
        // next renewal will be half way through our lease time
        KitlSetTimerCallback (DHCPLeaseTime >> 1, RenewDHCP, pMyAddr);
        break;
    }
}

// This routine will look for a DHCP option in the field that starts at the
//  location that pbParse points too.  Note that all DHCP fields MUST end in
//  a DHCP_END option, so that this search won't run away.
static LPBYTE EdbgDHCPParseField (DHCPOptions DHCPOption, BYTE *pbParse) 
{
    while (*pbParse != DHCP_END) {
        if (*pbParse == DHCPOption)
            return pbParse;
        pbParse += *(pbParse + 1) + 2;
    } // for every option code in this field

    return NULL;

} // EdbgDHCPParseField



// This routine will parse through the DHCP message looking for the specified option.
//  Note that the options can extend beyond the Options field into the file and sname
//  fields.  The order is not arranged very well, so that the Options field doesn't
//  simply spill over into the others.  Further, there is a defined parsing order that
//  doesn't make much sense.  This is why this routine is so confusing.
static LPBYTE EdbgDHCPFindOption (DHCPOptions DHCPOption, DHCPMsgFormat *pDHCPMsg) 
{
    BYTE *pbParse;
    BYTE fUseSname = 0;
    BYTE fUseFile = 0;

    // First determine if the file or sname fields have been used to include addtional options.
    // If they have, a DHCP_OPTION_OVERLOAD will appear in the normal Options field
    // Don't forget to skip over Magic Cookie in Options field
    pbParse = EdbgDHCPParseField (DHCP_OPTION_OVERLOAD, pDHCPMsg->bOptions + 4);
    if (pbParse != NULL) {
        fUseFile = (*(pbParse + 2)) & 1;
        fUseSname = (*(pbParse + 2)) & 2;
    }

    // Now look for the option that we were called for, in the order specified by RFC1541
    // Don't forget to skip over Magic Cookie in Options field
    pbParse = EdbgDHCPParseField (DHCPOption, pDHCPMsg->bOptions + 4);
    if (pbParse != NULL)
        return pbParse;
    if (fUseFile) {
        pbParse = EdbgDHCPParseField (DHCPOption, pDHCPMsg->szFILE);
        if (pbParse != NULL)

⌨️ 快捷键说明

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