W5200(WIZ820io) network interface
Embed:
(wiki syntax)
Show/hide line numbers
DHCPClient.cpp
00001 // DHCPClient.cpp 2012/4/14 00002 // DHCP Client for WIZ820io(W5200) 00003 #include "mbed.h" 00004 #include "w5100.h" 00005 #include "UDPSocket.h" 00006 #include "DHCPClient.h" 00007 00008 //#define DEBUG 00009 00010 #ifdef DEBUG 00011 #include "Utils.h" 00012 #define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) 00013 #else //DEBUG 00014 #define PRINT_FUNC() 00015 #endif //DEBUG 00016 00017 int DHCPClient::discover(uint8_t buf[], int size) { 00018 memset(buf, 0x00, size); 00019 const uint8_t headers[] = {0x01,0x01,0x06,0x00, 00020 0x12,0x34,0x56,0x78}; // xid 00021 memcpy(buf, headers, sizeof(headers)); 00022 int t = clock(); 00023 xid[0] = t<<24; 00024 xid[1] = t<<16; 00025 xid[2] = t<<8; 00026 xid[3] = t; 00027 memcpy(buf+DHCP_OFFSET_XID, xid, 4); 00028 W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR); 00029 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00030 0x35,0x01,0x01, // DHCP DISCOVER 00031 0xff}; 00032 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); 00033 uint8_t ip[4] = {0,0,0,0}; 00034 W5100.setIPAddress(ip); 00035 return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); 00036 } 00037 00038 int DHCPClient::request(uint8_t buf[], int size) { 00039 memset(buf, 0x00, size); 00040 const uint8_t headers[] = {0x01,0x01,0x06,0x00, 00041 0x12,0x34,0x56,0x78}; // xid 00042 memcpy(buf, headers, sizeof(headers)); 00043 memcpy(buf+DHCP_OFFSET_XID, xid, 4); 00044 memcpy(buf+DHCP_OFFSET_YIADDR, yiaddr, 4); 00045 W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR); 00046 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00047 0x35,0x01,0x03, // DHCP REQUEST 00048 0x32,0x04,0x00,0x00,0x00,0x00, // request IP 00049 0xff}; 00050 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); 00051 memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE+9, yiaddr, 4); 00052 return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); 00053 } 00054 00055 int DHCPClient::offer_ack(uint8_t buf[], int size) { 00056 memcpy(yiaddr, &buf[DHCP_OFFSET_YIADDR], 4); 00057 uint8_t *p; 00058 int msg_type = -1; 00059 p = buf + DHCP_OFFSET_OPTIONS; 00060 while(*p != 0xff && p < (uint8_t*)&buf[DHCP_MAX_PACKET_SIZE]) { 00061 int code = *p++; 00062 if (code == 0x00) { 00063 continue; 00064 } 00065 int len = *p++; 00066 #ifdef DEBUG 00067 char codeStr[24]; 00068 snprintf(codeStr, sizeof(codeStr), "DHCP option: %d", code); 00069 printfBytes(codeStr, p, len); 00070 #endif //DEBUG 00071 if (code == 53) { 00072 msg_type = *p; 00073 } else if (code == 1) { 00074 memcpy(netmask, p, 4); // Subnet mask address 00075 } else if (code == 3) { 00076 memcpy(gateway, p, 4); // Gateway IP address 00077 } else if (code == 6) {// DNS 00078 memcpy(dnsaddr, p, 4); 00079 } 00080 p += len; 00081 } 00082 return msg_type; 00083 } 00084 00085 bool DHCPClient::verify(uint8_t buf[], int len) { 00086 if (len < DHCP_OFFSET_OPTIONS) { 00087 return false; 00088 } 00089 if (buf[DHCP_OFFSET_OP] != 0x02) { 00090 return false; 00091 } 00092 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { 00093 return false; 00094 } 00095 return true; 00096 } 00097 00098 void DHCPClient::callback(UDPSocketEvent e) 00099 { 00100 PRINT_FUNC(); 00101 uint8_t buf[DHCP_MAX_PACKET_SIZE]; 00102 Host host; 00103 int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host); 00104 if (!verify(buf, len)) { 00105 return; 00106 } 00107 int r = offer_ack(buf, len); 00108 if (r == 2) { // OFFER 00109 request(buf, 300); 00110 Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast 00111 m_udp->sendto((char*)buf, 300, &server); 00112 } else if (r == 5) { // ACK 00113 exit_flag = true; 00114 } 00115 } 00116 00117 int DHCPClient::setup(int timeout_ms) 00118 { 00119 PRINT_FUNC(); 00120 Timer t; 00121 t.start(); 00122 m_udp = new UDPSocket; 00123 m_udp->setOnEvent(this, &DHCPClient::callback); 00124 Host local(IpAddr(0,0,0,0), 68); 00125 Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast 00126 m_udp->bind(local); 00127 uint8_t buf[300]; 00128 discover(buf, sizeof(buf)); 00129 m_udp->sendto((char*)buf, sizeof(buf), &server); 00130 exit_flag = false; 00131 int err = 0; 00132 while(1) { 00133 Net::poll(); 00134 if (exit_flag) { 00135 break; 00136 } 00137 if (t.read_ms() > timeout_ms) { 00138 err = -1; 00139 break; 00140 } 00141 #ifdef DEBUG 00142 wait_ms(500); 00143 #endif //DEBUG 00144 } 00145 delete m_udp; 00146 return err; 00147 } 00148 00149 DHCPClient::DHCPClient() { 00150 m_udp = NULL; 00151 }
Generated on Tue Jul 12 2022 19:58:52 by 1.7.2