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

📄 dhcpc.c

📁 Linux下DHCP Client的实现。
💻 C
📖 第 1 页 / 共 5 页
字号:
			iTmpAddr = pCurCtxtBlock->DHCPServerIpAddr;
			memcpy((void *)PktPos, (void *)&iTmpAddr, sizeof(ipaddr));
			PktPos += sizeof(ipaddr);
			*ulTotLength += sizeof(ipaddr);
		}
	}
	//xhema 11.10
	if ((pCurCtxtBlock->CurrentState == DHCP_CLIENT_RENEW) ||
		(pCurCtxtBlock->CurrentState == DHCP_CLIENT_REQUEST))
	{
		if (pCurCtxtBlock->LeasedIpAddress>0)
		{
			*PktPos++ = DHO_DHCP_REQUESTED_ADDRESS;
			*PktPos++ = sizeof(ipaddr);
			*ulTotLength += 2;
#ifdef DEBUG_NAK_PKT
			iTmpAddr = 0;
#else
			iTmpAddr = pCurCtxtBlock->LeasedIpAddress;//htonl(pCurCtxtBlock->LeasedIpAddress);
#endif
			memcpy((void *)PktPos, (void *)&iTmpAddr, sizeof(ipaddr));
			PktPos += sizeof(ipaddr);
			*ulTotLength += sizeof(ipaddr);
		}
	}
	printf("Fill options in %s\n", pCurCtxtBlock->cszIfName);
	DHCPCFunctionInfo.FillOptions(pCurCtxtBlock->cszIfName, caSendingPkt, ulTotLength, ucDHCPMsgType);
}

void DHCPCFillOptions(
		const char *cszIfName, 
		uint8_t *pData, 
		uint32_t *ulDataLen, 
		uint8_t ucDHCPMsgType
	)
{
	uint8_t OptString[100];
	uint32_t iOptLen = 0;
	uint8_t *PktPos = pData + *ulDataLen;
	/*//host name	
	memset(OptString, 0, sizeof(OptString));
	GetHostName(OptString);
	printf("host name = %s\n", OptString);
	iOptLen = strlen(OptString);
	if (iOptLen > 0)
	{
		*PktPos++ = DHO_HOST_NAME;
		*PktPos++ = iOptLen;
		*ulDataLen += 2;
		memcpy(PktPos, OptString, iOptLen);
		*PktPos += iOptLen;
		*ulDataLen += iOptLen;
	}*/
	//client identifier
	memset(OptString, 0, sizeof(OptString));
	iOptLen = 0;
	*PktPos++ = DHO_DHCP_CLIENT_IDENTIFIER;
	*PktPos++ = 7;
	*ulDataLen += 2;
	*PktPos += 1;
	PktPos++;
	GetHwAddr(PktPos, cszIfName);
	PktPos += 6;
	*ulDataLen += 7;
#ifdef DEBUG_LEASE_TIME
	uint32_t uiLeaseTime = 0;
	/* get the lease time */
	DHCPClientGetLeaseTime(&uiLeaseTime);
	if (uiLeaseTime>0)
	{
		*PktPos++ = DHO_DHCP_LEASE_TIME;
		*PktPos++ = 4;//sizeof(ipaddr)
		*ulDataLen += 2;
		uiLeaseTime = htonl(uiLeaseTime);
		//g_DHCPClientBlock.ulLeasedTime = uiLeaseTime;
		memcpy(PktPos, &uiLeaseTime, sizeof(ipaddr));
		PktPos += 4;
		*ulDataLen += 4;
	}
#endif
	/* get client id 61 */
	if ((ucDHCPMsgType == DHCPDISCOVER) ||
		(ucDHCPMsgType == DHCPREQUEST))
	{
		*PktPos++ = DHO_DHCP_PARAMETER_REQUEST_LIST;
		*PktPos++ = 4;
		*PktPos++ = DHO_SUBNET_MASK;
		*PktPos++ = DHO_ROUTERS;
		*PktPos++ = DHO_DOMAIN_NAME_SERVERS;
		*PktPos++ = DHO_BROADCAST_ADDRESS;
		*ulDataLen += 6;
	}
	*PktPos++ = DHO_END;
	*ulDataLen += 1;
}

