WIZnetInterface using namespace
Dependents: DualNetworkInterface-Basic
Fork of WIZnetInterface by
DHCPClient.cpp
00001 // DHCPClient.cpp 2013/4/10 00002 #include "mbed.h" 00003 #include "mbed_debug.h" 00004 #include "UDPSocket.hpp" 00005 #include "DHCPClient.hpp" 00006 00007 #define DBG_DHCP 0 00008 00009 #if DBG_DHCP 00010 #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0); 00011 #define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0); 00012 #else 00013 #define DBG(...) while(0); 00014 #define DBG_HEX(A,B) while(0); 00015 #endif 00016 00017 using namespace wiznet_space; 00018 00019 int DHCPClient::discover() 00020 { 00021 m_pos = 0; 00022 const uint8_t header[] = {0x01,0x01,0x06,0x00}; 00023 add_buf((uint8_t*)header, sizeof(header)); 00024 uint32_t x = time(NULL) + rand(); 00025 xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x; 00026 add_buf(xid, 4); 00027 fill_buf(20, 0x00); 00028 add_buf(chaddr, 6); 00029 fill_buf(10+192, 0x00); 00030 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00031 53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover 00032 55,4,1,3,15,6, 00033 255}; 00034 add_buf((uint8_t*)options, sizeof(options)); 00035 return m_pos; 00036 } 00037 00038 int DHCPClient::request() 00039 { 00040 m_pos = 0; 00041 const uint8_t header[] = {0x01,0x01,0x06,0x00}; 00042 add_buf((uint8_t*)header, sizeof(header)); 00043 add_buf(xid, 4); 00044 fill_buf(12, 0x00); 00045 add_buf(siaddr, 4); 00046 fill_buf(4, 0x00); // giaddr 00047 add_buf(chaddr, 6); 00048 fill_buf(10+192, 0x00); 00049 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00050 53,1,DHCPREQUEST, // DHCP option 53: DHCP Request 00051 55,4,1,3,15,6, // DHCP option 55: 00052 }; 00053 add_buf((uint8_t*)options, sizeof(options)); 00054 add_option(50, yiaddr, 4); 00055 add_option(54, siaddr, 4); 00056 add_option(255); 00057 return m_pos; 00058 } 00059 00060 int DHCPClient::offer(uint8_t buf[], int size) { 00061 memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4); 00062 memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4); 00063 uint8_t *p; 00064 int msg_type = -1; 00065 p = buf + DHCP_OFFSET_OPTIONS; 00066 while(*p != 255 && p < (buf+size)) { 00067 uint8_t code = *p++; 00068 if (code == 0) { // Pad Option 00069 continue; 00070 } 00071 int len = *p++; 00072 00073 DBG("DHCP option: %d\r\n", code); 00074 DBG_HEX(p, len); 00075 00076 switch(code) { 00077 case 53: 00078 msg_type = *p; 00079 break; 00080 case 1: 00081 memcpy(netmask, p, 4); // Subnet mask address 00082 break; 00083 case 3: 00084 memcpy(gateway, p, 4); // Gateway IP address 00085 break; 00086 case 6: // DNS server 00087 memcpy(dnsaddr, p, 4); 00088 break; 00089 case 51: // IP lease time 00090 break; 00091 case 54: // DHCP server 00092 memcpy(siaddr, p, 4); 00093 break; 00094 } 00095 p += len; 00096 } 00097 return msg_type; 00098 } 00099 00100 bool DHCPClient::verify(uint8_t buf[], int len) { 00101 if (len < DHCP_OFFSET_OPTIONS) { 00102 return false; 00103 } 00104 if (buf[DHCP_OFFSET_OP] != 0x02) { 00105 return false; 00106 } 00107 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { 00108 return false; 00109 } 00110 return true; 00111 } 00112 00113 void DHCPClient::callback() 00114 { 00115 Endpoint host; 00116 int recv_len = m_udp->receiveFrom(host, (char*)m_buf, sizeof(m_buf)); 00117 if (recv_len < 0) { 00118 return; 00119 } 00120 if (!verify(m_buf, recv_len)) { 00121 return; 00122 } 00123 int r = offer(m_buf, recv_len); 00124 if (r == DHCPOFFER) { 00125 int send_size = request(); 00126 m_udp->sendTo(m_server, (char*)m_buf, send_size); 00127 } else if (r == DHCPACK) { 00128 exit_flag = true; 00129 } 00130 } 00131 00132 void DHCPClient::add_buf(uint8_t c) 00133 { 00134 m_buf[m_pos++] = c; 00135 } 00136 00137 void DHCPClient::add_buf(uint8_t* buf, int len) 00138 { 00139 for(int i = 0; i < len; i++) { 00140 add_buf(buf[i]); 00141 } 00142 } 00143 00144 void DHCPClient::fill_buf(int len, uint8_t data) 00145 { 00146 while(len-- > 0) { 00147 add_buf(data); 00148 } 00149 } 00150 00151 void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len) 00152 { 00153 add_buf(code); 00154 if (len > 0) { 00155 add_buf((uint8_t)len); 00156 add_buf(buf, len); 00157 } 00158 } 00159 00160 int DHCPClient::setup(int timeout_ms) 00161 { 00162 eth = WIZnet_Chip::getInstance(); 00163 if (eth == NULL) { 00164 return -1; 00165 } 00166 eth->reg_rd_mac(SHAR, chaddr); 00167 int interval_ms = 5*1000; // 5000msec 00168 if (timeout_ms < interval_ms) { 00169 interval_ms = timeout_ms; 00170 } 00171 m_udp = new UDPSocket; 00172 m_udp->init(); 00173 m_udp->set_blocking(false); 00174 eth->reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0" 00175 m_udp->bind(68); // local port 00176 m_server.set_address("255.255.255.255", 67); // DHCP broadcast 00177 exit_flag = false; 00178 int err = 0; 00179 int seq = 0; 00180 int send_size; 00181 while(!exit_flag) { 00182 switch(seq) { 00183 case 0: 00184 m_retry = 0; 00185 seq++; 00186 break; 00187 case 1: 00188 send_size = discover(); 00189 m_udp->sendTo(m_server, (char*)m_buf, send_size); 00190 m_interval.reset(); 00191 m_interval.start(); 00192 seq++; 00193 break; 00194 case 2: 00195 callback(); 00196 if (m_interval.read_ms() > interval_ms) { 00197 DBG("m_retry: %d\n", m_retry); 00198 if (++m_retry >= (timeout_ms/interval_ms)) { 00199 err = -1; 00200 exit_flag = true; 00201 } 00202 seq--; 00203 } 00204 break; 00205 } 00206 } 00207 DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); 00208 delete m_udp; 00209 return err; 00210 } 00211 00212 DHCPClient::DHCPClient() { 00213 } 00214
Generated on Wed Jul 13 2022 05:21:37 by 1.7.2