WIZNet W5500 with additional enhancements

Fork of WIZnetInterface by WIZnet

Committer:
Helmut Tschemernjak
Date:
Thu Oct 12 12:19:11 2017 +0200
Revision:
38:67e763cdde02
Parent:
36:0ba2e8d5274a
Enable Interrupts for all sockets by default.
Added a Soft-Reset in the reset() functions which works perfect
when no Reset line is connected.

Who changed what in which revision?

UserRevisionLine numberNew 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;
Helmut Tschemernjak 36:0ba2e8d5274a 20 const uint8_t zero[] = { 0, 0, 0, 0 };
Soohwan Kim 0:6f28332c466f 21 const uint8_t header[] = {0x01,0x01,0x06,0x00};
Soohwan Kim 0:6f28332c466f 22 add_buf((uint8_t*)header, sizeof(header));
Soohwan Kim 0:6f28332c466f 23 uint32_t x = time(NULL) + rand();
Soohwan Kim 0:6f28332c466f 24 xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x;
Helmut Tschemernjak 36:0ba2e8d5274a 25 add_buf(xid, 4); // transaction id
Helmut Tschemernjak 36:0ba2e8d5274a 26 add_buf((uint8_t*)zero, 2); // seconds elapsed
Helmut Tschemernjak 36:0ba2e8d5274a 27 add_buf((uint8_t*)zero, 2); // bootp flags
Helmut Tschemernjak 36:0ba2e8d5274a 28 add_buf((uint8_t*)zero, 4); // requester ip address
Helmut Tschemernjak 36:0ba2e8d5274a 29 add_buf((uint8_t*)zero, 4); // client ip address
Helmut Tschemernjak 36:0ba2e8d5274a 30 add_buf((uint8_t*)zero, 4); // next server ip address
Helmut Tschemernjak 36:0ba2e8d5274a 31 add_buf((uint8_t*)zero, 4); // relay agent ip address
Helmut Tschemernjak 36:0ba2e8d5274a 32 add_buf(chaddr, 6); // MAC address
Helmut Tschemernjak 36:0ba2e8d5274a 33 fill_buf(10, 0x00); // padding
Helmut Tschemernjak 36:0ba2e8d5274a 34 fill_buf(192, 0x00);
Helmut Tschemernjak 35:fe3028eda085 35 const uint8_t options[] = {0x63,0x82,0x53,0x63, // DHCP_MAGIC_COOKIE
Helmut Tschemernjak 35:fe3028eda085 36 OPT_DHCP_MESSAGE, 1, DHCPDISCOVER, // // DHCP message, len, discover
Helmut Tschemernjak 36:0ba2e8d5274a 37 OPT_PARAMETER_REQ, 5, OPT_SUBNET_MASK, OPT_ROUTER, OPT_TIME_SERVER, OPT_DOMAIN_NAME, OPT_DNS };
Soohwan Kim 0:6f28332c466f 38 add_buf((uint8_t*)options, sizeof(options));
Helmut Tschemernjak 36:0ba2e8d5274a 39 if (_hostname) {
Helmut Tschemernjak 36:0ba2e8d5274a 40 int hlen = strlen(_hostname);
Helmut Tschemernjak 36:0ba2e8d5274a 41 add_buf(OPT_HOSTNAME);
Helmut Tschemernjak 36:0ba2e8d5274a 42 add_buf(hlen);
Helmut Tschemernjak 36:0ba2e8d5274a 43 add_buf((uint8_t *)_hostname, hlen);
Helmut Tschemernjak 36:0ba2e8d5274a 44 }
Helmut Tschemernjak 36:0ba2e8d5274a 45 add_option(OPT_END);
Helmut Tschemernjak 36:0ba2e8d5274a 46
Soohwan Kim 0:6f28332c466f 47 return m_pos;
Soohwan Kim 0:6f28332c466f 48 }
Soohwan Kim 0:6f28332c466f 49
Soohwan Kim 0:6f28332c466f 50 int DHCPClient::request()
Soohwan Kim 0:6f28332c466f 51 {
Soohwan Kim 0:6f28332c466f 52 m_pos = 0;
Helmut Tschemernjak 36:0ba2e8d5274a 53 const uint8_t zero[] = { 0, 0, 0, 0 };
Soohwan Kim 0:6f28332c466f 54 const uint8_t header[] = {0x01,0x01,0x06,0x00};
Soohwan Kim 0:6f28332c466f 55 add_buf((uint8_t*)header, sizeof(header));
Helmut Tschemernjak 36:0ba2e8d5274a 56 add_buf(xid, 4); // transaction id
Helmut Tschemernjak 36:0ba2e8d5274a 57 add_buf((uint8_t*)zero, 2); // seconds elapsed
Helmut Tschemernjak 36:0ba2e8d5274a 58 add_buf((uint8_t*)zero, 2); // bootp flags
Helmut Tschemernjak 36:0ba2e8d5274a 59 add_buf((uint8_t*)zero, 4); // requester ip address
Helmut Tschemernjak 36:0ba2e8d5274a 60 add_buf((uint8_t*)zero, 4); // client ip address
Helmut Tschemernjak 36:0ba2e8d5274a 61 add_buf(siaddr, 4); // next server ip address
Helmut Tschemernjak 36:0ba2e8d5274a 62 add_buf((uint8_t*)zero, 4); // relay agent ip address (giaddr)
Helmut Tschemernjak 36:0ba2e8d5274a 63 add_buf(chaddr, 6); // MAC address
Helmut Tschemernjak 36:0ba2e8d5274a 64 fill_buf(10, 0x00); // padding
Helmut Tschemernjak 36:0ba2e8d5274a 65 fill_buf(192, 0x00);
Helmut Tschemernjak 35:fe3028eda085 66 const uint8_t options[] = {0x63,0x82,0x53,0x63, // DHCP_MAGIC_COOKIE
Helmut Tschemernjak 35:fe3028eda085 67 OPT_DHCP_MESSAGE,1, DHCPREQUEST, // DHCP message, len, request
Helmut Tschemernjak 35:fe3028eda085 68 OPT_PARAMETER_REQ, 5, OPT_SUBNET_MASK, OPT_ROUTER, OPT_TIME_SERVER, OPT_DOMAIN_NAME, OPT_DNS };
Soohwan Kim 0:6f28332c466f 69 add_buf((uint8_t*)options, sizeof(options));
Helmut Tschemernjak 35:fe3028eda085 70 add_option(OPT_IP_ADDR_REQ, yiaddr, 4);
Helmut Tschemernjak 35:fe3028eda085 71 add_option(OPT_SERVER_IDENT, siaddr, 4);
Helmut Tschemernjak 36:0ba2e8d5274a 72 if (_hostname) {
Helmut Tschemernjak 36:0ba2e8d5274a 73 int hlen = strlen(_hostname);
Helmut Tschemernjak 36:0ba2e8d5274a 74 add_buf(OPT_HOSTNAME);
Helmut Tschemernjak 36:0ba2e8d5274a 75 add_buf(hlen);
Helmut Tschemernjak 36:0ba2e8d5274a 76 add_buf((uint8_t *)_hostname, hlen);
Helmut Tschemernjak 36:0ba2e8d5274a 77 }
Helmut Tschemernjak 35:fe3028eda085 78 add_option(OPT_END);
Soohwan Kim 0:6f28332c466f 79 return m_pos;
Soohwan Kim 0:6f28332c466f 80 }
Soohwan Kim 0:6f28332c466f 81
Soohwan Kim 0:6f28332c466f 82 int DHCPClient::offer(uint8_t buf[], int size) {
Soohwan Kim 0:6f28332c466f 83 memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4);
Helmut Tschemernjak 35:fe3028eda085 84 memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4);
Helmut Tschemernjak 35:fe3028eda085 85
Helmut Tschemernjak 35:fe3028eda085 86 memset(dnsaddr, 0, sizeof(dnsaddr));
Helmut Tschemernjak 35:fe3028eda085 87 memset(gateway, 0, sizeof(gateway));
Helmut Tschemernjak 35:fe3028eda085 88 memset(netmask, 0, sizeof(netmask));
Helmut Tschemernjak 35:fe3028eda085 89 memset(timesrv, 0, sizeof(timesrv));
Helmut Tschemernjak 35:fe3028eda085 90 memset(leaseTime, 0, sizeof(leaseTime));
Helmut Tschemernjak 35:fe3028eda085 91
Soohwan Kim 0:6f28332c466f 92 uint8_t *p;
Soohwan Kim 0:6f28332c466f 93 int msg_type = -1;
Soohwan Kim 0:6f28332c466f 94 p = buf + DHCP_OFFSET_OPTIONS;
Helmut Tschemernjak 35:fe3028eda085 95 while(*p != OPT_END && p < (buf+size)) {
Soohwan Kim 0:6f28332c466f 96 uint8_t code = *p++;
Soohwan Kim 0:6f28332c466f 97 if (code == 0) { // Pad Option
Soohwan Kim 0:6f28332c466f 98 continue;
Soohwan Kim 0:6f28332c466f 99 }
Soohwan Kim 0:6f28332c466f 100 int len = *p++;
Soohwan Kim 0:6f28332c466f 101
Soohwan Kim 0:6f28332c466f 102 DBG("DHCP option: %d\r\n", code);
Soohwan Kim 0:6f28332c466f 103 DBG_HEX(p, len);
Soohwan Kim 0:6f28332c466f 104
Soohwan Kim 0:6f28332c466f 105 switch(code) {
Helmut Tschemernjak 35:fe3028eda085 106 case OPT_DHCP_MESSAGE:
Soohwan Kim 0:6f28332c466f 107 msg_type = *p;
Soohwan Kim 0:6f28332c466f 108 break;
Helmut Tschemernjak 35:fe3028eda085 109 case OPT_SUBNET_MASK:
Helmut Tschemernjak 35:fe3028eda085 110 memcpy(netmask, p, 4);
Soohwan Kim 0:6f28332c466f 111 break;
Helmut Tschemernjak 35:fe3028eda085 112 case OPT_ROUTER:
Helmut Tschemernjak 35:fe3028eda085 113 memcpy(gateway, p, 4);
Soohwan Kim 0:6f28332c466f 114 break;
Helmut Tschemernjak 35:fe3028eda085 115 case OPT_DNS:
Soohwan Kim 0:6f28332c466f 116 memcpy(dnsaddr, p, 4);
Soohwan Kim 0:6f28332c466f 117 break;
Helmut Tschemernjak 35:fe3028eda085 118 case OPT_TIME_SERVER:
Helmut Tschemernjak 35:fe3028eda085 119 memcpy(timesrv, p, 4);
Helmut Tschemernjak 35:fe3028eda085 120 break;
Helmut Tschemernjak 35:fe3028eda085 121 case OPT_ADDR_LEASE_TIME:
Helmut Tschemernjak 35:fe3028eda085 122 memcpy(leaseTime, p, 4);
Soohwan Kim 0:6f28332c466f 123 break;
Helmut Tschemernjak 35:fe3028eda085 124 case OPT_DOMAIN_NAME:
Helmut Tschemernjak 35:fe3028eda085 125 {
Helmut Tschemernjak 35:fe3028eda085 126 int cplen = len;
Helmut Tschemernjak 35:fe3028eda085 127 if (cplen > 63)
Helmut Tschemernjak 35:fe3028eda085 128 cplen = 63; // max domain name
Helmut Tschemernjak 35:fe3028eda085 129 if (domainName) {
Helmut Tschemernjak 35:fe3028eda085 130 free(domainName);
Helmut Tschemernjak 35:fe3028eda085 131 domainName = NULL;
Helmut Tschemernjak 35:fe3028eda085 132 }
Helmut Tschemernjak 35:fe3028eda085 133 if (cplen) {
Helmut Tschemernjak 35:fe3028eda085 134 domainName = (char *)calloc(1, cplen+1);
Helmut Tschemernjak 35:fe3028eda085 135 memcpy(domainName, p, cplen); // zero term is already here via calloc
Helmut Tschemernjak 35:fe3028eda085 136 }
Helmut Tschemernjak 35:fe3028eda085 137 }
Helmut Tschemernjak 35:fe3028eda085 138 break;
Helmut Tschemernjak 35:fe3028eda085 139 case OPT_SERVER_IDENT:
Soohwan Kim 0:6f28332c466f 140 memcpy(siaddr, p, 4);
Soohwan Kim 0:6f28332c466f 141 break;
Soohwan Kim 0:6f28332c466f 142 }
Soohwan Kim 0:6f28332c466f 143 p += len;
Soohwan Kim 0:6f28332c466f 144 }
Soohwan Kim 0:6f28332c466f 145 return msg_type;
Soohwan Kim 0:6f28332c466f 146 }
Soohwan Kim 0:6f28332c466f 147
Soohwan Kim 0:6f28332c466f 148 bool DHCPClient::verify(uint8_t buf[], int len) {
Soohwan Kim 0:6f28332c466f 149 if (len < DHCP_OFFSET_OPTIONS) {
Soohwan Kim 0:6f28332c466f 150 return false;
Soohwan Kim 0:6f28332c466f 151 }
Soohwan Kim 0:6f28332c466f 152 if (buf[DHCP_OFFSET_OP] != 0x02) {
Soohwan Kim 0:6f28332c466f 153 return false;
Soohwan Kim 0:6f28332c466f 154 }
Soohwan Kim 0:6f28332c466f 155 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) {
Soohwan Kim 0:6f28332c466f 156 return false;
Soohwan Kim 0:6f28332c466f 157 }
Soohwan Kim 0:6f28332c466f 158 return true;
Soohwan Kim 0:6f28332c466f 159 }
Soohwan Kim 0:6f28332c466f 160
Soohwan Kim 0:6f28332c466f 161 void DHCPClient::callback()
Soohwan Kim 0:6f28332c466f 162 {
embeddist 15:24a9f2df2145 163 Endpoint host;
embeddist 15:24a9f2df2145 164 int recv_len = m_udp->receiveFrom(host, (char*)m_buf, sizeof(m_buf));
Soohwan Kim 0:6f28332c466f 165 if (recv_len < 0) {
Soohwan Kim 0:6f28332c466f 166 return;
Soohwan Kim 0:6f28332c466f 167 }
Soohwan Kim 0:6f28332c466f 168 if (!verify(m_buf, recv_len)) {
Soohwan Kim 0:6f28332c466f 169 return;
Soohwan Kim 0:6f28332c466f 170 }
Soohwan Kim 0:6f28332c466f 171 int r = offer(m_buf, recv_len);
Soohwan Kim 0:6f28332c466f 172 if (r == DHCPOFFER) {
Soohwan Kim 0:6f28332c466f 173 int send_size = request();
Soohwan Kim 0:6f28332c466f 174 m_udp->sendTo(m_server, (char*)m_buf, send_size);
Soohwan Kim 0:6f28332c466f 175 } else if (r == DHCPACK) {
Soohwan Kim 0:6f28332c466f 176 exit_flag = true;
Soohwan Kim 0:6f28332c466f 177 }
Soohwan Kim 0:6f28332c466f 178 }
Soohwan Kim 0:6f28332c466f 179
Soohwan Kim 0:6f28332c466f 180 void DHCPClient::add_buf(uint8_t c)
Soohwan Kim 0:6f28332c466f 181 {
Soohwan Kim 0:6f28332c466f 182 m_buf[m_pos++] = c;
Soohwan Kim 0:6f28332c466f 183 }
Soohwan Kim 0:6f28332c466f 184
Soohwan Kim 0:6f28332c466f 185 void DHCPClient::add_buf(uint8_t* buf, int len)
Soohwan Kim 0:6f28332c466f 186 {
Soohwan Kim 0:6f28332c466f 187 for(int i = 0; i < len; i++) {
Soohwan Kim 0:6f28332c466f 188 add_buf(buf[i]);
Soohwan Kim 0:6f28332c466f 189 }
Soohwan Kim 0:6f28332c466f 190 }
Soohwan Kim 0:6f28332c466f 191
Soohwan Kim 0:6f28332c466f 192 void DHCPClient::fill_buf(int len, uint8_t data)
Soohwan Kim 0:6f28332c466f 193 {
Soohwan Kim 0:6f28332c466f 194 while(len-- > 0) {
Soohwan Kim 0:6f28332c466f 195 add_buf(data);
Soohwan Kim 0:6f28332c466f 196 }
Soohwan Kim 0:6f28332c466f 197 }
Soohwan Kim 0:6f28332c466f 198
Soohwan Kim 0:6f28332c466f 199 void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len)
Soohwan Kim 0:6f28332c466f 200 {
Soohwan Kim 0:6f28332c466f 201 add_buf(code);
Soohwan Kim 0:6f28332c466f 202 if (len > 0) {
Soohwan Kim 0:6f28332c466f 203 add_buf((uint8_t)len);
Soohwan Kim 0:6f28332c466f 204 add_buf(buf, len);
Soohwan Kim 0:6f28332c466f 205 }
Soohwan Kim 0:6f28332c466f 206 }
Soohwan Kim 0:6f28332c466f 207
Helmut Tschemernjak 36:0ba2e8d5274a 208 int DHCPClient::setup(const char *hostnane, int timeout_ms)
Soohwan Kim 0:6f28332c466f 209 {
Soohwan Kim 0:6f28332c466f 210 eth = WIZnet_Chip::getInstance();
Soohwan Kim 0:6f28332c466f 211 if (eth == NULL) {
Soohwan Kim 0:6f28332c466f 212 return -1;
Helmut Tschemernjak 36:0ba2e8d5274a 213 }
Helmut Tschemernjak 36:0ba2e8d5274a 214 _hostname = hostnane;
Soohwan Kim 0:6f28332c466f 215 eth->reg_rd_mac(SHAR, chaddr);
Soohwan Kim 0:6f28332c466f 216 int interval_ms = 5*1000; // 5000msec
Soohwan Kim 0:6f28332c466f 217 if (timeout_ms < interval_ms) {
Soohwan Kim 0:6f28332c466f 218 interval_ms = timeout_ms;
Soohwan Kim 0:6f28332c466f 219 }
Soohwan Kim 0:6f28332c466f 220 m_udp = new UDPSocket;
Soohwan Kim 0:6f28332c466f 221 m_udp->init();
Soohwan Kim 0:6f28332c466f 222 m_udp->set_blocking(false);
Soohwan Kim 0:6f28332c466f 223 eth->reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
Helmut Tschemernjak 35:fe3028eda085 224 m_udp->bind(DHCP_CLIENT_PORT); // local port
Helmut Tschemernjak 35:fe3028eda085 225 m_server.set_address("255.255.255.255", DHCP_SERVER_PORT); // DHCP broadcast
Soohwan Kim 0:6f28332c466f 226 exit_flag = false;
Soohwan Kim 0:6f28332c466f 227 int err = 0;
Soohwan Kim 0:6f28332c466f 228 int seq = 0;
Soohwan Kim 0:6f28332c466f 229 int send_size;
Soohwan Kim 0:6f28332c466f 230 while(!exit_flag) {
Soohwan Kim 0:6f28332c466f 231 switch(seq) {
Soohwan Kim 0:6f28332c466f 232 case 0:
Soohwan Kim 0:6f28332c466f 233 m_retry = 0;
Soohwan Kim 0:6f28332c466f 234 seq++;
Soohwan Kim 0:6f28332c466f 235 break;
Soohwan Kim 0:6f28332c466f 236 case 1:
Soohwan Kim 0:6f28332c466f 237 send_size = discover();
Soohwan Kim 0:6f28332c466f 238 m_udp->sendTo(m_server, (char*)m_buf, send_size);
Soohwan Kim 0:6f28332c466f 239 m_interval.reset();
Soohwan Kim 0:6f28332c466f 240 m_interval.start();
Soohwan Kim 0:6f28332c466f 241 seq++;
Soohwan Kim 0:6f28332c466f 242 break;
Soohwan Kim 0:6f28332c466f 243 case 2:
Soohwan Kim 0:6f28332c466f 244 callback();
Soohwan Kim 0:6f28332c466f 245 if (m_interval.read_ms() > interval_ms) {
Soohwan Kim 0:6f28332c466f 246 DBG("m_retry: %d\n", m_retry);
Soohwan Kim 0:6f28332c466f 247 if (++m_retry >= (timeout_ms/interval_ms)) {
Soohwan Kim 0:6f28332c466f 248 err = -1;
Soohwan Kim 0:6f28332c466f 249 exit_flag = true;
Soohwan Kim 0:6f28332c466f 250 }
Soohwan Kim 0:6f28332c466f 251 seq--;
Soohwan Kim 0:6f28332c466f 252 }
Soohwan Kim 0:6f28332c466f 253 break;
Soohwan Kim 0:6f28332c466f 254 }
Soohwan Kim 0:6f28332c466f 255 }
Soohwan Kim 0:6f28332c466f 256 DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms());
Soohwan Kim 0:6f28332c466f 257 delete m_udp;
Soohwan Kim 0:6f28332c466f 258 return err;
Soohwan Kim 0:6f28332c466f 259 }
Soohwan Kim 0:6f28332c466f 260
Soohwan Kim 0:6f28332c466f 261 DHCPClient::DHCPClient() {
Helmut Tschemernjak 35:fe3028eda085 262 domainName = NULL;
Soohwan Kim 0:6f28332c466f 263 }
Soohwan Kim 0:6f28332c466f 264
Helmut Tschemernjak 35:fe3028eda085 265 DHCPClient::~DHCPClient() {
Helmut Tschemernjak 35:fe3028eda085 266 if (domainName)
Helmut Tschemernjak 35:fe3028eda085 267 free(domainName);
Helmut Tschemernjak 35:fe3028eda085 268 }