int DHCPClientGetDNS(
		uint8_t *pBuffer,
		int32_t iLength,
		ipaddr *addr,
		int *Len
	)
{
	uint8_t *ucStart;
	uint8_t *ucEnd = pBuffer + iLength;
	int iLen, iCode;
	int i = 0;

	for (ucStart=pBuffer; (*ucStart!=END_OPTION)&&(ucStart<ucEnd);)
	{
		iCode = ucStart[0];
		iLen = ucStart[1];
		if (iCode == DHO_PAD)
		{
			++ucStart;
			continue;
		}
		if ((ucStart+iLen+2)>ucEnd)
		{
			return FALSE;
		}
		switch (iCode)
		{
		case DHO_DOMAIN_NAME_SERVERS:
			for (i=0; i<iLen/sizeof(ipaddr); i++)
			{
				(*Len)++;
				memcpy(addr, &ucStart[2], sizeof(ipaddr));
				ucStart += sizeof(ipaddr);
				addr++;
			}
			break;
		default:
			break;
		}
		ucStart += (iLen +2);
	}
	return TRUE;
}

int DHCPClientGetParam(
		uint8_t	*pBuffer,
		int32_t		iLength,
		DhcpcIPSetting_t	 *ConfigStruct
	)
{
	uint8_t *ucStart;
	uint8_t *ucEnd = pBuffer + iLength;
	int iLen, iCode;

	for (ucStart=pBuffer; (*ucStart!=END_OPTION)&&(ucStart<ucEnd);)
	{
		iCode = ucStart[0];
		iLen = ucStart[1];
		if (iCode == DHO_PAD)
		{
			++ucStart;
			continue;
		}
		if ((ucStart+iLen+2)>ucEnd)
		{
			return FALSE;
		}
		switch (iCode)
		{
		case DHO_SUBNET_MASK:
			memcpy(&ConfigStruct->ulNetmask, &ucStart[2], IPADDR_LEN);
			break;
		case DHO_ROUTERS:
			memcpy(&ConfigStruct->ulGateway, &ucStart[2], IPADDR_LEN);
			//gateway only one
			/*if (iLen>IPADDR_LEN)
			{
				ucStart += IPADDR_LEN;
				memcpy(&ConfigStruct->ifGateway[1], &ucStart[2], IPADDR_LEN);
			}*/
			break;
		case DHO_DOMAIN_NAME_SERVERS:
			//DNS
			memcpy(&ConfigStruct->ulDNS[0], &ucStart[2], IPADDR_LEN);
			if (iLen>IPADDR_LEN)
			{
				ucStart += IPADDR_LEN;
				memcpy(&ConfigStruct->ulDNS[1], &ucStart[2], IPADDR_LEN);
			}
			break;
		default:
			break;
		}
		ucStart += (iLen +2);
	}
	return TRUE;
}

int DHCPClientGetOptionBuf(uint8_t   *pBuffer,
                        int32_t     iLength,
                        uint8_t   *DhcpMessageType,
                        ipaddr     *DHCPServerIpAddr,
                        uint32_t   *ulLeasedTime,
                        uint32_t   *ulRenewTmOut,
                        uint32_t   *ulRebindTmOut
                      ) 
{
	uint8_t *ucStart;
	uint8_t *ucEnd = pBuffer + iLength;
	int iLen, iCode;

	for (ucStart=pBuffer; (*ucStart!=END_OPTION)&&(ucStart<ucEnd);)
	{
		iCode = ucStart[0];
		iLen = ucStart[1];
		if (iCode == DHO_PAD)
		{
			++ucStart;
			continue;
		}
		if ((ucStart+iLen+2)>ucEnd)
		{
			return FALSE;
		}
		//printf("**in GetOptional buffer iCode = %d  iLength = %d, *ucStart=%c\n", iCode,iLength,*ucStart);
		switch (iCode)
		{			
		case DHO_DHCP_MESSAGE_TYPE:
			memcpy(DhcpMessageType, &ucStart[2], DHCP_MESSAGE_OPTION_LEN);
			break;
		case DHO_DHCP_LEASE_TIME:
			memcpy(ulLeasedTime, &ucStart[2], TIME_LEN);
			*ulLeasedTime = ntohl(*ulLeasedTime);
			//printf("********Get Leased Time: Leased time = %d\n", *ulLeasedTime);
			break;
		case DHO_DHCP_SERVER_IDENTIFIER:
			memcpy(DHCPServerIpAddr, &ucStart[2], IPADDR_LEN);
			*DHCPServerIpAddr = ntohl(*DHCPServerIpAddr);
			break;
		case DHO_DHCP_RENEWAL_TIME:
			memcpy(ulRenewTmOut, &ucStart[2], TIME_LEN);
			*ulRenewTmOut = ntohl(*ulRenewTmOut);
			break;
		case DHO_DHCP_REBINDING_TIME:
			memcpy(ulRebindTmOut, &ucStart[2], TIME_LEN);
			*ulRebindTmOut = ntohl(*ulRebindTmOut);
			break;
		default:
			break;
		}
		ucStart += (iLen +2);
	}
	return TRUE;
}


