8 #include "LibEndian.hpp"
9 #include "NetClientDhcp.hpp"
13 NetClientDhcp::STATE NetClientDhcp::sState = STATE_DISABLED;
14 uint32_t NetClientDhcp::sTransactionId = 0xabcdef01;
15 NetDefs::IP_ADDR NetClientDhcp::sOfferedYourIpAddr;
16 NetDefs::IP_ADDR NetClientDhcp::sOfferedMask;
17 NetDefs::IP_ADDR NetClientDhcp::sOfferedServerIpAddr;
18 NetDefs::IP_ADDR NetClientDhcp::sOfferedGatewayIpAddr;
19 NetDefs::IP_ADDR NetClientDhcp::sOfferedDnsIpAddr;
20 uint32_t NetClientDhcp::sLeaseTime = 0;
21 uint32_t NetClientDhcp::sTimeout = 0;
23 void NetClientDhcp::processFrame(NetDefs::FRAME& frame, NetDefs::DHCP_HEADER& header,
int len) {
28 if (sState == STATE_DISABLED) {
29 Net::freeFrame(frame);
33 if (parseMsg(frame, header, msgType, len)) {
34 Net::freeFrame(frame);
37 case STATE_WAIT_OFFER:
38 if (msgType == MSG_OFFER) {
39 if (!sendMessage(MSG_REQUEST)) {
43 sState = STATE_WAIT_ACK;
47 if (msgType == MSG_ACK) {
48 Net::sConfig.ipAddr = sOfferedYourIpAddr;
49 Net::sConfig.mask = sOfferedMask;
50 Net::sConfig.gatewayIpAddr = sOfferedGatewayIpAddr;
51 if (sOfferedDnsIpAddr.val != 0) {
52 Net::sConfig.dnsIpAddr = sOfferedDnsIpAddr;
55 Net::sConfig.dnsIpAddr = sOfferedGatewayIpAddr;
57 sTimeout = sLeaseTime - 60;
67 Net::freeFrame(frame);
72 void NetClientDhcp::tick() {
74 if (!Net::sConfig.dhcpEnabled) {
75 sState = STATE_DISABLED;
86 if (!sendMessage(MSG_DISCOVER)) {
90 sState = STATE_WAIT_OFFER;
94 case STATE_WAIT_OFFER:
107 if (!sendMessage(MSG_REQUEST)) {
111 sState = STATE_WAIT_ACK;
121 bool NetClientDhcp::sendMessage(MSG_TYPE type) {
144 NetDefs::FRAME * sendFrame = Net::allocFrame(
145 sizeof(NetDefs::MAC_HEADER) +
sizeof(NetDefs::IP_HEADER) +
sizeof(NetDefs::UDP_HEADER) +
sizeof(NetDefs::DHCP_HEADER) + optLen);
150 NetDefs::DHCP_HEADER& dhcpHeader = sendFrame->types.dhcp.dhcpHeader;
152 dhcpHeader.opCode = NetDefs::DHCP_OPCODE_BOOT_REQUEST;
153 dhcpHeader.hardwareType = 1;
154 dhcpHeader.macAddrLen = 6;
155 dhcpHeader.hopCount = 0;
156 dhcpHeader.transactionID = sTransactionId;
157 dhcpHeader.numberOfSeconds = 0x0000;
158 dhcpHeader.flags = LibEndian::hwToBe((uint16_t) 0x8000);
159 dhcpHeader.clientIpAddr = Net::sConfig.ipAddr;
161 dhcpHeader.yourIPAddr.val = dhcpHeader.serverIpAddr.val = dhcpHeader.gatewayIpAddr.val = 0;
163 memset(&dhcpHeader.clientHwAddr, 0,
sizeof(dhcpHeader.clientHwAddr));
164 *((NetDefs::MAC_ADDR*) &dhcpHeader.clientHwAddr) = Net::sMacAddr;
166 memset(&dhcpHeader.serverHostName, 0,
sizeof(dhcpHeader.serverHostName));
167 memset(&dhcpHeader.bootFileName, 0,
sizeof(dhcpHeader.bootFileName));
169 swapHeader(dhcpHeader);
171 uint8_t* p = (uint8_t*) sendFrame->types.dhcp.data;
173 memcpy(p, NetDefs::DHCP_MAGIC_COOKIE, 4);
176 p = writeOption(p, OPT_DHCP_MESSAGE_TYPE, (uint8_t*) &type, 1);
178 if (type == MSG_REQUEST) {
179 p = writeOption(p, OPT_REQUESTED_IP_ADDRESS, (uint8_t*) &sOfferedYourIpAddr, 4);
180 p = writeOption(p, OPT_SERVER_IDENTIFIER, (uint8_t*) &sOfferedServerIpAddr, 4);
183 uint8_t optList[] = {
184 OPT_SUBNET_MASK, OPT_ROUTER, OPT_DNS };
185 p = writeOption(p, OPT_PARAM_REQUEST_LIST, optList, 3);
188 p = writeOption(p, OPT_HOST_NAME, (uint8_t*)
"emb", 3);
192 NetUdp::putHeader(*sendFrame, NetDefs::MAC_BROADCAST, NetDefs::IP_BROADCAST, NetDefs::UDP_PORT_DHCP_CLIENT, NetDefs::UDP_PORT_DHCP_SERVER,
193 sizeof(NetDefs::DHCP_HEADER) + optLen);
195 NetUdp::flush(*sendFrame,
sizeof(NetDefs::DHCP_HEADER) + optLen,
true);
200 bool NetClientDhcp::parseMsg(NetDefs::FRAME& frame, NetDefs::DHCP_HEADER& header, MSG_TYPE& msgType,
int len) {
201 if (header.transactionID != sTransactionId) {
204 if (header.opCode != NetDefs::DHCP_OPCODE_BOOT_REPLY) {
207 if (*((NetDefs::MAC_ADDR*) &header.clientHwAddr) != Net::sMacAddr) {
211 uint8_t* p = ((uint8_t*) &header) +
sizeof(header);
213 if (memcmp(p, &NetDefs::DHCP_MAGIC_COOKIE, 4)) {
219 sOfferedYourIpAddr = header.yourIPAddr;
220 sOfferedDnsIpAddr.val = 0;
224 uint8_t* end = ((uint8_t*) &header) + len;
227 while ((uint32_t) p < (uint32_t) end) {
232 const MSG_OPT opt = (
const MSG_OPT) *p++;
233 const uint8_t parLen = *p++;
236 case OPT_DHCP_MESSAGE_TYPE:
238 msgType = (MSG_TYPE) *p;
241 case OPT_SUBNET_MASK:
243 sOfferedMask.v[0] = p[0];
244 sOfferedMask.v[1] = p[1];
245 sOfferedMask.v[2] = p[2];
246 sOfferedMask.v[3] = p[3];
251 sOfferedGatewayIpAddr.v[0] = p[0];
252 sOfferedGatewayIpAddr.v[1] = p[1];
253 sOfferedGatewayIpAddr.v[2] = p[2];
254 sOfferedGatewayIpAddr.v[3] = p[3];
257 case OPT_SERVER_IDENTIFIER:
259 sOfferedServerIpAddr.v[0] = p[0];
260 sOfferedServerIpAddr.v[1] = p[1];
261 sOfferedServerIpAddr.v[2] = p[2];
262 sOfferedServerIpAddr.v[3] = p[3];
267 sOfferedDnsIpAddr.v[0] = p[0];
268 sOfferedDnsIpAddr.v[1] = p[1];
269 sOfferedDnsIpAddr.v[2] = p[2];
270 sOfferedDnsIpAddr.v[3] = p[3];
273 case OPT_IP_LEASE_TIME:
275 sLeaseTime = ((uint32_t) p[0] << 24) + ((uint32_t) p[1] << 16) + ((uint32_t) p[2] << 8) + ((uint32_t) p[0]);
288 uint8_t* NetClientDhcp::writeOption(uint8_t* dst, MSG_OPT option,
const uint8_t* parameters,
int len) {
292 *dst++ = *parameters++;
297 void NetClientDhcp::swapHeader(NetDefs::DHCP_HEADER& header) {
298 header.transactionID = LibEndian::hwToBe(header.transactionID);