From 547650a9208443e3e628f70a76637fcc4623d1f0 Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 23 Dec 2016 14:55:04 +1100 Subject: [PATCH 01/15] Add packet data filtering for firmware update - multi-part data packet filtering for Chrome-style packets --- ZodiacFX/src/flash.c | 30 +- ZodiacFX/src/flash.h | 4 +- ZodiacFX/src/http.c | 1684 ++++++++++++++++++++++-------------------- 3 files changed, 901 insertions(+), 817 deletions(-) diff --git a/ZodiacFX/src/flash.c b/ZodiacFX/src/flash.c index 0869ad2..a4627ae 100644 --- a/ZodiacFX/src/flash.c +++ b/ZodiacFX/src/flash.c @@ -42,7 +42,7 @@ extern uint8_t shared_buffer[SHARED_BUFFER_LEN]; static uint32_t page_addr; //static uint32_t ul_rc; -static uint32_t ul_test_page_addr; +static uint32_t flash_page_addr; static uint32_t ul_rc; static uint32_t ul_idx; static uint32_t ul_page_buffer[IFLASH_PAGE_SIZE / sizeof(uint32_t)]; @@ -62,49 +62,49 @@ void get_serial(uint32_t *uid_buf) * Firmware update function * */ -void firmware_update_init(void) +int firmware_update_init(void) { - ul_test_page_addr = NEW_FW_BASE; + flash_page_addr = NEW_FW_BASE; /* Initialize flash: 6 wait states for flash writing. */ ul_rc = flash_init(FLASH_ACCESS_MODE_128, 6); if (ul_rc != FLASH_RC_OK) { - printf("-F- Initialization error %lu\n\r", (unsigned long)ul_rc); + //printf("-F- Initialization error %lu\n\r", (unsigned long)ul_rc); return 0; } // Unlock 8k lock regions (these should be unlocked by default) - uint32_t unlock_address = ul_test_page_addr; + uint32_t unlock_address = flash_page_addr; while(unlock_address < IFLASH_ADDR + IFLASH_SIZE - (IFLASH_LOCK_REGION_SIZE - 1)) { - printf("-I- Unlocking region start at: 0x%08x\r\n", unlock_address); + //printf("-I- Unlocking region start at: 0x%08x\r\n", unlock_address); ul_rc = flash_unlock(unlock_address, unlock_address + (4*IFLASH_PAGE_SIZE) - 1, 0, 0); if (ul_rc != FLASH_RC_OK) { - printf("-F- Unlock error %lu\n\r", (unsigned long)ul_rc); + //printf("-F- Unlock error %lu\n\r", (unsigned long)ul_rc); return 0; } unlock_address += IFLASH_LOCK_REGION_SIZE; } - // Erase 3 64k sectors - uint32_t erase_address = ul_test_page_addr; + // Erase 192k + uint32_t erase_address = flash_page_addr; while(erase_address < IFLASH_ADDR + IFLASH_SIZE - (ERASE_SECTOR_SIZE - 1)) { - printf("-I- Erasing sector with address: 0x%08x\r\n", erase_address); + //printf("-I- Erasing sector with address: 0x%08x\r\n", erase_address); ul_rc = flash_erase_sector(erase_address); if (ul_rc != FLASH_RC_OK) { - printf("-F- Flash programming error %lu\n\r", (unsigned long)ul_rc); + //printf("-F- Flash programming error %lu\n\r", (unsigned long)ul_rc); return 0; } erase_address += ERASE_SECTOR_SIZE; } - return; + return 1; } /* @@ -113,9 +113,9 @@ void firmware_update_init(void) */ int flash_write_page(uint8_t *flash_page) { - if(ul_test_page_addr <= IFLASH_ADDR + IFLASH_SIZE - IFLASH_PAGE_SIZE) + if(flash_page_addr <= IFLASH_ADDR + IFLASH_SIZE - IFLASH_PAGE_SIZE) { - ul_rc = flash_write(ul_test_page_addr, flash_page, + ul_rc = flash_write(flash_page_addr, flash_page, IFLASH_PAGE_SIZE, 0); } else @@ -129,7 +129,7 @@ int flash_write_page(uint8_t *flash_page) return 0; } - ul_test_page_addr += IFLASH_PAGE_SIZE; + flash_page_addr += IFLASH_PAGE_SIZE; return 1; } diff --git a/ZodiacFX/src/flash.h b/ZodiacFX/src/flash.h index febf1fd..a242c9e 100644 --- a/ZodiacFX/src/flash.h +++ b/ZodiacFX/src/flash.h @@ -35,7 +35,7 @@ void get_serial(uint32_t *uid_buf); void cli_update(void); int flash_write_page(uint8_t *flash_page); -void firmware_update_init(void); +int firmware_update_init(void); __no_inline RAMFUNC void firmware_update(void); int xmodem_xfer(void); void xmodem_clear_padding(uint8_t *buff); @@ -44,7 +44,7 @@ void xmodem_clear_padding(uint8_t *buff); #define X_ACK 0x06 #define X_NAK 0x15 -#define ERASE_SECTOR_SIZE 65536 +#define ERASE_SECTOR_SIZE 8192 #define NEW_FW_BASE (IFLASH_ADDR + (5*IFLASH_NB_OF_PAGES/8)*IFLASH_PAGE_SIZE) #define NEW_FW_MAX_SIZE 196608 diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 51c678b..c75ec8c 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -66,6 +66,9 @@ extern struct ofp10_port_stats phys10_port_stats[4]; extern struct ofp13_port_stats phys13_port_stats[4]; extern struct table_counter table_counters[MAX_TABLES]; +extern int firmware_update_init(void); +extern int flash_write_page(uint8_t *flash_page); + // Local Variables struct tcp_pcb *http_pcb; char http_msg[64]; // Buffer for HTTP message filtering @@ -91,7 +94,7 @@ static uint8_t interfaceCreate_Config_VLANs(void); static uint8_t interfaceCreate_Config_OpenFlow(void); static uint8_t interfaceCreate_About(void); -static uint8_t file_handler(char *ppart, int len); +static uint8_t upload_handler(char *ppart, int len); /* @@ -153,1020 +156,1031 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err if(file_upload == true) { // Handle multi-part file data - file_handler(http_payload, len); + upload_handler(http_payload, len); } - - // Check HTTP method - i = 0; - while(i < 63 && (http_payload[i] != ' ')) + else { - http_msg[i] = http_payload[i]; - i++; - } - TRACE("http.c: %s method received", http_msg); - - if(strcmp(http_msg,"GET") == 0) - { - memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - - // Specified resource directly follows GET + // Check HTTP method i = 0; - while(i < 63 && (http_payload[i+5] != ' ')) + while(i < 63 && (http_payload[i] != ' ')) { - http_msg[i] = http_payload[i+5]; // Offset http_payload to isolate resource + http_msg[i] = http_payload[i]; i++; } - - if(http_msg[0] == '\0') + TRACE("http.c: %s method received", http_msg); + + if(strcmp(http_msg,"GET") == 0) { - TRACE("http.c: resource request for page frames"); - } - else - { - TRACE("http.c: resource request for %s", http_msg); - } + memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - // Check resource & serve page - if(http_msg[0] == '\0') - { - if(interfaceCreate_Frames()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); - } - else - { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); - } - } - else if(strcmp(http_msg,"header.htm") == 0) - { - if(interfaceCreate_Header()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); - } - else + // Specified resource directly follows GET + i = 0; + while(i < 63 && (http_payload[i+5] != ' ')) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + http_msg[i] = http_payload[i+5]; // Offset http_payload to isolate resource + i++; } - } - else if(strcmp(http_msg,"menu.htm") == 0) - { - if(interfaceCreate_Menu()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + + if(http_msg[0] == '\0') + { + TRACE("http.c: resource request for page frames"); } else { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); - } - } - else if(strcmp(http_msg,"home.htm") == 0) - { - if(interfaceCreate_Home()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + TRACE("http.c: resource request for %s", http_msg); } - else + + // Check resource & serve page + if(http_msg[0] == '\0') { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Frames()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"upload.htm") == 0) - { - if(interfaceCreate_Upload()) + else if(strcmp(http_msg,"header.htm") == 0) { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Header()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"menu.htm") == 0) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Menu()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"d_home.htm") == 0) - { - if(interfaceCreate_Display_Home()) + else if(strcmp(http_msg,"home.htm") == 0) { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Home()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"upload.htm") == 0) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Upload()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"d_ports.htm") == 0) - { - if(interfaceCreate_Display_Ports(0)) + else if(strcmp(http_msg,"d_home.htm") == 0) { - // Only write to buffer - don't send - http_send(&shared_buffer, pcb, 0); + if(interfaceCreate_Display_Home()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"d_ports.htm") == 0) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); - } + if(interfaceCreate_Display_Ports(0)) + { + // Only write to buffer - don't send + http_send(&shared_buffer, pcb, 0); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } - if(interfaceCreate_Display_Ports(1)) - { - // Call TCP output & close the connection - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); - } - else - { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); - } - } - else if(strcmp(http_msg,"d_of.htm") == 0) - { - if(interfaceCreate_Display_OpenFlow()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); - } - else - { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); - } - } - else if(strcmp(http_msg,"d_flo.htm") == 0) - { - if(interfaceCreate_Display_Flows()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); - } - else - { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Display_Ports(1)) + { + // Call TCP output & close the connection + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"cfg_home.htm") == 0) - { - if(interfaceCreate_Config_Home()) + else if(strcmp(http_msg,"d_of.htm") == 0) { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Display_OpenFlow()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"d_flo.htm") == 0) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Display_Flows()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"cfg_net.htm") == 0) - { - if(interfaceCreate_Config_Network()) + else if(strcmp(http_msg,"cfg_home.htm") == 0) { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Config_Home()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"cfg_net.htm") == 0) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Config_Network()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"cfg_vlan.htm") == 0) - { - if(interfaceCreate_Config_VLANs()) + else if(strcmp(http_msg,"cfg_vlan.htm") == 0) { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Config_VLANs()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"cfg_of.htm") == 0) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Config_OpenFlow()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"cfg_of.htm") == 0) - { - if(interfaceCreate_Config_OpenFlow()) + else if(strcmp(http_msg,"about.htm") == 0) { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_About()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + } } else { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + TRACE("http.c: resource doesn't exist:\"%s\"", http_msg); } } - else if(strcmp(http_msg,"about.htm") == 0) + else if(strcmp(http_msg,"POST") == 0) { - if(interfaceCreate_About()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: Page sent successfully - %d bytes", strlen(shared_buffer)); - } - else + memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array + + // Specified resource directly follows POST + i = 0; + while(i < 63 && (http_payload[i+6] != ' ')) { - TRACE("http.c: Unable to serve page - buffer at %d bytes", strlen(shared_buffer)); + http_msg[i] = http_payload[i+6]; // Offset http_payload to isolate resource + i++; } - } - else - { - TRACE("http.c: resource doesn't exist:\"%s\"", http_msg); - } - } - else if(strcmp(http_msg,"POST") == 0) - { - memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - - // Specified resource directly follows POST - i = 0; - while(i < 63 && (http_payload[i+6] != ' ')) - { - http_msg[i] = http_payload[i+6]; // Offset http_payload to isolate resource - i++; - } - TRACE("http.c: request for %s", http_msg); + TRACE("http.c: request for %s", http_msg); - if(strcmp(http_msg,"upload") == 0) - { - // All following packets will contain multi-part file data - file_upload = true; - } - else if(strcmp(http_msg,"save_config") == 0) - { - memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - - // Device Name - pdat = strstr(http_payload, "wi_deviceName"); // Search for element - if(pdat != NULL) // Check that element exists + if(strcmp(http_msg,"upload") == 0) { - pdat += (strlen("wi_deviceName")+1); // Data format: wi_deviceName=(name) - - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) - { - http_msg[i] = pdat[i]; // Store value of element - i++; - } - if(pdat[i+1] == 'w') // Check that the next parameter directly follows the "&" at end of data + // Initialise flash programming + if(firmware_update_init()) { - uint8_t namelen = strlen(http_msg); - if (namelen > 15 ) namelen = 15; // Make sure name is less than 16 characters - sprintf(Zodiac_Config.device_name, http_msg, namelen); - TRACE("http.c: device name set to '%s'",Zodiac_Config.device_name); + TRACE("http.c: firmware update initialisation successful"); } else { - TRACE("http.c: \"&\" cannot be used in device name"); + TRACE("http.c: firmware update initialisation failed"); } + + // All following packets will contain multi-part file data + file_upload = true; } - else + else if(strcmp(http_msg,"save_config") == 0) { - TRACE("http.c: no device name found"); - } + memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - memset(&http_msg, 0, sizeof(http_msg)); - - // MAC Address - pdat = strstr(http_payload, "wi_macAddress"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_macAddress")+1); // Data format: wi_deviceName=(name) + // Device Name + pdat = strstr(http_payload, "wi_deviceName"); // Search for element + if(pdat != NULL) // Check that element exists + { + pdat += (strlen("wi_deviceName")+1); // Data format: wi_deviceName=(name) - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + { + http_msg[i] = pdat[i]; // Store value of element + i++; + } + if(pdat[i+1] == 'w') // Check that the next parameter directly follows the "&" at end of data + { + uint8_t namelen = strlen(http_msg); + if (namelen > 15 ) namelen = 15; // Make sure name is less than 16 characters + sprintf(Zodiac_Config.device_name, http_msg, namelen); + TRACE("http.c: device name set to '%s'",Zodiac_Config.device_name); + } + else + { + TRACE("http.c: \"&\" cannot be used in device name"); + } + } + else { - http_msg[i] = pdat[i]; // Store value of element - i++; + TRACE("http.c: no device name found"); } - if(pdat[i+1] == 'w') + + memset(&http_msg, 0, sizeof(http_msg)); + + // MAC Address + pdat = strstr(http_payload, "wi_macAddress"); + if(pdat != NULL) // Check that element exists { - int mac1,mac2,mac3,mac4,mac5,mac6; - char decArr[18] = ""; - int j, k; - - if (strlen(http_msg) != 27 ) // Accounting for ":" as "%3A" + pdat += (strlen("wi_macAddress")+1); // Data format: wi_deviceName=(name) + + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) { - TRACE("http.c: incorrect MAC address format"); - return; + http_msg[i] = pdat[i]; // Store value of element + i++; } - - // Decode http string - j = 0; k = 0; - while(j < strlen(http_msg) && k < 18) + if(pdat[i+1] == 'w') { - if(http_msg[j] == '%' && http_msg[j+1] == '3' && http_msg[j+2] == 'A') + int mac1,mac2,mac3,mac4,mac5,mac6; + char decArr[18] = ""; + int j, k; + + if (strlen(http_msg) != 27 ) // Accounting for ":" as "%3A" { - decArr[k] = ':'; - j+=3; k++; + TRACE("http.c: incorrect MAC address format"); + return; } - else + + // Decode http string + j = 0; k = 0; + while(j < strlen(http_msg) && k < 18) { - decArr[k] = http_msg[j]; - j++; k++; + if(http_msg[j] == '%' && http_msg[j+1] == '3' && http_msg[j+2] == 'A') + { + decArr[k] = ':'; + j+=3; k++; + } + else + { + decArr[k] = http_msg[j]; + j++; k++; + } } - } - sscanf(decArr, "%x:%x:%x:%x:%x:%x", &mac1, &mac2, &mac3, &mac4, &mac5, &mac6); - Zodiac_Config.MAC_address[0] = mac1; - Zodiac_Config.MAC_address[1] = mac2; - Zodiac_Config.MAC_address[2] = mac3; - Zodiac_Config.MAC_address[3] = mac4; - Zodiac_Config.MAC_address[4] = mac5; - Zodiac_Config.MAC_address[5] = mac6; - TRACE("http.c: MAC address set to %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",Zodiac_Config.MAC_address[0], Zodiac_Config.MAC_address[1], Zodiac_Config.MAC_address[2], Zodiac_Config.MAC_address[3], Zodiac_Config.MAC_address[4], Zodiac_Config.MAC_address[5]); + sscanf(decArr, "%x:%x:%x:%x:%x:%x", &mac1, &mac2, &mac3, &mac4, &mac5, &mac6); + Zodiac_Config.MAC_address[0] = mac1; + Zodiac_Config.MAC_address[1] = mac2; + Zodiac_Config.MAC_address[2] = mac3; + Zodiac_Config.MAC_address[3] = mac4; + Zodiac_Config.MAC_address[4] = mac5; + Zodiac_Config.MAC_address[5] = mac6; + TRACE("http.c: MAC address set to %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",Zodiac_Config.MAC_address[0], Zodiac_Config.MAC_address[1], Zodiac_Config.MAC_address[2], Zodiac_Config.MAC_address[3], Zodiac_Config.MAC_address[4], Zodiac_Config.MAC_address[5]); + } + else + { + TRACE("http.c: \"&\" cannot be used in form"); + } } else { - TRACE("http.c: \"&\" cannot be used in form"); + TRACE("http.c: no MAC address found"); } - } - else - { - TRACE("http.c: no MAC address found"); - } - memset(&http_msg, 0, sizeof(http_msg)); + memset(&http_msg, 0, sizeof(http_msg)); - // IP Address - pdat = strstr(http_payload, "wi_ipAddress"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_ipAddress")+1); // Data format: wi_deviceName=(name) - - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) - { - http_msg[i] = pdat[i]; // Store value of element - i++; - } - if(pdat[i+1] == 'w') + // IP Address + pdat = strstr(http_payload, "wi_ipAddress"); + if(pdat != NULL) // Check that element exists { - int ip1,ip2,ip3,ip4; - if (strlen(http_msg) > 15 ) + pdat += (strlen("wi_ipAddress")+1); // Data format: wi_deviceName=(name) + + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) { - TRACE("http.c: incorrect IP format"); - return; + http_msg[i] = pdat[i]; // Store value of element + i++; + } + if(pdat[i+1] == 'w') + { + int ip1,ip2,ip3,ip4; + if (strlen(http_msg) > 15 ) + { + TRACE("http.c: incorrect IP format"); + return; + } + sscanf(http_msg, "%d.%d.%d.%d", &ip1, &ip2,&ip3,&ip4); + Zodiac_Config.IP_address[0] = ip1; + Zodiac_Config.IP_address[1] = ip2; + Zodiac_Config.IP_address[2] = ip3; + Zodiac_Config.IP_address[3] = ip4; + TRACE("http.c: IP address set to %d.%d.%d.%d" , Zodiac_Config.IP_address[0], Zodiac_Config.IP_address[1], Zodiac_Config.IP_address[2], Zodiac_Config.IP_address[3]); + } + else + { + TRACE("http.c: \"&\" cannot be used in form"); } - sscanf(http_msg, "%d.%d.%d.%d", &ip1, &ip2,&ip3,&ip4); - Zodiac_Config.IP_address[0] = ip1; - Zodiac_Config.IP_address[1] = ip2; - Zodiac_Config.IP_address[2] = ip3; - Zodiac_Config.IP_address[3] = ip4; - TRACE("http.c: IP address set to %d.%d.%d.%d" , Zodiac_Config.IP_address[0], Zodiac_Config.IP_address[1], Zodiac_Config.IP_address[2], Zodiac_Config.IP_address[3]); } else { - TRACE("http.c: \"&\" cannot be used in form"); + TRACE("http.c: no IP address found"); } - } - else - { - TRACE("http.c: no IP address found"); - } - memset(&http_msg, 0, sizeof(http_msg)); + memset(&http_msg, 0, sizeof(http_msg)); - // Netmask - pdat = strstr(http_payload, "wi_netmask"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_netmask")+1); // Data format: wi_deviceName=(name) - - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) - { - http_msg[i] = pdat[i]; // Store value of element - i++; - } - if(pdat[i+1] == 'w') + // Netmask + pdat = strstr(http_payload, "wi_netmask"); + if(pdat != NULL) // Check that element exists { - int nm1,nm2,nm3,nm4; - if (strlen(http_msg) > 15 ) + pdat += (strlen("wi_netmask")+1); // Data format: wi_deviceName=(name) + + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) { - TRACE("http.c: incorrect netmask format"); - return; + http_msg[i] = pdat[i]; // Store value of element + i++; } - sscanf(http_msg, "%d.%d.%d.%d", &nm1, &nm2,&nm3,&nm4); - Zodiac_Config.netmask[0] = nm1; - Zodiac_Config.netmask[1] = nm2; - Zodiac_Config.netmask[2] = nm3; - Zodiac_Config.netmask[3] = nm4; - TRACE("http.c: netmask set to %d.%d.%d.%d" , Zodiac_Config.netmask[0], Zodiac_Config.netmask[1], Zodiac_Config.netmask[2], Zodiac_Config.netmask[3]); - } - else + if(pdat[i+1] == 'w') + { + int nm1,nm2,nm3,nm4; + if (strlen(http_msg) > 15 ) + { + TRACE("http.c: incorrect netmask format"); + return; + } + sscanf(http_msg, "%d.%d.%d.%d", &nm1, &nm2,&nm3,&nm4); + Zodiac_Config.netmask[0] = nm1; + Zodiac_Config.netmask[1] = nm2; + Zodiac_Config.netmask[2] = nm3; + Zodiac_Config.netmask[3] = nm4; + TRACE("http.c: netmask set to %d.%d.%d.%d" , Zodiac_Config.netmask[0], Zodiac_Config.netmask[1], Zodiac_Config.netmask[2], Zodiac_Config.netmask[3]); + } + else + { + TRACE("http.c: \"&\" cannot be used in form"); + } + } + else { - TRACE("http.c: \"&\" cannot be used in form"); + TRACE("http.c: no netmask found"); } - } - else - { - TRACE("http.c: no netmask found"); - } - memset(&http_msg, 0, sizeof(http_msg)); + memset(&http_msg, 0, sizeof(http_msg)); - // Gateway - pdat = strstr(http_payload, "wi_gateway"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_gateway")+1); // Data format: wi_deviceName=(name) - - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + // Gateway + pdat = strstr(http_payload, "wi_gateway"); + if(pdat != NULL) // Check that element exists { - http_msg[i] = pdat[i]; // Store value of element - i++; - } + pdat += (strlen("wi_gateway")+1); // Data format: wi_deviceName=(name) + + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + { + http_msg[i] = pdat[i]; // Store value of element + i++; + } - // No next 'w' character check as this is the last element + // No next 'w' character check as this is the last element - int gw1,gw2,gw3,gw4; - if (strlen(http_msg) > 15 ) - { - TRACE("http.c: incorrect gateway format"); - return; - } - sscanf(http_msg, "%d.%d.%d.%d", &gw1, &gw2,&gw3,&gw4); - Zodiac_Config.gateway_address[0] = gw1; - Zodiac_Config.gateway_address[1] = gw2; - Zodiac_Config.gateway_address[2] = gw3; - Zodiac_Config.gateway_address[3] = gw4; - TRACE("http.c: gateway set to %d.%d.%d.%d" , Zodiac_Config.gateway_address[0], Zodiac_Config.gateway_address[1], Zodiac_Config.gateway_address[2], Zodiac_Config.gateway_address[3]); - } - else - { - TRACE("http.c: no gateway address found"); - } + int gw1,gw2,gw3,gw4; + if (strlen(http_msg) > 15 ) + { + TRACE("http.c: incorrect gateway format"); + return; + } + sscanf(http_msg, "%d.%d.%d.%d", &gw1, &gw2,&gw3,&gw4); + Zodiac_Config.gateway_address[0] = gw1; + Zodiac_Config.gateway_address[1] = gw2; + Zodiac_Config.gateway_address[2] = gw3; + Zodiac_Config.gateway_address[3] = gw4; + TRACE("http.c: gateway set to %d.%d.%d.%d" , Zodiac_Config.gateway_address[0], Zodiac_Config.gateway_address[1], Zodiac_Config.gateway_address[2], Zodiac_Config.gateway_address[3]); + } + else + { + TRACE("http.c: no gateway address found"); + } - // Save configuration to EEPROM - eeprom_write(); - TRACE("http.c: config written to EEPROM"); + // Save configuration to EEPROM + eeprom_write(); + TRACE("http.c: config written to EEPROM"); - // Set update required flag - reset_required = true; + // Set update required flag + reset_required = true; - // Send updated config page - if(interfaceCreate_Config_Network()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); + // Send updated config page + if(interfaceCreate_Config_Network()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); + } + + // Send updated header page (with restart button) + + // ***** Placeholder until frame refresh targeting is implemented + // + // + // + } - else + else if(strcmp(http_msg,"btn_restart") == 0) { - TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); + TRACE("http.c: restarting the Zodiac FX. Please reconnect."); + for(int x = 0;x<100000;x++); // Let the above message get sent to the terminal before detaching + udc_detach(); // Detach the USB device before restart + rstc_start_software_reset(RSTC); // Software reset + while (1); } - - // Send updated header page (with restart button) + else if(strcmp(http_msg,"btn_default") == 0) + { + TRACE("http.c: restoring factory settings"); - // ***** Placeholder until frame refresh targeting is implemented - // - // - // - - } - else if(strcmp(http_msg,"btn_restart") == 0) - { - TRACE("http.c: restarting the Zodiac FX. Please reconnect."); - for(int x = 0;x<100000;x++); // Let the above message get sent to the terminal before detaching - udc_detach(); // Detach the USB device before restart - rstc_start_software_reset(RSTC); // Software reset - while (1); - } - else if(strcmp(http_msg,"btn_default") == 0) - { - TRACE("http.c: restoring factory settings"); + struct zodiac_config reset_config = + { + "Zodiac_FX", // Name + 0,0,0,0,0,0, // MAC Address + 10,0,1,99, // IP Address + 255,255,255,0, // Netmask + 10,0,1,1, // Gateway Address + 10,0,1,8, // IP Address of the SDN Controller + 6633, // TCP port of SDN Controller + 1 // OpenFlow enabled + }; + memset(&reset_config.vlan_list, 0, sizeof(struct virtlan)* MAX_VLANS); // Clear vlan array + + // Config VLAN 100 + sprintf(&reset_config.vlan_list[0].cVlanName, "OpenFlow"); // Vlan name + reset_config.vlan_list[0].portmap[0] = 1; // Assign port 1 to this vlan + reset_config.vlan_list[0].portmap[1] = 1; // Assign port 2 to this vlan + reset_config.vlan_list[0].portmap[2] = 1; // Assign port 3 to this vlan + reset_config.vlan_list[0].uActive = 1; // Vlan is active + reset_config.vlan_list[0].uVlanID = 100; // Vlan ID is 100 + reset_config.vlan_list[0].uVlanType = 1; // Set as an Openflow Vlan + reset_config.vlan_list[0].uTagged = 0; // Set as untagged + + // Config VLAN 200 + sprintf(&reset_config.vlan_list[1].cVlanName, "Controller"); + reset_config.vlan_list[1].portmap[3] = 1; // Assign port 4 to this vlan + reset_config.vlan_list[1].uActive = 1; // Vlan is active + reset_config.vlan_list[1].uVlanID = 200; // Vlan ID is 200 + reset_config.vlan_list[1].uVlanType = 2; // Set as an Native Vlan + reset_config.vlan_list[1].uTagged = 0; // Set as untagged + + // Set ports + reset_config.of_port[0] = 1; // Port 1 is an OpenFlow port + reset_config.of_port[1] = 1; // Port 2 is an Openflow port + reset_config.of_port[2] = 1; // Port 3 is an OpenFlow port + reset_config.of_port[3] = 2; // Port 4 is an Native port + + // Failstate + reset_config.failstate = 0; // Failstate Secure + + // Force OpenFlow version + reset_config.of_version = 0; // Force version disabled + + memcpy(&reset_config.MAC_address, &Zodiac_Config.MAC_address, 6); // Copy over existing MAC address so it is not reset + memcpy(&Zodiac_Config, &reset_config, sizeof(struct zodiac_config)); + eeprom_write(); - struct zodiac_config reset_config = + TRACE("http.c: restarting the Zodiac FX. Please reconnect."); + for(int x = 0;x<100000;x++); // Let the above message get sent to the terminal before detaching + udc_detach(); // Detach the USB device before restart + rstc_start_software_reset(RSTC); // Software reset + while (1); + } + else if(strcmp(http_msg,"save_ports") == 0) { - "Zodiac_FX", // Name - 0,0,0,0,0,0, // MAC Address - 10,0,1,99, // IP Address - 255,255,255,0, // Netmask - 10,0,1,1, // Gateway Address - 10,0,1,8, // IP Address of the SDN Controller - 6633, // TCP port of SDN Controller - 1 // OpenFlow enabled - }; - memset(&reset_config.vlan_list, 0, sizeof(struct virtlan)* MAX_VLANS); // Clear vlan array - - // Config VLAN 100 - sprintf(&reset_config.vlan_list[0].cVlanName, "OpenFlow"); // Vlan name - reset_config.vlan_list[0].portmap[0] = 1; // Assign port 1 to this vlan - reset_config.vlan_list[0].portmap[1] = 1; // Assign port 2 to this vlan - reset_config.vlan_list[0].portmap[2] = 1; // Assign port 3 to this vlan - reset_config.vlan_list[0].uActive = 1; // Vlan is active - reset_config.vlan_list[0].uVlanID = 100; // Vlan ID is 100 - reset_config.vlan_list[0].uVlanType = 1; // Set as an Openflow Vlan - reset_config.vlan_list[0].uTagged = 0; // Set as untagged - - // Config VLAN 200 - sprintf(&reset_config.vlan_list[1].cVlanName, "Controller"); - reset_config.vlan_list[1].portmap[3] = 1; // Assign port 4 to this vlan - reset_config.vlan_list[1].uActive = 1; // Vlan is active - reset_config.vlan_list[1].uVlanID = 200; // Vlan ID is 200 - reset_config.vlan_list[1].uVlanType = 2; // Set as an Native Vlan - reset_config.vlan_list[1].uTagged = 0; // Set as untagged - - // Set ports - reset_config.of_port[0] = 1; // Port 1 is an OpenFlow port - reset_config.of_port[1] = 1; // Port 2 is an Openflow port - reset_config.of_port[2] = 1; // Port 3 is an OpenFlow port - reset_config.of_port[3] = 2; // Port 4 is an Native port - - // Failstate - reset_config.failstate = 0; // Failstate Secure - - // Force OpenFlow version - reset_config.of_version = 0; // Force version disabled - - memcpy(&reset_config.MAC_address, &Zodiac_Config.MAC_address, 6); // Copy over existing MAC address so it is not reset - memcpy(&Zodiac_Config, &reset_config, sizeof(struct zodiac_config)); - eeprom_write(); - - TRACE("http.c: restarting the Zodiac FX. Please reconnect."); - for(int x = 0;x<100000;x++); // Let the above message get sent to the terminal before detaching - udc_detach(); // Detach the USB device before restart - rstc_start_software_reset(RSTC); // Software reset - while (1); - } - else if(strcmp(http_msg,"save_ports") == 0) - { - // Save VLAN port associations + // Save VLAN port associations - memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - int port = 0; - int x, y; - int vlanid; - char portID[10]; + memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array + int port = 0; + int x, y; + int vlanid; + char portID[10]; - // Search for "wi_pxID" - for (x=0;x= 31) && (pdat[i] <= 122)) + port = x+1; + snprintf(portID, 10, "wi_p%dID=", port); + pdat = strstr(http_payload, portID); // Search for element + if(pdat != NULL) // Check that the element exists { - http_msg[i] = pdat[i]; // Store value of element - i++; - } + pdat += (strlen(portID)); // Data format: wi_p1ID=(VLAN ID) + + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + { + http_msg[i] = pdat[i]; // Store value of element + i++; + } - vlanid = atoi(http_msg); + vlanid = atoi(http_msg); - if(vlanid == 0) - { - // Not a valid selection + if(vlanid == 0) + { + // Not a valid selection - //for (y=0;y 1 ) + if(Zodiac_Config.vlan_list[y].uVlanID == vlanid) { - Zodiac_Config.vlan_list[y].portmap[port-1] = 1; - Zodiac_Config.of_port[port-1] = Zodiac_Config.vlan_list[y].uVlanType; - TRACE("http.c: port %d is now assigned to VLAN %d", port, vlanid); + if(Zodiac_Config.vlan_list[y].portmap[port-1] == 0 || Zodiac_Config.vlan_list[x].portmap[port-1] > 1 ) + { + Zodiac_Config.vlan_list[y].portmap[port-1] = 1; + Zodiac_Config.of_port[port-1] = Zodiac_Config.vlan_list[y].uVlanType; + TRACE("http.c: port %d is now assigned to VLAN %d", port, vlanid); + } } } } } + else + { + TRACE("http.c: port VLAN ID not found in Display: Ports response") + } + } + + // Save configuration to EEPROM + eeprom_write(); + TRACE("http.c: config written to EEPROM"); + + // Send updated page + if(interfaceCreate_Display_Ports(0)) + { + // Only write to buffer - don't send + http_send(&shared_buffer, pcb, 0); + TRACE("http.c: updated ports page sent successfully (1/2) - %d bytes", strlen(shared_buffer)); } else { - TRACE("http.c: port VLAN ID not found in Display: Ports response") + TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); } - } - // Save configuration to EEPROM - eeprom_write(); - TRACE("http.c: config written to EEPROM"); - - // Send updated page - if(interfaceCreate_Display_Ports(0)) - { - // Only write to buffer - don't send - http_send(&shared_buffer, pcb, 0); - TRACE("http.c: updated ports page sent successfully (1/2) - %d bytes", strlen(shared_buffer)); + if(interfaceCreate_Display_Ports(1)) + { + // Call TCP output & close the connection + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: updated ports page sent successfully (2/2) - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); + } } - else + else if(strcmp(http_msg,"btn_ofNext") == 0) { - TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); - } - if(interfaceCreate_Display_Ports(1)) - { - // Call TCP output & close the connection - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: updated ports page sent successfully (2/2) - %d bytes", strlen(shared_buffer)); } - else + else if(strcmp(http_msg,"btn_ofPrev") == 0) { - TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); - } - } - else if(strcmp(http_msg,"btn_ofNext") == 0) - { - } - else if(strcmp(http_msg,"btn_ofPrev") == 0) - { - - } - else if(strcmp(http_msg,"btn_ofClear") == 0) - { - // Clear the flow table - TRACE("http.c: clearing flow table, %d flow deleted.\r\n", iLastFlow); - clear_flows(); - - // Send updated page - if(interfaceCreate_Display_Flows()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); } - else + else if(strcmp(http_msg,"btn_ofClear") == 0) { - TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); + // Clear the flow table + TRACE("http.c: clearing flow table, %d flow deleted.\r\n", iLastFlow); + clear_flows(); + + // Send updated page + if(interfaceCreate_Display_Flows()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); + } } - } - else if(strcmp(http_msg,"save_vlan") == 0) - { - memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array - - // Search for btn= - pdat = strstr(http_payload, "btn="); // Search for element - if(pdat != NULL) // Check that the element exists + else if(strcmp(http_msg,"save_vlan") == 0) { - pdat += (strlen("btn=")); // Data format: btn=btn_name + memset(&http_msg, 0, sizeof(http_msg)); // Clear HTTP message array + + // Search for btn= + pdat = strstr(http_payload, "btn="); // Search for element + if(pdat != NULL) // Check that the element exists + { + pdat += (strlen("btn=")); // Data format: btn=btn_name - i = 0; - while(i < 7) // VLAN button can only be "btn_add" or "btn_del" + i = 0; + while(i < 7) // VLAN button can only be "btn_add" or "btn_del" + { + http_msg[i] = pdat[i]; // Store value of element + i++; + } + } + else { - http_msg[i] = pdat[i]; // Store value of element - i++; + TRACE("http.c: button not found in Config: VLANs response") } - } - else - { - TRACE("http.c: button not found in Config: VLANs response") - } - // Match pressed button - if(strcmp(http_msg,"btn_del") == 0) - { - int num = -1; - pdat += (strlen("btn_del")); // Data format: btn=btn_del[number] + // Match pressed button + if(strcmp(http_msg,"btn_del") == 0) + { + int num = -1; + pdat += (strlen("btn_del")); // Data format: btn=btn_del[number] - num = pdat[0] - '0'; // Convert single char element to int + num = pdat[0] - '0'; // Convert single char element to int - TRACE("http.c: deleting element %d in vlan list", num); + TRACE("http.c: deleting element %d in vlan list", num); - // Table row must be mapped to the ACTIVE VLANs - i = 0; // for stepping through the vlan list - uint8_t ctr = 0; // for mapping active items & checking against desired delete - uint8_t done = 0; // Break once the correct element is found - while(i >= 0 && i < MAX_VLANS && !done) - { - // Check if vlan is active - if(Zodiac_Config.vlan_list[i].uActive == 1) + // Table row must be mapped to the ACTIVE VLANs + i = 0; // for stepping through the vlan list + uint8_t ctr = 0; // for mapping active items & checking against desired delete + uint8_t done = 0; // Break once the correct element is found + while(i >= 0 && i < MAX_VLANS && !done) { - // Check if this is the element to be deleted - if(ctr == num) + // Check if vlan is active + if(Zodiac_Config.vlan_list[i].uActive == 1) { - // Delete existing VLAN - Zodiac_Config.vlan_list[i].uActive = 0; - Zodiac_Config.vlan_list[i].uVlanType = 0; - Zodiac_Config.vlan_list[i].uTagged = 0; - Zodiac_Config.vlan_list[i].uVlanID = 0; - done = 1; + // Check if this is the element to be deleted + if(ctr == num) + { + // Delete existing VLAN + Zodiac_Config.vlan_list[i].uActive = 0; + Zodiac_Config.vlan_list[i].uVlanType = 0; + Zodiac_Config.vlan_list[i].uTagged = 0; + Zodiac_Config.vlan_list[i].uVlanID = 0; + done = 1; + } + else + { + ctr++; + } + } + i++; + } + } + else if(strcmp(http_msg,"btn_add") == 0) + { + int vlID = 0; + char vlName[16] = ""; + int vlType = 0; + + // Find ID input + memset(&http_msg, 0, sizeof(http_msg)); + pdat = strstr(http_payload, "wi_vlID"); + if(pdat != NULL) // Check that element exists + { + pdat += (strlen("wi_vlID")+1); // Data format: wi_vlID=(ID) + + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + { + http_msg[i] = pdat[i]; // Store value of element + i++; + } + if(pdat[i+1] == 'w' && strlen(http_msg)) // Check to make sure data follows + { + vlID = atoi(http_msg); + TRACE("http.c: VLAN ID: %d", vlID); } else { - ctr++; + TRACE("http.c: invalid VLAN ID input"); } } - i++; + else + { + TRACE("http.c: no VLAN ID found"); + } + + // Find VLAN name input + pdat = strstr(http_payload, "wi_vlName"); + if(pdat != NULL) // Check that element exists + { + pdat += (strlen("wi_vlName")+1); // Data format: wi_vlName=(Name) + + i = 0; + while(i < 15 && (pdat[i] != '&')) + { + vlName[i] = pdat[i]; // Store value of element + i++; + } + if(pdat[i+1] == 'w' && strlen(vlName)) // Check to make sure data follows + { + TRACE("http.c: VLAN Name: %s", vlName); + } + else + { + TRACE("http.c: invalid VLAN Name input"); + } + } + else + { + TRACE("http.c: no VLAN Name found"); + } + + // Find VLAN type input + pdat = strstr(http_payload, "wi_vlType"); + if(pdat != NULL) // Check that element exists + { + pdat += (strlen("wi_vlType")+1); // Data format: wi_vlType=(Type) + vlType = pdat[0] - '0'; // Convert single char element to int + } + else + { + TRACE("http.c: no VLAN Type found"); + } + + // Add new VLAN + int v=0; + uint8_t done = 0; + while(v < MAX_VLANS && !done) + { + if(Zodiac_Config.vlan_list[v].uActive != 1) + { + Zodiac_Config.vlan_list[v].uActive = 1; + Zodiac_Config.vlan_list[v].uVlanID = vlID; + sprintf(Zodiac_Config.vlan_list[v].cVlanName, vlName, strlen(vlName)); + Zodiac_Config.vlan_list[v].uVlanType = vlType; + TRACE("http.c: added VLAN %d '%s', type %d",Zodiac_Config.vlan_list[v].uVlanID, Zodiac_Config.vlan_list[v].cVlanName, Zodiac_Config.vlan_list[v].uVlanType); + done = 1; + } + v++; + } + if(!done) + { + TRACE("http.c: maximum VLAN limit reached"); + } + } + else + { + TRACE("http.c: unhandled button in Config: VLANs") + } + + // Save configuration to EEPROM + eeprom_write(); + TRACE("http.c: config written to EEPROM"); + + // Send updated config page + if(interfaceCreate_Config_VLANs()) + { + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); + } + else + { + TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); } } - else if(strcmp(http_msg,"btn_add") == 0) + else if(strcmp(http_msg,"save_of") == 0) { - int vlID = 0; - char vlName[16] = ""; - int vlType = 0; - - // Find ID input - memset(&http_msg, 0, sizeof(http_msg)); - pdat = strstr(http_payload, "wi_vlID"); + // Controller IP Address + memset(&http_msg, 0, sizeof(http_msg)); + pdat = strstr(http_payload, "wi_ofIP"); if(pdat != NULL) // Check that element exists { - pdat += (strlen("wi_vlID")+1); // Data format: wi_vlID=(ID) - + pdat += (strlen("wi_ofIP")+1); // Data format: wi_ofIP=(IP) + i = 0; while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) { http_msg[i] = pdat[i]; // Store value of element i++; } - if(pdat[i+1] == 'w' && strlen(http_msg)) // Check to make sure data follows + if(pdat[i+1] == 'w') { - vlID = atoi(http_msg); - TRACE("http.c: VLAN ID: %d", vlID); + int oc1,oc2,oc3,oc4; + if (strlen(http_msg) > 15 ) + { + TRACE("http.c: incorrect IP format"); + return; + } + sscanf(http_msg, "%d.%d.%d.%d", &oc1,&oc2,&oc3,&oc4); + Zodiac_Config.OFIP_address[0] = oc1; + Zodiac_Config.OFIP_address[1] = oc2; + Zodiac_Config.OFIP_address[2] = oc3; + Zodiac_Config.OFIP_address[3] = oc4; + TRACE("http.c: openflow server address set to %d.%d.%d.%d" ,\ + Zodiac_Config.OFIP_address[0], Zodiac_Config.OFIP_address[1],\ + Zodiac_Config.OFIP_address[2], Zodiac_Config.OFIP_address[3]\ + ); } else { - TRACE("http.c: invalid VLAN ID input"); + TRACE("http.c: \"&\" cannot be used in form"); } } - else - { - TRACE("http.c: no VLAN ID found"); - } - // Find VLAN name input - pdat = strstr(http_payload, "wi_vlName"); + // Controller Port + memset(&http_msg, 0, sizeof(http_msg)); + pdat = strstr(http_payload, "wi_ofPort"); if(pdat != NULL) // Check that element exists { - pdat += (strlen("wi_vlName")+1); // Data format: wi_vlName=(Name) + pdat += (strlen("wi_ofPort")+1); // Data format: wi_ofPort=(Port) i = 0; - while(i < 15 && (pdat[i] != '&')) + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) { - vlName[i] = pdat[i]; // Store value of element + http_msg[i] = pdat[i]; // Store value of element i++; } - if(pdat[i+1] == 'w' && strlen(vlName)) // Check to make sure data follows + if(pdat[i+1] == 'w') { - TRACE("http.c: VLAN Name: %s", vlName); + Zodiac_Config.OFPort = atoi(http_msg); + TRACE("OpenFlow Port set to %d" , Zodiac_Config.OFPort); } else { - TRACE("http.c: invalid VLAN Name input"); + TRACE("http.c: \"&\" cannot be used in form"); } } - else - { - TRACE("http.c: no VLAN Name found"); - } - - // Find VLAN type input - pdat = strstr(http_payload, "wi_vlType"); + + // OpenFlow Status + memset(&http_msg, 0, sizeof(http_msg)); + pdat = strstr(http_payload, "wi_ofStatus"); if(pdat != NULL) // Check that element exists { - pdat += (strlen("wi_vlType")+1); // Data format: wi_vlType=(Type) - vlType = pdat[0] - '0'; // Convert single char element to int - } - else - { - TRACE("http.c: no VLAN Type found"); - } + pdat += (strlen("wi_ofStatus")+1); // Data format: wi_ofPort=(Port) - // Add new VLAN - int v=0; - uint8_t done = 0; - while(v < MAX_VLANS && !done) - { - if(Zodiac_Config.vlan_list[v].uActive != 1) + i = 0; + while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) { - Zodiac_Config.vlan_list[v].uActive = 1; - Zodiac_Config.vlan_list[v].uVlanID = vlID; - sprintf(Zodiac_Config.vlan_list[v].cVlanName, vlName, strlen(vlName)); - Zodiac_Config.vlan_list[v].uVlanType = vlType; - TRACE("http.c: added VLAN %d '%s', type %d",Zodiac_Config.vlan_list[v].uVlanID, Zodiac_Config.vlan_list[v].cVlanName, Zodiac_Config.vlan_list[v].uVlanType); - done = 1; + http_msg[i] = pdat[i]; // Store value of element + i++; } - v++; - } - if(!done) - { - TRACE("http.c: maximum VLAN limit reached"); - } - } - else - { - TRACE("http.c: unhandled button in Config: VLANs") - } - - // Save configuration to EEPROM - eeprom_write(); - TRACE("http.c: config written to EEPROM"); - - // Send updated config page - if(interfaceCreate_Config_VLANs()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); - } - else - { - TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); - } - } - else if(strcmp(http_msg,"save_of") == 0) - { - // Controller IP Address - memset(&http_msg, 0, sizeof(http_msg)); - pdat = strstr(http_payload, "wi_ofIP"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_ofIP")+1); // Data format: wi_ofIP=(IP) - - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) - { - http_msg[i] = pdat[i]; // Store value of element - i++; - } - if(pdat[i+1] == 'w') - { - int oc1,oc2,oc3,oc4; - if (strlen(http_msg) > 15 ) + + if(strcmp(http_msg,"Enable") == 0) { - TRACE("http.c: incorrect IP format"); - return; + Zodiac_Config.OFEnabled = OF_ENABLED; + enableOF(); + TRACE("http.c: openflow enabled"); + } + else if(strcmp(http_msg,"Disable") == 0) + { + Zodiac_Config.OFEnabled = OF_DISABLED; + disableOF(); + TRACE("http.c: openflow disabled"); + } + else + { + TRACE("http.c: unhandled openflow status"); } - sscanf(http_msg, "%d.%d.%d.%d", &oc1,&oc2,&oc3,&oc4); - Zodiac_Config.OFIP_address[0] = oc1; - Zodiac_Config.OFIP_address[1] = oc2; - Zodiac_Config.OFIP_address[2] = oc3; - Zodiac_Config.OFIP_address[3] = oc4; - TRACE("http.c: openflow server address set to %d.%d.%d.%d" ,\ - Zodiac_Config.OFIP_address[0], Zodiac_Config.OFIP_address[1],\ - Zodiac_Config.OFIP_address[2], Zodiac_Config.OFIP_address[3]\ - ); - } - else - { - TRACE("http.c: \"&\" cannot be used in form"); } - } - // Controller Port - memset(&http_msg, 0, sizeof(http_msg)); - pdat = strstr(http_payload, "wi_ofPort"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_ofPort")+1); // Data format: wi_ofPort=(Port) - - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) - { - http_msg[i] = pdat[i]; // Store value of element - i++; - } - if(pdat[i+1] == 'w') - { - Zodiac_Config.OFPort = atoi(http_msg); - TRACE("OpenFlow Port set to %d" , Zodiac_Config.OFPort); - } - else + // OpenFlow Status + pdat = strstr(http_payload, "wi_failstate"); + if(pdat != NULL) // Check that element exists { - TRACE("http.c: \"&\" cannot be used in form"); - } - } - - // OpenFlow Status - memset(&http_msg, 0, sizeof(http_msg)); - pdat = strstr(http_payload, "wi_ofStatus"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_ofStatus")+1); // Data format: wi_ofPort=(Port) + pdat += (strlen("wi_failstate")+1); // Data format: wi_failstate=(state) - i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) - { - http_msg[i] = pdat[i]; // Store value of element - i++; - } + int failstate = 0; + failstate = pdat[0] - '0'; // Convert single char element to int - if(strcmp(http_msg,"Enable") == 0) - { - Zodiac_Config.OFEnabled = OF_ENABLED; - enableOF(); - TRACE("http.c: openflow enabled"); - } - else if(strcmp(http_msg,"Disable") == 0) - { - Zodiac_Config.OFEnabled = OF_DISABLED; - disableOF(); - TRACE("http.c: openflow disabled"); - } - else - { - TRACE("http.c: unhandled openflow status"); + if(failstate == 0) + { + Zodiac_Config.failstate = 0; + TRACE("http.c: failstate set to Secure (0)"); + } + else if(failstate == 1) + { + Zodiac_Config.failstate = 1; + TRACE("http.c: failstate set to Safe (1)"); + } + else + { + TRACE("http.c: unhandled failstate"); + } } - } - // OpenFlow Status - pdat = strstr(http_payload, "wi_failstate"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_failstate")+1); // Data format: wi_failstate=(state) - - int failstate = 0; - failstate = pdat[0] - '0'; // Convert single char element to int - - if(failstate == 0) - { - Zodiac_Config.failstate = 0; - TRACE("http.c: failstate set to Secure (0)"); - } - else if(failstate == 1) - { - Zodiac_Config.failstate = 1; - TRACE("http.c: failstate set to Safe (1)"); - } - else + // OpenFlow Force Version + pdat = strstr(http_payload, "wi_ofVer"); + if(pdat != NULL) // Check that element exists { - TRACE("http.c: unhandled failstate"); - } - } - - // OpenFlow Force Version - pdat = strstr(http_payload, "wi_ofVer"); - if(pdat != NULL) // Check that element exists - { - pdat += (strlen("wi_ofVer")+1); // Data format: wi_ofVer=(version) + pdat += (strlen("wi_ofVer")+1); // Data format: wi_ofVer=(version) - int forceVer = 0; - forceVer = pdat[0] - '0'; // Convert single char element to int + int forceVer = 0; + forceVer = pdat[0] - '0'; // Convert single char element to int - if(forceVer == 0) - { - Zodiac_Config.of_version = 0; - TRACE("http.c: force openflow version set to auto (0)"); - } - else if(forceVer == 1) - { - Zodiac_Config.of_version = 1; - TRACE("http.c: force openflow version set to 1.0 (1)"); + if(forceVer == 0) + { + Zodiac_Config.of_version = 0; + TRACE("http.c: force openflow version set to auto (0)"); + } + else if(forceVer == 1) + { + Zodiac_Config.of_version = 1; + TRACE("http.c: force openflow version set to 1.0 (1)"); + } + else if(forceVer == 4) + { + Zodiac_Config.of_version = 4; + TRACE("http.c: force openflow version set to 1.3 (4)"); + } + else + { + TRACE("http.c: unhandled openflow version"); + } } - else if(forceVer == 4) + + // Save configuration to EEPROM + eeprom_write(); + TRACE("http.c: config written to EEPROM"); + + // Send updated config page + if(interfaceCreate_Config_OpenFlow()) { - Zodiac_Config.of_version = 4; - TRACE("http.c: force openflow version set to 1.3 (4)"); + http_send(&shared_buffer, pcb, 1); + TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); } else { - TRACE("http.c: unhandled openflow version"); + TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); } } - - // Save configuration to EEPROM - eeprom_write(); - TRACE("http.c: config written to EEPROM"); - - // Send updated config page - if(interfaceCreate_Config_OpenFlow()) - { - http_send(&shared_buffer, pcb, 1); - TRACE("http.c: updated page sent successfully - %d bytes", strlen(shared_buffer)); - } else { - TRACE("http.c: unable to serve updated page - buffer at %d bytes", strlen(shared_buffer)); + TRACE("http.c: unknown request: \"%s\"", http_msg); } } else { - TRACE("http.c: unknown request: \"%s\"", http_msg); + TRACE("http.c: WARNING: unknown HTTP method received"); } } - else - { - TRACE("http.c: WARNING: unknown HTTP method received"); - } - } pbuf_free(p); @@ -1213,9 +1227,77 @@ void http_send(char *buffer, struct tcp_pcb *pcb, bool out) return; } -static uint8_t file_handler(char *ppart, int len) +static uint8_t upload_handler(char *ppart, int len) { - // + // Current browser support: Chrome + + char *px; // Data byte pointer + char *py; // End address pointer + int i; // Counter + + px = strstr(ppart, "application/"); // Check for valid binary data + + if(px == NULL) // Check that element exists + { + TRACE("http.c: invalid request"); + return 0; + } + + px += (strlen("application/")); + + // Find pointer to last element in payload + py = ppart + len; + + // Find end of data + i = 128; + while(i>0) + { + py--; + if((*py) == '\x0d' && (*(py+1)) == '\x0a' && (*(py+2)) == '\x2d' && (*(py+3)) == '\x2d') + { + i = 0; + // 'i' will be decremented to -1 if this line is run + } + i--; + } + + if(i == 0) + { + TRACE("http.c: end of data part not found"); + return 0; + } + + // Search for start of data + i = 0; + while(i<20) + { + px++; + if((*px) == '\x0a' && (*(px-1)) == '\x0d' && (*(px-2)) == '\x0a' && (*(px-3)) == '\x0d') + { + i = 20; + px++; + // 'i' will be incremented to 21 if this line is run + } + i++; + } + + if(i == 20) + { + TRACE("http.c: start of data part not found"); + return 0; + } + + memset(&shared_buffer, 0, 513); // Clear a 512-byte part + NULL for strstr operations + + i = 0; + while(px < py && i < 512) + { + shared_buffer[i] = *px; // Store value of element + px++; + i++; + } + + return 1; } /* @@ -1537,9 +1619,11 @@ static uint8_t interfaceCreate_Upload(void) ""\ ""\ "

