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

📄 dhcp.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
	} else	// if (Sock)
		Status = GetLastError();

	if (DHCP_SUCCESS == Status)
		pInfo->Socket = Sock;

	DEBUGMSG(ZONE_INIT, (TEXT("-DhcpInitSock: pInfo 0x%X/0x%X Ret: %d\r\n"),
			pInfo, pInfo->Socket, Status));

	return Status;

}	// InitSocket()


//
// Function to call ARP's SetDHCPNTE - caller must have pDhcp->Lock
//
BOOL
SetDHCPNTE(
    DhcpInfo * pDhcp
    )
{
	BOOL	RetStatus = FALSE;

	if (0 == (pDhcp->SFlags & DHCPSTATE_DHCPNTE_SET)) {
		RetStatus = (*pfnSetDHCPNTE)(pDhcp->NteContext, NULL, NULL, NULL);
		if (RetStatus)
			pDhcp->SFlags |= DHCPSTATE_DHCPNTE_SET;
	}

	return RetStatus;
}


BOOL
ClearDHCPNTE(
    DhcpInfo * pDhcp
    )
{
	BOOL	RetStatus = FALSE;

	if (pDhcp->SFlags & DHCPSTATE_DHCPNTE_SET) {
		// even if this fails we're going to assume that we no longer have
		// the dhcpnte set
		pDhcp->SFlags &= ~DHCPSTATE_DHCPNTE_SET;
	    RetStatus = (*pfnSetDHCPNTE)(0x1fff, NULL, NULL, NULL);
	}

	return RetStatus;
}


void ProcessT2(DhcpInfo *pDhcp) {
	STATUS		Status = DHCP_SUCCESS;
	DhcpPkt		Pkt;
	int			cPkt;
	FILETIME	CurTime;
	int			fStatus;
	DhcpInfo	**ppDhcp;

	DEBUGMSG(ZONE_TIMER, (TEXT("+ProcessT2: pDhcp 0x%X\r\n"), pDhcp));	
	
	if (*_FindDhcp(pDhcp, NULL)) {
		CTEFreeLock(&v_GlobalListLock, 0);
		pDhcp->SFlags |= DHCPSTATE_T2_EXPIRE;

		if (DHCP_SUCCESS == (Status = DhcpInitSock(pDhcp, pDhcp->IPAddr))) {

			BuildDhcpPkt(pDhcp, &Pkt, DHCPREQUEST, (NEW_PKT_FL), pDhcp->ReqOptions, &cPkt);

            fStatus = SetDHCPNTE(pDhcp);
            GetCurrentFT(&CurTime);
            DEBUGMSG(ZONE_TIMER, (TEXT("\tProcess T2: CurTime: %x %x\r\n"),
                CurTime.dwHighDateTime, CurTime.dwLowDateTime));
            
            if (fStatus)
                Status = SendDhcpPkt(pDhcp, &Pkt, cPkt, DHCPACK, 
                    (ONCE_FL | BCAST_FL));
            else
                Status = DHCP_NOCARD;

            if (Status == DHCP_SUCCESS) {
                pDhcp->SFlags &= ~(DHCPSTATE_T2_EXPIRE | DHCPSTATE_T1_EXPIRE);
                memcpy(&pDhcp->LeaseObtained, &CurTime, sizeof(CurTime));
                SetDhcpConfig(pDhcp);
                CalcT1Time(pDhcp);

            } else if (Status == DHCP_NACK) {
                DEBUGMSG(ZONE_WARN, 
                    (TEXT("\t!ProcessT2: Take Net Down\r\n")));
                TakeNetDown(pDhcp, TRUE, TRUE);
                ClearDHCPNTE(pDhcp);
		        pDhcp->SFlags &= ~(DHCPSTATE_T2_EXPIRE | DHCPSTATE_T1_EXPIRE);
	            CloseDhcpSocket(pDhcp);
				CTEFreeLock(&pDhcp->Lock, 0);

				if (*(ppDhcp = _FindDhcp(pDhcp, NULL))) {
					*ppDhcp = pDhcp->pNext;

//					CallNetMsgBox(NULL, NMB_FL_EXCLAIM | NMB_FL_OK | NMB_FL_TOPMOST,
//						NETUI_GETNETSTR_LEASE_EXPIRED);

	                PutInWorkerQ(pDhcp);
	                CTEFreeLock(&pDhcp->Lock, 0);
				}
                CTEFreeLock(&v_GlobalListLock, 0);

                return;
            } else {
                CalcMidwayTime(pDhcp, pDhcp->Lease, (CTEEventRtn)ProcessT2, 
                    (CTEEventRtn)ProcessExpire);
            }
            if (fStatus)
                ClearDHCPNTE(pDhcp);
			CloseDhcpSocket(pDhcp);

		} else {	// (DHCP_SUCCESS == DhcpInitSock())
			DEBUGMSG(ZONE_WARN, 
				(TEXT("\t!ProcessT2: DhcpInitSock failed %d!!\r\n"),
				Status));
			CalcMidwayTime(pDhcp, pDhcp->Lease, (CTEEventRtn)ProcessT2, 
				(CTEEventRtn)ProcessExpire);
		}
		CTEFreeLock(&pDhcp->Lock, 0);
	} else	// if (*_FindDhcp())
		CTEFreeLock(&v_GlobalListLock, 0);

	DEBUGMSG(ZONE_TIMER, (TEXT("-ProcessT2: pDhcp 0x%X\r\n"),
			pDhcp));	
}	// ProcessT2()


