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

📄 dhcpc.c

📁 Linux下DHCP Client的实现。
💻 C
📖 第 1 页 / 共 5 页
字号:
	uint8_t  *PktPos = NULL;
	ipaddr     htonlIpAddr=0;

	memset(&DhClientRequestPkt, 0, sizeof(DhClientRequestPkt));
	memset(caSendingPkt, 0, sizeof(caSendingPkt));
	DhClientRequestPkt.op = BOOTREQUEST;
	DhClientRequestPkt.htype = 1;
	DhClientRequestPkt.hlen = 6;
	DhClientRequestPkt.hops = 0;
	DhClientRequestPkt.secs = 0;
	DhClientRequestPkt.xid = htonl(pCurCtxtBlock->ulTransActionId);
	DhClientRequestPkt.ciaddr = pCurCtxtBlock->LeasedIpAddress;
	//memcpy(DhClientRequestPkt.chaddr, pCurCtxtBlock->aucHwAddress, 6);
	GetHwAddr(DhClientRequestPkt.chaddr, pCurCtxtBlock->cszIfName);
	memcpy(caSendingPkt, &DhClientRequestPkt, sizeof(DhClientRequestPkt));
	index = sizeof(DhClientRequestPkt);
	PktPos = caSendingPkt + index;
	memcpy(PktPos, DHCP_OPTIONS_COOKIE, 4);
	PktPos += 4;
	*PktPos++ = DHCP_MESSAGE_TYPE;
	*PktPos++ = DHCP_MESSAGE_OPTION_LEN;
	*PktPos++ = DHCPRELEASE;
	index += 7;
	uiLen = index;

	DHCPCFunctionInfo.FillOptions(pCurCtxtBlock->cszIfName, caSendingPkt, &uiLen, DHCPRELEASE);
	PktPos += (uiLen-index);
	index = uiLen;
	*PktPos++ = DHO_DHCP_SERVER_IDENTIFIER;
	*PktPos++ = sizeof(ipaddr);
	index += 2; 
	htonlIpAddr =  htonl(pCurCtxtBlock->DHCPServerIpAddr);	
	memcpy(PktPos, &htonlIpAddr, sizeof(ipaddr));
	PktPos += sizeof(ipaddr);
	index += sizeof(ipaddr);

	*PktPos = END_OPTION;
	index += 1;
	printf("*************************Send DHCP Release*************************\n");
	if (DHCPCFunctionInfo.SendPacket(pCurCtxtBlock->cszIfName, 
						caSendingPkt,
						index,
						htonl(pCurCtxtBlock->LeasedIpAddress),
						pCurCtxtBlock->DHCPServerIpAddr)<0)
	{
		printf("Sending Release pkt error\n");
		return FALSE;
	}
	return TRUE;
}

