W5200(WIZ820io) network interface

Committer:
va009039
Date:
Thu Apr 19 11:14:43 2012 +0000
Revision:
2:a8df39b4f3aa
Parent:
0:61831b843b44

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:61831b843b44 1 // DHCPClient.cpp 2012/4/14
va009039 0:61831b843b44 2 // DHCP Client for WIZ820io(W5200)
va009039 0:61831b843b44 3 #include "mbed.h"
va009039 0:61831b843b44 4 #include "w5100.h"
va009039 0:61831b843b44 5 #include "UDPSocket.h"
va009039 0:61831b843b44 6 #include "DHCPClient.h"
va009039 0:61831b843b44 7
va009039 0:61831b843b44 8 //#define DEBUG
va009039 0:61831b843b44 9
va009039 0:61831b843b44 10 #ifdef DEBUG
va009039 0:61831b843b44 11 #include "Utils.h"
va009039 0:61831b843b44 12 #define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__)
va009039 0:61831b843b44 13 #else //DEBUG
va009039 0:61831b843b44 14 #define PRINT_FUNC()
va009039 0:61831b843b44 15 #endif //DEBUG
va009039 0:61831b843b44 16
va009039 0:61831b843b44 17 int DHCPClient::discover(uint8_t buf[], int size) {
va009039 0:61831b843b44 18 memset(buf, 0x00, size);
va009039 0:61831b843b44 19 const uint8_t headers[] = {0x01,0x01,0x06,0x00,
va009039 0:61831b843b44 20 0x12,0x34,0x56,0x78}; // xid
va009039 0:61831b843b44 21 memcpy(buf, headers, sizeof(headers));
va009039 0:61831b843b44 22 int t = clock();
va009039 0:61831b843b44 23 xid[0] = t<<24;
va009039 0:61831b843b44 24 xid[1] = t<<16;
va009039 0:61831b843b44 25 xid[2] = t<<8;
va009039 0:61831b843b44 26 xid[3] = t;
va009039 0:61831b843b44 27 memcpy(buf+DHCP_OFFSET_XID, xid, 4);
va009039 0:61831b843b44 28 W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR);
va009039 0:61831b843b44 29 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
va009039 0:61831b843b44 30 0x35,0x01,0x01, // DHCP DISCOVER
va009039 0:61831b843b44 31 0xff};
va009039 0:61831b843b44 32 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options));
va009039 0:61831b843b44 33 uint8_t ip[4] = {0,0,0,0};
va009039 0:61831b843b44 34 W5100.setIPAddress(ip);
va009039 0:61831b843b44 35 return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options);
va009039 0:61831b843b44 36 }
va009039 0:61831b843b44 37
va009039 0:61831b843b44 38 int DHCPClient::request(uint8_t buf[], int size) {
va009039 0:61831b843b44 39 memset(buf, 0x00, size);
va009039 0:61831b843b44 40 const uint8_t headers[] = {0x01,0x01,0x06,0x00,
va009039 0:61831b843b44 41 0x12,0x34,0x56,0x78}; // xid
va009039 0:61831b843b44 42 memcpy(buf, headers, sizeof(headers));
va009039 0:61831b843b44 43 memcpy(buf+DHCP_OFFSET_XID, xid, 4);
va009039 0:61831b843b44 44 memcpy(buf+DHCP_OFFSET_YIADDR, yiaddr, 4);
va009039 0:61831b843b44 45 W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR);
va009039 0:61831b843b44 46 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
va009039 0:61831b843b44 47 0x35,0x01,0x03, // DHCP REQUEST
va009039 0:61831b843b44 48 0x32,0x04,0x00,0x00,0x00,0x00, // request IP
va009039 0:61831b843b44 49 0xff};
va009039 0:61831b843b44 50 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options));
va009039 0:61831b843b44 51 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE+9, yiaddr, 4);
va009039 0:61831b843b44 52 return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options);
va009039 0:61831b843b44 53 }
va009039 0:61831b843b44 54
va009039 0:61831b843b44 55 int DHCPClient::offer_ack(uint8_t buf[], int size) {
va009039 0:61831b843b44 56 memcpy(yiaddr, &buf[DHCP_OFFSET_YIADDR], 4);
va009039 0:61831b843b44 57 uint8_t *p;
va009039 0:61831b843b44 58 int msg_type = -1;
va009039 0:61831b843b44 59 p = buf + DHCP_OFFSET_OPTIONS;
va009039 0:61831b843b44 60 while(*p != 0xff && p < (uint8_t*)&buf[DHCP_MAX_PACKET_SIZE]) {
va009039 0:61831b843b44 61 int code = *p++;
va009039 0:61831b843b44 62 if (code == 0x00) {
va009039 0:61831b843b44 63 continue;
va009039 0:61831b843b44 64 }
va009039 0:61831b843b44 65 int len = *p++;
va009039 0:61831b843b44 66 #ifdef DEBUG
va009039 0:61831b843b44 67 char codeStr[24];
va009039 0:61831b843b44 68 snprintf(codeStr, sizeof(codeStr), "DHCP option: %d", code);
va009039 0:61831b843b44 69 printfBytes(codeStr, p, len);
va009039 0:61831b843b44 70 #endif //DEBUG
va009039 0:61831b843b44 71 if (code == 53) {
va009039 0:61831b843b44 72 msg_type = *p;
va009039 0:61831b843b44 73 } else if (code == 1) {
va009039 0:61831b843b44 74 memcpy(netmask, p, 4); // Subnet mask address
va009039 0:61831b843b44 75 } else if (code == 3) {
va009039 0:61831b843b44 76 memcpy(gateway, p, 4); // Gateway IP address
va009039 0:61831b843b44 77 } else if (code == 6) {// DNS
va009039 0:61831b843b44 78 memcpy(dnsaddr, p, 4);
va009039 0:61831b843b44 79 }
va009039 0:61831b843b44 80 p += len;
va009039 0:61831b843b44 81 }
va009039 0:61831b843b44 82 return msg_type;
va009039 0:61831b843b44 83 }
va009039 0:61831b843b44 84
va009039 0:61831b843b44 85 bool DHCPClient::verify(uint8_t buf[], int len) {
va009039 0:61831b843b44 86 if (len < DHCP_OFFSET_OPTIONS) {
va009039 0:61831b843b44 87 return false;
va009039 0:61831b843b44 88 }
va009039 0:61831b843b44 89 if (buf[DHCP_OFFSET_OP] != 0x02) {
va009039 0:61831b843b44 90 return false;
va009039 0:61831b843b44 91 }
va009039 0:61831b843b44 92 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) {
va009039 0:61831b843b44 93 return false;
va009039 0:61831b843b44 94 }
va009039 0:61831b843b44 95 return true;
va009039 0:61831b843b44 96 }
va009039 0:61831b843b44 97
va009039 0:61831b843b44 98 void DHCPClient::callback(UDPSocketEvent e)
va009039 0:61831b843b44 99 {
va009039 0:61831b843b44 100 PRINT_FUNC();
va009039 0:61831b843b44 101 uint8_t buf[DHCP_MAX_PACKET_SIZE];
va009039 0:61831b843b44 102 Host host;
va009039 0:61831b843b44 103 int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host);
va009039 0:61831b843b44 104 if (!verify(buf, len)) {
va009039 0:61831b843b44 105 return;
va009039 0:61831b843b44 106 }
va009039 0:61831b843b44 107 int r = offer_ack(buf, len);
va009039 0:61831b843b44 108 if (r == 2) { // OFFER
va009039 0:61831b843b44 109 request(buf, 300);
va009039 0:61831b843b44 110 Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast
va009039 0:61831b843b44 111 m_udp->sendto((char*)buf, 300, &server);
va009039 0:61831b843b44 112 } else if (r == 5) { // ACK
va009039 0:61831b843b44 113 exit_flag = true;
va009039 0:61831b843b44 114 }
va009039 0:61831b843b44 115 }
va009039 0:61831b843b44 116
va009039 0:61831b843b44 117 int DHCPClient::setup(int timeout_ms)
va009039 0:61831b843b44 118 {
va009039 0:61831b843b44 119 PRINT_FUNC();
va009039 0:61831b843b44 120 Timer t;
va009039 0:61831b843b44 121 t.start();
va009039 0:61831b843b44 122 m_udp = new UDPSocket;
va009039 0:61831b843b44 123 m_udp->setOnEvent(this, &DHCPClient::callback);
va009039 0:61831b843b44 124 Host local(IpAddr(0,0,0,0), 68);
va009039 0:61831b843b44 125 Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast
va009039 0:61831b843b44 126 m_udp->bind(local);
va009039 0:61831b843b44 127 uint8_t buf[300];
va009039 0:61831b843b44 128 discover(buf, sizeof(buf));
va009039 0:61831b843b44 129 m_udp->sendto((char*)buf, sizeof(buf), &server);
va009039 0:61831b843b44 130 exit_flag = false;
va009039 0:61831b843b44 131 int err = 0;
va009039 0:61831b843b44 132 while(1) {
va009039 0:61831b843b44 133 Net::poll();
va009039 0:61831b843b44 134 if (exit_flag) {
va009039 0:61831b843b44 135 break;
va009039 0:61831b843b44 136 }
va009039 0:61831b843b44 137 if (t.read_ms() > timeout_ms) {
va009039 0:61831b843b44 138 err = -1;
va009039 0:61831b843b44 139 break;
va009039 0:61831b843b44 140 }
va009039 0:61831b843b44 141 #ifdef DEBUG
va009039 0:61831b843b44 142 wait_ms(500);
va009039 0:61831b843b44 143 #endif //DEBUG
va009039 0:61831b843b44 144 }
va009039 0:61831b843b44 145 delete m_udp;
va009039 0:61831b843b44 146 return err;
va009039 0:61831b843b44 147 }
va009039 0:61831b843b44 148
va009039 0:61831b843b44 149 DHCPClient::DHCPClient() {
va009039 0:61831b843b44 150 m_udp = NULL;
va009039 0:61831b843b44 151 }