W5200(WIZ820io) network interface
DHCPClient.cpp
- Committer:
- va009039
- Date:
- 2012-04-19
- Revision:
- 2:a8df39b4f3aa
- Parent:
- 0:61831b843b44
File content as of revision 2:a8df39b4f3aa:
// DHCPClient.cpp 2012/4/14 // DHCP Client for WIZ820io(W5200) #include "mbed.h" #include "w5100.h" #include "UDPSocket.h" #include "DHCPClient.h" //#define DEBUG #ifdef DEBUG #include "Utils.h" #define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) #else //DEBUG #define PRINT_FUNC() #endif //DEBUG int DHCPClient::discover(uint8_t buf[], int size) { memset(buf, 0x00, size); const uint8_t headers[] = {0x01,0x01,0x06,0x00, 0x12,0x34,0x56,0x78}; // xid memcpy(buf, headers, sizeof(headers)); int t = clock(); xid[0] = t<<24; xid[1] = t<<16; xid[2] = t<<8; xid[3] = t; memcpy(buf+DHCP_OFFSET_XID, xid, 4); W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR); const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 0x35,0x01,0x01, // DHCP DISCOVER 0xff}; memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); uint8_t ip[4] = {0,0,0,0}; W5100.setIPAddress(ip); return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); } int DHCPClient::request(uint8_t buf[], int size) { memset(buf, 0x00, size); const uint8_t headers[] = {0x01,0x01,0x06,0x00, 0x12,0x34,0x56,0x78}; // xid memcpy(buf, headers, sizeof(headers)); memcpy(buf+DHCP_OFFSET_XID, xid, 4); memcpy(buf+DHCP_OFFSET_YIADDR, yiaddr, 4); W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR); const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 0x35,0x01,0x03, // DHCP REQUEST 0x32,0x04,0x00,0x00,0x00,0x00, // request IP 0xff}; memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE+9, yiaddr, 4); return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); } int DHCPClient::offer_ack(uint8_t buf[], int size) { memcpy(yiaddr, &buf[DHCP_OFFSET_YIADDR], 4); uint8_t *p; int msg_type = -1; p = buf + DHCP_OFFSET_OPTIONS; while(*p != 0xff && p < (uint8_t*)&buf[DHCP_MAX_PACKET_SIZE]) { int code = *p++; if (code == 0x00) { continue; } int len = *p++; #ifdef DEBUG char codeStr[24]; snprintf(codeStr, sizeof(codeStr), "DHCP option: %d", code); printfBytes(codeStr, p, len); #endif //DEBUG if (code == 53) { msg_type = *p; } else if (code == 1) { memcpy(netmask, p, 4); // Subnet mask address } else if (code == 3) { memcpy(gateway, p, 4); // Gateway IP address } else if (code == 6) {// DNS memcpy(dnsaddr, p, 4); } p += len; } return msg_type; } bool DHCPClient::verify(uint8_t buf[], int len) { if (len < DHCP_OFFSET_OPTIONS) { return false; } if (buf[DHCP_OFFSET_OP] != 0x02) { return false; } if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { return false; } return true; } void DHCPClient::callback(UDPSocketEvent e) { PRINT_FUNC(); uint8_t buf[DHCP_MAX_PACKET_SIZE]; Host host; int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host); if (!verify(buf, len)) { return; } int r = offer_ack(buf, len); if (r == 2) { // OFFER request(buf, 300); Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast m_udp->sendto((char*)buf, 300, &server); } else if (r == 5) { // ACK exit_flag = true; } } int DHCPClient::setup(int timeout_ms) { PRINT_FUNC(); Timer t; t.start(); m_udp = new UDPSocket; m_udp->setOnEvent(this, &DHCPClient::callback); Host local(IpAddr(0,0,0,0), 68); Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast m_udp->bind(local); uint8_t buf[300]; discover(buf, sizeof(buf)); m_udp->sendto((char*)buf, sizeof(buf), &server); exit_flag = false; int err = 0; while(1) { Net::poll(); if (exit_flag) { break; } if (t.read_ms() > timeout_ms) { err = -1; break; } #ifdef DEBUG wait_ms(500); #endif //DEBUG } delete m_udp; return err; } DHCPClient::DHCPClient() { m_udp = NULL; }