int DHCPClientSendDHCPRequest(DHCPClientBlock_t *pCurCtxtBlock)
{
	uint8_t caSendingPkt[1024];
	uint32_t ulTotLen = 0, iRet = 0;
	uint32_t t;
	time((time_t *)&t);
	memset(caSendingPkt, 0, sizeof(caSendingPkt));
	memset(&DhClientRequestPkt, 0, sizeof(struct dhcp_packet));
	GetHwAddr(pCurCtxtBlock->aucHwAddress, pCurCtxtBlock->cszIfName);

	DhClientRequestPkt.op = BOOTREQUEST;
	DhClientRequestPkt.htype = ETHERNET_HW_TYPE;
	DhClientRequestPkt.hlen = ETHERNET_HWADDR_LEN;
	DhClientRequestPkt.xid = pCurCtxtBlock->ulTransActionId;
	DhClientRequestPkt.secs = t;
	memcpy(DhClientRequestPkt.chaddr, pCurCtxtBlock->aucHwAddress, ETHERNET_HWADDR_LEN);

	switch (pCurCtxtBlock->CurrentState)
	{
	case DHCP_CLIENT_SELECT:
	case DHCP_CLIENT_REQUEST:
		DhClientRequestPkt.flags = htons(DhClientRequestPkt.flags | DHCP_CLIENT_BROADCAST);		
		break;
	case DHCP_CLIENT_RENEW:
		//DhClientRequestPkt.ciaddr = pCurCtxtBlock->LeasedIpAddress; /*xhema */
		DhClientRequestPkt.flags = htons(DhClientRequestPkt.flags | DHCP_CLIENT_BROADCAST);		
		DhClientRequestPkt.ciaddr = 0;
		break;
	case DHCP_CLIENT_REBIND:
		DhClientRequestPkt.flags = htons(DhClientRequestPkt.flags | DHCP_CLIENT_BROADCAST);
		DhClientRequestPkt.ciaddr = htonl(pCurCtxtBlock->LeasedIpAddress);
		break;
	default:
		break;
	}
	memcpy(caSendingPkt, &DhClientRequestPkt, sizeof(DhClientRequestPkt));
	ulTotLen += sizeof(DhClientRequestPkt);

	DHCPCAddOptionsToPkt(caSendingPkt, pCurCtxtBlock, &ulTotLen, DHCPREQUEST);
	//printf("========Sending Request Server ip = %d\n", pCurCtxtBlock->DHCPServerIpAddr);
	//judge
	if (pCurCtxtBlock->CurrentState == DHCP_CLIENT_RENEW)
	{
		//Lease time is over half (续租)
		//printf("renewing server ip = %d\n", pCurCtxtBlock->DHCPServerIpAddr);
		DHCPCIpAddressInfo.ulServerIpAddress = BROADCAST_IP_ADDRESS; 
		//DHCPCIpAddressInfo.ulServerIpAddress = pCurCtxtBlock->DHCPServerIpAddr;/*xhema*/
		iRet = DHCPCFunctionInfo.SendPacket(pCurCtxtBlock->cszIfName, (uint8_t *)caSendingPkt,
				ulTotLen, htonl(DhClientRequestPkt.ciaddr), DHCPCIpAddressInfo.ulServerIpAddress);
		if (iRet<0)
		{
			printf("send request pkt error\n");
			return FALSE;
		}
	}
	else
	{
		DHCPCIpAddressInfo.ulServerIpAddress = BROADCAST_IP_ADDRESS;
		DhClientRequestPkt.ciaddr = ntohl(DhClientRequestPkt.ciaddr);
		
		iRet = DHCPCFunctionInfo.SendPacket(
			pCurCtxtBlock->cszIfName, 
			(uint8_t *)caSendingPkt,
			ulTotLen, 
			DhClientRequestPkt.ciaddr, 
			DHCPCIpAddressInfo.ulServerIpAddress);
		if (iRet<0)
		{
			printf("send request pkt error\n");
			return FALSE;
		}
	}

	return TRUE;
}

