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_Ricky by
Socket/DHCPClient.cpp@15:24a9f2df2145, 2015-06-22 (annotated)
- Committer:
- embeddist
- Date:
- Mon Jun 22 09:11:47 2015 +0000
- Revision:
- 15:24a9f2df2145
- Parent:
- 0:6f28332c466f
- fixed DHCP bug.; - fixed link check func.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Soohwan Kim |
0:6f28332c466f | 1 | // DHCPClient.cpp 2013/4/10 |
Soohwan Kim |
0:6f28332c466f | 2 | #include "mbed.h" |
Soohwan Kim |
0:6f28332c466f | 3 | #include "mbed_debug.h" |
Soohwan Kim |
0:6f28332c466f | 4 | #include "UDPSocket.h" |
Soohwan Kim |
0:6f28332c466f | 5 | #include "DHCPClient.h" |
Soohwan Kim |
0:6f28332c466f | 6 | |
Soohwan Kim |
0:6f28332c466f | 7 | #define DBG_DHCP 0 |
Soohwan Kim |
0:6f28332c466f | 8 | |
Soohwan Kim |
0:6f28332c466f | 9 | #if DBG_DHCP |
Soohwan Kim |
0:6f28332c466f | 10 | #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0); |
Soohwan Kim |
0:6f28332c466f | 11 | #define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0); |
Soohwan Kim |
0:6f28332c466f | 12 | #else |
Soohwan Kim |
0:6f28332c466f | 13 | #define DBG(...) while(0); |
Soohwan Kim |
0:6f28332c466f | 14 | #define DBG_HEX(A,B) while(0); |
Soohwan Kim |
0:6f28332c466f | 15 | #endif |
Soohwan Kim |
0:6f28332c466f | 16 | |
Soohwan Kim |
0:6f28332c466f | 17 | int DHCPClient::discover() |
Soohwan Kim |
0:6f28332c466f | 18 | { |
Soohwan Kim |
0:6f28332c466f | 19 | m_pos = 0; |
Soohwan Kim |
0:6f28332c466f | 20 | const uint8_t header[] = {0x01,0x01,0x06,0x00}; |
Soohwan Kim |
0:6f28332c466f | 21 | add_buf((uint8_t*)header, sizeof(header)); |
Soohwan Kim |
0:6f28332c466f | 22 | uint32_t x = time(NULL) + rand(); |
Soohwan Kim |
0:6f28332c466f | 23 | xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x; |
Soohwan Kim |
0:6f28332c466f | 24 | add_buf(xid, 4); |
Soohwan Kim |
0:6f28332c466f | 25 | fill_buf(20, 0x00); |
Soohwan Kim |
0:6f28332c466f | 26 | add_buf(chaddr, 6); |
Soohwan Kim |
0:6f28332c466f | 27 | fill_buf(10+192, 0x00); |
Soohwan Kim |
0:6f28332c466f | 28 | const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie |
Soohwan Kim |
0:6f28332c466f | 29 | 53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover |
Soohwan Kim |
0:6f28332c466f | 30 | 55,4,1,3,15,6, |
Soohwan Kim |
0:6f28332c466f | 31 | 255}; |
Soohwan Kim |
0:6f28332c466f | 32 | add_buf((uint8_t*)options, sizeof(options)); |
Soohwan Kim |
0:6f28332c466f | 33 | return m_pos; |
Soohwan Kim |
0:6f28332c466f | 34 | } |
Soohwan Kim |
0:6f28332c466f | 35 | |
Soohwan Kim |
0:6f28332c466f | 36 | int DHCPClient::request() |
Soohwan Kim |
0:6f28332c466f | 37 | { |
Soohwan Kim |
0:6f28332c466f | 38 | m_pos = 0; |
Soohwan Kim |
0:6f28332c466f | 39 | const uint8_t header[] = {0x01,0x01,0x06,0x00}; |
Soohwan Kim |
0:6f28332c466f | 40 | add_buf((uint8_t*)header, sizeof(header)); |
Soohwan Kim |
0:6f28332c466f | 41 | add_buf(xid, 4); |
Soohwan Kim |
0:6f28332c466f | 42 | fill_buf(12, 0x00); |
Soohwan Kim |
0:6f28332c466f | 43 | add_buf(siaddr, 4); |
Soohwan Kim |
0:6f28332c466f | 44 | fill_buf(4, 0x00); // giaddr |
Soohwan Kim |
0:6f28332c466f | 45 | add_buf(chaddr, 6); |
Soohwan Kim |
0:6f28332c466f | 46 | fill_buf(10+192, 0x00); |
Soohwan Kim |
0:6f28332c466f | 47 | const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie |
Soohwan Kim |
0:6f28332c466f | 48 | 53,1,DHCPREQUEST, // DHCP option 53: DHCP Request |
Soohwan Kim |
0:6f28332c466f | 49 | 55,4,1,3,15,6, // DHCP option 55: |
Soohwan Kim |
0:6f28332c466f | 50 | }; |
Soohwan Kim |
0:6f28332c466f | 51 | add_buf((uint8_t*)options, sizeof(options)); |
Soohwan Kim |
0:6f28332c466f | 52 | add_option(50, yiaddr, 4); |
Soohwan Kim |
0:6f28332c466f | 53 | add_option(54, siaddr, 4); |
Soohwan Kim |
0:6f28332c466f | 54 | add_option(255); |
Soohwan Kim |
0:6f28332c466f | 55 | return m_pos; |
Soohwan Kim |
0:6f28332c466f | 56 | } |
Soohwan Kim |
0:6f28332c466f | 57 | |
Soohwan Kim |
0:6f28332c466f | 58 | int DHCPClient::offer(uint8_t buf[], int size) { |
Soohwan Kim |
0:6f28332c466f | 59 | memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4); |
Soohwan Kim |
0:6f28332c466f | 60 | memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4); |
Soohwan Kim |
0:6f28332c466f | 61 | uint8_t *p; |
Soohwan Kim |
0:6f28332c466f | 62 | int msg_type = -1; |
Soohwan Kim |
0:6f28332c466f | 63 | p = buf + DHCP_OFFSET_OPTIONS; |
Soohwan Kim |
0:6f28332c466f | 64 | while(*p != 255 && p < (buf+size)) { |
Soohwan Kim |
0:6f28332c466f | 65 | uint8_t code = *p++; |
Soohwan Kim |
0:6f28332c466f | 66 | if (code == 0) { // Pad Option |
Soohwan Kim |
0:6f28332c466f | 67 | continue; |
Soohwan Kim |
0:6f28332c466f | 68 | } |
Soohwan Kim |
0:6f28332c466f | 69 | int len = *p++; |
Soohwan Kim |
0:6f28332c466f | 70 | |
Soohwan Kim |
0:6f28332c466f | 71 | DBG("DHCP option: %d\r\n", code); |
Soohwan Kim |
0:6f28332c466f | 72 | DBG_HEX(p, len); |
Soohwan Kim |
0:6f28332c466f | 73 | |
Soohwan Kim |
0:6f28332c466f | 74 | switch(code) { |
Soohwan Kim |
0:6f28332c466f | 75 | case 53: |
Soohwan Kim |
0:6f28332c466f | 76 | msg_type = *p; |
Soohwan Kim |
0:6f28332c466f | 77 | break; |
Soohwan Kim |
0:6f28332c466f | 78 | case 1: |
Soohwan Kim |
0:6f28332c466f | 79 | memcpy(netmask, p, 4); // Subnet mask address |
Soohwan Kim |
0:6f28332c466f | 80 | break; |
Soohwan Kim |
0:6f28332c466f | 81 | case 3: |
Soohwan Kim |
0:6f28332c466f | 82 | memcpy(gateway, p, 4); // Gateway IP address |
Soohwan Kim |
0:6f28332c466f | 83 | break; |
Soohwan Kim |
0:6f28332c466f | 84 | case 6: // DNS server |
Soohwan Kim |
0:6f28332c466f | 85 | memcpy(dnsaddr, p, 4); |
Soohwan Kim |
0:6f28332c466f | 86 | break; |
Soohwan Kim |
0:6f28332c466f | 87 | case 51: // IP lease time |
Soohwan Kim |
0:6f28332c466f | 88 | break; |
Soohwan Kim |
0:6f28332c466f | 89 | case 54: // DHCP server |
Soohwan Kim |
0:6f28332c466f | 90 | memcpy(siaddr, p, 4); |
Soohwan Kim |
0:6f28332c466f | 91 | break; |
Soohwan Kim |
0:6f28332c466f | 92 | } |
Soohwan Kim |
0:6f28332c466f | 93 | p += len; |
Soohwan Kim |
0:6f28332c466f | 94 | } |
Soohwan Kim |
0:6f28332c466f | 95 | return msg_type; |
Soohwan Kim |
0:6f28332c466f | 96 | } |
Soohwan Kim |
0:6f28332c466f | 97 | |
Soohwan Kim |
0:6f28332c466f | 98 | bool DHCPClient::verify(uint8_t buf[], int len) { |
Soohwan Kim |
0:6f28332c466f | 99 | if (len < DHCP_OFFSET_OPTIONS) { |
Soohwan Kim |
0:6f28332c466f | 100 | return false; |
Soohwan Kim |
0:6f28332c466f | 101 | } |
Soohwan Kim |
0:6f28332c466f | 102 | if (buf[DHCP_OFFSET_OP] != 0x02) { |
Soohwan Kim |
0:6f28332c466f | 103 | return false; |
Soohwan Kim |
0:6f28332c466f | 104 | } |
Soohwan Kim |
0:6f28332c466f | 105 | if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { |
Soohwan Kim |
0:6f28332c466f | 106 | return false; |
Soohwan Kim |
0:6f28332c466f | 107 | } |
Soohwan Kim |
0:6f28332c466f | 108 | return true; |
Soohwan Kim |
0:6f28332c466f | 109 | } |
Soohwan Kim |
0:6f28332c466f | 110 | |
Soohwan Kim |
0:6f28332c466f | 111 | void DHCPClient::callback() |
Soohwan Kim |
0:6f28332c466f | 112 | { |
embeddist | 15:24a9f2df2145 | 113 | Endpoint host; |
embeddist | 15:24a9f2df2145 | 114 | int recv_len = m_udp->receiveFrom(host, (char*)m_buf, sizeof(m_buf)); |
Soohwan Kim |
0:6f28332c466f | 115 | if (recv_len < 0) { |
Soohwan Kim |
0:6f28332c466f | 116 | return; |
Soohwan Kim |
0:6f28332c466f | 117 | } |
Soohwan Kim |
0:6f28332c466f | 118 | if (!verify(m_buf, recv_len)) { |
Soohwan Kim |
0:6f28332c466f | 119 | return; |
Soohwan Kim |
0:6f28332c466f | 120 | } |
Soohwan Kim |
0:6f28332c466f | 121 | int r = offer(m_buf, recv_len); |
Soohwan Kim |
0:6f28332c466f | 122 | if (r == DHCPOFFER) { |
Soohwan Kim |
0:6f28332c466f | 123 | int send_size = request(); |
Soohwan Kim |
0:6f28332c466f | 124 | m_udp->sendTo(m_server, (char*)m_buf, send_size); |
Soohwan Kim |
0:6f28332c466f | 125 | } else if (r == DHCPACK) { |
Soohwan Kim |
0:6f28332c466f | 126 | exit_flag = true; |
Soohwan Kim |
0:6f28332c466f | 127 | } |
Soohwan Kim |
0:6f28332c466f | 128 | } |
Soohwan Kim |
0:6f28332c466f | 129 | |
Soohwan Kim |
0:6f28332c466f | 130 | void DHCPClient::add_buf(uint8_t c) |
Soohwan Kim |
0:6f28332c466f | 131 | { |
Soohwan Kim |
0:6f28332c466f | 132 | m_buf[m_pos++] = c; |
Soohwan Kim |
0:6f28332c466f | 133 | } |
Soohwan Kim |
0:6f28332c466f | 134 | |
Soohwan Kim |
0:6f28332c466f | 135 | void DHCPClient::add_buf(uint8_t* buf, int len) |
Soohwan Kim |
0:6f28332c466f | 136 | { |
Soohwan Kim |
0:6f28332c466f | 137 | for(int i = 0; i < len; i++) { |
Soohwan Kim |
0:6f28332c466f | 138 | add_buf(buf[i]); |
Soohwan Kim |
0:6f28332c466f | 139 | } |
Soohwan Kim |
0:6f28332c466f | 140 | } |
Soohwan Kim |
0:6f28332c466f | 141 | |
Soohwan Kim |
0:6f28332c466f | 142 | void DHCPClient::fill_buf(int len, uint8_t data) |
Soohwan Kim |
0:6f28332c466f | 143 | { |
Soohwan Kim |
0:6f28332c466f | 144 | while(len-- > 0) { |
Soohwan Kim |
0:6f28332c466f | 145 | add_buf(data); |
Soohwan Kim |
0:6f28332c466f | 146 | } |
Soohwan Kim |
0:6f28332c466f | 147 | } |
Soohwan Kim |
0:6f28332c466f | 148 | |
Soohwan Kim |
0:6f28332c466f | 149 | void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len) |
Soohwan Kim |
0:6f28332c466f | 150 | { |
Soohwan Kim |
0:6f28332c466f | 151 | add_buf(code); |
Soohwan Kim |
0:6f28332c466f | 152 | if (len > 0) { |
Soohwan Kim |
0:6f28332c466f | 153 | add_buf((uint8_t)len); |
Soohwan Kim |
0:6f28332c466f | 154 | add_buf(buf, len); |
Soohwan Kim |
0:6f28332c466f | 155 | } |
Soohwan Kim |
0:6f28332c466f | 156 | } |
Soohwan Kim |
0:6f28332c466f | 157 | |
Soohwan Kim |
0:6f28332c466f | 158 | int DHCPClient::setup(int timeout_ms) |
Soohwan Kim |
0:6f28332c466f | 159 | { |
Soohwan Kim |
0:6f28332c466f | 160 | eth = WIZnet_Chip::getInstance(); |
Soohwan Kim |
0:6f28332c466f | 161 | if (eth == NULL) { |
Soohwan Kim |
0:6f28332c466f | 162 | return -1; |
Soohwan Kim |
0:6f28332c466f | 163 | } |
Soohwan Kim |
0:6f28332c466f | 164 | eth->reg_rd_mac(SHAR, chaddr); |
Soohwan Kim |
0:6f28332c466f | 165 | int interval_ms = 5*1000; // 5000msec |
Soohwan Kim |
0:6f28332c466f | 166 | if (timeout_ms < interval_ms) { |
Soohwan Kim |
0:6f28332c466f | 167 | interval_ms = timeout_ms; |
Soohwan Kim |
0:6f28332c466f | 168 | } |
Soohwan Kim |
0:6f28332c466f | 169 | m_udp = new UDPSocket; |
Soohwan Kim |
0:6f28332c466f | 170 | m_udp->init(); |
Soohwan Kim |
0:6f28332c466f | 171 | m_udp->set_blocking(false); |
Soohwan Kim |
0:6f28332c466f | 172 | eth->reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0" |
Soohwan Kim |
0:6f28332c466f | 173 | m_udp->bind(68); // local port |
Soohwan Kim |
0:6f28332c466f | 174 | m_server.set_address("255.255.255.255", 67); // DHCP broadcast |
Soohwan Kim |
0:6f28332c466f | 175 | exit_flag = false; |
Soohwan Kim |
0:6f28332c466f | 176 | int err = 0; |
Soohwan Kim |
0:6f28332c466f | 177 | int seq = 0; |
Soohwan Kim |
0:6f28332c466f | 178 | int send_size; |
Soohwan Kim |
0:6f28332c466f | 179 | while(!exit_flag) { |
Soohwan Kim |
0:6f28332c466f | 180 | switch(seq) { |
Soohwan Kim |
0:6f28332c466f | 181 | case 0: |
Soohwan Kim |
0:6f28332c466f | 182 | m_retry = 0; |
Soohwan Kim |
0:6f28332c466f | 183 | seq++; |
Soohwan Kim |
0:6f28332c466f | 184 | break; |
Soohwan Kim |
0:6f28332c466f | 185 | case 1: |
Soohwan Kim |
0:6f28332c466f | 186 | send_size = discover(); |
Soohwan Kim |
0:6f28332c466f | 187 | m_udp->sendTo(m_server, (char*)m_buf, send_size); |
Soohwan Kim |
0:6f28332c466f | 188 | m_interval.reset(); |
Soohwan Kim |
0:6f28332c466f | 189 | m_interval.start(); |
Soohwan Kim |
0:6f28332c466f | 190 | seq++; |
Soohwan Kim |
0:6f28332c466f | 191 | break; |
Soohwan Kim |
0:6f28332c466f | 192 | case 2: |
Soohwan Kim |
0:6f28332c466f | 193 | callback(); |
Soohwan Kim |
0:6f28332c466f | 194 | if (m_interval.read_ms() > interval_ms) { |
Soohwan Kim |
0:6f28332c466f | 195 | DBG("m_retry: %d\n", m_retry); |
Soohwan Kim |
0:6f28332c466f | 196 | if (++m_retry >= (timeout_ms/interval_ms)) { |
Soohwan Kim |
0:6f28332c466f | 197 | err = -1; |
Soohwan Kim |
0:6f28332c466f | 198 | exit_flag = true; |
Soohwan Kim |
0:6f28332c466f | 199 | } |
Soohwan Kim |
0:6f28332c466f | 200 | seq--; |
Soohwan Kim |
0:6f28332c466f | 201 | } |
Soohwan Kim |
0:6f28332c466f | 202 | break; |
Soohwan Kim |
0:6f28332c466f | 203 | } |
Soohwan Kim |
0:6f28332c466f | 204 | } |
Soohwan Kim |
0:6f28332c466f | 205 | DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); |
Soohwan Kim |
0:6f28332c466f | 206 | delete m_udp; |
Soohwan Kim |
0:6f28332c466f | 207 | return err; |
Soohwan Kim |
0:6f28332c466f | 208 | } |
Soohwan Kim |
0:6f28332c466f | 209 | |
Soohwan Kim |
0:6f28332c466f | 210 | DHCPClient::DHCPClient() { |
Soohwan Kim |
0:6f28332c466f | 211 | } |
Soohwan Kim |
0:6f28332c466f | 212 |