Fork of original library, increased Tx buffer to 16kB

Dependents:   W5500-SNTPClient-example

Committer:
star297
Date:
Thu May 02 20:47:25 2019 +0000
Revision:
0:e9275bdfa393
First commit

Who changed what in which revision?

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