void ProcessT1(DhcpInfo *pDhcp) {
	STATUS		Status = DHCP_SUCCESS;
	DhcpPkt		Pkt;
	int			cPkt;
	FILETIME	CurTime;
	int			fStatus;
	DhcpInfo	**ppDhcp;

	DEBUGMSG(ZONE_TIMER, (TEXT("+ProcessT1: pDhcp 0x%X\r\n"), pDhcp));	

	if (*_FindDhcp(pDhcp, NULL)) {
		CTEFreeLock(&v_GlobalListLock, 0);
		pDhcp->SFlags |= DHCPSTATE_T1_EXPIRE;
		if (DHCP_SUCCESS == (Status = DhcpInitSock(pDhcp, pDhcp->IPAddr))) {

			BuildDhcpPkt(pDhcp, &Pkt, DHCPREQUEST, (NEW_PKT_FL), pDhcp->ReqOptions, &cPkt);

            fStatus = SetDHCPNTE(pDhcp);
            GetCurrentFT(&CurTime);

            DEBUGMSG(ZONE_TIMER, (TEXT("\tProcess T1: CurTime: %x %x\r\n"),
                CurTime.dwHighDateTime, CurTime.dwLowDateTime));

            if (fStatus)
                Status = SendDhcpPkt(pDhcp, &Pkt, cPkt, DHCPACK, ONCE_FL);
            else
                Status = DHCP_NOCARD;

            if (Status == DHCP_SUCCESS) {
                pDhcp->SFlags &= ~(DHCPSTATE_T1_EXPIRE);
                memcpy(&pDhcp->LeaseObtained, &CurTime, sizeof(CurTime));
                SetDhcpConfig(pDhcp);
                CalcT1Time(pDhcp);

            } else if (Status == DHCP_NACK) {
                // Take Net Down !!!
                DEBUGMSG(ZONE_WARN, 
                    (TEXT("\t!ProcessT1: Take Net Down\r\n")));
                TakeNetDown(pDhcp, TRUE, TRUE);
				ClearDHCPNTE(pDhcp);
				pDhcp->SFlags &= ~(DHCPSTATE_T1_EXPIRE);
				CloseDhcpSocket(pDhcp);
				CTEFreeLock(&pDhcp->Lock, 0);

				if (*(ppDhcp = _FindDhcp(pDhcp, NULL))) {
					*ppDhcp = pDhcp->pNext;

	//					CallNetMsgBox(NULL, NMB_FL_EXCLAIM | NMB_FL_OK | NMB_FL_TOPMOST,
	//						NETUI_GETNETSTR_LEASE_EXPIRED);
					PutInWorkerQ(pDhcp);
					CTEFreeLock(&pDhcp->Lock, 0);
				}
                CTEFreeLock(&v_GlobalListLock, 0);
                return;
            } else {
                CalcMidwayTime(pDhcp, pDhcp->T2, (CTEEventRtn)ProcessT1, 
                    (CTEEventRtn)ProcessT2);
            }
            if (fStatus)
                ClearDHCPNTE(pDhcp);
			CloseDhcpSocket(pDhcp);

		} else {	// if (DHCP_SUCCESS == DhcpInitSock)
			DEBUGMSG(ZONE_WARN, 
				(TEXT("\t!ProcessT1: DhcpInitSock failed %d!!\r\n"),
				Status));
			CalcMidwayTime(pDhcp, pDhcp->T2, (CTEEventRtn)ProcessT1, 
				(CTEEventRtn)ProcessT2);
		}
		CTEFreeLock(&pDhcp->Lock, 0);
	} else	// if (FindDhcp())
		CTEFreeLock(&v_GlobalListLock, 0);

	DEBUGMSG(ZONE_TIMER, (TEXT("-ProcessT1: pDhcp 0x%X\r\n"),
			pDhcp));	
}	// ProcessT1()

