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