int DHCPClientReadPort68Message(void)
{
	int n;
	uint32_t ulLeasedTime = 0, ulRenewTmOut=0,ulRebindTmOut = 0;
	ipaddr DHCPServerIpAddr=0, addr1, addr2;
	uint8_t   DhcpMessageType = 0;
	uint8_t pReplyPkt[1024],Buff[1024], hwaddr[6],desthwaddr[6];
	DhcpcIPSetting_t	 ConfigStruct = {0};
	DHCPClientBlock_t *pCurBlock = NULL;
	ArpReplyType_t ArpReply;
	struct dhcp_packet *pkt = NULL;
	ipaddr AddressArr[10];
	int AddressLen = 0;
	struct sockaddr_ll from;
	int iFromLen = sizeof(from);
	int ulIPHdrLen /*,iUdpLen*/ ;
	int iInterfaceIndex = -1;
	char szInterfaceName[16] = {0};
	static uint32_t ulAckedID;

	memset(pReplyPkt, 0, sizeof(pReplyPkt));

	n = recvfrom(s_iDCSocket, Buff, 1024, 0, 
			(struct sockaddr *)&from, &iFromLen);
	Buff[n] = '\0';
	ulIPHdrLen = ((Buff[0] & 0x0f) << 2);
	if ((Buff[9]!=17) ||
        (IGW_BUFGET16(Buff+ulIPHdrLen+0) != 67)||
         (IGW_BUFGET16(Buff+ulIPHdrLen+2) != 68))
	{
		//printf("Not a DHCP packet!\n");
		return TRUE;
	}

	memcpy(pReplyPkt, Buff+ulIPHdrLen+8, n-ulIPHdrLen-8);
	//printf("port 68 have message\n");
	pkt = (struct dhcp_packet *)pReplyPkt;
	if (memcmp(&pReplyPkt[DHCP_FIXED_NON_UDP], DHCP_OPTIONS_COOKIE, 4) != 0)
	{
		printf("Magic cookie is not match\n");
		return TRUE;
	}

	//printf("Magic cookie is match and received card index = %d\n", 
	//	from.sll_ifindex);
	//在链表中判断此接口是否已经分配,如果没有则分配并加入到链表中。如果已经分配过
	//则判断链表中接口是否处于Active状态,如果没有处于Active,则判断系统中此接口卡
	//的状态,如果可用则将链表中接口卡的Active=TRUE,否则Active=FALSE
	iInterfaceIndex = from.sll_ifindex;
	if (FALSE == getIfNamebyIndex(iInterfaceIndex, szInterfaceName))
	{
		printf("can't get interface name from index!\n");
		//send a error msg to config server
		return TRUE;
	}
	
	pCurBlock = DHCPClientIfaceIsAllocByIndex(
		iInterfaceIndex, 
		0,
		TRUE);

	if (NULL == pCurBlock)
	{
		//this card is not be alloc, that is to say: config server haven't set it to DHCP Client
		return TRUE;
	}
	else
	{
		//interface is in list 
		//judge if it is Active state
		if (FALSE == IsInterfaceUp(szInterfaceName))
		{
			//系统中此接口不处于活动状态
			g_pDHCPClientCurrent->bIfActive = FALSE;
			return TRUE;
		}
		//printf("point change to set to %s !!!!!!!!!!!!!!!!\n", szInterfaceName);
		g_pDHCPClientCurrent = pCurBlock;
	}
	

	if (DHCPClientGetOptionBuf(&pReplyPkt[DHCP_FIXED_NON_UDP+4], 
			(n-DHCP_FIXED_NON_UDP-4), &DhcpMessageType, &DHCPServerIpAddr, 
			&ulLeasedTime, &ulRenewTmOut, &ulRebindTmOut) == FALSE)
	{
		printf("get option buffer error\n");
		return TRUE;
	}

	//Get DNS
	DHCPClientGetDNS(&pReplyPkt[DHCP_FIXED_NON_UDP+4],
		(n-DHCP_FIXED_NON_UDP-4), AddressArr, &AddressLen);
	
	//fill in network mask, dns, router
	DHCPClientGetParam(&pReplyPkt[DHCP_FIXED_NON_UDP+4],
			(n-DHCP_FIXED_NON_UDP-4), &ConfigStruct);

	if ((DhcpMessageType != DHCPOFFER) &&
		(DhcpMessageType != DHCPACK) &&
		(DhcpMessageType != DHCPNAK))
	{
		printf("message type error\n");
		return FALSE;
	}

	switch (DhcpMessageType)
	{
	case DHCPOFFER://Send discover the recv offer pkt
		if (g_pDHCPClientCurrent->ulTransActionId == ntohl(pkt->xid))
		{
			printf("this off packet is me\n");			
			if (ulAckedID == g_pDHCPClientCurrent->ulTransActionId)
			{
				printf("this id have been the other server acked!{}{}{}{}{}\n");
				return TRUE;
			}
			g_pDHCPClientCurrent->pTimer->iSendNums = 0;
			g_pDHCPClientCurrent->pTimer->bStartWaitEvent = FALSE;
			printf("this packet's ulTransActionId is me\n");
			g_pDHCPClientCurrent->bRequestToConnect = FALSE;
			g_pDHCPClientCurrent->ulTransActionId = ntohl(pkt->xid);
			g_pDHCPClientCurrent->DHCPServerIpAddr = pkt->siaddr;
			
			g_pDHCPClientCurrent->LeasedIpAddress = pkt->yiaddr;
			memcpy(g_pDHCPClientCurrent->aucHwAddress, pkt->chaddr, 6);	
			if (FALSE == IsValidIP(g_pDHCPClientCurrent->LeasedIpAddress))
			{
				printf("**************false ip*****************\n");
				//Server given ip is not correct
				DHCPClientSendDHCPDecline(g_pDHCPClientCurrent);    //refuse this addr
				sleep(1);
				g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_INITIALIZED;
				TimerStart(g_pDHCPClientCurrent->pTimer,
					DEFAULT_DISCOVER_TIMEOUT, 
					WAIT_DISCOVER);
				g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_SELECT;			
				DHCPClientSendDHCPDiscover(g_pDHCPClientCurrent);
			}
			TimerStart(g_pDHCPClientCurrent->pTimer,
				DEFAULT_REQUEST_TIMEOUT, 
				WAIT_REQUEST);
			g_pDHCPClientCurrent->CurrentState= DHCP_CLIENT_REQUEST;
			if (FALSE == DHCPClientSendDHCPRequest(g_pDHCPClientCurrent))
			{
				printf("send request error\n");
			}
		}
		else
		{
			printf("this offer pkt isn't me!\n");
		}
		break;
	case DHCPACK:
	
#ifdef RUNONPC
		if (g_pDHCPClientCurrent->ulTransActionId != pkt->xid)
#else
		if (g_pDHCPClientCurrent->ulTransActionId != ntohl(pkt->xid))
#endif
		{
			printf("this ack isn't me!%d\n", ntohl(pkt->xid));
			return TRUE;
		}
		else
		{
			printf("this ack is me!%d\n", ntohl(pkt->xid));
		}
		ulAckedID = g_pDHCPClientCurrent->ulTransActionId;
		g_pDHCPClientCurrent->pTimer->iSendNums = 0;
		g_pDHCPClientCurrent->pTimer->fWillSend = FALSE;
		g_pDHCPClientCurrent->pTimer->iTimeOutNums = 0;
		g_pDHCPClientCurrent->pTimer->bStartWaitEvent = FALSE;

		g_pDHCPClientCurrent->bRequestToConnect = FALSE;

		if (g_pDHCPClientCurrent->CurrentState == DHCP_CLIENT_RENEW)
		{
			time((time_t *)&g_pDHCPClientCurrent->ulStartLeaseTime);
			g_pDHCPClientCurrent->pTimer->uiStartLeaseTime = g_pDHCPClientCurrent->ulStartLeaseTime;
			g_pDHCPClientCurrent->ulTransActionId = pkt->xid;
			g_pDHCPClientCurrent->DHCPServerIpAddr = DHCPServerIpAddr; //get option buff's result
			g_pDHCPClientCurrent->LeasedIpAddress = pkt->yiaddr;// inet_addr("192.168.12.29");
			memcpy(g_pDHCPClientCurrent->aucHwAddress, pkt->chaddr, 6);	//copy hw addr
			g_pDHCPClientCurrent->ulLeasedTime = ulLeasedTime;
			g_pDHCPClientCurrent->ulRemainingTime = ulLeasedTime;
			//set ip addr
			ConfigStruct.ulIP= pkt->yiaddr;
			
			memset(&g_pDHCPClientCurrent->sAllocedStruct, 0, 
				sizeof(g_pDHCPClientCurrent->sAllocedStruct));
			memcpy((void *)&g_pDHCPClientCurrent->sAllocedStruct,
				(void *)&ConfigStruct,
				sizeof(ConfigStruct));
			//xhema not set parma
			if (FALSE == DHCPCFunctionInfo.DHCPNetworkConfig(g_pDHCPClientCurrent->cszIfName , &ConfigStruct))
			{
				printf("RENEW: set network parma error\n");
				return FALSE;
			}
			//retry set DNS
			/*if (FALSE == DHCPClientSystemDNSet(AddressArr, AddressLen))
			{
				printf("set dns error\n");
				return FALSE;
			}*/
			g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_BOUND;	
			g_pDHCPClientCurrent->pTimer->bStartWaitEvent = FALSE;
			g_pDHCPClientCurrent->bUsed = TRUE;
			time((time_t *)&g_pDHCPClientCurrent->ulLeaveArpSendTime);
		}
		else
		{			
			GetHwAddr(hwaddr, g_pDHCPClientCurrent->cszIfName);
			memset(desthwaddr, 0, 6);
			addr1 = inet_addr("127.0.0.1");
			addr2 = pkt->yiaddr;
			g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_ARP_AWAIT;
			ArpReply = DHCPClientSendArp(g_pDHCPClientCurrent->cszIfName, hwaddr, desthwaddr, 
				addr1, addr2);
			if (ArpReply == ARP_HAVE_SAME_ADDR)
			{
				printf("In network a machine hava the same addr\n");
				//judge whether this interface is me
				if (0 == memcmp(g_pDHCPClientCurrent->aucHwAddress, desthwaddr, 6))
				{
					//this clash IP is myself, then continue to set it
					goto ARP;
				}
				DHCPClientSendDHCPDecline(g_pDHCPClientCurrent);    //refuse this addr
				sleep(1);
				g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_INITIALIZED;
				TimerStart(g_pDHCPClientCurrent->pTimer,
					DEFAULT_DISCOVER_TIMEOUT, 
					WAIT_DISCOVER);
				g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_SELECT;			
				DHCPClientSendDHCPDiscover(g_pDHCPClientCurrent);
				return TRUE;
			}
			if (ArpReply == ARP_SUCCESS)
			{
				//printf("IP ACK, i will set it to interface, Get Server IP = %d\n", DHCPServerIpAddr);
				ARP:
				time((time_t *)&g_pDHCPClientCurrent->ulStartLeaseTime);
				g_uiStartLeaseTime = g_pDHCPClientCurrent->ulStartLeaseTime;
				g_pDHCPClientCurrent->ulTransActionId = pkt->xid;
				g_pDHCPClientCurrent->DHCPServerIpAddr = DHCPServerIpAddr; //get option buff's result
				g_pDHCPClientCurrent->LeasedIpAddress = pkt->yiaddr;// inet_addr("192.168.12.29");
				memcpy(g_pDHCPClientCurrent->aucHwAddress, pkt->chaddr, 6);	//copy hw addr
				g_pDHCPClientCurrent->ulLeasedTime = ulLeasedTime;
				g_pDHCPClientCurrent->ulRemainingTime = ulLeasedTime;
				//set ip addr				
				ConfigStruct.ulIP= pkt->yiaddr;
				
				memset(&g_pDHCPClientCurrent->sAllocedStruct, 0, 
					sizeof(g_pDHCPClientCurrent->sAllocedStruct));
				memcpy((void *)&g_pDHCPClientCurrent->sAllocedStruct,
					(void *)&ConfigStruct,
					sizeof(ConfigStruct));
				if (FALSE == DHCPCFunctionInfo.DHCPNetworkConfig(g_pDHCPClientCurrent->cszIfName, &ConfigStruct))
				{
					printf("ARP: set network parma error\n");
					return FALSE;
				}
				//retry set DNS
				/*if (FALSE == DHCPClientSystemDNSet(AddressArr, AddressLen))
				{
					printf("set dns error\n");
					return FALSE;
				}*/

				g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_BOUND;	
				g_pDHCPClientCurrent->pTimer->bStartWaitEvent = FALSE;
				g_pDHCPClientCurrent->bUsed = TRUE;
				time((time_t *)&g_pDHCPClientCurrent->ulLeaveArpSendTime);
			}
		}
		break;
	case DHCPNAK:
		if (g_pDHCPClientCurrent->ulTransActionId != ntohl(pkt->xid))
		{
			printf("this nak isn't me\n");
			return TRUE;
		}
		if (ulAckedID == g_pDHCPClientCurrent->ulTransActionId)
		{
			printf("this id have been the other server acked!{}{}{}{}{}\n");
			return TRUE;
		}
		g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_INITIALIZED;
		sleep(1);	//sleep 1 second
		TimerStart(g_pDHCPClientCurrent->pTimer,
			DEFAULT_DISCOVER_TIMEOUT, 
			WAIT_DISCOVER);
		g_pDHCPClientCurrent->CurrentState = DHCP_CLIENT_SELECT;
		DHCPClientSendDHCPDiscover(g_pDHCPClientCurrent);
		break;
	default:
		break;
	}

	return TRUE;
}
//////////////////////////////////////////////////////////////
int DhcpMonitorStartup(void)
{
	int opt = 1, len = sizeof(opt);
	bzero(&s_DhcpServerAddr, sizeof(s_DhcpServerAddr));
	s_DhcpServerAddr.sin_family = AF_INET;
	s_DhcpServerAddr.sin_port = htons(DHCP_CLIENT_CONFIG_PORT);
	//s_DhcpServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	//s_DhcpServerAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	s_DhcpServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	s_iConfigServerSocket = socket(AF_INET, SOCK_DGRAM, 0);	
	//if socket bind a port, when this socket close or the process is exit. this port
	//will be the bind state in a while, but the next source will solve the problem
	setsockopt(s_iConfigServerSocket, SOL_SOCKET, SO_REUSEADDR, &opt, len);

	if (INVALID_SOCKET == s_iConfigServerSocket)
	{
		perror("Create Socket error!");
		return FALSE;
	}

	if (-1 == bind(s_iConfigServerSocket, (struct sockaddr *)&s_DhcpServerAddr,
		sizeof(struct sockaddr_in)))
	{
		perror("bind error!");
		return FALSE;
	}

	return TRUE;
}

#define CONFIG_MAXLEN 255
static uint32_t s_ConfigServerRequest[CONFIG_MAXLEN/sizeof(uint32_t)] = {0};
void ClientMonitor(void)
{
	uint32_t count;
	DHCPClientBlock_t          	 *sReturnStruct;
	int32_t iLen;
	int32_t iFdResult = 0, iFdsChecked = 0;
	int ii = 0;		
	time((time_t *)&CurrentTime);	//get current time
	DHCPClientTimerProc();		//find timeout or the other event

	DHCPClientPo

⌨️ 快捷键说明

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