(6) DHCP Coding을 해봅시다.

자, DHCP 설명 꽤나 길었습니다.

이제부터는 코딩을 시작해보려고 하는데요.


 

DHCP에 관해서 잘 모르겠다고 하신다면 아래의 링크를 참조해주세요.

DHCP 시작하기 !  – https://jinheeahn.wordpress.com/2015/04/29/dhcp시작하기!

DHCP 전체 동작 과정 및 Protocol 분석 – https://jinheeahn.wordpress.com/2015/06/04/dhcp 분석

DHCP Packet 분석 1 – https://jinheeahn.wordpress.com/2015/10/28/4-dhcp-packet 분석 첫번째

DHCP Packet 분석 1 –https://jinheeahn.wordpress.com/2015/10/28/5-dhcp-packet 분석 두번째


더불어서 DHCP의 Packet을 잡는 방법도 게시하였습니다.

DHCP packet 잡아보기 – https://jinheeahn.wordpress.com/2015/10/28/3-DHCP 패킷 잡기!!


 

 

사용할 Module은 WIZnet사의 W5500-EVB입니다.

Tool은 LPCXpresso를 사용하겠습니다.

이건 무료 배포버전이구요. 유료로 업그레이드 가능합니다.

무료와 유료버전의 차이는 코드 사이즈라고 보시면 되겠습니다.

근데 ! 왜 LPCXpresso를 사용하냐구요?? W5500-EVB가 NXP사의 Cortex-M0의 MCU를 사용하기 때문입니다!

Module에 대한 자세한 정보는 아래의 링크를 확인해주세요!

http://wizwiki.net/wiki/doku.php?id=products:w5500:w5500_evb:start

그 밖의 처음 사용하시는 분들은 Getting Started를 확인해주세요.

  1. Getting Started – getting_started#hello_world
  2. Getting Started – Firmware Upload

W5500-EVB의 Application 예제들은 GITHUB이라는 사이트에 업로드 되어 있습니다. 참조해주세요.

https://github.com/Wiznet/ioLibrary_Driver


 

자, 이제 코딩을 올려보도록 하겠습니다. 분명 너무 길어서 무슨 코드인지 한번에 알아보기는 어려우실 거에요. 일단 WIZnet사에서 제공하는 ioLibrary에는 DHCP도 있습니다.

하지만, DHCP를 어떻게 만드는지는 모르기 때문에 저는 실제로 제작해보기로 했습니다. 다소 코드가 중구난방이고 어려워보일 수도 있지만 참고 봐주셨으면 합니다… ㅎㅎ



/*
===============================================================================
 Name : W5500-EVB.c
 Author : $(author)
 Version :
 Copyright : $(copyright)
 Description : main definition
===============================================================================
*/

#if defined (__USE_LPCOPEN)
#if defined(NO_BOARD_LIB)
#include <chip.h>
#else
#include <board.h>
#endif
#endif

#include "cr_section_macros.h"
#include "socket.h"
#include"spi_handler.h"
#include "w5500_init.h"
#include "w5500.h"
#include <stdio.h>
#include <string.h>
#include "w5500_DHCP.h"

// TODO: insert other include files here

// TODO: insert other definitions and declarations here

#define DHCP_DISCOVER      		 1        ///< send DISCOVER and wait OFFER

#define STATE_DHCP_DISCOVER      0        ///< Initialize
#define STATE_DHCP_OFFER	     1        ///< send DISCOVER and wait OFFER
#define STATE_DHCP_REQUEST       2        ///< send REQEUST and wait ACK or NACK
#define STATE_DHCP_ACK			 3
#define STATE_DHCP_REREQUEST	 4

#define DHCP_FLAGSBROADCAST      0x8000   ///< The broadcast value of flags in @ref RIP_MSG

/* DHCP message OP code */
#define DHCP_BOOTREQUEST         1        ///< Request Message used in op of @ref RIP_MSG

/* DHCP message type */
#define DHCP_DISCOVER            1        ///< DISCOVER message in OPT of @ref RIP_MSG
#define DHCP_REQUEST			 3
#define DHCP_ACK				 5
#define DHCP_NAK				 6

#define DHCP_HTYPE10MB           1        ///< Used in type of @ref RIP_MSG

/////////////////////////////////////////////////// DHCP Option pakcet

#define DHCP_Message_type		 0x35
#define Client_identifier		 0x3D
#define Requested_IP_ADDRESS	 0x32 		// want IP
#define Host_Name				 0x0C
#define DHCP_HOST_NAME			 "WIZnet"
#define Vendor_class_identifier	 0x3C
#define Parameter_request_list	 0x37
#define DHCP_SEVER_Identifier	 0x36

#define subnet_mask 						1
#define domain_name							15
#define	router								3
#define	domain_name_server					6

#define	netbios_over_tcp_name_server		44
#define	netbios_over_tcp_node_type			46
#define	netbios_over_tcp_scope				47
#define	perform_router_discover				31
#define	static_route						33
#define	classless_static_route				121
#define	private_classless_static_route		249
#define	vendor_specific_information			43

////////////////////////////////////////////////////

