자, 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를 확인해주세요.
- Getting Started - getting_started#hello_world
- Getting Started - Firmware Upload
W5500-EVB의 Application 예제들은 GITHUB이라는 사이트에 업로드 되어 있습니다. 참조해주세요.
https://github.com/Wiznet/ioLibrary_Driver
자, 이제 코딩을 올려보도록 하겠습니다. 분명 너무 길어서 무슨 코드인지 한번에 알아보기는 어려우실 거에요. 일단 WIZnet사에서 제공하는 ioLibrary에는 DHCP도 있습니다.
하지만, DHCP를 어떻게 만드는지는 모르기 때문에 저는 실제로 제작해보기로 했습니다. 다소 코드가 중구난방이고 어려워보일 수도 있지만 참고 봐주셨으면 합니다... ㅎㅎ
[code language="c"] /* =============================================================================== 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 ; } [/code]
코드가 생각보다 많이 길어요.
코드 구현은 DHCP Client를 구성해서 IP를 할당받은 것 까지 하였습니다.
추가적으로 구현되어야할 기능은,
- Timeout - 일정시간 이상 응답없으면 발생하는 Delay
- ReRequest - 임대시간 종료시 재 IP 신청
- Lease time calculation - 임대시간 계산
- easy code read - 가독성이 좋게 코드 다듬기
여기까지입니다.
코드를 그대로 Copy하셔서 LPCXpresso에 붙여넣기 하신뒤에 보시면 좀 더 보기 편하실거에요.
이 후 프로젝트는 DHCP를 할당받았으니깐 이제 여기에 DNS까지 이용해서 도메인의 IP를 알아보는 것을 업로드하겠습니다 !
감사합니다.