From 60b30c036397cb5627fa374bb930794b225daa29 Mon Sep 17 00:00:00 2001
From: Jack Humbert <jack.humb@gmail.com>
Date: Fri, 7 Jul 2017 11:55:23 -0400
Subject: Squashed 'lib/lufa/' content from commit 385d40300

git-subtree-dir: lib/lufa
git-subtree-split: 385d4030035dbaf41591309dbde47653bd03841b
---
 Projects/Webserver/Config/AppConfig.h       |   73 +
 Projects/Webserver/Config/LUFAConfig.h      |   93 +
 Projects/Webserver/Descriptors.c            |  295 ++
 Projects/Webserver/Descriptors.h            |  128 +
 Projects/Webserver/LUFA Webserver RNDIS.inf |   59 +
 Projects/Webserver/Lib/DHCPClientApp.c      |  208 ++
 Projects/Webserver/Lib/DHCPClientApp.h      |   69 +
 Projects/Webserver/Lib/DHCPCommon.c         |  103 +
 Projects/Webserver/Lib/DHCPCommon.h         |  159 +
 Projects/Webserver/Lib/DHCPServerApp.c      |  265 ++
 Projects/Webserver/Lib/DHCPServerApp.h      |   64 +
 Projects/Webserver/Lib/DataflashManager.c   |  534 ++++
 Projects/Webserver/Lib/DataflashManager.h   |   87 +
 Projects/Webserver/Lib/FATFs/00readme.txt   |  135 +
 Projects/Webserver/Lib/FATFs/diskio.c       |   65 +
 Projects/Webserver/Lib/FATFs/diskio.h       |   52 +
 Projects/Webserver/Lib/FATFs/ff.c           | 4139 +++++++++++++++++++++++++++
 Projects/Webserver/Lib/FATFs/ff.h           |  337 +++
 Projects/Webserver/Lib/FATFs/ffconf.h       |  190 ++
 Projects/Webserver/Lib/FATFs/integer.h      |   38 +
 Projects/Webserver/Lib/HTTPServerApp.c      |  284 ++
 Projects/Webserver/Lib/HTTPServerApp.h      |   84 +
 Projects/Webserver/Lib/SCSI.c               |  344 +++
 Projects/Webserver/Lib/SCSI.h               |   87 +
 Projects/Webserver/Lib/TELNETServerApp.c    |  163 ++
 Projects/Webserver/Lib/TELNETServerApp.h    |   71 +
 Projects/Webserver/Lib/uIPManagement.c      |  298 ++
 Projects/Webserver/Lib/uIPManagement.h      |   69 +
 Projects/Webserver/Lib/uip/clock.c          |   37 +
 Projects/Webserver/Lib/uip/clock.h          |   13 +
 Projects/Webserver/Lib/uip/timer.c          |  128 +
 Projects/Webserver/Lib/uip/timer.h          |   87 +
 Projects/Webserver/Lib/uip/uip-split.c      |  151 +
 Projects/Webserver/Lib/uip/uip-split.h      |  104 +
 Projects/Webserver/Lib/uip/uip.c            | 1941 +++++++++++++
 Projects/Webserver/Lib/uip/uip.h            | 2130 ++++++++++++++
 Projects/Webserver/Lib/uip/uip_arp.c        |  432 +++
 Projects/Webserver/Lib/uip/uip_arp.h        |  146 +
 Projects/Webserver/Lib/uip/uipopt.h         |  740 +++++
 Projects/Webserver/USBDeviceMode.c          |  162 ++
 Projects/Webserver/USBDeviceMode.h          |   62 +
 Projects/Webserver/USBHostMode.c            |  172 ++
 Projects/Webserver/USBHostMode.h            |   60 +
 Projects/Webserver/Webserver.c              |   77 +
 Projects/Webserver/Webserver.h              |   76 +
 Projects/Webserver/Webserver.txt            |  126 +
 Projects/Webserver/asf.xml                  |   96 +
 Projects/Webserver/doxyfile                 | 2396 ++++++++++++++++
 Projects/Webserver/makefile                 |   46 +
 49 files changed, 17675 insertions(+)
 create mode 100644 Projects/Webserver/Config/AppConfig.h
 create mode 100644 Projects/Webserver/Config/LUFAConfig.h
 create mode 100644 Projects/Webserver/Descriptors.c
 create mode 100644 Projects/Webserver/Descriptors.h
 create mode 100644 Projects/Webserver/LUFA Webserver RNDIS.inf
 create mode 100644 Projects/Webserver/Lib/DHCPClientApp.c
 create mode 100644 Projects/Webserver/Lib/DHCPClientApp.h
 create mode 100644 Projects/Webserver/Lib/DHCPCommon.c
 create mode 100644 Projects/Webserver/Lib/DHCPCommon.h
 create mode 100644 Projects/Webserver/Lib/DHCPServerApp.c
 create mode 100644 Projects/Webserver/Lib/DHCPServerApp.h
 create mode 100644 Projects/Webserver/Lib/DataflashManager.c
 create mode 100644 Projects/Webserver/Lib/DataflashManager.h
 create mode 100644 Projects/Webserver/Lib/FATFs/00readme.txt
 create mode 100644 Projects/Webserver/Lib/FATFs/diskio.c
 create mode 100644 Projects/Webserver/Lib/FATFs/diskio.h
 create mode 100644 Projects/Webserver/Lib/FATFs/ff.c
 create mode 100644 Projects/Webserver/Lib/FATFs/ff.h
 create mode 100644 Projects/Webserver/Lib/FATFs/ffconf.h
 create mode 100644 Projects/Webserver/Lib/FATFs/integer.h
 create mode 100644 Projects/Webserver/Lib/HTTPServerApp.c
 create mode 100644 Projects/Webserver/Lib/HTTPServerApp.h
 create mode 100644 Projects/Webserver/Lib/SCSI.c
 create mode 100644 Projects/Webserver/Lib/SCSI.h
 create mode 100644 Projects/Webserver/Lib/TELNETServerApp.c
 create mode 100644 Projects/Webserver/Lib/TELNETServerApp.h
 create mode 100644 Projects/Webserver/Lib/uIPManagement.c
 create mode 100644 Projects/Webserver/Lib/uIPManagement.h
 create mode 100644 Projects/Webserver/Lib/uip/clock.c
 create mode 100644 Projects/Webserver/Lib/uip/clock.h
 create mode 100644 Projects/Webserver/Lib/uip/timer.c
 create mode 100644 Projects/Webserver/Lib/uip/timer.h
 create mode 100644 Projects/Webserver/Lib/uip/uip-split.c
 create mode 100644 Projects/Webserver/Lib/uip/uip-split.h
 create mode 100644 Projects/Webserver/Lib/uip/uip.c
 create mode 100644 Projects/Webserver/Lib/uip/uip.h
 create mode 100644 Projects/Webserver/Lib/uip/uip_arp.c
 create mode 100644 Projects/Webserver/Lib/uip/uip_arp.h
 create mode 100644 Projects/Webserver/Lib/uip/uipopt.h
 create mode 100644 Projects/Webserver/USBDeviceMode.c
 create mode 100644 Projects/Webserver/USBDeviceMode.h
 create mode 100644 Projects/Webserver/USBHostMode.c
 create mode 100644 Projects/Webserver/USBHostMode.h
 create mode 100644 Projects/Webserver/Webserver.c
 create mode 100644 Projects/Webserver/Webserver.h
 create mode 100644 Projects/Webserver/Webserver.txt
 create mode 100644 Projects/Webserver/asf.xml
 create mode 100644 Projects/Webserver/doxyfile
 create mode 100644 Projects/Webserver/makefile

