Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
DHCPClient.cpp
00001 // DHCPClient.cpp 2012/4/21 00002 // DHCP Client for WIZ820io(W5200) 00003 #include "mbed.h" 00004 #include "w5200.h" 00005 //#include "UDPSocket.h" 00006 #include "DHCPClient.h" 00007 //#define __DEBUG 00008 #include "dbg/dbg.h" 00009 00010 #ifdef __DEBUG 00011 #define DBG2(...) do{ DebugStream::debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); DebugStream::debug(__VA_ARGS__); } while(0); 00012 #else 00013 #define DBG2(...) while(0); 00014 #endif //__DEBUG 00015 00016 //#define DEBUG 00017 00018 #ifdef DEBUG 00019 #include "Utils.h" 00020 #define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) 00021 #else //DEBUG 00022 #define PRINT_FUNC() 00023 #endif //DEBUG 00024 00025 int DHCPClient::discover(uint8_t buf[], int size) { 00026 memset(buf, 0x00, size); 00027 const uint8_t headers[] = {0x01,0x01,0x06,0x00, 00028 0x12,0x34,0x56,0x78}; // xid 00029 memcpy(buf, headers, sizeof(headers)); 00030 int t = clock(); 00031 xid[0] = t<<24; 00032 xid[1] = t<<16; 00033 xid[2] = t<<8; 00034 xid[3] = t; 00035 memcpy(buf+DHCP_OFFSET_XID, xid, 4); 00036 W5200.getMACAddress(buf+DHCP_OFFSET_CHADDR); 00037 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00038 0x35,0x01,0x01, // DHCP DISCOVER 00039 0xff}; 00040 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); 00041 uint8_t ip[4] = {0,0,0,0}; 00042 W5200.setIPAddress(ip); 00043 return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); 00044 } 00045 00046 int DHCPClient::request(uint8_t buf[], int size) { 00047 memset(buf, 0x00, size); 00048 const uint8_t headers[] = {0x01,0x01,0x06,0x00, 00049 0x12,0x34,0x56,0x78}; // xid 00050 memcpy(buf, headers, sizeof(headers)); 00051 memcpy(buf+DHCP_OFFSET_XID, xid, 4); 00052 memcpy(buf+DHCP_OFFSET_YIADDR, yiaddr, 4); 00053 W5200.getMACAddress(buf+DHCP_OFFSET_CHADDR); 00054 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00055 0x35,0x01,0x03, // DHCP REQUEST 00056 0x32,0x04,0x00,0x00,0x00,0x00, // request IP 00057 0xff}; 00058 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); 00059 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE+9, yiaddr, 4); 00060 return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); 00061 } 00062 00063 int DHCPClient::offer_ack(uint8_t buf[], int size) { 00064 memcpy(yiaddr, &buf[DHCP_OFFSET_YIADDR], 4); 00065 uint8_t *p; 00066 int msg_type = -1; 00067 p = buf + DHCP_OFFSET_OPTIONS; 00068 while(*p != 0xff && p < (uint8_t*)&buf[DHCP_MAX_PACKET_SIZE]) { 00069 int code = *p++; 00070 if (code == 0x00) { 00071 continue; 00072 } 00073 int len = *p++; 00074 #ifdef DEBUG 00075 char codeStr[24]; 00076 snprintf(codeStr, sizeof(codeStr), "DHCP option: %d", code); 00077 printfBytes(codeStr, p, len); 00078 #endif //DEBUG 00079 if (code == 53) { 00080 msg_type = *p; 00081 } else if (code == 1) { 00082 memcpy(netmask, p, 4); // Subnet mask address 00083 } else if (code == 3) { 00084 memcpy(gateway, p, 4); // Gateway IP address 00085 } else if (code == 6) {// DNS 00086 memcpy(dnsaddr, p, 4); 00087 } 00088 p += len; 00089 } 00090 return msg_type; 00091 } 00092 00093 bool DHCPClient::verify(uint8_t buf[], int len) { 00094 if (len < DHCP_OFFSET_OPTIONS) { 00095 return false; 00096 } 00097 if (buf[DHCP_OFFSET_OP] != 0x02) { 00098 return false; 00099 } 00100 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { 00101 return false; 00102 } 00103 return true; 00104 } 00105 00106 void DHCPClient::callback(UDPSocketEvent e) 00107 { 00108 PRINT_FUNC(); 00109 uint8_t buf[DHCP_MAX_PACKET_SIZE]; 00110 Host host; 00111 int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host); 00112 if (!verify(buf, len)) { 00113 return; 00114 } 00115 int r = offer_ack(buf, len); 00116 if (r == 2) { // OFFER 00117 request(buf, 300); 00118 Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast 00119 m_udp->sendto((char*)buf, 300, &server); 00120 } else if (r == 5) { // ACK 00121 exit_flag = true; 00122 } 00123 } 00124 00125 int DHCPClient::setup(int timeout_ms) 00126 { 00127 PRINT_FUNC(); 00128 int interval_ms = 2000; // 2000msec 00129 if (timeout_ms < interval_ms) { 00130 interval_ms = timeout_ms; 00131 } 00132 m_retry = 0; 00133 m_interval.start(); 00134 m_udp = new UDPSocket; 00135 m_udp->setOnEvent(this, &DHCPClient::callback); 00136 Host local(IpAddr(0,0,0,0), 68); 00137 Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast 00138 m_udp->bind(local); 00139 uint8_t buf[300]; 00140 discover(buf, sizeof(buf)); 00141 m_udp->sendto((char*)buf, sizeof(buf), &server); 00142 m_interval.reset(); 00143 exit_flag = false; 00144 int err = 0; 00145 while(1) { 00146 Net::poll(); 00147 if (exit_flag) { 00148 DBG2("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); 00149 break; 00150 } 00151 if (m_interval.read_ms() > interval_ms) { 00152 DBG2("m_retry: %d\n", m_retry); 00153 if (++m_retry >= (timeout_ms/interval_ms)) { 00154 err = -1; 00155 break; 00156 } 00157 m_udp->sendto((char*)buf, sizeof(buf), &server); 00158 m_interval.reset(); 00159 } 00160 #ifdef DEBUG 00161 wait_ms(500); 00162 #endif //DEBUG 00163 } 00164 delete m_udp; 00165 return err; 00166 } 00167 00168 DHCPClient::DHCPClient() { 00169 m_udp = NULL; 00170 }
Generated on Tue Jul 12 2022 13:04:14 by
1.7.2