-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2010.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, distribute, and sell this \r
- software and its documentation for any purpose is hereby granted\r
- without fee, provided that the above copyright notice appear in \r
- all copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting \r
- documentation, and that the name of the author not be used in \r
- advertising or publicity pertaining to distribution of the \r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * DHCP Client Application. When connected to the uIP stack, this will retrieve IP configuration settings from the\r
- * DHCP server on the network.\r
- */\r
- \r
-#include "DHCPClientApp.h"\r
-\r
-#if defined(ENABLE_DHCP_CLIENT) || defined(__DOXYGEN__)\r
-/** Timer for managing the timeout period for a DHCP server to respond */\r
-struct timer DHCPTimer;\r
-\r
-/** Initialization function for the DHCP client. */\r
-void DHCPClientApp_Init(void)\r
-{\r
- /* Create an IP address to the broadcast network address */\r
- uip_ipaddr_t DHCPServerIPAddress;\r
- uip_ipaddr(&DHCPServerIPAddress, 255, 255, 255, 255);\r
-\r
- /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */\r
- struct uip_udp_conn* Connection = uip_udp_new(&DHCPServerIPAddress, HTONS(DHCPC_SERVER_PORT));\r
- \r
- /* If the connection was successfully created, bind it to the local DHCP client port */\r
- if (Connection != NULL)\r
- {\r
- uip_udp_appstate_t* const AppState = &Connection->appstate;\r
-\r
- uip_udp_bind(Connection, HTONS(DHCPC_CLIENT_PORT));\r
- AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;\r
- }\r
-\r
- /* Set timeout period to half a second for a DHCP server to respond */\r
- timer_set(&DHCPTimer, CLOCK_SECOND / 2);\r
-}\r
- \r
-/** uIP stack application callback for the DHCP client. This function must be called each time the TCP/IP stack \r
- * needs a UDP packet to be processed.\r
- */\r
-void DHCPClientApp_Callback(void)\r
-{\r
- uip_udp_appstate_t* const AppState = &uip_udp_conn->appstate;\r
- DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;\r
- uint16_t AppDataSize = 0;\r
- \r
- switch (AppState->DHCPClient.CurrentState)\r
- {\r
- case DHCP_STATE_SendDiscover:\r
- /* Clear all DHCP settings, reset client IP address */\r
- memset(&AppState->DHCPClient.DHCPOffer_Data, 0x00, sizeof(AppState->DHCPClient.DHCPOffer_Data));\r
- uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);\r
-\r
- /* Fill out the DHCP response header */\r
- AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState);\r
- \r
- /* Add the required DHCP options list to the packet */\r
- uint8_t RequiredOptionList[] = {DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_ROUTER, DHCP_OPTION_DNS_SERVER};\r
- AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_REQ_LIST, sizeof(RequiredOptionList),\r
- RequiredOptionList); \r
- \r
- /* Send the DHCP DISCOVER packet */\r
- uip_udp_send(AppDataSize);\r
-\r
- /* Reset the timeout timer, progress to next state */\r
- timer_reset(&DHCPTimer);\r
- AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForOffer; \r
- \r
- break;\r
- case DHCP_STATE_WaitForOffer:\r
- if (!(uip_newdata()))\r
- {\r
- /* Check if the DHCP timeout period has expired while waiting for a response */\r
- if (timer_expired(&DHCPTimer))\r
- AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;\r
- \r
- break;\r
- }\r
- \r
- uint8_t OfferResponse_MessageType;\r
- if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&\r
- DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) &&\r
- (OfferResponse_MessageType == DHCP_OFFER))\r
- {\r
- /* Received a DHCP offer for an IP address, copy over values for later request */\r
- memcpy(&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, &AppData->YourIP, sizeof(uip_ipaddr_t));\r
- DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPClient.DHCPOffer_Data.Netmask);\r
- DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPClient.DHCPOffer_Data.GatewayIP);\r
- DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPClient.DHCPOffer_Data.ServerIP);\r
- \r
- timer_reset(&DHCPTimer);\r
- AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest;\r
- }\r
-\r
- break;\r
- case DHCP_STATE_SendRequest:\r
- /* Fill out the DHCP response header */\r
- AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_REQUEST, AppState);\r
-\r
- /* Add the DHCP REQUESTED IP ADDRESS option to the packet */\r
- AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t),\r
- &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);\r
-\r
- /* Add the DHCP SERVER IP ADDRESS option to the packet */\r
- AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t),\r
- &AppState->DHCPClient.DHCPOffer_Data.ServerIP);\r
-\r
- /* Send the DHCP REQUEST packet */\r
- uip_udp_send(AppDataSize);\r
- \r
- /* Reset the timeout timer, progress to next state */\r
- timer_reset(&DHCPTimer);\r
- AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForACK;\r
-\r
- break;\r
- case DHCP_STATE_WaitForACK:\r
- if (!(uip_newdata()))\r
- {\r
- /* Check if the DHCP timeout period has expired while waiting for a response */\r
- if (timer_expired(&DHCPTimer))\r
- AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;\r
- \r
- break;\r
- }\r
- \r
- uint8_t RequestResponse_MessageType;\r
- if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&\r
- DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) &&\r
- (RequestResponse_MessageType == DHCP_ACK))\r
- {\r
- /* Set the new network parameters from the DHCP server */\r
- uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);\r
- uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.Netmask);\r
- uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.GatewayIP);\r
- \r
- AppState->DHCPClient.CurrentState = DHCP_STATE_AddressLeased;\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Fills the DHCP packet response with the appropriate BOOTP header for DHCP. This fills out all the required\r
- * fields, leaving only the additional DHCP options to be added to the packet before it is sent to the DHCP server.\r
- *\r
- * \param[out] DHCPHeader Location in the packet buffer where the BOOTP header should be written to\r
- * \param[in] DHCPMessageType DHCP Message type, such as DHCP_DISCOVER\r
- * \param[in] AppState Application state of the current UDP connection\r
- *\r
- * \return Size in bytes of the created DHCP packet\r
- */\r
-uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* DHCPHeader, uint8_t DHCPMessageType, uip_udp_appstate_t* AppState)\r
-{\r
- /* Erase existing packet data so that we start will all 0x00 DHCP header data */\r
- memset(DHCPHeader, 0, sizeof(DHCP_Header_t));\r
-\r
- /* Fill out the DHCP packet header */\r
- DHCPHeader->Operation = DHCP_OP_BOOTREQUEST;\r
- DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;\r
- DHCPHeader->HardwareAddressLength = sizeof(MACAddress);\r
- DHCPHeader->Hops = 0;\r
- DHCPHeader->TransactionID = DHCP_TRANSACTION_ID;\r
- DHCPHeader->ElapsedSeconds = 0;\r
- DHCPHeader->Flags = HTONS(BOOTP_BROADCAST);\r
- memcpy(&DHCPHeader->ClientIP, &uip_hostaddr, sizeof(uip_ipaddr_t));\r
- memcpy(&DHCPHeader->YourIP, &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, sizeof(uip_ipaddr_t));\r
- memcpy(&DHCPHeader->NextServerIP, &AppState->DHCPClient.DHCPOffer_Data.ServerIP, sizeof(uip_ipaddr_t));\r
- memcpy(&DHCPHeader->ClientHardwareAddress, &MACAddress, sizeof(struct uip_eth_addr));\r
- DHCPHeader->Cookie = DHCP_MAGIC_COOKIE;\r
- \r
- /* Add a DHCP message type and terminator options to the start of the DHCP options field */\r
- DHCPHeader->Options[0] = DHCP_OPTION_MSG_TYPE;\r
- DHCPHeader->Options[1] = 1;\r
- DHCPHeader->Options[2] = DHCPMessageType;\r
- DHCPHeader->Options[3] = DHCP_OPTION_END;\r
- \r
- /* Calculate the total number of bytes added to the outgoing packet */\r
- return (sizeof(DHCP_Header_t) + 4);\r
-}\r
-\r
-/** Sets the given DHCP option in the DHCP packet's option list. This automatically moves the\r
- * end of options terminator past the new option in the options list.\r
- *\r
- * \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list\r
- * \param[in] Option DHCP option to add to the list\r
- * \param[in] DataLen Size in bytes of the option data to add\r
- * \param[in] OptionData Buffer where the option's data is to be sourced from\r
- *\r
- * \return Number of bytes added to the DHCP packet\r
- */\r
-uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen, void* OptionData)\r
-{\r
- /* Skip through the DHCP options list until the terminator option is found */\r
- while (*DHCPOptionList != DHCP_OPTION_END)\r
- DHCPOptionList += (DHCPOptionList[1] + 2);\r
-\r
- /* Overwrite the existing terminator with the new option, add a new terminator at the end of the list */\r
- DHCPOptionList[0] = Option;\r
- DHCPOptionList[1] = DataLen;\r
- memcpy(&DHCPOptionList[2], OptionData, DataLen);\r
- DHCPOptionList[2 + DataLen] = DHCP_OPTION_END;\r
- \r
- /* Calculate the total number of bytes added to the outgoing packet */\r
- return (2 + DataLen);\r
-}\r
-\r
-/** Retrieves the given option's data (if present) from the DHCP packet's options list.\r
- *\r
- * \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list\r
- * \param[in] Option DHCP option to retrieve to the list\r
- * \param[out] Destination Buffer where the option's data is to be written to if found\r
- *\r
- * \return Boolean true if the option was found in the DHCP packet's options list, false otherwise\r
- */\r
-bool DHCPClientApp_GetOption(uint8_t* DHCPOptionList, uint8_t Option, void* Destination)\r
-{\r
- /* Look through the incoming DHCP packet's options list for the requested option */\r
- while (*DHCPOptionList != DHCP_OPTION_END)\r
- {\r
- /* Check if the current DHCP option in the packet is the one requested */\r
- if (DHCPOptionList[0] == Option)\r
- {\r
- /* Copy request option's data to the destination buffer */\r
- memcpy(Destination, &DHCPOptionList[2], DHCPOptionList[1]);\r
- \r
- /* Indicate that the requested option data was successfully retrieved */\r
- return true;\r
- }\r
- \r
- /* Skip to next DHCP option in the options list */\r
- DHCPOptionList += (DHCPOptionList[1] + 2);\r
- }\r
- \r
- /* Requested option not found in the incoming packet's DHCP options list */\r
- return false;\r
-}\r
-#endif\r
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2011.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(ENABLE_DHCP_CLIENT) || defined(__DOXYGEN__)
+
+/** \file
+ *
+ * DHCP Client Application. When connected to the uIP stack, this will retrieve IP configuration settings from the
+ * DHCP server on the network.
+ */
+
+#define INCLUDE_FROM_DHCPCLIENTAPP_C
+#include "DHCPClientApp.h"
+
+/** Initialization function for the DHCP client. */
+void DHCPClientApp_Init(void)
+{
+ /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */
+ struct uip_udp_conn* Connection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCP_SERVER_PORT));
+
+ /* If the connection was successfully created, bind it to the local DHCP client port */
+ if (Connection != NULL)
+ {
+ uip_udp_appstate_t* const AppState = &Connection->appstate;
+ uip_udp_bind(Connection, HTONS(DHCP_CLIENT_PORT));
+
+ /* Set the initial client state */
+ AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
+
+ /* Set timeout period to half a second for a DHCP server to respond */
+ timer_set(&AppState->DHCPClient.Timeout, CLOCK_SECOND / 2);
+ }
+}
+
+/** uIP stack application callback for the DHCP client. This function must be called each time the TCP/IP stack
+ * needs a UDP packet to be processed.
+ */
+void DHCPClientApp_Callback(void)
+{
+ uip_udp_appstate_t* const AppState = &uip_udp_conn->appstate;
+ DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;
+ uint16_t AppDataSize = 0;
+
+ switch (AppState->DHCPClient.CurrentState)
+ {
+ case DHCP_STATE_SendDiscover:
+ /* Clear all DHCP settings, reset client IP address */
+ memset(&AppState->DHCPClient.DHCPOffer_Data, 0x00, sizeof(AppState->DHCPClient.DHCPOffer_Data));
+ uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
+
+ /* Fill out the DHCP response header */
+ AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState);
+
+ /* Add the required DHCP options list to the packet */
+ uint8_t RequiredOptionList[] = {DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_ROUTER, DHCP_OPTION_DNS_SERVER};
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_REQ_LIST, sizeof(RequiredOptionList),
+ RequiredOptionList);
+
+ /* Send the DHCP DISCOVER packet */
+ uip_udp_send(AppDataSize);
+
+ /* Reset the timeout timer, progress to next state */
+ timer_reset(&AppState->DHCPClient.Timeout);
+ AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForOffer;
+
+ break;
+ case DHCP_STATE_WaitForOffer:
+ if (!(uip_newdata()))
+ {
+ /* Check if the DHCP timeout period has expired while waiting for a response */
+ if (timer_expired(&AppState->DHCPClient.Timeout))
+ AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
+
+ break;
+ }
+
+ uint8_t OfferResponse_MessageType;
+ if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&
+ DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) &&
+ (OfferResponse_MessageType == DHCP_OFFER))
+ {
+ /* Received a DHCP offer for an IP address, copy over values for later request */
+ memcpy(&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, &AppData->YourIP, sizeof(uip_ipaddr_t));
+ DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPClient.DHCPOffer_Data.Netmask);
+ DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPClient.DHCPOffer_Data.GatewayIP);
+ DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPClient.DHCPOffer_Data.ServerIP);
+
+ timer_reset(&AppState->DHCPClient.Timeout);
+ AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest;
+ }
+
+ break;
+ case DHCP_STATE_SendRequest:
+ /* Fill out the DHCP response header */
+ AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_REQUEST, AppState);
+
+ /* Add the DHCP REQUESTED IP ADDRESS option to the packet */
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t),
+ &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
+
+ /* Add the DHCP SERVER IP ADDRESS option to the packet */
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t),
+ &AppState->DHCPClient.DHCPOffer_Data.ServerIP);
+
+ /* Send the DHCP REQUEST packet */
+ uip_udp_send(AppDataSize);
+
+ /* Reset the timeout timer, progress to next state */
+ timer_reset(&AppState->DHCPClient.Timeout);
+ AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForACK;
+
+ break;
+ case DHCP_STATE_WaitForACK:
+ if (!(uip_newdata()))
+ {
+ /* Check if the DHCP timeout period has expired while waiting for a response */
+ if (timer_expired(&AppState->DHCPClient.Timeout))
+ AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
+
+ break;
+ }
+
+ uint8_t RequestResponse_MessageType;
+ if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&
+ DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) &&
+ (RequestResponse_MessageType == DHCP_ACK))
+ {
+ /* Set the new network parameters from the DHCP server */
+ uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
+ uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.Netmask);
+ uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.GatewayIP);
+
+ AppState->DHCPClient.CurrentState = DHCP_STATE_AddressLeased;
+ }
+
+ break;
+ }
+}
+
+/** Fills the DHCP packet response with the appropriate BOOTP header for DHCP. This fills out all the required
+ * fields, leaving only the additional DHCP options to be added to the packet before it is sent to the DHCP server.
+ *
+ * \param[out] DHCPHeader Location in the packet buffer where the BOOTP header should be written to
+ * \param[in] DHCPMessageType DHCP Message type, such as DHCP_DISCOVER
+ * \param[in] AppState Application state of the current UDP connection
+ *
+ * \return Size in bytes of the created DHCP packet
+ */
+static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
+ const uint8_t DHCPMessageType,
+ uip_udp_appstate_t* const AppState)
+{
+ /* Erase existing packet data so that we start will all 0x00 DHCP header data */
+ memset(DHCPHeader, 0, sizeof(DHCP_Header_t));
+
+ /* Fill out the DHCP packet header */
+ DHCPHeader->Operation = DHCP_OP_BOOTREQUEST;
+ DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;
+ DHCPHeader->HardwareAddressLength = sizeof(MACAddress);
+ DHCPHeader->Hops = 0;
+ DHCPHeader->TransactionID = DHCP_TRANSACTION_ID;
+ DHCPHeader->ElapsedSeconds = 0;
+ DHCPHeader->Flags = HTONS(BOOTP_BROADCAST);
+ memcpy(&DHCPHeader->ClientIP, &uip_hostaddr, sizeof(uip_ipaddr_t));
+ memcpy(&DHCPHeader->YourIP, &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, sizeof(uip_ipaddr_t));
+ memcpy(&DHCPHeader->NextServerIP, &AppState->DHCPClient.DHCPOffer_Data.ServerIP, sizeof(uip_ipaddr_t));
+ memcpy(&DHCPHeader->ClientHardwareAddress, &MACAddress, sizeof(struct uip_eth_addr));
+ DHCPHeader->Cookie = DHCP_MAGIC_COOKIE;
+
+ /* Add a DHCP message type and terminator options to the start of the DHCP options field */
+ DHCPHeader->Options[0] = DHCP_OPTION_MSG_TYPE;
+ DHCPHeader->Options[1] = 1;
+ DHCPHeader->Options[2] = DHCPMessageType;
+ DHCPHeader->Options[3] = DHCP_OPTION_END;
+
+ /* Calculate the total number of bytes added to the outgoing packet */
+ return (sizeof(DHCP_Header_t) + 4);
+}
+
+#endif
+