(limited to 'Projects/Webserver')

diff --git a/Projects/Webserver/Config/AppConfig.h b/Projects/Webserver/Config/AppConfig.h
new file mode 100644
index 0000000000..30a265767c
--- /dev/null
+++ b/Projects/Webserver/Config/AppConfig.h
@@ -0,0 +1,73 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *  \brief Application Configuration Header File
+ *
+ *  This is a header file which is be used to configure some of
+ *  the application's compile time options, as an alternative to
+ *  specifying the compile time constants supplied through a
+ *  makefile or build system.
+ *
+ *  For information on what each token does, refer to the
+ *  \ref Sec_Options section of the application documentation.
+ */
+
+#ifndef _APP_CONFIG_H_
+#define _APP_CONFIG_H_
+
+	#define ENABLE_DHCP_CLIENT
+	#define ENABLE_DHCP_SERVER
+	#define ENABLE_TELNET_SERVER
+	#define MAX_URI_LENGTH                50
+
+	#define DEVICE_IP_ADDRESS             (uint8_t[]){ 10,   0,   0,   2}
+	#define DEVICE_NETMASK                (uint8_t[]){255, 255, 255,   0}
+	#define DEVICE_GATEWAY                (uint8_t[]){ 10,   0,   0,   1}
+	#define SERVER_MAC_ADDRESS            (uint8_t[]){  1,   0,   1,   0,   1,   0}
+
+	#define UIP_CONF_UDP                  (defined(ENABLE_DHCP_CLIENT) || defined(ENABLE_DHCP_SERVER))
+	#define UIP_CONF_BROADCAST            1
+	#define UIP_CONF_TCP                  1
+	#define UIP_CONF_UDP_CONNS            1
+	#define UIP_CONF_MAX_CONNECTIONS      3
+	#define UIP_CONF_MAX_LISTENPORTS      5
+	#define UIP_CONF_BUFFER_SIZE          1514
+	#define UIP_CONF_LL_802154            0
+	#define UIP_CONF_LL_80211             0
+	#define UIP_CONF_ROUTER               0
+	#define UIP_CONF_ICMP6                0
+	#define UIP_CONF_ICMP_DEST_UNREACH    1
+	#define UIP_URGDATA                   0
+	#define UIP_ARCH_CHKSUM               0
+	#define UIP_ARCH_ADD32                0
+	#define UIP_NEIGHBOR_CONF_ADDRTYPE    0
+
+#endif
diff --git a/Projects/Webserver/Config/LUFAConfig.h b/Projects/Webserver/Config/LUFAConfig.h
new file mode 100644
index 0000000000..ba602dbad6
--- /dev/null
+++ b/Projects/Webserver/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *  \brief LUFA Library Configuration Header File
+ *
+ *  This header file is used to configure LUFA's compile time options,
+ *  as an alternative to the compile time constants supplied through
+ *  a makefile.
+ *
+ *  For information on what each token does, refer to the LUFA
+ *  manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+	#if (ARCH == ARCH_AVR8)
+
+		/* Non-USB Related Configuration Tokens: */
+//		#define DISABLE_TERMINAL_CODES
+
+		/* USB Class Driver Related Tokens: */
+//		#define HID_HOST_BOOT_PROTOCOL_ONLY
+//		#define HID_STATETABLE_STACK_DEPTH       {Insert Value Here}
+//		#define HID_USAGE_STACK_DEPTH            {Insert Value Here}
+//		#define HID_MAX_COLLECTIONS              {Insert Value Here}
+//		#define HID_MAX_REPORTITEMS              {Insert Value Here}
+//		#define HID_MAX_REPORT_IDS               {Insert Value Here}
+//		#define NO_CLASS_DRIVER_AUTOFLUSH
+
+		/* General USB Driver Related Tokens: */
+//		#define ORDERED_EP_CONFIG
+		#define USE_STATIC_OPTIONS               (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+//		#define USB_DEVICE_ONLY
+//		#define USB_HOST_ONLY
+//		#define USB_STREAM_TIMEOUT_MS            {Insert Value Here}
+//		#define NO_LIMITED_CONTROLLER_CONNECT
+//		#define NO_SOF_EVENTS
+
+		/* USB Device Mode Driver Related Tokens: */
+//		#define USE_RAM_DESCRIPTORS
+		#define USE_FLASH_DESCRIPTORS
+//		#define USE_EEPROM_DESCRIPTORS
+//		#define NO_INTERNAL_SERIAL
+		#define FIXED_CONTROL_ENDPOINT_SIZE      8
+		#define DEVICE_STATE_AS_GPIOR            0
+		#define FIXED_NUM_CONFIGURATIONS         1
+//		#define CONTROL_ONLY_DEVICE
+		#define INTERRUPT_CONTROL_ENDPOINT
+//		#define NO_DEVICE_REMOTE_WAKEUP
+//		#define NO_DEVICE_SELF_POWER
+
+		/* USB Host Mode Driver Related Tokens: */
+		#define HOST_STATE_AS_GPIOR              0
+//		#define USB_HOST_TIMEOUT_MS              {Insert Value Here}
+//		#define HOST_DEVICE_SETTLE_DELAY_MS	     {Insert Value Here}
+//		#define NO_AUTO_VBUS_MANAGEMENT
+//		#define INVERTED_VBUS_ENABLE_LINE
+
+	#else
+
+		#error Unsupported architecture for this LUFA configuration file.
+
+	#endif
+#endif
diff --git a/Projects/Webserver/Descriptors.c b/Projects/Webserver/Descriptors.c
new file mode 100644
index 0000000000..72dda9f124
--- /dev/null
+++ b/Projects/Webserver/Descriptors.c
@@ -0,0 +1,295 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *
+ *  USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ *  computer-readable structures which the host requests upon device enumeration, to determine
+ *  the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+
+/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
+ *  device characteristics, including the supported USB version, control endpoint size and the
+ *  number of device configurations. The descriptor is read out by the USB host when the enumeration
+ *  process begins.
+ */
+const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
+{
+	.Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+	.USBSpecification       = VERSION_BCD(1,1,0),
+	.Class                  = USB_CSCP_IADDeviceClass,
+	.SubClass               = USB_CSCP_IADDeviceSubclass,
+	.Protocol               = USB_CSCP_IADDeviceProtocol,
+
+	.Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
+
+	.VendorID               = 0x03EB,
+	.ProductID              = 0x2069,
+	.ReleaseNumber          = VERSION_BCD(0,0,1),
+
+	.ManufacturerStrIndex   = STRING_ID_Manufacturer,
+	.ProductStrIndex        = STRING_ID_Product,
+	.SerialNumStrIndex      = USE_INTERNAL_SERIAL,
+
+	.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
+ *  of the device in one of its supported configurations, including information about any device interfaces
+ *  and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ *  a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
+{
+	.Config =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+			.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+			.TotalInterfaces        = 3,
+
+			.ConfigurationNumber    = 1,
+			.ConfigurationStrIndex  = NO_DESCRIPTOR,
+
+			.ConfigAttributes       = USB_CONFIG_ATTR_RESERVED,
+
+			.MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)
+		},
+
+	.CDC_IAD =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
+
+			.FirstInterfaceIndex    = INTERFACE_ID_CDC_CCI,
+			.TotalInterfaces        = 2,
+
+			.Class                  = CDC_CSCP_CDCClass,
+			.SubClass               = CDC_CSCP_ACMSubclass,
+			.Protocol               = CDC_CSCP_VendorSpecificProtocol,
+
+			.IADStrIndex            = NO_DESCRIPTOR
+		},
+
+	.CDC_CCI_Interface =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+			.InterfaceNumber        = INTERFACE_ID_CDC_CCI,
+			.AlternateSetting       = 0,
+
+			.TotalEndpoints         = 1,
+
+			.Class                  = CDC_CSCP_CDCClass,
+			.SubClass               = CDC_CSCP_ACMSubclass,
+			.Protocol               = CDC_CSCP_VendorSpecificProtocol,
+
+			.InterfaceStrIndex      = NO_DESCRIPTOR
+		},
+
+	.CDC_Functional_Header =
+		{
+			.Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
+			.Subtype                = CDC_DSUBTYPE_CSInterface_Header,
+
+			.CDCSpecification       = VERSION_BCD(1,1,0),
+		},
+
+	.CDC_Functional_ACM =
+		{
+			.Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
+			.Subtype                = CDC_DSUBTYPE_CSInterface_ACM,
+
+			.Capabilities           = 0x00,
+		},
+
+	.CDC_Functional_Union =
+		{
+			.Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
+			.Subtype                = CDC_DSUBTYPE_CSInterface_Union,
+
+			.MasterInterfaceNumber  = INTERFACE_ID_CDC_CCI,
+			.SlaveInterfaceNumber   = INTERFACE_ID_CDC_DCI,
+		},
+
+	.CDC_NotificationEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = CDC_NOTIFICATION_EPADDR,
+			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = CDC_NOTIFICATION_EPSIZE,
+			.PollingIntervalMS      = 0xFF
+		},
+
+	.CDC_DCI_Interface =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+			.InterfaceNumber        = INTERFACE_ID_CDC_DCI,
+			.AlternateSetting       = 0,
+
+			.TotalEndpoints         = 2,
+
+			.Class                  = CDC_CSCP_CDCDataClass,
+			.SubClass               = CDC_CSCP_NoDataSubclass,
+			.Protocol               = CDC_CSCP_NoDataProtocol,
+
+			.InterfaceStrIndex      = NO_DESCRIPTOR
+		},
+
+	.RNDIS_DataOutEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = CDC_RX_EPADDR,
+			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = CDC_TXRX_EPSIZE,
+			.PollingIntervalMS      = 0x05
+		},
+
+	.RNDIS_DataInEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = CDC_TX_EPADDR,
+			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = CDC_TXRX_EPSIZE,
+			.PollingIntervalMS      = 0x05
+		},
+
+	.MS_Interface =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+			.InterfaceNumber        = INTERFACE_ID_MassStorage,
+			.AlternateSetting       = 0,
+
+			.TotalEndpoints         = 2,
+
+			.Class                  = MS_CSCP_MassStorageClass,
+			.SubClass               = MS_CSCP_SCSITransparentSubclass,
+			.Protocol               = MS_CSCP_BulkOnlyTransportProtocol,
+
+			.InterfaceStrIndex      = NO_DESCRIPTOR
+		},
+
+	.MS_DataInEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = MASS_STORAGE_IN_EPADDR,
+			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = MASS_STORAGE_IO_EPSIZE,
+			.PollingIntervalMS      = 0x05
+		},
+
+	.MS_DataOutEndpoint =
+		{
+			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+			.EndpointAddress        = MASS_STORAGE_OUT_EPADDR,
+			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+			.EndpointSize           = MASS_STORAGE_IO_EPSIZE,
+			.PollingIntervalMS      = 0x05
+		}
+};
+
+/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
+ *  the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
+ *  via the language ID table available at USB.org what languages the device supports for its string descriptors.
+ */
+const USB_Descriptor_String_t PROGMEM LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
+ *  form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ *  Descriptor.
+ */
+const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
+ *  and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ *  Descriptor.
+ */
+const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"LUFA Webserver");
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ *  documentation) by the application code so that the address and size of a requested descriptor can be given
+ *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ *  USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+                                    const uint16_t wIndex,
+                                    const void** const DescriptorAddress)
+{
+	const uint8_t  DescriptorType   = (wValue >> 8);
+	const uint8_t  DescriptorNumber = (wValue & 0xFF);
+
+	const void* Address = NULL;
+	uint16_t    Size    = NO_DESCRIPTOR;
+
+	switch (DescriptorType)
+	{
+		case DTYPE_Device:
+			Address = &DeviceDescriptor;
+			Size    = sizeof(USB_Descriptor_Device_t);
+			break;
+		case DTYPE_Configuration:
+			Address = &ConfigurationDescriptor;
+			Size    = sizeof(USB_Descriptor_Configuration_t);
+			break;
+		case DTYPE_String:
+			switch (DescriptorNumber)
+			{
+				case STRING_ID_Language:
+					Address = &LanguageString;
+					Size    = pgm_read_byte(&LanguageString.Header.Size);
+					break;
+				case STRING_ID_Manufacturer:
+					Address = &ManufacturerString;
+					Size    = pgm_read_byte(&ManufacturerString.Header.Size);
+					break;
+				case STRING_ID_Product:
+					Address = &ProductString;
+					Size    = pgm_read_byte(&ProductString.Header.Size);
+					break;
+			}
+
+			break;
+	}
+
+	*DescriptorAddress = Address;
+	return Size;
+}
+
diff --git a/Projects/Webserver/Descriptors.h b/Projects/Webserver/Descriptors.h
new file mode 100644
index 0000000000..66da1b654c
--- /dev/null
+++ b/Projects/Webserver/Descriptors.h
@@ -0,0 +1,128 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *
+ *  Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+	/* Includes: */
+		#include <avr/pgmspace.h>
+
+		#include <LUFA/Drivers/USB/USB.h>
+
+		#include "Config/AppConfig.h"
+
+	/* Macros: */
+		/** Endpoint address of the Mass Storage device-to-host data IN endpoint. */
+		#define MASS_STORAGE_IN_EPADDR         (ENDPOINT_DIR_IN  | 3)
+
+		/** Endpoint address of the Mass Storage host-to-device data OUT endpoint. */
+		#define MASS_STORAGE_OUT_EPADDR        (ENDPOINT_DIR_OUT | 4)
+
+		/** Size in bytes of the Mass Storage data endpoints. */
+		#define MASS_STORAGE_IO_EPSIZE         64
+
+		/** Endpoint address of the CDC device-to-host notification IN endpoint. */
+		#define CDC_NOTIFICATION_EPADDR        (ENDPOINT_DIR_IN  | 5)
+
+		/** Endpoint address of the CDC device-to-host data IN endpoint. */
+		#define CDC_TX_EPADDR                  (ENDPOINT_DIR_IN  | 1)
+
+		/** Endpoint address of the CDC host-to-device data OUT endpoint. */
+		#define CDC_RX_EPADDR                  (ENDPOINT_DIR_OUT | 2)
+
+		/** Size in bytes of the CDC device-to-host notification IN endpoint. */
+		#define CDC_NOTIFICATION_EPSIZE        8
+
+		/** Size in bytes of the CDC data IN and OUT endpoints. */
+		#define CDC_TXRX_EPSIZE                64
+
+	/* Type Defines: */
+		/** Type define for the device configuration descriptor structure. This must be defined in the
+		 *  application code, as the configuration descriptor contains several sub-descriptors which
+		 *  vary between devices, and which describe the device's usage to the host.
+		 */
+		typedef struct
+		{
+			USB_Descriptor_Configuration_Header_t  Config;
+
+			// RNDIS CDC Command Interface
+			USB_Descriptor_Interface_Association_t CDC_IAD;
+			USB_Descriptor_Interface_t             CDC_CCI_Interface;
+			USB_CDC_Descriptor_FunctionalHeader_t  CDC_Functional_Header;
+			USB_CDC_Descriptor_FunctionalACM_t     CDC_Functional_ACM;
+			USB_CDC_Descriptor_FunctionalUnion_t   CDC_Functional_Union;
+			USB_Descriptor_Endpoint_t              CDC_NotificationEndpoint;
+
+			// RNDIS CDC Data Interface
+			USB_Descriptor_Interface_t             CDC_DCI_Interface;
+			USB_Descriptor_Endpoint_t              RNDIS_DataOutEndpoint;
+			USB_Descriptor_Endpoint_t              RNDIS_DataInEndpoint;
+
+			// Mass Storage Interface
+			USB_Descriptor_Interface_t             MS_Interface;
+			USB_Descriptor_Endpoint_t              MS_DataInEndpoint;
+			USB_Descriptor_Endpoint_t              MS_DataOutEndpoint;
+		} USB_Descriptor_Configuration_t;
+
+		/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
+		 *  should have a unique ID index associated with it, which can be used to refer to the
+		 *  interface from other descriptors.
+		 */
+		enum InterfaceDescriptors_t
+		{
+			INTERFACE_ID_CDC_CCI     = 0, /**< CDC CCI interface descriptor ID */
+			INTERFACE_ID_CDC_DCI     = 1, /**< CDC DCI interface descriptor ID */
+			INTERFACE_ID_MassStorage = 2, /**< Mass storage interface descriptor ID */
+		};
+
+		/** Enum for the device string descriptor IDs within the device. Each string descriptor should
+		 *  have a unique ID index associated with it, which can be used to refer to the string from
+		 *  other descriptors.
+		 */
+		enum StringDescriptors_t
+		{
+			STRING_ID_Language     = 0, /**< Supported Languages string descriptor ID (must be zero) */
+			STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
+			STRING_ID_Product      = 2, /**< Product string ID */
+		};
+
+	/* Function Prototypes: */
+		uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+		                                    const uint16_t wIndex,
+		                                    const void** const DescriptorAddress)
+		                                    ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
diff --git a/Projects/Webserver/LUFA Webserver RNDIS.inf b/Projects/Webserver/LUFA Webserver RNDIS.inf
new file mode 100644
index 0000000000..c77de8f6bb
--- /dev/null
+++ b/Projects/Webserver/LUFA Webserver RNDIS.inf	
@@ -0,0 +1,59 @@
+;     Windows LUFA RNDIS Setup File
+; Copyright (c) 2000 Microsoft Corporation
+
+[DefaultInstall]
+CopyINF="LUFA Webserver RNDIS.inf"
+
+[Version]
+Signature="$Windows NT$"
+Class=Net
+ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}
+Provider=%MFGNAME%
+DriverVer=7/1/2012,10.0.0.0
+
+[Manufacturer]
+%MFGNAME%=DeviceList, NTx86, NTamd64, NTia64
+
+[ControlFlags]
+ExcludeFromSelect=*
+
+[DriverInstall]
+Characteristics=0x84 ; NCF_PHYSICAL + NCF_HAS_UI
+BusType=15
+include=netrndis.inf
+needs=Usb_Rndis.ndi
+AddReg=Rndis_AddReg_Vista
+
+[DriverInstall.Services]
+include=netrndis.inf
+needs=Usb_Rndis.ndi.Services
+
+;------------------------------------------------------------------------------
+;  Vendor and Product ID Definitions
+;------------------------------------------------------------------------------
+; When developing your USB device, the VID and PID used in the PC side
+; application program and the firmware on the microcontroller must match.
+; Modify the below line to use your VID and PID.  Use the format as shown below.
+; Note: One INF file can be used for multiple devices with different VID and PIDs.
+; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line.
+;------------------------------------------------------------------------------
+[DeviceList]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2069
+
+[DeviceList.NTx86]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2069
+
+[DeviceList.NTamd64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2069
+
+[DeviceList.NTia64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2069
+
+;------------------------------------------------------------------------------
+;  String Definitions
+;------------------------------------------------------------------------------
+;Modify these strings to customize your device
+;------------------------------------------------------------------------------
+[Strings]
+MFGNAME="http://www.lufa-lib.org"
+DESCRIPTION="LUFA USB RNDIS Demo"
diff --git a/Projects/Webserver/Lib/DHCPClientApp.c b/Projects/Webserver/Lib/DHCPClientApp.c
new file mode 100644
index 0000000000..760718127e
--- /dev/null
+++ b/Projects/Webserver/Lib/DHCPClientApp.c
@@ -0,0 +1,208 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \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"
+
+#if defined(ENABLE_DHCP_CLIENT) || defined(__DOXYGEN__)
+
+/** 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
+
diff --git a/Projects/Webserver/Lib/DHCPClientApp.h b/Projects/Webserver/Lib/DHCPClientApp.h
new file mode 100644
index 0000000000..0aec00331c
--- /dev/null
+++ b/Projects/Webserver/Lib/DHCPClientApp.h
@@ -0,0 +1,69 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *
+ *  Header file for DHCPClientApp.c.
+ */
+
+#ifndef _DHCPCLIENT_APP_H_
+#define _DHCPCLIENT_APP_H_
+
+	/* Includes: */
+		#include <stdio.h>
+
+		#include <uip.h>
+
+		#include "Config/AppConfig.h"
+		#include "../Webserver.h"
+		#include "DHCPCommon.h"
+
+	/* Enums: */
+		/** States for each DHCP connection to a DHCP client. */
+		enum DHCP_Client_States_t
+		{
+			DHCP_STATE_SendDiscover,  /**< Send DISCOVER packet to retrieve DHCP lease offers */
+			DHCP_STATE_WaitForOffer,  /**< Waiting for OFFER packet giving available DHCP leases */
+			DHCP_STATE_SendRequest,   /**< Send REQUEST packet to request a DHCP lease */
+			DHCP_STATE_WaitForACK,    /**< Wait for ACK packet to complete the DHCP lease */
+			DHCP_STATE_AddressLeased, /**< DHCP address has been leased from a DHCP server */
+		};
+
+	/* Function Prototypes: */
+		void DHCPClientApp_Init(void);
+		void DHCPClientApp_Callback(void);
+
+		#if defined(INCLUDE_FROM_DHCPCLIENTAPP_C)
+			static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
+			                                             const uint8_t DHCPMessageType,
+			                                             uip_udp_appstate_t* const AppState);
+		#endif
+#endif
+
diff --git a/Projects/Webserver/Lib/DHCPCommon.c b/Projects/Webserver/Lib/DHCPCommon.c
new file mode 100644
index 0000000000..6d80f65cae
--- /dev/null
+++ b/Projects/Webserver/Lib/DHCPCommon.c
@@ -0,0 +1,103 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *
+ *  Common DHCP routines to manage DHCP packet data.
+ */
+
+#include "DHCPCommon.h"
+
+#if defined(ENABLE_DHCP_CLIENT) || defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__)
+
+/** Sets the given DHCP option in the DHCP packet's option list. This automatically moves the
+ *  end of options terminator past the new option in the options list.
+ *
+ *  \param[in,out] DHCPOptionList  Pointer to the start of the DHCP packet's options list
+ *  \param[in]     Option          DHCP option to add to the list
+ *  \param[in]     DataLen         Size in bytes of the option data to add
+ *  \param[in]     OptionData      Buffer where the option's data is to be sourced from
+ *
+ *  \return Number of bytes added to the DHCP packet
+ */
+uint8_t DHCPCommon_SetOption(uint8_t* DHCPOptionList,
+                             const uint8_t Option,
+                             const uint8_t DataLen,
+                             void* const OptionData)
+{
+	/* Skip through the DHCP options list until the terminator option is found */
+	while (*DHCPOptionList != DHCP_OPTION_END)
+	  DHCPOptionList += (DHCPOptionList[1] + 2);
+
+	/* Overwrite the existing terminator with the new option, add a new terminator at the end of the list */
+	DHCPOptionList[0] = Option;
+	DHCPOptionList[1] = DataLen;
+	memcpy(&DHCPOptionList[2], OptionData, DataLen);
+	DHCPOptionList[2 + DataLen] = DHCP_OPTION_END;
+
+	/* Calculate the total number of bytes added to the outgoing packet */
+	return (2 + DataLen);
+}
+
+/** Retrieves the given option's data (if present) from the DHCP packet's options list.
+ *
+ *  \param[in,out] DHCPOptionList  Pointer to the start of the DHCP packet's options list
+ *  \param[in]     Option          DHCP option to retrieve to the list
+ *  \param[out]    Destination     Buffer where the option's data is to be written to if found
+ *
+ *  \return Boolean \c true if the option was found in the DHCP packet's options list, \c false otherwise
+ */
+bool DHCPCommon_GetOption(const uint8_t* DHCPOptionList,
+                          const uint8_t Option,
+                          void* const Destination)
+{
+	/* Look through the incoming DHCP packet's options list for the requested option */
+	while (*DHCPOptionList != DHCP_OPTION_END)
+	{
+		/* Check if the current DHCP option in the packet is the one requested */
+		if (DHCPOptionList[0] == Option)
+		{
+			/* Copy request option's data to the destination buffer */
+			memcpy(Destination, &DHCPOptionList[2], DHCPOptionList[1]);
+
+			/* Indicate that the requested option data was successfully retrieved */
+			return true;
+		}
+
+		/* Skip to next DHCP option in the options list */
+		DHCPOptionList += (DHCPOptionList[1] + 2);
+	}
+
+	/* Requested option not found in the incoming packet's DHCP options list */
+	return false;
+}
+
+#endif
+
diff --git a/Projects/Webserver/Lib/DHCPCommon.h b/Projects/Webserver/Lib/DHCPCommon.h
new file mode 100644
index 0000000000..8f54c16717
--- /dev/null
+++ b/Projects/Webserver/Lib/DHCPCommon.h
@@ -0,0 +1,159 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \file
+ *
+ *  Header file for common DHCP defines.
+ */
+
+#ifndef _DHCP_COMMON_H_
+#define _DHCP_COMMON_H_
+
+	/* Includes: */
+		#include <stdint.h>
+		#include <stdbool.h>
+		#include <string.h>
+
+		#include "Config/AppConfig.h"
+
+		#include <uip.h>
+
+	/* Macros: */
+		/** UDP listen port for a BOOTP server. */
+		#define DHCP_SERVER_PORT          67
+
+		/** UDP listen port for a BOOTP client. */
+		#define DHCP_CLIENT_PORT          68
+
+		/** BOOTP message type for a BOOTP REQUEST message. */
+		#define DHCP_OP_BOOTREQUEST       0x01
+
+		/** BOOTP message type for a BOOTP REPLY message. */
+		#define DHCP_OP_BOOTREPLY         0x02
+
+		/** BOOTP flag for a BOOTP broadcast message. */
+		#define BOOTP_BROADCAST           0x8000
+
+		/** Magic DHCP cookie for a BOOTP message to identify it as a DHCP message. */
+		#define DHCP_MAGIC_COOKIE         0x63538263
+
+		/** Unique transaction ID used to identify DHCP responses to the client. */
+		#define DHCP_TRANSACTION_ID       0x13245466
+
+		/** DHCP message type for a DISCOVER message. */
+		#define DHCP_DISCOVER             1
+
+		/** DHCP message type for an OFFER message. */
+		#define DHCP_OFFER                2
+
+		/** DHCP message type for a REQUEST message. */
+		#define DHCP_REQUEST              3
+
+		/** DHCP message type for a DECLINE message. */
+		#define DHCP_DECLINE              4
+
+		/** DHCP message type for an ACK message. */
+		#define DHCP_ACK                  5
+
+		/** DHCP message type for a NAK message. */
+		#define DHCP_NAK                  6
+
+		/** DHCP message type for a RELEASE message. */
+		#define DHCP_RELEASE              7
+
+		/** DHCP medium type for standard Ethernet. */
+		#define DHCP_HTYPE_ETHERNET       1
+
+		/** DHCP message option for the network subnet mask. */
+		#define DHCP_OPTION_SUBNET_MASK   1
+
+		/** DHCP message option for the network gateway IP. */
+		#define DHCP_OPTION_ROUTER        3
+
+		/** DHCP message option for the network DNS server. */
+		#define DHCP_OPTION_DNS_SERVER    6
+
+		/** DHCP message option for the requested client IP address. */
+		#define DHCP_OPTION_REQ_IPADDR    50
+
+		/** DHCP message option for the IP address lease time. */
+		#define DHCP_OPTION_LEASE_TIME    51
+
+		/** DHCP message option for the DHCP message type. */
+		#define DHCP_OPTION_MSG_TYPE      53
+
+		/** DHCP message option for the DHCP server IP. */
+		#define DHCP_OPTION_SERVER_ID     54
+
+		/** DHCP message option for the list of required options from the server. */
+		#define DHCP_OPTION_REQ_LIST      55
+
+		/** DHCP message option for the options list terminator. */
+		#define DHCP_OPTION_END           255
+
+	/* Type Defines: */
+		/** Type define for a DHCP packet inside an Ethernet frame. */
+		typedef struct
+		{
+			uint8_t      Operation; /**< DHCP operation, either DHCP_OP_BOOTREQUEST or DHCP_OP_BOOTREPLY */
+			uint8_t      HardwareType; /**< Hardware carrier type constant */
+			uint8_t      HardwareAddressLength;  /**< Length in bytes of a hardware (MAC) address on the network */
+			uint8_t      Hops; /**< Number of hops required to reach the server, unused */
+
+			uint32_t     TransactionID; /**< Unique ID of the DHCP packet, for positive matching between sent and received packets */
+
+			uint16_t     ElapsedSeconds; /**< Elapsed seconds since the request was made */
+			uint16_t     Flags; /**< BOOTP packet flags */
+
+			uip_ipaddr_t ClientIP; /**< Client IP address, if already leased an IP */
+			uip_ipaddr_t YourIP; /**< Client IP address */
+			uip_ipaddr_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */
+			uip_ipaddr_t RelayAgentIP; /**< Legacy BOOTP protocol field, unused for DHCP */
+
+			uint8_t      ClientHardwareAddress[16]; /**< Hardware (MAC) address of the client making a request to the DHCP server */
+			uint8_t      ServerHostnameString[64]; /**< Legacy BOOTP protocol field, unused for DHCP */
+			uint8_t      BootFileName[128]; /**< Legacy BOOTP protocol field, unused for DHCP */
+
+			uint32_t     Cookie; /**< Magic BOOTP protocol cookie to indicate a valid packet */
+
+			uint8_t      Options[]; /**< DHCP message options */
+		} DHCP_Header_t;
+
+	/* Function Prototypes: */
+		uint8_t  DHCPCommon_SetOption(uint8_t* DHCPOptionList,
+			                          const uint8_t Option,
+			                          const uint8_t DataLen,
+			                          void* const OptionData);
+		bool     DHCPCommon_GetOption(const uint8_t* DHCPOptionList,
+			                          const uint8_t Option,
+			                          void* const Destination);
+
+#endif
+
diff --git a/Projects/Webserver/Lib/DHCPServerApp.c b/Projects/Webserver/Lib/DHCPServerApp.c
new file mode 100644
index 0000000000..fea54ddb0e
--- /dev/null
+++ b/Projects/Webserver/Lib/DHCPServerApp.c
@@ -0,0 +1,265 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  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 disclaims 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.
+*/
+
+/** \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"
+
+#if defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__)
+
+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 \c true if the IP has already been leased to a client, \c 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
+
diff --git a/Projects/Webserver/Lib/DHCPServerApp.h b/Projects/Webserver/Lib/DHCPServerApp.h
new file mode 100644
index 0000000000..a9dae7bf3a
--- /dev/null
+++ b/Projects/Webserver/Lib/DHCPServerApp.h
@@ -0,0 +1,64 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2017.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2017  Dean Camera (dean [at] four