#ifdef UNDER_CE
// Handles by which to notify applications of changes to IP data structures.
HANDLE	g_hAddrChangeEvent;

void
NotifyXxxChange(HANDLE hEvent)
//
// Pulse the event to let applications know a change has occurred
//
{
	if (hEvent)
	{
				PulseEvent(hEvent);
	}
}
#endif //UNDER_CE

//
// PutNetUp - Cause TCP/IP to use DHCP negotiated IP address for this net.
// The TCP/IP stack will call our ARPResult function if there is an IP address conflict.
// ARPResult sets the ARPEvent to indicate it was called.
//
// Return: DHCP_* error code from comm\inc\dhcp.h
//
STATUS PutNetUp(DhcpInfo *pDhcp) {
    int i, j;

    pDhcp->ARPResult = ERROR_SUCCESS;   // assume no IP address collision
    ResetEvent(pDhcp->ARPEvent);
    i = (*pfnIPSetNTEAddr)((ushort)pDhcp->NteContext, NULL, 
                           pDhcp->IPAddr, pDhcp->SubnetMask, pDhcp->Gateway);
    if (i == IP_PENDING)
        WaitForSingleObject(pDhcp->ARPEvent, ARP_RESPONSE_WAIT);
    else if (i != IP_SUCCESS) {
        DEBUGMSG(ZONE_WARN, (L"DHCP:PutNetUp - IPSetNTEAddr failed!\n"));
        return (i == IP_DUPLICATE_ADDRESS) ? DHCP_COLLISION : DHCP_FAILURE;
    }
    if (ERROR_SUCCESS == pDhcp->ARPResult) {
        // no IP address collision, proceed
        i = j = 0;
    	if (pDhcp->DNS[0]) {
            i++;
            if (pDhcp->DNS[1]) {
                i++;
            }
    	}

    	if (pDhcp->WinsServer[0]) {
            j++;
            if (pDhcp->WinsServer[1]) {
                j++;
            }
    	}
    	CallAfd(AddInterface)(pDhcp->Name, pDhcp->Nte, pDhcp->NteContext, 0, pDhcp->IPAddr, 
    		pDhcp->SubnetMask, i, pDhcp->DNS, j, pDhcp->WinsServer);	 

        NotifyXxxChange(g_hAddrChangeEvent);

        return DHCP_SUCCESS;
	} else {
        DEBUGMSG(ZONE_WARN, (L"DHCP:PutNetUp - ARPResult == %d, assuming IP addr collision\n", pDhcp->ARPResult));
        return DHCP_COLLISION;
    }
}	// PutNetUp()


STATUS DhcpSendDown(DhcpInfo *pDhcp, DhcpPkt *pPkt, int cPkt, int DestIP);


void DhcpDecline(DhcpInfo * pDhcp, DhcpPkt *pPkt) {
    int cPkt;

    BuildDhcpPkt(pDhcp, pPkt, DHCPDECLINE, RIP_PKT_FL|NEW_PKT_FL, NULL, &cPkt);
    DhcpSendDown(pDhcp, pPkt, cPkt, INADDR_BROADCAST);

    // AFD info not added at this point
    TakeNetDown(pDhcp, TRUE, FALSE);  
}


BOOL CanUseCachedLease(DhcpInfo * pDhcp) {
	FILETIME	BeginTime, EndTime;

    // we only try to use our old lease if we're not in T2 stage!
    EndTime.dwHighDateTime = 0;
    EndTime.dwLowDateTime = pDhcp->T2;
    mul64_32_64(&EndTime, TEN_M, &EndTime);
    add64_64_64(&pDhcp->LeaseObtained, &EndTime, &EndTime);				

    GetCurrentFT(&BeginTime);
    if (CompareFileTime(&EndTime, &BeginTime) >= 0) {
        return TRUE;
    }

    return FALSE;
}   // CanUseCachedLease


