-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2011.\r
-\r
- dean [at] fourwalledcubicle [dot] com\r
- www.lufa-lib.org\r
-*/\r
-\r
-/*\r
- Copyright 2011 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
-#if defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__)\r
-\r
-/** \file\r
- *\r
- * DHCP Server Application. When connected to the uIP stack, this will send IP configuration settings to a\r
- * DHCP client on the network.\r
- */\r
-\r
-#define INCLUDE_FROM_DHCPSERVERAPP_C\r
-#include "DHCPServerApp.h"\r
-\r
-struct uip_conn* BroadcastConnection;\r
-\r
-uint8_t LeasedIPs[255 / 8];\r
- \r
-/** Initialization function for the DHCP server. */\r
-void DHCPServerApp_Init(void)\r
-{\r
- /* Listen on port 67 for DHCP server connections from hosts */\r
- uip_listen(HTONS(DHCP_SERVER_PORT));\r
- \r
- /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */\r
- struct uip_udp_conn* BroadcastConnection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCP_CLIENT_PORT));\r
-\r
- /* If the connection was successfully created, bind it to the local DHCP client port */\r
- if (BroadcastConnection != NULL)\r
- uip_udp_bind(BroadcastConnection, HTONS(DHCP_SERVER_PORT));\r
- \r
- /* Set all IP addresses as unleased */\r
- memset(LeasedIPs, 0x00, sizeof(LeasedIPs));\r
-}\r
-\r
-/** uIP stack application callback for the DHCP server. This function must be called each time the TCP/IP stack\r
- * needs a UDP packet to be processed.\r
- */\r
-void DHCPServerApp_Callback(void)\r
-{\r
- DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;\r
- uint16_t AppDataSize = 0;\r
-\r
- /* Only process when new data arrives - don't retransmit lost packets */\r
- if (uip_newdata())\r
- {\r
- /* Get the DHCP message type (if present), otherwise early-abort */\r
- uint8_t DHCPMessageType;\r
- if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &DHCPMessageType)))\r
- return;\r
-\r
- uip_ipaddr_t Netmask, GatewayIPAddress, PreferredClientIP;\r
- struct uip_eth_addr RemoteMACAddress;\r
- uint32_t TransactionID;\r
-\r
- /* Get configured network mask, gateway IP and extract out DHCP transaction ID and remote IP */\r
- uip_getnetmask(&Netmask);\r
- uip_getdraddr(&GatewayIPAddress);\r
- memcpy(&RemoteMACAddress, &AppData->ClientHardwareAddress, sizeof(struct uip_eth_addr));\r
- TransactionID = AppData->TransactionID;\r
-\r
- /* Try to extract out the client's preferred IP address if it is indicated in the packet */\r
- if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, &PreferredClientIP)))\r
- memcpy(&PreferredClientIP, &uip_all_zeroes_addr, sizeof(uip_ipaddr_t)); \r
- \r
- switch (DHCPMessageType)\r
- {\r
- case DHCP_DISCOVER:\r
- /* If no preference was made or the preferred IP is already taken, find a new address */\r
- if (DHCPServerApp_CheckIfIPLeased(&PreferredClientIP))\r
- DHCPServerApp_GetUnleasedIP(&PreferredClientIP);\r
-\r
- /* Create a new DHCP OFFER packet with the offered IP address */\r
- AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_OFFER, &RemoteMACAddress, &PreferredClientIP, TransactionID);\r
-\r
- /* Add network mask and router information to the list of DHCP OFFER packet options */\r
- AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK,\r
- sizeof(uip_ipaddr_t), &Netmask);\r
- AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER,\r
- sizeof(uip_ipaddr_t), &GatewayIPAddress);\r
-\r
- /* Send the DHCP OFFER packet */\r
- uip_poll_conn(BroadcastConnection);\r
- memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t));\r
- uip_udp_send(AppDataSize);\r
-\r
- break;\r
- case DHCP_REQUEST:\r
- /* Check to see if the requested IP address has already been leased to a client */\r
- if (!(DHCPServerApp_CheckIfIPLeased(&PreferredClientIP)))\r
- {\r
- /* Create a new DHCP ACK packet to accept the IP address lease */ \r
- AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_ACK, &RemoteMACAddress, &PreferredClientIP, TransactionID);\r
-\r
- /* Add network mask and router information to the list of DHCP ACK packet options */\r
- AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK,\r
- sizeof(uip_ipaddr_t), &Netmask);\r
- AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER,\r
- sizeof(uip_ipaddr_t), &GatewayIPAddress);\r
-\r
- /* Mark the requested IP as leased to a client */\r
- DHCPServerApp_LeaseIP(&PreferredClientIP);\r
- }\r
- else\r
- {\r
- /* Create a new DHCP NAK packet to reject the requested allocation */\r
- AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_NAK, &RemoteMACAddress, &uip_all_zeroes_addr, TransactionID);\r
- }\r
- \r
- /* Send the DHCP ACK or NAK packet */\r
- uip_poll_conn(BroadcastConnection);\r
- memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t));\r
- uip_udp_send(AppDataSize);\r
- \r
- break;\r
- case DHCP_RELEASE:\r
- /* Mark the IP address as released in the allocation table */\r
- DHCPServerApp_UnleaseIP(&uip_udp_conn->ripaddr);\r
- break;\r
- }\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 client.\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] ClientHardwareAddress Client MAC address the created transaction should be directed to\r
- * \param[in] TransactionID Transaction ID the created transaction should be associated with\r
- *\r
- * \return Size in bytes of the created DHCP packet\r
- */\r
-static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,\r
- const uint8_t DHCPMessageType,\r
- const struct uip_eth_addr* const ClientHardwareAddress,\r
- const uip_ipaddr_t* const PreferredClientIP,\r
- const uint32_t TransactionID)\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
- DHCPHeader->Operation = DHCPMessageType;\r
- DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;\r
- DHCPHeader->HardwareAddressLength = sizeof(MACAddress);\r
- DHCPHeader->Hops = 0;\r
- DHCPHeader->TransactionID = TransactionID;\r
- DHCPHeader->ElapsedSeconds = 0;\r
- DHCPHeader->Flags = 0;\r
- memcpy(&DHCPHeader->NextServerIP, &uip_hostaddr, sizeof(uip_ipaddr_t));\r
- memcpy(&DHCPHeader->YourIP, PreferredClientIP, sizeof(uip_ipaddr_t));\r
- memcpy(&DHCPHeader->ClientHardwareAddress, ClientHardwareAddress, 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
-/** Checks to see if the nominated IP address has already been allocated to a client.\r
- *\r
- * \param[in] IPAddress IP Address whose lease status should be checked\r
- *\r
- * \pre The IP address must be within the same /24 subnet as the virtual webserver.\r
- *\r
- * \return Boolean true if the IP has already been leased to a client, false otherwise.\r
- */\r
-static bool DHCPServerApp_CheckIfIPLeased(const uip_ipaddr_t* const IPAddress)\r
-{\r
- uint8_t Byte = (IPAddress->u8[3] / 8);\r
- uint8_t Mask = (1 << (IPAddress->u8[3] % 8));\r
- \r
- /* Make sure that the requested IP address isn't already leased to the virtual server or another client */\r
- if (IPAddress->u8[3] && !(IPAddress->u8[3] == uip_hostaddr.u8[3]) && !(LeasedIPs[Byte] & Mask))\r
- return false;\r
- else\r
- return true;\r
-}\r
-\r
-/** Retrieves the next unleased IP in the IP address pool.\r
- *\r
- * \param[out] NewIPAddress Location where the generated IP Address should be stored\r
- */\r
-static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* const NewIPAddress)\r
-{\r
- uip_ipaddr_copy(NewIPAddress, &uip_hostaddr);\r
- \r
- /** Look through the current subnet, skipping the broadcast and zero IP addresses */\r
- for (uint8_t IP = 1; IP < 254; IP++)\r
- {\r
- /* Update new IP address to lease with the current IP address to test */\r
- NewIPAddress->u8[3] = IP;\r
- \r
- /* If we've found an unleased IP, abort with the updated IP stored for the called */\r
- if (!(DHCPServerApp_CheckIfIPLeased(NewIPAddress)))\r
- return;\r
- }\r
-}\r
-\r
-/** Marks the given IP Address as leased in the address pool, so that it will not be\r
- * allocated to another client unless it is first released.\r
- *\r
- * \param[in] IPAddress IP Address to mark as leased\r
- *\r
- * \pre The IP address must be within the same /24 subnet as the virtual webserver.\r
- */\r
-static void DHCPServerApp_LeaseIP(const uip_ipaddr_t* const IPAddress)\r
-{\r
- uint8_t Byte = (IPAddress->u8[3] / 8);\r
- uint8_t Mask = (1 << (IPAddress->u8[3] % 8));\r
- \r
- /* Mark the IP address as leased in the allocation table */\r
- LeasedIPs[Byte] |= Mask;\r
-}\r
-\r
-/** Marks the given IP Address as not leased in the address pool, so that it can be\r
- * allocated to another client upon request.\r
- *\r
- * \param[in] IPAddress IP Address to mark as not leased\r
- *\r
- * \pre The IP address must be within the same /24 subnet as the virtual webserver.\r
- */\r
-static void DHCPServerApp_UnleaseIP(const uip_ipaddr_t* const IPAddress)\r
-{\r
- uint8_t Byte = (IPAddress->u8[3] / 8);\r
- uint8_t Mask = (1 << (IPAddress->u8[3] % 8));\r
- \r
- /* Mark the IP address as unleased in the allocation table */\r
- LeasedIPs[Byte] &= ~Mask;\r
-}\r
-#endif\r
-\r
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2012.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2012 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_SERVER) || defined(__DOXYGEN__)
+
+/** \file
+ *
+ * DHCP Server Application. When connected to the uIP stack, this will send IP configuration settings to a
+ * DHCP client on the network.
+ */
+
+#define INCLUDE_FROM_DHCPSERVERAPP_C
+#include "DHCPServerApp.h"
+
+struct uip_conn* BroadcastConnection;
+
+uint8_t LeasedIPs[255 / 8];
+
+/** Initialization function for the DHCP server. */
+void DHCPServerApp_Init(void)
+{
+ /* Listen on port 67 for DHCP server connections from hosts */
+ uip_listen(HTONS(DHCP_SERVER_PORT));
+
+ /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */
+ struct uip_udp_conn* BroadcastConnection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCP_CLIENT_PORT));
+
+ /* If the connection was successfully created, bind it to the local DHCP client port */
+ if (BroadcastConnection != NULL)
+ uip_udp_bind(BroadcastConnection, HTONS(DHCP_SERVER_PORT));
+
+ /* Set all IP addresses as unleased */
+ memset(LeasedIPs, 0x00, sizeof(LeasedIPs));
+}
+
+/** uIP stack application callback for the DHCP server. This function must be called each time the TCP/IP stack
+ * needs a UDP packet to be processed.
+ */
+void DHCPServerApp_Callback(void)
+{
+ DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;
+ uint16_t AppDataSize = 0;
+
+ /* Only process when new data arrives - don't retransmit lost packets */
+ if (uip_newdata())
+ {
+ /* Get the DHCP message type (if present), otherwise early-abort */
+ uint8_t DHCPMessageType;
+ if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &DHCPMessageType)))
+ return;
+
+ uip_ipaddr_t Netmask, GatewayIPAddress, PreferredClientIP;
+ struct uip_eth_addr RemoteMACAddress;
+ uint32_t TransactionID;
+
+ /* Get configured network mask, gateway IP and extract out DHCP transaction ID and remote IP */
+ uip_getnetmask(&Netmask);
+ uip_getdraddr(&GatewayIPAddress);
+ memcpy(&RemoteMACAddress, &AppData->ClientHardwareAddress, sizeof(struct uip_eth_addr));
+ TransactionID = AppData->TransactionID;
+
+ /* Try to extract out the client's preferred IP address if it is indicated in the packet */
+ if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, &PreferredClientIP)))
+ memcpy(&PreferredClientIP, &uip_all_zeroes_addr, sizeof(uip_ipaddr_t));
+
+ switch (DHCPMessageType)
+ {
+ case DHCP_DISCOVER:
+ /* If no preference was made or the preferred IP is already taken, find a new address */
+ if (DHCPServerApp_CheckIfIPLeased(&PreferredClientIP))
+ DHCPServerApp_GetUnleasedIP(&PreferredClientIP);
+
+ /* Create a new DHCP OFFER packet with the offered IP address */
+ AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_OFFER, &RemoteMACAddress, &PreferredClientIP, TransactionID);
+
+ /* Add network mask and router information to the list of DHCP OFFER packet options */
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK,
+ sizeof(uip_ipaddr_t), &Netmask);
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER,
+ sizeof(uip_ipaddr_t), &GatewayIPAddress);
+
+ /* Send the DHCP OFFER packet */
+ uip_poll_conn(BroadcastConnection);
+ memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t));
+ uip_udp_send(AppDataSize);
+
+ break;
+ case DHCP_REQUEST:
+ /* Check to see if the requested IP address has already been leased to a client */
+ if (!(DHCPServerApp_CheckIfIPLeased(&PreferredClientIP)))
+ {
+ /* Create a new DHCP ACK packet to accept the IP address lease */
+ AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_ACK, &RemoteMACAddress, &PreferredClientIP, TransactionID);
+
+ /* Add network mask and router information to the list of DHCP ACK packet options */
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK,
+ sizeof(uip_ipaddr_t), &Netmask);
+ AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER,
+ sizeof(uip_ipaddr_t), &GatewayIPAddress);
+
+ /* Mark the requested IP as leased to a client */
+ DHCPServerApp_LeaseIP(&PreferredClientIP);
+ }
+ else
+ {
+ /* Create a new DHCP NAK packet to reject the requested allocation */
+ AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_NAK, &RemoteMACAddress, &uip_all_zeroes_addr, TransactionID);
+ }
+
+ /* Send the DHCP ACK or NAK packet */
+ uip_poll_conn(BroadcastConnection);
+ memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t));
+ uip_udp_send(AppDataSize);
+
+ break;
+ case DHCP_RELEASE:
+ /* Mark the IP address as released in the allocation table */
+ DHCPServerApp_UnleaseIP(&uip_udp_conn->ripaddr);
+ 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 client.
+ *
+ * \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] ClientHardwareAddress Client MAC address the created transaction should be directed to
+ * \param[in] PreferredClientIP Preferred IP that should be given to the client if it is unallocated
+ * \param[in] TransactionID Transaction ID the created transaction should be associated with
+ *
+ * \return Size in bytes of the created DHCP packet
+ */
+static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
+ const uint8_t DHCPMessageType,
+ const struct uip_eth_addr* const ClientHardwareAddress,
+ const uip_ipaddr_t* const PreferredClientIP,
+ const uint32_t TransactionID)
+{
+ /* Erase existing packet data so that we start will all 0x00 DHCP header data */
+ memset(DHCPHeader, 0, sizeof(DHCP_Header_t));
+
+ DHCPHeader->Operation = DHCPMessageType;
+ DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;
+ DHCPHeader->HardwareAddressLength = sizeof(MACAddress);
+ DHCPHeader->Hops = 0;
+ DHCPHeader->TransactionID = TransactionID;
+ DHCPHeader->ElapsedSeconds = 0;
+ DHCPHeader->Flags = 0;
+ memcpy(&DHCPHeader->NextServerIP, &uip_hostaddr, sizeof(uip_ipaddr_t));
+ memcpy(&DHCPHeader->YourIP, PreferredClientIP, sizeof(uip_ipaddr_t));
+ memcpy(&DHCPHeader->ClientHardwareAddress, ClientHardwareAddress, 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);
+}
+
+/** Checks to see if the nominated IP address has already been allocated to a client.
+ *
+ * \param[in] IPAddress IP Address whose lease status should be checked
+ *
+ * \pre The IP address must be within the same /24 subnet as the virtual webserver.
+ *
+ * \return Boolean true if the IP has already been leased to a client, false otherwise.
+ */
+static bool DHCPServerApp_CheckIfIPLeased(const uip_ipaddr_t* const IPAddress)
+{
+ uint8_t Byte = (IPAddress->u8[3] / 8);
+ uint8_t Mask = (1 << (IPAddress->u8[3] % 8));
+
+ /* Make sure that the requested IP address isn't already leased to the virtual server or another client */
+ if (IPAddress->u8[3] && !(IPAddress->u8[3] == uip_hostaddr.u8[3]) && !(LeasedIPs[Byte] & Mask))
+ return false;
+ else
+ return true;
+}
+
+/** Retrieves the next unleased IP in the IP address pool.
+ *
+ * \param[out] NewIPAddress Location where the generated IP Address should be stored
+ */
+static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* const NewIPAddress)
+{
+ uip_ipaddr_copy(NewIPAddress, &uip_hostaddr);
+
+ /** Look through the current subnet, skipping the broadcast and zero IP addresses */
+ for (uint8_t IP = 1; IP < 254; IP++)
+ {
+ /* Update new IP address to lease with the current IP address to test */
+ NewIPAddress->u8[3] = IP;
+
+ /* If we've found an unleased IP, abort with the updated IP stored for the called */
+ if (!(DHCPServerApp_CheckIfIPLeased(NewIPAddress)))
+ return;
+ }
+}
+
+/** Marks the given IP Address as leased in the address pool, so that it will not be
+ * allocated to another client unless it is first released.
+ *
+ * \param[in] IPAddress IP Address to mark as leased
+ *
+ * \pre The IP address must be within the same /24 subnet as the virtual webserver.
+ */
+static void DHCPServerApp_LeaseIP(const uip_ipaddr_t* const IPAddress)
+{
+ uint8_t Byte = (IPAddress->u8[3] / 8);
+ uint8_t Mask = (1 << (IPAddress->u8[3] % 8));
+
+ /* Mark the IP address as leased in the allocation table */
+ LeasedIPs[Byte] |= Mask;
+}
+
+/** Marks the given IP Address as not leased in the address pool, so that it can be
+ * allocated to another client upon request.
+ *
+ * \param[in] IPAddress IP Address to mark as not leased
+ *
+ * \pre The IP address must be within the same /24 subnet as the virtual webserver.
+ */
+static void DHCPServerApp_UnleaseIP(const uip_ipaddr_t* const IPAddress)
+{
+ uint8_t Byte = (IPAddress->u8[3] / 8);
+ uint8_t Mask = (1 << (IPAddress->u8[3] % 8));
+
+ /* Mark the IP address as unleased in the allocation table */
+ LeasedIPs[Byte] &= ~Mask;
+}
+#endif
+