Minor documentation adjustments to the demos, projects and bootloaders to ensure...
[pub/USBasp.git] / Projects / Webserver / Lib / DHCPServerApp.c
index 4399e9a..e2b72af 100644 (file)
-/*\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]  PreferredClientIP      Preferred IP that should be given to the client if it is unallocated\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
+