STATUS GetParams(DhcpInfo *pDhcp) {
	STATUS		Status = DHCP_SUCCESS;
	DhcpPkt		Pkt;
	int			cPkt, fDiscover, Flags, fDone;
	FILETIME	BeginTime;
	uint		cRetry, cDelay;

	DEBUGMSG(ZONE_INIT, (TEXT("+GetParams: pDhcp 0x%X/0x%X\n"),
			pDhcp, pDhcp->Socket));

	cRetry = fDone = 0;
	pDhcp->SFlags &= ~(DHCPSTATE_T1_EXPIRE | DHCPSTATE_T2_EXPIRE | 
		DHCPSTATE_LEASE_EXPIRE | DHCPSTATE_SAW_DHCP_SRV);
		
	GetDhcpConfig(pDhcp);

	if (pDhcp->Flags & DHCP_ENABLED_FL) {

        // If the IP address is currently auto cfg and the user has requested "ipconfig /renew"
        // then stop the 5 minute discover timer and force a discover to happen 
        if (pDhcp->SFlags & DHCPSTATE_AUTO_CFG_IP) {
            CTEStopFTimer(&pDhcp->Timer);
			pDhcp->SFlags &= ~DHCPSTATE_AUTO_CFG_IP;
            pDhcp->IPAddr = 0;  // force a discover
        }

		for ( ; ! fDone && cRetry <= pDhcp->cMaxRetry; cRetry++) {
			cDelay = (GetTickCount() % pDhcp->InitDelay);
			Sleep(cDelay);
			
			if (SetDHCPNTE(pDhcp)) {
				Status = DHCP_SUCCESS;
				GetCurrentFT(&BeginTime);

                fDiscover = (!pDhcp->IPAddr) || (pDhcp->Flags & OPTION_CHANGE_FL);

				if (fDiscover) {	// if no prev IP or lease exp. or option change
					pDhcp->IPAddr = 0;
					pDhcp->Flags &= ~OPTION_CHANGE_FL;
					BuildDhcpPkt(pDhcp, &Pkt, DHCPDISCOVER, (NEW_PKT_FL), pDhcp->ReqOptions, &cPkt);

					Status = SendDhcpPkt(pDhcp, &Pkt, cPkt, DHCPOFFER, 
						BCAST_FL | DFT_LOOP_FL);
				}

				if (DHCP_SUCCESS == Status) {
					Flags = RIP_PKT_FL;	// request IP addr must be filled in
					if (fDiscover) 
						Flags |= SID_PKT_FL;
					else {
						Flags |= NEW_PKT_FL;
					}
					BuildDhcpPkt(pDhcp, &Pkt, DHCPREQUEST, Flags, pDhcp->ReqOptions, &cPkt);
					Status = SendDhcpPkt(pDhcp, &Pkt, cPkt, DHCPACK, 
						BCAST_FL | DFT_LOOP_FL);
				}

				ClearDHCPNTE(pDhcp);


                if ((pDhcp->Flags & AUTO_IP_ENABLED_FL) &&
				   (!(pDhcp->SFlags & DHCPSTATE_SAW_DHCP_SRV))) {
                    // No response from a DHCP server, so try AutoIP.
                    DEBUGMSG(ZONE_AUTOIP, (TEXT("DHCP:GetParams - No response from DHCP server, trying AutoIP\n")));
                    Status = AutoIP(pDhcp);
                }

				if (DHCP_SUCCESS == Status) {
					memcpy(&pDhcp->LeaseObtained, &BeginTime, sizeof(BeginTime));
					SetDhcpConfig(pDhcp);
					fDone = TRUE;

                    // We need to PutNetUp() here only when we've negotiated a lease with a DHCP server.
                    // If we didn't auto configure and didn't see a DHCP server, then AutoIP() was able to
                    // ping the default gateway so it decided to use the cached lease already.
					if ((!(pDhcp->SFlags & DHCPSTATE_AUTO_CFG_IP)) &&
                        (pDhcp->SFlags & DHCPSTATE_SAW_DHCP_SRV)) {
						Status = PutNetUp(pDhcp); 
						switch (Status) {
						case DHCP_SUCCESS:
							CalcT1Time(pDhcp);
							break;

						case DHCP_COLLISION:
							DhcpDecline(pDhcp, &Pkt);
							// fall through

						default:
							fDone = FALSE;
							break;
						}
					}

				} else if (DHCP_NACK == Status) {
					pDhcp->IPAddr = 0;

				} else if (!fDiscover) {
					// didn't get a NAK see if we can use our old lease
					if (pDhcp->IPAddr) {
                        if (CanUseCachedLease(pDhcp)) {
                            DEBUGMSG(ZONE_WARN, 
                                (TEXT("\tGetParams: using cached DHCP lease\r\n")));                    
                            CallNetMsgBox(NULL, NMB_FL_OK, NETUI_GETNETSTR_CACHED_LEASE);

							Status = PutNetUp(pDhcp);
							switch (Status) {
							case DHCP_SUCCESS:
								// even if we're already in T1 stage this should work
								// it just sets up a timer to call ProcessT1 right away
								// ProcessT1 should then do the right thing
								CalcT1Time(pDhcp);
								fDone = TRUE;
								break;

							case DHCP_COLLISION:
								DhcpDecline(pDhcp, &Pkt);
								// fall through

⌨️ 快捷键说明

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