int32_t IGWCreateLpfSock (int8_t *cszIfName)
{
	int32_t LpfSockFd;
	struct sockaddr_ll to;

	memset(&to, 0, sizeof(to));

	/* Create an LPF socket. */
	//xhema if ((LpfSockFd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
	if ((LpfSockFd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
	{
		perror("Unable To Create the LPF Socket");
		return -1;
	}

	to.sll_ifindex = getIndexByIfName(cszIfName);
	to.sll_family = AF_PACKET;
	printf("Create LPF Socket Card index = %d, name =%s\n", to.sll_ifindex, cszIfName);
	if (bind (LpfSockFd, (struct sockaddr *)&to, sizeof(to))<0)
	{
		perror("Unable To Bind the LPF Socket");
		close(LpfSockFd);
		return -1;
	}
	return LpfSockFd;
}

void make_discover(struct dhcp_packet *pkt, DHCPClientBlock_t *pCurCtxtBlock)
{
	uint32_t t;
	time((time_t *)&t);
	srand(t);	

	memset(pkt, 0, sizeof(struct dhcp_packet));
	pkt->op = BOOTREQUEST;
	pkt->htype = 1;
	pkt->hlen = 6;
	pkt->hops = 0;
	pkt->xid = (uint32_t)rand();
	pkt->secs = t;
	pkt->flags = htons(BOOTP_BROADCAST);
	memset(&pkt->ciaddr, 0, sizeof(pkt->ciaddr));
	memset(&pkt->yiaddr, 0, sizeof(pkt->yiaddr));
	memset(&pkt->siaddr, 0, sizeof(pkt->siaddr));
	memset(&pkt->giaddr, 0, sizeof(pkt->giaddr));
	GetHwAddr(pkt->chaddr, pCurCtxtBlock->cszIfName);

	//g_DHCPClientBlock.ulTransActionId = htonl(pkt->xid);
	pCurCtxtBlock->ulTransActionId = htonl(pkt->xid);
}

//SendPacket
int DHCPClientSendPacket(
		int8_t *cszIfName, 
		uint8_t *data,
		uint32_t len, 
		ipaddr source, 
		ipaddr dest
	)
{
	return (ZCOM_IGWSendPacket(cszIfName, data, len, htonl(source), htonl(dest))<0?FALSE:TRUE);
}

int32_t ZCOM_IGWSendPacket(int8_t *cszIfName, uint8_t *data,
				uint32_t len, ipaddr source, ipaddr dest)
{
	int32_t sd, index = 0, LpfSd, result=0, i=1;
	uint8_t buff[1500];
	struct sockaddr sa;
	struct sockaddr_ll ll;
	struct ifreq ifr;
	struct hardware hfrom, hto;

	memset(buff, 0, sizeof(buff));
	memset(&ifr, 0, sizeof(ifr));
	memset(&sa, 0, sizeof(sa));
	memset(&hfrom, 0, sizeof(hfrom));
	memset(&hto, 0, sizeof(hto));
	memset(&ll, 0, sizeof(ll));

	sd = socket(AF_INET, SOCK_DGRAM, 0);

	GetHwAddr(hfrom.haddr, cszIfName);
	
	hfrom.htype = 1;
	hfrom.hlen = 6;

	strcpy(ifr.ifr_name, cszIfName);
	ioctl(sd, SIOCGIFFLAGS, &ifr);
	close(sd);
	if (dest> 0x0 && dest< BROADCAST_IP_ADDRESS)
	{
		hto.htype = 1;
		hto.hlen = 6;
		//memcpy(hto.haddr, g_DHCPClientBlock.serHwAddress, 6);
		//send arp packet
		while((result = DHCPClientSendArp(cszIfName,hfrom.haddr,hto.haddr,source,dest))<0 && i++<=3);
	}
	if (ARP_HAVE_SAME_ADDR == result)
	{
		IGWAssembleEthernetHeader(buff, &index, &hfrom, &hto);
	}
	else
	{
		IGWAssembleEthernetHeader(buff, &index, &hfrom, (struct hardware *)0);  //broadcast
	}
	/*switch (g_DHCPClientBlock.CurrentState)
	{
	case DHCP_CLIENT_RENEW:
		IGWAssembleEthernetHeader(buff, &index, &hfrom, &hto);  
		break;
	default:
		IGWAssembleEthernetHeader(buff, &index, &hfrom, (struct hardware *)0);  //broadcast
		break;
	}*/
	//IGWAssembleEthernetHeader(buff, &index, &hfrom, &hto);
	IGWAssembleUdpIpHeader(buff, &index, source, dest, BOOTP_PORT,
			data, len);
	memcpy(buff+index, data, len);
	memset(&sa, 0, sizeof(sa));
	sa.sa_family = AF_PACKET;
	ll.sll_family = AF_PACKET;
	ll.sll_ifindex = getIndexByIfName(cszIfName);
	printf("send packet index = %d\n", ll.sll_ifindex);
	strncpy(sa.sa_data, (uint8_t *)&ifr, sizeof(sa.sa_data));
	LpfSd = IGWCreateLpfSock(cszIfName);

	//xhema result = sendto(LpfSd, buff, index+len, 0, (struct sockaddr *)&sa, sizeof(sa));
	result = sendto(LpfSd, buff, index+len, 0, (struct sockaddr *)&ll, sizeof(ll));
	close(LpfSd);
	return result;
}

ArpReplyType_t DHCPClientSendArp(
		char *cszIfName, 
		uint8_t *shaddr, //source hardware addr
		uint8_t *thaddr, 
		ipaddr source, 
		ipaddr dest
	)
{
	struct arpheader arp,reparp;
	struct ifreq ifr;
	struct sockaddr sa;
	struct sockaddr_ll ll;
	uint8_t buff[1500];
	int index=0,sd,result,LpfSd,arptype,htype,op,ethsize,arpsize;
	struct ethhdr e,eh;
	struct pollfd pfd[1];//wait response

	memset(pfd, 0, sizeof(pfd));
	memset(buff, 0, sizeof(buff));
	memset(&arp, 0, sizeof(arp));
	memset(&reparp, 0, sizeof(reparp));
	memset(&ll, 0, sizeof(ll));

	sd = socket(AF_INET, SOCK_DGRAM, 0);
	strcpy(ifr.ifr_name, cszIfName);
	ioctl(sd, SIOCGIFFLAGS, &ifr);
	close(sd);

	//adding eth header
	memset(eh.h_dest, 0xff, 6);
	memcpy(eh.h_source, shaddr, 6);
	eh.h_proto = htons(0x0806);
	memcpy(buff, &eh, sizeof(eh));
	index += sizeof(eh);
	//adding arp header
	arp.ar_hrd = htons(ARPHRD_ETHER);
	arp.ar_pro = htons(0x0800);	//ip protocol
	arp.ar_hlen = 6;
	arp.ar_plen = 4;
	arp.ar_op = htons(ARPOP_REQUEST);
	memcpy(&arp.sha, shaddr, 6);
	memcpy(&arp.sip, &source, 4);
	memcpy(&arp.tip, &dest, 4);
	memcpy(&buff[index], &arp, sizeof(arp));
	index += sizeof(arp);
	arptype = htons(0x0806);
	htype = htons(ARPHRD_ETHER);
	op = htons(ARPOP_REPLY);
	ethsize = sizeof(e);
	arpsize = sizeof(arp);
	
	memset(&sa, 0, sizeof(sa));
	strncpy(sa.sa_data, (char *)&ifr, sizeof(sa.sa_data));
	ll.sll_family = AF_PACKET;
	ll.sll_ifindex = getIndexByIfName(cszIfName);
	if ((LpfSd=IGWCreateLpfSock(cszIfName))<0)
	{
		printf("send arp, create lpf socket error\n");
		return ARP_ERROR;
	}
	pfd[0].fd = LpfSd;
	pfd[0].events = POLLIN;
	//xhema if ((result=sendto(LpfSd, buff, index, 0, &sa, sizeof(sa)))<0)
	if ((result=sendto(LpfSd, buff, index, 0, (struct sockaddr *)&ll, sizeof(ll)))<0)
	{
		close(LpfSd);
		perror("send lpf socket error");
		return ARP_ERROR;
	}
	result = 0;
	while (TRUE)
	{
		//wait arp reply
		if (poll(pfd, 1, 1000)>0)
		{
			recvfrom(LpfSd, buff, 1500, 0, NULL, NULL);
			if (result++>25)
			{
				return ARP_SUCCESS;
				//printf("return successful\n");
				//break;
			}
			memcpy(&e, buff, sizeof(e));
			if (e.h_proto == arptype)
			{
				//copy arp header
				memcpy(&reparp, &buff[ethsize], arpsize);
				if (reparp.ar_hrd == htype && reparp.ar_op == op &&
					!memcmp(&reparp.sip, &dest, 4))
				{
					//a pc have same ip addr

⌨️ 快捷键说明

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