"\ - "

Firmware Upload

"\ + "

Firmware Update

"\ "

"\ ""\ + "

Browser firmware update is currently only supported in Chrome.
"\ + "Do not attempt an update with an unsupported browser.

"\ "
"\ "

"\ ""\ From 1e4f7c55ae645391a6642f502370033c46cfba39 Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 23 Dec 2016 17:41:35 +1100 Subject: [PATCH 02/15] Add web updater flash code - can currently only write single page --- ZodiacFX/src/http.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index c75ec8c..5cf89b4 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -95,6 +95,7 @@ static uint8_t interfaceCreate_Config_OpenFlow(void); static uint8_t interfaceCreate_About(void); static uint8_t upload_handler(char *ppart, int len); +static int page_ctr = 1; /* @@ -1296,7 +1297,18 @@ static uint8_t upload_handler(char *ppart, int len) px++; i++; } - + + // Write data to page + if(flash_write_page(&shared_buffer)) + { + TRACE("http.c: firmware page written successfully (%02d)", page_ctr); + page_ctr++; + } + else + { + TRACE("http.c: firmware page write FAILED (%02d)", page_ctr); + } + return 1; } From 2166f0e0766bffa0cdc1c67d32e101214305885c Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Tue, 3 Jan 2017 13:55:15 +1100 Subject: [PATCH 03/15] Fix OF disconnect issue Raised number of active connections to prevent web interface from disconnecting OpenFlow connection. --- ZodiacFX/src/config/lwipopts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZodiacFX/src/config/lwipopts.h b/ZodiacFX/src/config/lwipopts.h index 1a004df..d31880e 100644 --- a/ZodiacFX/src/config/lwipopts.h +++ b/ZodiacFX/src/config/lwipopts.h @@ -114,7 +114,7 @@ * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. * (requires the LWIP_TCP option) */ -#define MEMP_NUM_TCP_PCB 3 +#define MEMP_NUM_TCP_PCB 5 /** * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. From e43d1e983091f518a4ff6d92ae0dd72c3c58ae3b Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Tue, 3 Jan 2017 18:59:26 +1100 Subject: [PATCH 04/15] Test web updater data receive --- ZodiacFX/src/http.c | 195 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 154 insertions(+), 41 deletions(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 5cf89b4..5563da2 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -156,8 +156,15 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err if(file_upload == true) { + int ret = 0; + int tst = 3000; // Handle multi-part file data - upload_handler(http_payload, len); + ret = upload_handler(http_payload, len); + while(tst) + { + tst--; + } + tst = 0; // _______________________________ for debug purposes } else { @@ -1232,24 +1239,56 @@ static uint8_t upload_handler(char *ppart, int len) { // Current browser support: Chrome - char *px; // Data byte pointer + static char page[512] = {0}; // Storage for each page of data + static uint16_t saved_bytes = 0; // Persistent counter of unwritten data + uint16_t handled_bytes = 0; // Counter of handled data + + char *px; // Start address pointer char *py; // End address pointer - int i; // Counter + int i = 0; + int final = 0; - px = strstr(ppart, "application/"); // Check for valid binary data + // Search for starting boundary + px = strstr(ppart, "application/"); - if(px == NULL) // Check that element exists + if(px == NULL) { - TRACE("http.c: invalid request"); - return 0; + TRACE("http.c: starting boundary not found - beginning data is valid"); + px = ppart; // Data begins at first value of array + } + else + { + TRACE("http.c: starting boundary found"); + + // Data begins after boundary + px += (strlen("application/")); + + // Search for start of data + i = 0; + while(i<20) + { + px++; + if((*px) == '\x0a' && (*(px-1)) == '\x0d' && (*(px-2)) == '\x0a' && (*(px-3)) == '\x0d') + { + i = 20; + px++; + // 'i' will be incremented to 21 if this line is run + } + i++; + } + + if(i == 20) + { + TRACE("http.c: start of data part not found"); + return 0; + } + + TRACE("http.c: pointer moved to start of data"); } - - px += (strlen("application/")); - // Find pointer to last element in payload + // Search for ending boundary py = ppart + len; - // Find end of data i = 128; while(i>0) { @@ -1264,52 +1303,126 @@ static uint8_t upload_handler(char *ppart, int len) if(i == 0) { - TRACE("http.c: end of data part not found"); - return 0; + TRACE("http.c: ending boundary not found - ending data is valid"); + } + else + { + TRACE("http.c: ending boundary found"); + + // Return ending pointer to the end + py = ppart + len; + + final = 1; } - // Search for start of data - i = 0; - while(i<20) + // Write data + if(saved_bytes) { - px++; - if((*px) == '\x0a' && (*(px-1)) == '\x0d' && (*(px-2)) == '\x0a' && (*(px-3)) == '\x0d') + // Fill in unwritten page (if it exists) + if(final) { - i = 20; - px++; - // 'i' will be incremented to 21 if this line is run + while(saved_bytes < 512 && handled_bytes < len) + { + page[saved_bytes] = *px; + px++; + saved_bytes++; + handled_bytes++; + } + } + else + { + while(saved_bytes < 512) + { + page[saved_bytes] = *px; + px++; + saved_bytes++; + handled_bytes++; + } + } + + // Write data to page + if(flash_write_page(&page)) // ___________________ CHECK + { + TRACE("http.c: firmware page written successfully (%02d)", page_ctr); + page_ctr++; + } + else + { + TRACE("http.c: firmware page write FAILED (%02d)", page_ctr); } - i++; + + memset(&page, 0, 512); + saved_bytes = 0; } - if(i == 20) + if(handled_bytes < len) { - TRACE("http.c: start of data part not found"); - return 0; - } - - memset(&shared_buffer, 0, 513); // Clear a 512-byte part + NULL for strstr operations + int j; - i = 0; - while(px < py && i < 512) - { - shared_buffer[i] = *px; // Store value of element - px++; - i++; + // Check for final page of data + if(final) + { + j = 0; + while(px < py) + { + page[j] = *px; + px++; + j++; + handled_bytes++; + } + } + + // Write full pages + while(len - handled_bytes >= 512) + { + j = 0; + while(j < 512) + { + page[j] = *px; // Store value of element + px++; + j++; + handled_bytes++; + } + + // Write data to page + if(flash_write_page(&page)) // ___________________ CHECK + { + TRACE("http.c: firmware page written successfully (%02d)", page_ctr); + page_ctr++; + } + else + { + TRACE("http.c: firmware page write FAILED (%02d)", page_ctr); + } + + memset(&page, 0, 512); + } + + // Save unwritten data + j = 0; + while(handled_bytes < len) + { + page[j] = *px; // Store value of element + px++; + j++; + handled_bytes++; + } + + if(px > py) + { + TRACE("http.c: ERROR - pointer has passed the data"); + return 0; + } } - // Write data to page - if(flash_write_page(&shared_buffer)) + if(final) { - TRACE("http.c: firmware page written successfully (%02d)", page_ctr); - page_ctr++; + return 2; } else { - TRACE("http.c: firmware page write FAILED (%02d)", page_ctr); + return 1; } - - return 1; } /* From 9e57558165856d8347589f38a5d9a547ab378112 Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Wed, 4 Jan 2017 16:38:01 +1100 Subject: [PATCH 05/15] Adjust maximum active connections --- ZodiacFX/src/config/lwipopts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZodiacFX/src/config/lwipopts.h b/ZodiacFX/src/config/lwipopts.h index d31880e..43b3a95 100644 --- a/ZodiacFX/src/config/lwipopts.h +++ b/ZodiacFX/src/config/lwipopts.h @@ -114,7 +114,7 @@ * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. * (requires the LWIP_TCP option) */ -#define MEMP_NUM_TCP_PCB 5 +#define MEMP_NUM_TCP_PCB 12 /** * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. From c1784e04cf5d78f53f0c56c983c458711cd10043 Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Wed, 4 Jan 2017 20:37:16 +1100 Subject: [PATCH 06/15] Web interface clean-up for merge --- ZodiacFX/src/config/config_zodiac.h | 2 +- ZodiacFX/src/http.c | 41 ++++++++++++++++++----------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/ZodiacFX/src/config/config_zodiac.h b/ZodiacFX/src/config/config_zodiac.h index 1470a2e..98ee342 100644 --- a/ZodiacFX/src/config/config_zodiac.h +++ b/ZodiacFX/src/config/config_zodiac.h @@ -31,7 +31,7 @@ #define CONFIG_ZODIAC_H_ -#define VERSION "0.69" // Firmware version number +#define VERSION "0.72" // Firmware version number #define MAX_OFP_VERSION 0x04 diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 5563da2..7ca805d 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -1226,8 +1226,8 @@ void http_send(char *buffer, struct tcp_pcb *pcb, bool out) // Check if more data needs to be written if(out == true) { - TRACE("http.c: calling tcp_output & closing connection"); if (err == ERR_OK) tcp_output(pcb); + TRACE("http.c: calling tcp_output & closing connection"); tcp_close(pcb); } } @@ -1646,7 +1646,7 @@ static uint8_t interfaceCreate_Menu(void) ""\ "
    "\ "
  • Status
  • "\ - "
  • Update f/w
  • " + //"
  • Update f/w
  • " "
  • Display
  • "\ "
  • Ports
  • "\ "
  • OpenFlow
  • "\ @@ -1791,15 +1791,15 @@ static uint8_t interfaceCreate_Display_Home(void) "

    Display Help

    "\ "

    Ports

    "\ "

    "\ - "Displays information for each of the Zodiac FX Ethernet ports, including its status, byte/packet statistics, and VLAN configuration."\ + "View information for each of the Zodiac FX Ethernet ports, including its status, byte/packet statistics, and VLAN configuration."\ "

    "\ "

    OpenFlow

    "\ "

    "\ - "Information about the OpenFlow status and configuration can be found in the OpenFlow display menu. The configured version, and details of the connected controller are also shown."\ + "View the current OpenFlow status and statistics."\ "

    "\ "

    Flows

    "\ "

    "\ - "Flow table contents can be viewed in the flows menu."\ + "View the current flows in the flow table. This page is currently limited to displaying a maximum of 5 flows."\ "

    "\ ""\ ""\ @@ -2800,15 +2800,15 @@ static uint8_t interfaceCreate_Config_Home(void) "

    Config Help

    "\ "

    Network

    "\ "

    "\ - "The network settings of the Zodiac FX can be configured in this menu, including the device name, IP address, MAC address, netmask, and default gateway."\ + "Configure the network settings of the Zodiac FX. This includes the device name, IP address, MAC address, netmask, and default gateway. After saving a configuration, a restart is required for changes to take effect."\ "

    "\ "

    VLANs

    "\ "

    "\ - "Virtual LANs can be added or removed in the VLANs menu. These can be assigned in the Ports menu on the left."\ + "Configure Virtual LANs. These can be added or deleted as required. To assign a port to a VLAN, go to the Display: Ports page. A restart is required for changes to take effect."\ "

    "\ "

    OpenFlow

    "\ "

    "\ - "The OpenFlow configuration can be modified here. OpenFlow can be enabled or disabled, the version can be specified, and the failstate can be set. The OpenFlow controller's IP address and port can be configured based on your network."\ + "Configure OpenFlow. Set the controller IP and port for your network configuration. OpenFlow failstate can be modified, and an OpenFlow version can be forced. Alternatively, OpenFlow may be disabled."\ "

    "\ ""\ ""\ @@ -3031,15 +3031,8 @@ static uint8_t interfaceCreate_Config_OpenFlow(void) ""\ "
    "\ "OpenFlow"\ - "Controller IP:
    "\ - "

    "\ - "Controller Port:
    "\ - "

    "\ - , Zodiac_Config.OFIP_address[0], Zodiac_Config.OFIP_address[1] - , Zodiac_Config.OFIP_address[2], Zodiac_Config.OFIP_address[3] - , Zodiac_Config.OFPort ); - + if(Zodiac_Config.OFEnabled == OF_ENABLED) { snprintf(shared_buffer+strlen(shared_buffer), SHARED_BUFFER_LEN-strlen(shared_buffer),\ @@ -3061,6 +3054,16 @@ static uint8_t interfaceCreate_Config_OpenFlow(void) ); } + snprintf(shared_buffer+strlen(shared_buffer), SHARED_BUFFER_LEN-strlen(shared_buffer),\ + "Controller IP:
    "\ + "

    "\ + "Controller Port:
    "\ + "

    "\ + , Zodiac_Config.OFIP_address[0], Zodiac_Config.OFIP_address[1] + , Zodiac_Config.OFIP_address[2], Zodiac_Config.OFIP_address[3] + , Zodiac_Config.OFPort + ); + if(Zodiac_Config.failstate == 0) { snprintf(shared_buffer+strlen(shared_buffer), SHARED_BUFFER_LEN-strlen(shared_buffer),\ @@ -3162,6 +3165,12 @@ static uint8_t interfaceCreate_About(void) "

    "\ "The Zodiac FX was created to allow the development of SDN applications on real hardware."\ "

    "\ +/* "

    What's new in v0.72

    "\ + "

    "\ + "- Feature
    "\ + "- Feature
    "\ + "- Feature
    "\ + "

    "\ */ ""\ ""\ ) < SHARED_BUFFER_LEN) From ccd9289a681faf89110f573de00ddbdebdf39fe3 Mon Sep 17 00:00:00 2001 From: Paul Zanna Date: Thu, 5 Jan 2017 22:24:00 +1100 Subject: [PATCH 07/15] Update config_zodiac.h --- ZodiacFX/src/config/config_zodiac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZodiacFX/src/config/config_zodiac.h b/ZodiacFX/src/config/config_zodiac.h index bef7ba7..98ee342 100644 --- a/ZodiacFX/src/config/config_zodiac.h +++ b/ZodiacFX/src/config/config_zodiac.h @@ -31,7 +31,7 @@ #define CONFIG_ZODIAC_H_ -#define VERSION "0.71" // Firmware version number +#define VERSION "0.72" // Firmware version number #define MAX_OFP_VERSION 0x04 From f7336fc662e521fcf97cfe766d29475d955d269c Mon Sep 17 00:00:00 2001 From: Paul Zanna Date: Thu, 5 Jan 2017 22:29:32 +1100 Subject: [PATCH 08/15] Update http.c --- ZodiacFX/src/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 5d7698e..bf94845 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -1439,7 +1439,7 @@ static uint8_t interfaceCreate_Menu(void) ""\ "
      "\ "
    • Status
    • "\ - /*"
    • Update f/w
    • "*/ + //"
    • Update f/w
    • " "
    • Display
    • "\ "
    • Ports
    • "\ "
    • OpenFlow
    • "\ From 40b48bf6e7ff553125012bd4db94f1091cf56dfa Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 6 Jan 2017 10:04:16 +1100 Subject: [PATCH 09/15] Fix Display: Ports loading failure - Queued TCP segments increased to 12, to accomodate maximum send buffer space - This resolves occassional page load failure --- ZodiacFX/src/config/lwipopts.h | 2 +- ZodiacFX/src/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ZodiacFX/src/config/lwipopts.h b/ZodiacFX/src/config/lwipopts.h index 43b3a95..785d4aa 100644 --- a/ZodiacFX/src/config/lwipopts.h +++ b/ZodiacFX/src/config/lwipopts.h @@ -126,7 +126,7 @@ * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. * (requires the LWIP_TCP option) */ -#define MEMP_NUM_TCP_SEG 8 +#define MEMP_NUM_TCP_SEG 12 /** * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for diff --git a/ZodiacFX/src/main.c b/ZodiacFX/src/main.c index 9da157c..95494ae 100644 --- a/ZodiacFX/src/main.c +++ b/ZodiacFX/src/main.c @@ -178,7 +178,7 @@ int main (void) sys_init_timing(); /* Initialize HTTP server. */ - //http_init(); + http_init(); // Create port map int v,p; From 621d66caf4315ecf2e51c53da2bfcdff2099febb Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 6 Jan 2017 10:22:06 +1100 Subject: [PATCH 10/15] Improve Display: Ports page stability --- ZodiacFX/src/config/lwipopts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZodiacFX/src/config/lwipopts.h b/ZodiacFX/src/config/lwipopts.h index 785d4aa..b488894 100644 --- a/ZodiacFX/src/config/lwipopts.h +++ b/ZodiacFX/src/config/lwipopts.h @@ -126,7 +126,7 @@ * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. * (requires the LWIP_TCP option) */ -#define MEMP_NUM_TCP_SEG 12 +#define MEMP_NUM_TCP_SEG 16 /** * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for From ea1e3efd85382e9e302abd10b5a7651a69bfbb04 Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 6 Jan 2017 13:12:58 +1100 Subject: [PATCH 11/15] Fix port VLAN assignment issues Display: Ports page now correctly assigns VLANs --- ZodiacFX/src/http.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index de370da..2c40ff1 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -731,7 +731,10 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err pdat += (strlen(portID)); // Data format: wi_p1ID=(VLAN ID) i = 0; - while(i < 63 && (pdat[i] != '&') && (pdat[i] >= 31) && (pdat[i] <= 122)) + while( i < 4 // Limit no. digits + && (pdat[i] >= 48 && pdat[i] <= 57) // Only digits allowed + && &pdat[i] < http_payload+len // Prevent overrun of payload data + ) { http_msg[i] = pdat[i]; // Store value of element i++; @@ -1792,6 +1795,8 @@ static uint8_t interfaceCreate_Display_Home(void) "

      Ports

      "\ "

      "\ "View information for each of the Zodiac FX Ethernet ports, including its status, byte/packet statistics, and VLAN configuration."\ + "
      Ports can be assigned to VLANs on this page."\ + "
      Warning: incorrectly assigning VLANs may cause the web interface to be unresponsive. Zodiac FX may need to be re-configured through a terminal application."\ "

      "\ "

      OpenFlow

      "\ "

      "\ @@ -2805,6 +2810,7 @@ static uint8_t interfaceCreate_Config_Home(void) "

      VLANs

      "\ "

      "\ "Configure Virtual LANs. These can be added or deleted as required. To assign a port to a VLAN, go to the Display: Ports page. A restart is required for changes to take effect."\ + "
      Warning: incorrectly configuring VLANs may cause the web interface to be unresponsive. Zodiac FX may need to be re-configured through a terminal application."\ "

      "\ "

      OpenFlow

      "\ "

      "\ From 085da6d11631aa982ec3a644aaa9f9ff9eee210a Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 6 Jan 2017 13:44:00 +1100 Subject: [PATCH 12/15] Improve ports formatting - Table column size fixed to prevent table size change on configuration - Added "nowrap" style to stop wrapping in some web browsers --- ZodiacFX/src/http.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 2c40ff1..cd8548a 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -1795,8 +1795,8 @@ static uint8_t interfaceCreate_Display_Home(void) "

      Ports

      "\ "

      "\ "View information for each of the Zodiac FX Ethernet ports, including its status, byte/packet statistics, and VLAN configuration."\ - "
      Ports can be assigned to VLANs on this page."\ - "
      Warning: incorrectly assigning VLANs may cause the web interface to be unresponsive. Zodiac FX may need to be re-configured through a terminal application."\ + "

      Ports can be assigned to VLANs on this page."\ + "

      Warning: incorrectly assigning VLANs may cause the web interface to be unresponsive. Zodiac FX may need to be re-configured through a terminal application."\ "

      "\ "

      OpenFlow

      "\ "

      "\ @@ -1879,6 +1879,10 @@ static uint8_t interfaceCreate_Display_Ports(uint8_t step) "padding-left: 7px;"\ "padding-right: 10px;"\ "border: 1px solid black;"\ + "white-space: nowrap;"\ + "}"\ + "th {"\ + "width: 75px;"\ "}"\ "#row {"\ "font-weight: bold;"\ @@ -2810,7 +2814,7 @@ static uint8_t interfaceCreate_Config_Home(void) "

      VLANs

      "\ "

      "\ "Configure Virtual LANs. These can be added or deleted as required. To assign a port to a VLAN, go to the Display: Ports page. A restart is required for changes to take effect."\ - "
      Warning: incorrectly configuring VLANs may cause the web interface to be unresponsive. Zodiac FX may need to be re-configured through a terminal application."\ + "

      Warning: incorrectly configuring VLANs may cause the web interface to be unresponsive. Zodiac FX may need to be re-configured through a terminal application."\ "

      "\ "

      OpenFlow

      "\ "

      "\ From 04a1a50328bdd8913503d750453666a84ce3d1ff Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 6 Jan 2017 15:40:42 +1100 Subject: [PATCH 13/15] Add VLAN ID limit --- ZodiacFX/src/http.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index cd8548a..48fac8a 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -976,25 +976,32 @@ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err TRACE("http.c: no VLAN Type found"); } - // Add new VLAN - int v=0; - uint8_t done = 0; - while(v < MAX_VLANS && !done) + if(vlID <= 4096) { - if(Zodiac_Config.vlan_list[v].uActive != 1) + // Add new VLAN + int v=0; + uint8_t done = 0; + while(v < MAX_VLANS && !done) { - Zodiac_Config.vlan_list[v].uActive = 1; - Zodiac_Config.vlan_list[v].uVlanID = vlID; - sprintf(Zodiac_Config.vlan_list[v].cVlanName, vlName, strlen(vlName)); - Zodiac_Config.vlan_list[v].uVlanType = vlType; - TRACE("http.c: added VLAN %d '%s', type %d",Zodiac_Config.vlan_list[v].uVlanID, Zodiac_Config.vlan_list[v].cVlanName, Zodiac_Config.vlan_list[v].uVlanType); - done = 1; + if(Zodiac_Config.vlan_list[v].uActive != 1) + { + Zodiac_Config.vlan_list[v].uActive = 1; + Zodiac_Config.vlan_list[v].uVlanID = vlID; + sprintf(Zodiac_Config.vlan_list[v].cVlanName, vlName, strlen(vlName)); + Zodiac_Config.vlan_list[v].uVlanType = vlType; + TRACE("http.c: added VLAN %d '%s', type %d",Zodiac_Config.vlan_list[v].uVlanID, Zodiac_Config.vlan_list[v].cVlanName, Zodiac_Config.vlan_list[v].uVlanType); + done = 1; + } + v++; + } + if(!done) + { + TRACE("http.c: maximum VLAN limit reached"); } - v++; } - if(!done) + else { - TRACE("http.c: maximum VLAN limit reached"); + TRACE("http.c: VLAN ID > 4096") } } else From 8d7538627096328dd668d9abab9ad42d9ceec94e Mon Sep 17 00:00:00 2001 From: Kristopher Chen Date: Fri, 6 Jan 2017 17:14:47 +1100 Subject: [PATCH 14/15] Change VLAN status naming --- ZodiacFX/src/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 48fac8a..5a0dafb 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -1844,7 +1844,7 @@ static uint8_t interfaceCreate_Display_Ports(uint8_t step) // Create VLAN type strings char portvlType[3][11]; - snprintf(portvlType[0], 11, "Unassigned"); + snprintf(portvlType[0], 11, "n/a"); snprintf(portvlType[1], 11, "OpenFlow"); snprintf(portvlType[2], 11, "Native"); From c3e709e40c86b3436a93f4295504412c89b52aaf Mon Sep 17 00:00:00 2001 From: Paul Zanna Date: Fri, 6 Jan 2017 20:44:33 +1100 Subject: [PATCH 15/15] v0.72 final save --- ZodiacFX/src/flash.c | 2 +- ZodiacFX/src/flash.h | 2 +- ZodiacFX/src/http.c | 2 +- ZodiacFX/src/http.h | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ZodiacFX/src/flash.c b/ZodiacFX/src/flash.c index 4af40db..0e345c8 100644 --- a/ZodiacFX/src/flash.c +++ b/ZodiacFX/src/flash.c @@ -8,7 +8,7 @@ /* * This file is part of the Zodiac FX firmware. - * Copyright (c) 2016 Northbound Networks. + * Copyright (c) 2016 Google Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/ZodiacFX/src/flash.h b/ZodiacFX/src/flash.h index a242c9e..06f1fde 100644 --- a/ZodiacFX/src/flash.h +++ b/ZodiacFX/src/flash.h @@ -8,7 +8,7 @@ /* * This file is part of the Zodiac FX firmware. - * Copyright (c) 2016 Northbound Networks. + * Copyright (c) 2016 Google Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/ZodiacFX/src/http.c b/ZodiacFX/src/http.c index 5a0dafb..27d5d00 100644 --- a/ZodiacFX/src/http.c +++ b/ZodiacFX/src/http.c @@ -8,7 +8,7 @@ /* * This file is part of the Zodiac FX firmware. - * Copyright (c) 2016 Northbound Networks. + * Copyright (c) 2016 Google Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/ZodiacFX/src/http.h b/ZodiacFX/src/http.h index 78aadb2..a2eb700 100644 --- a/ZodiacFX/src/http.h +++ b/ZodiacFX/src/http.h @@ -8,7 +8,7 @@ /* * This file is part of the Zodiac FX firmware. - * Copyright (c) 2016 Northbound Networks. + * Copyright (c) 2016 Google Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,7 +23,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * Author: Paul Zanna + * Authors: Paul Zanna + * & Kristopher Chen * */