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