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.
Fork of WIZnetInterface 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 zero[] = { 0, 0, 0, 0 }; 00021 const uint8_t header[] = {0x01,0x01,0x06,0x00}; 00022 add_buf((uint8_t*)header, sizeof(header)); 00023 uint32_t x = time(NULL) + rand(); 00024 xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x; 00025 add_buf(xid, 4); // transaction id 00026 add_buf((uint8_t*)zero, 2); // seconds elapsed 00027 add_buf((uint8_t*)zero, 2); // bootp flags 00028 add_buf((uint8_t*)zero, 4); // requester ip address 00029 add_buf((uint8_t*)zero, 4); // client ip address 00030 add_buf((uint8_t*)zero, 4); // next server ip address 00031 add_buf((uint8_t*)zero, 4); // relay agent ip address 00032 add_buf(chaddr, 6); // MAC address 00033 fill_buf(10, 0x00); // padding 00034 fill_buf(192, 0x00); 00035 const uint8_t options[] = {0x63,0x82,0x53,0x63, // DHCP_MAGIC_COOKIE 00036 OPT_DHCP_MESSAGE, 1, DHCPDISCOVER, // // DHCP message, len, discover 00037 OPT_PARAMETER_REQ, 5, OPT_SUBNET_MASK, OPT_ROUTER, OPT_TIME_SERVER, OPT_DOMAIN_NAME, OPT_DNS }; 00038 add_buf((uint8_t*)options, sizeof(options)); 00039 if (_hostname) { 00040 int hlen = strlen(_hostname); 00041 add_buf(OPT_HOSTNAME); 00042 add_buf(hlen); 00043 add_buf((uint8_t *)_hostname, hlen); 00044 } 00045 add_option(OPT_END); 00046 00047 return m_pos; 00048 } 00049 00050 int DHCPClient::request() 00051 { 00052 m_pos = 0; 00053 const uint8_t zero[] = { 0, 0, 0, 0 }; 00054 const uint8_t header[] = {0x01,0x01,0x06,0x00}; 00055 add_buf((uint8_t*)header, sizeof(header)); 00056 add_buf(xid, 4); // transaction id 00057 add_buf((uint8_t*)zero, 2); // seconds elapsed 00058 add_buf((uint8_t*)zero, 2); // bootp flags 00059 add_buf((uint8_t*)zero, 4); // requester ip address 00060 add_buf((uint8_t*)zero, 4); // client ip address 00061 add_buf(siaddr, 4); // next server ip address 00062 add_buf((uint8_t*)zero, 4); // relay agent ip address (giaddr) 00063 add_buf(chaddr, 6); // MAC address 00064 fill_buf(10, 0x00); // padding 00065 fill_buf(192, 0x00); 00066 const uint8_t options[] = {0x63,0x82,0x53,0x63, // DHCP_MAGIC_COOKIE 00067 OPT_DHCP_MESSAGE,1, DHCPREQUEST, // DHCP message, len, request 00068 OPT_PARAMETER_REQ, 5, OPT_SUBNET_MASK, OPT_ROUTER, OPT_TIME_SERVER, OPT_DOMAIN_NAME, OPT_DNS }; 00069 add_buf((uint8_t*)options, sizeof(options)); 00070 add_option(OPT_IP_ADDR_REQ, yiaddr, 4); 00071 add_option(OPT_SERVER_IDENT, siaddr, 4); 00072 if (_hostname) { 00073 int hlen = strlen(_hostname); 00074 add_buf(OPT_HOSTNAME); 00075 add_buf(hlen); 00076 add_buf((uint8_t *)_hostname, hlen); 00077 } 00078 add_option(OPT_END); 00079 return m_pos; 00080 } 00081 00082 int DHCPClient::offer(uint8_t buf[], int size) { 00083 memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4); 00084 memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4); 00085 00086 memset(dnsaddr, 0, sizeof(dnsaddr)); 00087 memset(gateway, 0, sizeof(gateway)); 00088 memset(netmask, 0, sizeof(netmask)); 00089 memset(timesrv, 0, sizeof(timesrv)); 00090 memset(leaseTime, 0, sizeof(leaseTime)); 00091 00092 uint8_t *p; 00093 int msg_type = -1; 00094 p = buf + DHCP_OFFSET_OPTIONS; 00095 while(*p != OPT_END && p < (buf+size)) { 00096 uint8_t code = *p++; 00097 if (code == 0) { // Pad Option 00098 continue; 00099 } 00100 int len = *p++; 00101 00102 DBG("DHCP option: %d\r\n", code); 00103 DBG_HEX(p, len); 00104 00105 switch(code) { 00106 case OPT_DHCP_MESSAGE: 00107 msg_type = *p; 00108 break; 00109 case OPT_SUBNET_MASK: 00110 memcpy(netmask, p, 4); 00111 break; 00112 case OPT_ROUTER: 00113 memcpy(gateway, p, 4); 00114 break; 00115 case OPT_DNS: 00116 memcpy(dnsaddr, p, 4); 00117 break; 00118 case OPT_TIME_SERVER: 00119 memcpy(timesrv, p, 4); 00120 break; 00121 case OPT_ADDR_LEASE_TIME: 00122 memcpy(leaseTime, p, 4); 00123 break; 00124 case OPT_DOMAIN_NAME: 00125 { 00126 int cplen = len; 00127 if (cplen > 63) 00128 cplen = 63; // max domain name 00129 if (domainName) { 00130 free(domainName); 00131 domainName = NULL; 00132 } 00133 if (cplen) { 00134 domainName = (char *)calloc(1, cplen+1); 00135 memcpy(domainName, p, cplen); // zero term is already here via calloc 00136 } 00137 } 00138 break; 00139 case OPT_SERVER_IDENT: 00140 memcpy(siaddr, p, 4); 00141 break; 00142 } 00143 p += len; 00144 } 00145 return msg_type; 00146 } 00147 00148 bool DHCPClient::verify(uint8_t buf[], int len) { 00149 if (len < DHCP_OFFSET_OPTIONS) { 00150 return false; 00151 } 00152 if (buf[DHCP_OFFSET_OP] != 0x02) { 00153 return false; 00154 } 00155 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { 00156 return false; 00157 } 00158 return true; 00159 } 00160 00161 void DHCPClient::callback() 00162 { 00163 Endpoint host; 00164 int recv_len = m_udp->receiveFrom(host, (char*)m_buf, sizeof(m_buf)); 00165 if (recv_len < 0) { 00166 return; 00167 } 00168 if (!verify(m_buf, recv_len)) { 00169 return; 00170 } 00171 int r = offer(m_buf, recv_len); 00172 if (r == DHCPOFFER) { 00173 int send_size = request(); 00174 m_udp->sendTo(m_server, (char*)m_buf, send_size); 00175 } else if (r == DHCPACK) { 00176 exit_flag = true; 00177 } 00178 } 00179 00180 void DHCPClient::add_buf(uint8_t c) 00181 { 00182 m_buf[m_pos++] = c; 00183 } 00184 00185 void DHCPClient::add_buf(uint8_t* buf, int len) 00186 { 00187 for(int i = 0; i < len; i++) { 00188 add_buf(buf[i]); 00189 } 00190 } 00191 00192 void DHCPClient::fill_buf(int len, uint8_t data) 00193 { 00194 while(len-- > 0) { 00195 add_buf(data); 00196 } 00197 } 00198 00199 void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len) 00200 { 00201 add_buf(code); 00202 if (len > 0) { 00203 add_buf((uint8_t)len); 00204 add_buf(buf, len); 00205 } 00206 } 00207 00208 int DHCPClient::setup(const char *hostnane, int timeout_ms) 00209 { 00210 eth = WIZnet_Chip::getInstance(); 00211 if (eth == NULL) { 00212 return -1; 00213 } 00214 _hostname = hostnane; 00215 eth->reg_rd_mac(SHAR, chaddr); 00216 int interval_ms = 5*1000; // 5000msec 00217 if (timeout_ms < interval_ms) { 00218 interval_ms = timeout_ms; 00219 } 00220 m_udp = new UDPSocket; 00221 m_udp->init(); 00222 m_udp->set_blocking(false); 00223 eth->reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0" 00224 m_udp->bind(DHCP_CLIENT_PORT); // local port 00225 m_server.set_address("255.255.255.255", DHCP_SERVER_PORT); // DHCP broadcast 00226 exit_flag = false; 00227 int err = 0; 00228 int seq = 0; 00229 int send_size; 00230 while(!exit_flag) { 00231 switch(seq) { 00232 case 0: 00233 m_retry = 0; 00234 seq++; 00235 break; 00236 case 1: 00237 send_size = discover(); 00238 m_udp->sendTo(m_server, (char*)m_buf, send_size); 00239 m_interval.reset(); 00240 m_interval.start(); 00241 seq++; 00242 break; 00243 case 2: 00244 callback(); 00245 if (m_interval.read_ms() > interval_ms) { 00246 DBG("m_retry: %d\n", m_retry); 00247 if (++m_retry >= (timeout_ms/interval_ms)) { 00248 err = -1; 00249 exit_flag = true; 00250 } 00251 seq--; 00252 } 00253 break; 00254 } 00255 } 00256 DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); 00257 delete m_udp; 00258 return err; 00259 } 00260 00261 DHCPClient::DHCPClient() { 00262 domainName = NULL; 00263 } 00264 00265 DHCPClient::~DHCPClient() { 00266 if (domainName) 00267 free(domainName); 00268 }
Generated on Tue Jul 12 2022 17:13:34 by
1.7.2