#define DHCP_HLENETHERNET        6        ///< Used in hlen of @ref RIP_MSG
#define DHCP_HOPS                0        ///< Used in hops of @ref RIP_MSG
#define DHCP_SECS                0        ///< Used in secs of @ref RIP_MSG //////////////////////////////////////////////////// Socket information #define DHCP_SERVER 67 #define DHCP_Client 68 #define TCP_SOCKET 0 #define UDP_SOCKET 1 #define TCP_PORT 5000 #define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG #define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG uint8_t UDP_buffer[RIP_MSG_SIZE]; ///////////////////////////////////////////////////// DHCP State uint8_t dhcp_states = STATE_DHCP_DISCOVER; enum { padOption = 0x00, subnetMask = 0x01, timerOffset = 0x02, routersOnSubnet = 0x03, timeServer = 0x04, nameServer = 0x05, dns = 0x06, logServer = 0x07, cookieServer = 0x08, lprServer = 0x09, impressServer = 0x0A, resourceLocationServer = 0x0B, hostName = 0x0C, bootFileSize = 0x0D, meritDumpFile = 0x0E, domainName = 0x0F, swapServer = 0x10, rootPath = 0x11, extentionsPath = 0x12, IPforwarding = 0x13, nonLocalSourceRouting = 0x14, policyFilter = 0x15, maxDgramReasmSize = 0x16, defaultIPTTL = 0x17, pathMTUagingTimeout = 0x18, pathMTUplateauTable = 0x19, ifMTU = 0x1A, allSubnetsLocal = 0x1B, broadcastAddr = 0x1C, performMaskDiscovery = 0x1D, maskSupplier = 0x1E, performRouterDiscovery = 0x1F, routerSolicitationAddr = 0x20, staticRoute = 0x21, trailerEncapsulation = 0x22, arpCacheTimeout = 0x23, ethernetEncapsulation = 0x24, tcpDefaultTTL = 0x25, tcpKeepaliveInterval = 0x26, tcpKeepaliveGarbage = 0x27, nisDomainName = 0x28, nisServers = 0x29, ntpServers = 0x2A, vendorSpecificInfo = 0x2B, netBIOSnameServer = 0x2C, netBIOSdgramDistServer = 0x2D, netBIOSnodeType = 0x2E, netBIOSscope = 0x2F, xFontServer = 0x30, xDisplayManager = 0x31, dhcpRequestedIPaddr = 0x32, dhcpIPaddrLeaseTime = 0x33, dhcpOptionOverload = 0x34, dhcpMessageType = 0x35, dhcpServerIdentifier = 0x36, dhcpParamRequest = 0x37, dhcpMsg = 0x38, dhcpMaxMsgSize = 0x39, dhcpT1value = 0x3A, dhcpT2value = 0x3B, dhcpClassIdentifier = 0x3C, dhcpClientIdentifier = 0x3D, endOption = 0xFF }; ////////////////////////////////////////////////////////// int main(void) { /////////////////////////////////////////// common variable uint8_t ip[4]={0,}; uint8_t DHCP_CHADDR[6]; uint8_t ptmp[7] = {0,}; /////////////////////////////////////////// BOOTP packet uint8_t OP = 0x01; uint8_t HTYPE = 0x01; uint8_t HLEN = 0x06; uint8_t HOPS = 0x00; uint32_t XID = 0x12345678; uint16_t SECS = 0x0000; uint16_t FLAGS_BORADCAST = 0x8000; uint16_t FLAGS_UNICAST = 0x0000; uint8_t CIADDR[4] = {0,}; uint8_t YIADDR[4] = {0,}; uint8_t SIADDR[4] = {0,}; uint8_t GIADDR[4] = {0,}; uint8_t CHADDR[16] = {0,}; //uint8_t host_name[64] = {0,}; //uint8_t file_name[128] = {0,}; uint32_t MAGIC_COOKIE = 0x63825363; //////////////////////////////////////////// make Discover Option //uint8_t host_names[] = DHCP_HOST_NAME; uint32_t host_name1 = 0x57495A6E; uint16_t host_name2 = 0x6574; //////////////////////////////////////////// offer & ACK uint8_t Target_ip[4]={255,255,255,255}; uint16_t Target_port; uint16_t Rx_len; uint8_t * pOption; uint8_t * eOption; uint16_t dOption; uint16_t dOption_CAL; uint8_t Option_len; uint32_t CHECK_XID = 0; uint32_t CHECK_DNSID = 0; uint32_t CHECK_MAGIC = 0; uint8_t DHCP_ASSIGN_Message_type; uint8_t DHCP_ASSIGN_IP[4] = {0,}; uint8_t DHCP_ServerIP[4] = {0,}; uint8_t DHCP_ASSIGN_LEASETIME[4] = {0,}; uint8_t DHCP_ASSIGN_SUBNET[4] = {0,}; uint8_t DHCP_ASSIGN_ROUTER_CAL[8] = {0,}; uint8_t DHCP_ASSIGN_ROUTER1[4] = {0,}; uint8_t DHCP_ASSIGN_ROUTER2[4] = {0,}; uint8_t DHCP_ASSIGN_Domain_server_CAL[8] = {0,}; uint8_t DHCP_ASSIGN_Domain_server1[4] = {0,}; uint8_t DHCP_ASSIGN_Domain_server2[4] = {0,}; uint8_t i; #if defined (__USE_LPCOPEN) #if !defined(NO_BOARD_LIB) // Read clock settings and update SystemCoreClock variable SystemCoreClockUpdate(); // Set up and initialize all required blocks and // functions related to the board hardware Board_Init(); // Set the LED to the state of On Board_LED_Set(0, true); #endif #endif SPI_Init(); W5500_Init(); Net_Conf(); getSHAR(DHCP_CHADDR); DHCP_CHADDR[0] = 0x00; DHCP_CHADDR[1] = 0x08; DHCP_CHADDR[2] = 0xdc; DHCP_CHADDR[3] = 0x19; DHCP_CHADDR[4] = 0x84; DHCP_CHADDR[5] = 0x82; setSHAR(DHCP_CHADDR); CHADDR[0] = DHCP_CHADDR[0]; CHADDR[1] = DHCP_CHADDR[1]; CHADDR[2] = DHCP_CHADDR[2]; CHADDR[3] = DHCP_CHADDR[3]; CHADDR[4] = DHCP_CHADDR[4]; CHADDR[5] = DHCP_CHADDR[5]; ///////////////////////////////////////////////////// Network assign void network_assign(void) { uint8_t tmp[4] = {0,}; setSIPR(DHCP_ASSIGN_IP); setSUBR(DHCP_ASSIGN_SUBNET); setGAR (DHCP_ASSIGN_ROUTER1); getSIPR(tmp); printf("IP ADDRESS : %d,%d,%d,%d\r\n",tmp[0],tmp[1],tmp[2],tmp[3]); getSUBR(tmp); printf("SUBNET MASK : %d,%d,%d,%d\r\n",tmp[0],tmp[1],tmp[2],tmp[3]); getGAR(tmp); printf("GATEWAY : %d,%d,%d,%d\r\n",tmp[0],tmp[1],tmp[2],tmp[3]); } if(socket(UDP_SOCKET,Sn_MR_UDP,DHCP_Client,0) == UDP_SOCKET) { printf("socket UDP creation\r\n"); } while(1) { switch(dhcp_states) { case STATE_DHCP_DISCOVER: UDP_buffer[0] = OP; UDP_buffer[1] = HTYPE; UDP_buffer[2] = HLEN; UDP_buffer[3] = HOPS; ptmp[0] = (uint8_t)((XID & 0xFF000000) >> 24);
			UDP_buffer[4] = ptmp[0];
			ptmp[1] = (uint8_t)((XID & 0x00FF0000) >> 16);
			UDP_buffer[5] = ptmp[1];
			ptmp[2] = (uint8_t)((XID & 0x0000FF00) >>  8);
			UDP_buffer[6] = ptmp[2];
			ptmp[3] = (uint8_t)((XID & 0x000000FF) >>  0);
			UDP_buffer[7] = ptmp[3];

			ptmp[4] = (uint8_t)((SECS & 0xFF00) >>  8);
			UDP_buffer[8] = ptmp[4];
			ptmp[5] = (uint8_t)((SECS & 0x00FF) >>  8);
			UDP_buffer[9] = ptmp[5];

			ptmp[6] = (uint8_t)((FLAGS_BORADCAST & 0xFF00) >> 8);
			UDP_buffer[10] = ptmp[6];
			ptmp[7] = (uint8_t)((FLAGS_BORADCAST & 0x00FF) >> 0);
			UDP_buffer[11] = ptmp[7];

			UDP_buffer[12] = CIADDR[0];
			UDP_buffer[13] = CIADDR[1];
			UDP_buffer[14] = CIADDR[2];
			UDP_buffer[15] = CIADDR[3];
			UDP_buffer[16] = YIADDR[0];
			UDP_buffer[17] = YIADDR[1];
			UDP_buffer[18] = YIADDR[2];
			UDP_buffer[19] = YIADDR[3];
			UDP_buffer[20] = SIADDR[0];
			UDP_buffer[21] = SIADDR[1];
			UDP_buffer[22] = SIADDR[2];
			UDP_buffer[23] = SIADDR[3];
			UDP_buffer[24] = GIADDR[0];
			UDP_buffer[25] = GIADDR[1];
			UDP_buffer[26] = GIADDR[2];
			UDP_buffer[27] = GIADDR[3];
			UDP_buffer[28] = CHADDR[0];
			UDP_buffer[29] = CHADDR[1];
			UDP_buffer[30] = CHADDR[2];
			UDP_buffer[31] = CHADDR[3];
			UDP_buffer[32] = CHADDR[4];
			UDP_buffer[33] = CHADDR[5];

			UDP_buffer[236] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
			UDP_buffer[237] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
			UDP_buffer[238] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >>  8);
			UDP_buffer[239] = (uint8_t)((MAGIC_COOKIE & 0x000000FF) >>  0);

			ip[0] = 255;
			ip[1] = 255;
			ip[2] = 255;
			ip[3] = 255;

			UDP_buffer[240] = DHCP_Message_type; // Just -> 0x53(No!) option name is decimal type
			UDP_buffer[241] = 0x01;
			UDP_buffer[242] = DHCP_DISCOVER;
			UDP_buffer[243] = Client_identifier;
			UDP_buffer[244] = 0x07;
			UDP_buffer[245] = 0x01;
			UDP_buffer[246] = DHCP_CHADDR[0];
			UDP_buffer[247] = DHCP_CHADDR[1];
			UDP_buffer[248] = DHCP_CHADDR[2];
			UDP_buffer[249] = DHCP_CHADDR[3];
			UDP_buffer[250] = DHCP_CHADDR[4];
			UDP_buffer[251] = DHCP_CHADDR[5];

			UDP_buffer[252] = Host_Name;
			UDP_buffer[253] = 0x0A; // Hex
			UDP_buffer[254] = (uint8_t)((host_name1 & 0xFF000000) >> 24);
			UDP_buffer[255] = (uint8_t)((host_name1 & 0x00FF0000) >> 16);
			UDP_buffer[256] = (uint8_t)((host_name1 & 0x0000FF00) >>  8);
			UDP_buffer[257] = (uint8_t)((host_name1 & 0x000000FF) >>  0);
			UDP_buffer[258] = (uint8_t)((host_name2 & 0x0FF00) >>  8);
			UDP_buffer[259] = (uint8_t)((host_name2 & 0x000FF) >>  0);

			UDP_buffer[264] = Parameter_request_list;
			UDP_buffer[265] = 0x04;
			UDP_buffer[266] = subnet_mask;
			UDP_buffer[267] = domain_name;
			UDP_buffer[268] = router;
			UDP_buffer[269] = domain_name_server;

			UDP_buffer[270] = 255;

			sendto(UDP_SOCKET, (uint8_t *)UDP_buffer, RIP_MSG_SIZE,ip,DHCP_SERVER);
			printf("----DISCOVER Message SEND----\r\n");
			memset(UDP_buffer,0,RIP_MSG_SIZE);
			dhcp_states = STATE_DHCP_OFFER;
				break;

		case STATE_DHCP_OFFER:
			if((Rx_len = getSn_RX_RSR(UDP_SOCKET)) > 0)
				{
					Rx_len = recvfrom(UDP_SOCKET, (uint8_t *)UDP_buffer, Rx_len, Target_ip, &Target_port);
					printf("----Offer Message----\r\n");
					if (Target_port == DHCP_SERVER)
					{
						printf("CHECK XID\r\n");
						CHECK_XID |= (uint32_t)((UDP_buffer[4] & 0xFFFFFFFF) << 24);
						CHECK_XID |= (uint32_t)((UDP_buffer[5] & 0xFFFFFFFF) << 16);
						CHECK_XID |= (uint32_t)((UDP_buffer[6] & 0xFFFFFFFF) <<  8);
						CHECK_XID |= (uint32_t)((UDP_buffer[7] & 0xFFFFFFFF) <<  0);
						if (XID != CHECK_XID)
						{
							printf("XID error\r\n");
							return 0;
						}
						printf("CHECK CHADDR\r\n");
						if ((UDP_buffer[28] != DHCP_CHADDR[0]) || (UDP_buffer[29] != DHCP_CHADDR[1]) ||
							 (UDP_buffer[30] != DHCP_CHADDR[2]) || (UDP_buffer[31] != DHCP_CHADDR[3]) ||
							 (UDP_buffer[32] != DHCP_CHADDR[4]) || (UDP_buffer[33] != DHCP_CHADDR[5]))
						{
							printf("CHADDR error\r\n");
							return 0;
						}
						printf("CHECK MAGIC\r\n");
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[236] & 0xFFFFFFFF) << 24);
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[237] & 0xFFFFFFFF) << 16);
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[238] & 0xFFFFFFFF) <<  8);
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[239] & 0xFFFFFFFF) <<  0);
						if(CHECK_MAGIC != 0x63825363)
						{
							printf("magic error\r\n");
							return 0;
						}
						printf("CHECK COMPLITE\r\n");

						//Your IP Address
						DHCP_ASSIGN_IP[0] = UDP_buffer[16];
						DHCP_ASSIGN_IP[1] = UDP_buffer[17];
						DHCP_ASSIGN_IP[2] = UDP_buffer[18];
						DHCP_ASSIGN_IP[3] = UDP_buffer[19];

						pOption = (uint8_t*)(&UDP_buffer); // OP start address
						pOption = pOption + 240;
						eOption = pOption + (Rx_len - 240);

						printf("-----Option Message-----\r\n");
						while ( pOption < eOption ) { switch(*pOption) { case dhcpMessageType: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 1) { DHCP_ASSIGN_Message_type = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("dhcpMessageType Value : %d\r\n",DHCP_ASSIGN_Message_type); break; case dhcpServerIdentifier: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ServerIP[i] = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("serverIP : %d,%d,%d,%d\r\n",DHCP_ServerIP[0],DHCP_ServerIP[1],DHCP_ServerIP[2],DHCP_ServerIP[3]); break; case dhcpIPaddrLeaseTime: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_LEASETIME[i] = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("LEASE : %d,%d,%d,%d\r\n",DHCP_ASSIGN_LEASETIME[0],DHCP_ASSIGN_LEASETIME[1],DHCP_ASSIGN_LEASETIME[2],DHCP_ASSIGN_LEASETIME[3]); break; case subnetMask: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_SUBNET[i] = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("subnet mask : %d,%d,%d,%d\r\n",DHCP_ASSIGN_SUBNET[0],DHCP_ASSIGN_SUBNET[1],DHCP_ASSIGN_SUBNET[2],DHCP_ASSIGN_SUBNET[3]); break; case routersOnSubnet: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_ROUTER1[i] = *pOption++; } else if(Option_len > 8)
									{
										pOption += Option_len;
									}
									else{
										DHCP_ASSIGN_ROUTER_CAL[i] = *pOption++;
									}
								}
								if(Option_len == 8)
								{
									DHCP_ASSIGN_ROUTER1[0] = DHCP_ASSIGN_ROUTER_CAL[0];
									DHCP_ASSIGN_ROUTER1[1] = DHCP_ASSIGN_ROUTER_CAL[1];
									DHCP_ASSIGN_ROUTER1[2] = DHCP_ASSIGN_ROUTER_CAL[2];
									DHCP_ASSIGN_ROUTER1[3] = DHCP_ASSIGN_ROUTER_CAL[3];
									DHCP_ASSIGN_ROUTER2[0] = DHCP_ASSIGN_ROUTER_CAL[4];
									DHCP_ASSIGN_ROUTER2[1] = DHCP_ASSIGN_ROUTER_CAL[5];
									DHCP_ASSIGN_ROUTER2[2] = DHCP_ASSIGN_ROUTER_CAL[6];
									DHCP_ASSIGN_ROUTER2[3] = DHCP_ASSIGN_ROUTER_CAL[7];
								}
								dOption = dOption - (Option_len + 2);
								dOption_CAL = dOption;
								printf("router1 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_ROUTER1[0],DHCP_ASSIGN_ROUTER1[1],DHCP_ASSIGN_ROUTER1[2],DHCP_ASSIGN_ROUTER1[3]);
								printf("router2 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_ROUTER2[0],DHCP_ASSIGN_ROUTER2[1],DHCP_ASSIGN_ROUTER2[2],DHCP_ASSIGN_ROUTER2[3]);
								break;
							case dns:
								pOption++;
								Option_len = *pOption++;
								if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len > 8)
									{
										pOption += Option_len;
									}
									else if(Option_len == 4)
									{
										DHCP_ASSIGN_Domain_server1[i] = *pOption++;
									}
									else{
										DHCP_ASSIGN_Domain_server_CAL[i] = *pOption++;
									}
								}
								if(Option_len == 8)
								{
									DHCP_ASSIGN_Domain_server1[0] = DHCP_ASSIGN_Domain_server_CAL[0];
									DHCP_ASSIGN_Domain_server1[1] = DHCP_ASSIGN_Domain_server_CAL[1];
									DHCP_ASSIGN_Domain_server1[2] = DHCP_ASSIGN_Domain_server_CAL[2];
									DHCP_ASSIGN_Domain_server1[3] = DHCP_ASSIGN_Domain_server_CAL[3];
									DHCP_ASSIGN_Domain_server2[0] = DHCP_ASSIGN_Domain_server_CAL[4];
									DHCP_ASSIGN_Domain_server2[1] = DHCP_ASSIGN_Domain_server_CAL[5];
									DHCP_ASSIGN_Domain_server2[2] = DHCP_ASSIGN_Domain_server_CAL[6];
									DHCP_ASSIGN_Domain_server2[3] = DHCP_ASSIGN_Domain_server_CAL[7];
								}
								dOption = dOption - (Option_len + 2);
								dOption_CAL = dOption;
								printf("domain1 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_Domain_server1[0],DHCP_ASSIGN_Domain_server1[1],DHCP_ASSIGN_Domain_server1[2],DHCP_ASSIGN_Domain_server1[3]);
								printf("domain2 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_Domain_server2[0],DHCP_ASSIGN_Domain_server2[1],DHCP_ASSIGN_Domain_server2[2],DHCP_ASSIGN_Domain_server2[3]);
								break;
							case endOption:
								pOption = eOption; // escape switch condition
								printf("end\r\n");
								dOption = dOption - dOption_CAL;
								dhcp_states = STATE_DHCP_REREQUEST;
								break;
							default: // If receive unregistration option packet, operate default case
								pOption++;
								Option_len = *pOption++;
								pOption += Option_len;
								printf("not search\r\n");
								break;
							}
						}
						if(dOption)
						{
							return 0;
						}
						else{
							printf("Option Parser End\r\n");
						}
				}
			dhcp_states = STATE_DHCP_REQUEST;
			}
			break;

		case STATE_DHCP_REQUEST :
		{
			UDP_buffer[0] = OP;
			UDP_buffer[1] = HTYPE;
			UDP_buffer[2] = HLEN;
			UDP_buffer[3] = HOPS;

			ptmp[0] = (uint8_t)((XID & 0xFF000000) >> 24);
			UDP_buffer[4] = ptmp[0];
			ptmp[1] = (uint8_t)((XID & 0x00FF0000) >> 16);
			UDP_buffer[5] = ptmp[1];
			ptmp[2] = (uint8_t)((XID & 0x0000FF00) >>  8);
			UDP_buffer[6] = ptmp[2];
			ptmp[3] = (uint8_t)((XID & 0x000000FF) >>  0);
			UDP_buffer[7] = ptmp[3];

			ptmp[4] = (uint8_t)((SECS & 0xFF00) >>  8);
			UDP_buffer[8] = ptmp[4];
			ptmp[5] = (uint8_t)((SECS & 0x00FF) >>  8);
			UDP_buffer[9] = ptmp[5];

			ptmp[6] = (uint8_t)((FLAGS_UNICAST & 0xFF00) >> 8);
			UDP_buffer[10] = ptmp[6];
			ptmp[7] = (uint8_t)((FLAGS_UNICAST & 0x00FF) >> 0);
			UDP_buffer[11] = ptmp[7];

			UDP_buffer[12] = CIADDR[0];
			UDP_buffer[13] = CIADDR[1];
			UDP_buffer[14] = CIADDR[2];
			UDP_buffer[15] = CIADDR[3];
			UDP_buffer[16] = YIADDR[0];
			UDP_buffer[17] = YIADDR[1];
			UDP_buffer[18] = YIADDR[2];
			UDP_buffer[19] = YIADDR[3];
			UDP_buffer[20] = SIADDR[0];
			UDP_buffer[21] = SIADDR[1];
			UDP_buffer[22] = SIADDR[2];
			UDP_buffer[23] = SIADDR[3];
			UDP_buffer[24] = GIADDR[0];
			UDP_buffer[25] = GIADDR[1];
			UDP_buffer[26] = GIADDR[2];
			UDP_buffer[27] = GIADDR[3];
			UDP_buffer[28] = CHADDR[0];
			UDP_buffer[29] = CHADDR[1];
			UDP_buffer[30] = CHADDR[2];
			UDP_buffer[31] = CHADDR[3];
			UDP_buffer[32] = CHADDR[4];
			UDP_buffer[33] = CHADDR[5];

			UDP_buffer[236] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
			UDP_buffer[237] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
			UDP_buffer[238] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >>  8);
			UDP_buffer[239] = (uint8_t)((MAGIC_COOKIE & 0x000000FF) >>  0);

			ip[0] = 255;
			ip[1] = 255;
			ip[2] = 255;
			ip[3] = 255;

			UDP_buffer[240] = DHCP_Message_type; // Just -> 0x53(No!) option name is decimal type
			UDP_buffer[241] = 0x01; // length
			UDP_buffer[242] = DHCP_REQUEST; // Data
			UDP_buffer[243] = Client_identifier;
			UDP_buffer[244] = 0x07;
			UDP_buffer[245] = 0x01;
			UDP_buffer[246] = DHCP_CHADDR[0];
			UDP_buffer[247] = DHCP_CHADDR[1];
			UDP_buffer[248] = DHCP_CHADDR[2];
			UDP_buffer[249] = DHCP_CHADDR[3];
			UDP_buffer[250] = DHCP_CHADDR[4];
			UDP_buffer[251] = DHCP_CHADDR[5];
			UDP_buffer[252]	= Requested_IP_ADDRESS;
			UDP_buffer[253]	= 0x04;
			UDP_buffer[254] = DHCP_ASSIGN_IP[0];
			UDP_buffer[255] = DHCP_ASSIGN_IP[1];
			UDP_buffer[256] = DHCP_ASSIGN_IP[2];
			UDP_buffer[257] = DHCP_ASSIGN_IP[3];

			UDP_buffer[258] = DHCP_SEVER_Identifier;
			UDP_buffer[259] = 0x04;
			UDP_buffer[260] = DHCP_ServerIP[0];;
			UDP_buffer[261] = DHCP_ServerIP[1];
			UDP_buffer[262] = DHCP_ServerIP[2];
			UDP_buffer[263] = DHCP_ServerIP[3];

			UDP_buffer[264] = Host_Name;
			UDP_buffer[265] = 0x0A; // Hex
			UDP_buffer[266] = (uint8_t)((host_name1 & 0xFF000000) >> 24);
			UDP_buffer[267] = (uint8_t)((host_name1 & 0x00FF0000) >> 16);
			UDP_buffer[268] = (uint8_t)((host_name1 & 0x0000FF00) >>  8);
			UDP_buffer[269] = (uint8_t)((host_name1 & 0x000000FF) >>  0);
			UDP_buffer[270] = (uint8_t)((host_name2 & 0x0FF00) >>  8);
			UDP_buffer[271] = (uint8_t)((host_name2 & 0x000FF) >>  0);

			UDP_buffer[276] = Parameter_request_list;
			UDP_buffer[277] = 0x04;
			UDP_buffer[278] = subnet_mask;
			UDP_buffer[279] = domain_name;
			UDP_buffer[280] = router;
			UDP_buffer[281] = domain_name_server;

			UDP_buffer[282] = 255;

			sendto(UDP_SOCKET, (uint8_t *)UDP_buffer, RIP_MSG_SIZE,ip,DHCP_SERVER);
			printf("----REQUEST Message SEND----\r\n");
			memset(UDP_buffer,0,RIP_MSG_SIZE);
			dhcp_states = STATE_DHCP_ACK;
		}
		break;

		case STATE_DHCP_ACK :
			if((Rx_len = getSn_RX_RSR(UDP_SOCKET)) > 0)
				{
					Rx_len = recvfrom(UDP_SOCKET, (uint8_t *)UDP_buffer, Rx_len, Target_ip, &Target_port);
					printf("----ACK Message----\r\n");
					if(UDP_buffer[10] == FLAGS_UNICAST)
					{
					if (Target_port == DHCP_SERVER)
					{
						printf("CHECK XID\r\n");
						CHECK_XID |= (uint32_t)((UDP_buffer[4] & 0xFFFFFFFF) << 24);
						CHECK_XID |= (uint32_t)((UDP_buffer[5] & 0xFFFFFFFF) << 16);
						CHECK_XID |= (uint32_t)((UDP_buffer[6] & 0xFFFFFFFF) <<  8);
						CHECK_XID |= (uint32_t)((UDP_buffer[7] & 0xFFFFFFFF) <<  0);
						if (XID != CHECK_XID)
						{
							printf("XID error\r\n");
							return 0;
						}
						printf("CHECK CHADDR\r\n");
						if ((UDP_buffer[28] != DHCP_CHADDR[0]) || (UDP_buffer[29] != DHCP_CHADDR[1]) ||
							 (UDP_buffer[30] != DHCP_CHADDR[2]) || (UDP_buffer[31] != DHCP_CHADDR[3]) ||
							 (UDP_buffer[32] != DHCP_CHADDR[4]) || (UDP_buffer[33] != DHCP_CHADDR[5]))
						{
							printf("CHADDR error\r\n");
							return 0;
						}
						printf("CHECK MAGIC\r\n");
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[236] & 0xFFFFFFFF) << 24);
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[237] & 0xFFFFFFFF) << 16);
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[238] & 0xFFFFFFFF) <<  8);
						CHECK_MAGIC |= (uint32_t)((UDP_buffer[239] & 0xFFFFFFFF) << 0); if(CHECK_MAGIC != 0x63825363) { printf("magic error\r\n"); return 0; } printf("CHECK COMPLITE\r\n"); //Your IP Address DHCP_ASSIGN_IP[0] = UDP_buffer[16]; DHCP_ASSIGN_IP[1] = UDP_buffer[17]; DHCP_ASSIGN_IP[2] = UDP_buffer[18]; DHCP_ASSIGN_IP[3] = UDP_buffer[19]; printf("ACK DHCP_ASSIGN_IP : %d,%d,%d,%d\r\n",DHCP_ASSIGN_IP[0],DHCP_ASSIGN_IP[1],DHCP_ASSIGN_IP[2],DHCP_ASSIGN_IP[3]); pOption = (uint8_t*)(&UDP_buffer); // OP start address pOption = pOption + 240; eOption = pOption + (Rx_len - 240); // pOption(pointer(address value)), (Rx_len - 240) -> option packet size
						dOption = Rx_len - 240; // all size - 240(BOOTP Packet) = option size + padding(0)

						printf("-----Reply Message-----\r\n");
						while ( pOption < eOption ) { switch(*pOption) { case dhcpMessageType: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 1) { DHCP_ASSIGN_Message_type = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("dhcpMessageType Value : %d\r\n",DHCP_ASSIGN_Message_type); break; case dhcpServerIdentifier: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ServerIP[i] = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("serverIP : %d,%d,%d,%d\r\n",DHCP_ServerIP[0],DHCP_ServerIP[1],DHCP_ServerIP[2],DHCP_ServerIP[3]); break; case dhcpIPaddrLeaseTime: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_LEASETIME[i] = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("LEASE : %d,%d,%d,%d\r\n",DHCP_ASSIGN_LEASETIME[0],DHCP_ASSIGN_LEASETIME[1],DHCP_ASSIGN_LEASETIME[2],DHCP_ASSIGN_LEASETIME[3]); break; case subnetMask: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_SUBNET[i] = *pOption++; } else{ pOption += Option_len; } } dOption = dOption - (Option_len + 2); dOption_CAL = dOption; printf("subnet mask : %d,%d,%d,%d\r\n",DHCP_ASSIGN_SUBNET[0],DHCP_ASSIGN_SUBNET[1],DHCP_ASSIGN_SUBNET[2],DHCP_ASSIGN_SUBNET[3]); break; case routersOnSubnet: pOption++; Option_len = *pOption++; if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_ROUTER1[i] = *pOption++; } else if(Option_len > 8)
									{
										pOption += Option_len;
									}
									else{
										DHCP_ASSIGN_ROUTER_CAL[i] = *pOption++;
									}
								}
								if(Option_len == 8)
								{
									DHCP_ASSIGN_ROUTER1[0] = DHCP_ASSIGN_ROUTER_CAL[0];
									DHCP_ASSIGN_ROUTER1[1] = DHCP_ASSIGN_ROUTER_CAL[1];
									DHCP_ASSIGN_ROUTER1[2] = DHCP_ASSIGN_ROUTER_CAL[2];
									DHCP_ASSIGN_ROUTER1[3] = DHCP_ASSIGN_ROUTER_CAL[3];
									DHCP_ASSIGN_ROUTER2[0] = DHCP_ASSIGN_ROUTER_CAL[4];
									DHCP_ASSIGN_ROUTER2[1] = DHCP_ASSIGN_ROUTER_CAL[5];
									DHCP_ASSIGN_ROUTER2[2] = DHCP_ASSIGN_ROUTER_CAL[6];
									DHCP_ASSIGN_ROUTER2[3] = DHCP_ASSIGN_ROUTER_CAL[7];
								}
								dOption = dOption - (Option_len + 2);
								dOption_CAL = dOption;
								printf("router1 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_ROUTER1[0],DHCP_ASSIGN_ROUTER1[1],DHCP_ASSIGN_ROUTER1[2],DHCP_ASSIGN_ROUTER1[3]);
								printf("router2 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_ROUTER2[0],DHCP_ASSIGN_ROUTER2[1],DHCP_ASSIGN_ROUTER2[2],DHCP_ASSIGN_ROUTER2[3]);
								break;
							case dns:
								pOption++;
								Option_len = *pOption++;
								if(Option_len > dOption) // check length. from hacking
								{
									return 0;
								}
								for(i=0;i<option_len;i++) { if(Option_len == 4) { DHCP_ASSIGN_Domain_server1[i] = *pOption++; } else if(Option_len > 8)
									{
										pOption += Option_len;
									}
									else{
										DHCP_ASSIGN_Domain_server_CAL[i] = *pOption++;
									}
								}
								if(Option_len == 8)
								{
									DHCP_ASSIGN_Domain_server1[0] = DHCP_ASSIGN_Domain_server_CAL[0];
									DHCP_ASSIGN_Domain_server1[1] = DHCP_ASSIGN_Domain_server_CAL[1];
									DHCP_ASSIGN_Domain_server1[2] = DHCP_ASSIGN_Domain_server_CAL[2];
									DHCP_ASSIGN_Domain_server1[3] = DHCP_ASSIGN_Domain_server_CAL[3];
									DHCP_ASSIGN_Domain_server2[0] = DHCP_ASSIGN_Domain_server_CAL[4];
									DHCP_ASSIGN_Domain_server2[1] = DHCP_ASSIGN_Domain_server_CAL[5];
									DHCP_ASSIGN_Domain_server2[2] = DHCP_ASSIGN_Domain_server_CAL[6];
									DHCP_ASSIGN_Domain_server2[3] = DHCP_ASSIGN_Domain_server_CAL[7];
								}
								dOption = dOption - (Option_len + 2);
								dOption_CAL = dOption;
								printf("domain1 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_Domain_server1[0],DHCP_ASSIGN_Domain_server1[1],DHCP_ASSIGN_Domain_server1[2],DHCP_ASSIGN_Domain_server1[3]);
								printf("domain2 : %d,%d,%d,%d\r\n",DHCP_ASSIGN_Domain_server2[0],DHCP_ASSIGN_Domain_server2[1],DHCP_ASSIGN_Domain_server2[2],DHCP_ASSIGN_Domain_server2[3]);
								break;
							case endOption:
								pOption = eOption; // escape switch condition
								printf("Network information setting end !! \r\n");
								dOption = dOption - dOption_CAL;
								dhcp_states = STATE_DHCP_REREQUEST;
								break;
							default: // If receive unregistration option packet, operate default case
								pOption++;
								Option_len = *pOption++;
								pOption += Option_len;
								printf("not search\r\n");
								break;
							}
						}
						if(dOption) // if dOption = 1;
						{
							return 0;
						}
						else{
							printf("Option Parser End\r\n");
						}
						if(DHCP_ASSIGN_Message_type == DHCP_ACK)
						{
							printf("Response the ACK message\r\n");
							network_assign(); // IP Assgin
							printf("IP assgin DONE!\r\n");
						}
						else{
							printf("Response the NAK massage\r\n");
							dhcp_states = STATE_DHCP_DISCOVER;
						}
					}
				}
			}
			break;
/*
		case STATE_DHCP_REREQUEST :

			break;
*/
		default :
			break;
		}
	}
// Need Condition List
// 1. Timeout
// 2. ReRequest
// 3. Lease time calculation
// 4. easy code read

	return 0 ;
}


코드가 생각보다 많이 길어요.

코드 구현은 DHCP Client를 구성해서 IP를 할당받은 것 까지 하였습니다.

추가적으로 구현되어야할 기능은,

  1. Timeout – 일정시간 이상 응답없으면 발생하는 Delay
  2. ReRequest – 임대시간 종료시 재 IP 신청
  3. Lease time calculation – 임대시간 계산
  4. easy code read – 가독성이 좋게 코드 다듬기

여기까지입니다.

코드를 그대로 Copy하셔서 LPCXpresso에 붙여넣기 하신뒤에 보시면 좀 더 보기 편하실거에요.

 

이 후 프로젝트는 DHCP를 할당받았으니깐 이제 여기에 DNS까지 이용해서 도메인의 IP를 알아보는 것을 업로드하겠습니다 !

 

감사합니다.

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중