This is WIZnet Ethernet Interface using Hardware TCP/IP chip, W5500, W5200 and W5100. One of them can be selected by enabling it in wiznet.h.

Dependents:   bigthingRecfinal

Fork of WIZnet_Library by WIZnet

Committer:
rohangala
Date:
Tue Mar 15 11:36:55 2016 +0000
Revision:
9:8b3bc4434031
Parent:
0:b72d22e10709
final without caliberated;

Who changed what in which revision?

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