Merge pull request #36 from logicog/config

System settings and configuration management
This commit is contained in:
René van Dorst
2025-12-01 19:22:03 +00:00
committed by GitHub
18 changed files with 796 additions and 76 deletions
+88 -8
View File
@@ -5,9 +5,6 @@
// #define DEBUG // #define DEBUG
// #define REGDBG 1 // #define REGDBG 1
#define CONFIG_START 0x70000
#define CONFIG_LEN 0x1000
#include "rtl837x_common.h" #include "rtl837x_common.h"
#include "rtl837x_port.h" #include "rtl837x_port.h"
#include "rtl837x_flash.h" #include "rtl837x_flash.h"
@@ -38,6 +35,8 @@ extern __code uint8_t * __code hex;
extern __xdata uint8_t flash_buf[512]; extern __xdata uint8_t flash_buf[512];
extern __xdata struct flash_region_t flash_region; extern __xdata struct flash_region_t flash_region;
extern __xdata char passwd[21];
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
__xdata uint16_t vlan_ptr; __xdata uint16_t vlan_ptr;
__xdata uint8_t gpio_last_value[8] = { 0 }; __xdata uint8_t gpio_last_value[8] = { 0 };
@@ -54,12 +53,16 @@ __xdata uint8_t cmd_available;
__xdata uint8_t l; __xdata uint8_t l;
__xdata uint8_t line_ptr; __xdata uint8_t line_ptr;
__xdata char is_white; __xdata char is_white;
__xdata char save_cmd;
__xdata uint8_t ip[4]; __xdata uint8_t ip[4];
#define N_WORDS SBUF_SIZE #define N_WORDS SBUF_SIZE
__xdata signed char cmd_words_b[N_WORDS]; __xdata signed char cmd_words_b[N_WORDS];
__xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
__xdata uint16_t cmd_history_ptr;
// Maps the physical port (starting from 0) to the logical port // Maps the physical port (starting from 0) to the logical port
__code uint8_t phys_to_log_port[6] = { __code uint8_t phys_to_log_port[6] = {
4, 5, 6, 7, 3, 8 4, 5, 6, 7, 3, 8
@@ -431,6 +434,36 @@ err:
} }
void parse_rnd(void)
{
// In order to get a new random numner, this bit has to be set each time!
reg_bit_set(RTL837X_RLDP_RLPP, RLDP_RND_EN);
reg_read_m(RTL837X_RAND_NUM1);
print_byte(sfr_data[2]);
print_byte(sfr_data[3]);
reg_read_m(RTL837X_RAND_NUM0);
print_byte(sfr_data[0]);
print_byte(sfr_data[1]);
print_byte(sfr_data[2]);
print_byte(sfr_data[3]);
write_char('\n');
}
void parse_passwd(void)
{
if (cmd_words_b[2] > 0) {
signed char i;
signed char j = 0;
for (i = cmd_words_b[1]; (i != cmd_words_b[2] && i - cmd_words_b[1] < 20); i++)
passwd[j++] = cmd_buffer[i];
passwd[j] = '\0';
return;
}
print_string("Missing password\n");
}
// Parse command into words // Parse command into words
uint8_t cmd_tokenize(void) __banked uint8_t cmd_tokenize(void) __banked
{ {
@@ -679,6 +712,12 @@ void cmd_parser(void) __banked
if (cmd_compare(0, "regset")) { if (cmd_compare(0, "regset")) {
parse_regset(); parse_regset();
} }
if (cmd_compare(0, "rnd")) {
parse_rnd();
}
if (cmd_compare(0, "passwd")) {
parse_passwd();
}
if (cmd_compare(0, "eee")) { if (cmd_compare(0, "eee")) {
int8_t port = -1; int8_t port = -1;
if (cmd_words_b[3] > 0) { if (cmd_words_b[3] > 0) {
@@ -706,17 +745,51 @@ void cmd_parser(void) __banked
if (cmd_compare(0, "version")) { if (cmd_compare(0, "version")) {
print_sw_version(); print_sw_version();
} }
if (cmd_compare(0, "history")) {
__xdata uint16_t p = (cmd_history_ptr + 1) & CMD_HISTORY_MASK;
__xdata uint8_t found_begin = 0;
print_string("History ptr: ");
print_short(cmd_history_ptr); write_char('\n');
while (p != cmd_history_ptr) {
print_short(p); write_char(' ');
if (!cmd_history[p] || cmd_history[p] == '\n')
found_begin = 1;
if (found_begin && cmd_history[p])
write_char(cmd_history[p]);
p = (p + 1) & CMD_HISTORY_MASK;
}
}
if (save_cmd) {
uint8_t i;
for (i = 0; i < N_WORDS; i++) {
if (cmd_words_b[i] < 0)
break;
}
if (i < N_WORDS) {
i = cmd_words_b[--i];
cmd_history_ptr = (cmd_history_ptr + i) & CMD_HISTORY_MASK;
__xdata uint16_t p = cmd_history_ptr;
cmd_history[cmd_history_ptr++] = '\n';
do {
i--;
cmd_history[--p & CMD_HISTORY_MASK] = cmd_buffer[i];
} while (i);
}
}
} }
} }
#define FLASH_READ_BURST_SIZE 0x100; #define FLASH_READ_BURST_SIZE 0x100
#define PASSWORD "1234"
void execute_config(void) __banked void execute_config(void) __banked
{ {
memcpyc(flash_buf, "test", 5);
print_string_x(flash_buf);
__xdata uint32_t pos = CONFIG_START; __xdata uint32_t pos = CONFIG_START;
__xdata uint16_t len_left = CONFIG_LEN; __xdata uint16_t len_left = CONFIG_LEN;
// Set default password, it can be overwritten in the configuration file
strtox(passwd, PASSWORD);
save_cmd = 0;
do { do {
flash_region.addr = pos; flash_region.addr = pos;
flash_region.len = FLASH_READ_BURST_SIZE; flash_region.len = FLASH_READ_BURST_SIZE;
@@ -737,7 +810,7 @@ void execute_config(void) __banked
if (cmd_idx && !cmd_tokenize()) if (cmd_idx && !cmd_tokenize())
cmd_parser(); cmd_parser();
if (c == 0) if (c == 0)
return; goto config_done;
break; break;
} }
@@ -749,4 +822,11 @@ void execute_config(void) __banked
len_left -= FLASH_READ_BURST_SIZE; len_left -= FLASH_READ_BURST_SIZE;
pos += FLASH_READ_BURST_SIZE; pos += FLASH_READ_BURST_SIZE;
} while(len_left); } while(len_left);
config_done:
// Start saving commands to cmd_history
save_cmd = 1;
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
cmd_history[cmd_history_ptr] = 0;
cmd_history_ptr = 0;
} }
+1
View File
@@ -0,0 +1 @@
../config.txt
+55
View File
@@ -0,0 +1,55 @@
var configInterval = Number();
var configuration = [];
const conf_cmds = [
/ip\s+(\d{1,3}\.){3}\d{1,3}/, /gw\s+(\d{1,3}\.){3}\d{1,3}/, /netmask\s+(\d{1,3}\.){3}\d{1,3}/,
/eee(\s+\d)?\s+(on|off)/, /mirror(\s+(\d|10))(\s+(\d|10)(t|r)?)+/, /vlan\s+(\d{1,4})(\s+(\d|10)(t|u)?)+/
];
const conf_overwrite = [
/ip/, /gw/, /netmask/, /eee\s+\w+/, /eee(\s+\w)/, /mirror/, /vlan\s+(\d{1,4})/
];
function parseConf(s){
var a = s.split(/\r\n|\n/);
for (var l = 0; l < a.length; l++) {
if (!a[l].length || a[l] == "\n" || a[l] == "\r\n")
continue;
console.log(l + ' --> ' + a[l]);
var ignore = true;
for (const x of conf_cmds)
if (x.test(a[l])) ignore = false;
if (ignore) continue;
for (const x of conf_overwrite) {
if (x.test(a[l])) {
console.log("Match ", x, " to ", a[l]);
m = a[l].match(x);
console.log("Starts with ", m[0]);
configuration = configuration.filter(item => !(item.startsWith(m[0])));
}
}
configuration.push(a[l]);
}
console.log("Configuration now:");
for (const x of configuration) { console.log(x); }
}
async function fetchConfig() {
try {
const response = await fetch('/config');
console.log("CONFIG: ", response);
const t = await response.text();
return t;
} catch(err) {
console.error("Error: ", err);
}
}
async function fetchCmdLog() {
try {
const response = await fetch('/cmd_log');
console.log("CMD-Log: ", response);
const t = await response.text();
return t;
} catch(error) {
console.error("Error: ", err);
}
}
+30
View File
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<title>RTL Switch Login</title>
<link rel="stylesheet" href="style.css">
<script>
function removeNote() {
document.getElementById("incorrect").innerHTML = "";
}
window.addEventListener("load", function() {
if (document.referrer.endsWith("login.html"))
document.getElementById("incorrect").innerHTML = "Wrong password!";
});
</script>
</head>
<body class="login_page">
<div class = "center">
<h1> RTL Switch Login</h1>
<form method="post" action="login">
<div class="txt_field">
<input name="pwd" type="password" onclick="removeNote()" required />
<span></span>
<label>Password</label>
</div>
<input type="submit" value="Login"/>
<h3 id="incorrect" style="margin-top: 5em;"></h3>
</form>
</body>
</html>
+2
View File
@@ -10,6 +10,8 @@ var numPorts = 0;
function update() { function update() {
var xhttp = new XMLHttpRequest(); var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() { xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 401)
document.location = "/login.html"
if (this.readyState == 4 && this.status == 200) { if (this.readyState == 4 && this.status == 200) {
const s = JSON.parse(xhttp.responseText); const s = JSON.parse(xhttp.responseText);
if (!numPorts) { if (!numPorts) {
+1
View File
@@ -5,5 +5,6 @@ document.getElementById('sidebar').innerHTML =
+ "<li><a href='mirror.html'>Mirroring</a></li>" + "<li><a href='mirror.html'>Mirroring</a></li>"
+ "<li><a href='trunk.html'>Port Aggregation</a></li>" + "<li><a href='trunk.html'>Port Aggregation</a></li>"
+ "<li><a href='eee.html'>EEE</a></li>" + "<li><a href='eee.html'>EEE</a></li>"
+ "<li><a href='system.html'>System Settings</a></li>"
+ "<li><a href='update.html'>Firmware Update</a></li></ul>"; + "<li><a href='update.html'>Firmware Update</a></li></ul>";
+48 -4
View File
@@ -1,4 +1,4 @@
h1, h2 { h1, h2, h3 {
color: #226; color: #226;
} }
ul { ul {
@@ -38,10 +38,17 @@ td {
text-align: right; text-align: right;
} }
input[type=submit] { padding: 8px 16px;background-color:#aaf;color:#000; margin-bottom: 2em;} input[type=submit] { padding: 8px 16px;background-color:#aaf;color:#000; margin-bottom: 2em;border-radius: 15px;width: 100%;}
input[type=submit]:hover { background-color: #226; color: white;} input[type=submit]:hover { background-color: #226; color: white;}
button {padding: 8px; background-color:#99f; color:#000;} input[type=file] { padding: 8px 16px;background-color:#aaf;color:#000; margin-bottom: 2em;border-radius: 15px;width: 60%;}
input[type=file]:hover { background-color: #226; color: white;}
b
button {padding: 8px; background-color:#99f; color:#000;border-radius: 15px;}
button:hover { background-color: #226; color: white;} button:hover { background-color: #226; color: white;}
.action{padding: 8px 16px;margin-top: 2em;margin-right: 3em; background-color: #aaf;color: #000;border-radius: 15px; width: 100%;}
.action:hover { background-color: #226; color: white;}
/* Port selection inputs */
.psel { .psel {
position: absolute; position: absolute;
opacity: 0; opacity: 0;
@@ -73,4 +80,41 @@ object {
.isSFP{ opacity: .4; background-color: #660;} .isSFP{ opacity: .4; background-color: #660;}
.isNOK{ color: #900;} .isNOK{ color: #900;}
.isOK{ color: #090;} .isOK{ color: #090;}
.action{padding: 8px 16px;margin-top: 2em;margin-right: 3em; background-color: #aaf;color: #000;} .ip{padding:8px 16px;margin-bottom: 1em;margin-left: 1em}
.row {display: flex;}
.rcol {flex: 90%;}
.lcol {flex: 10%;}
span::before{ content:''; position: absolute; top: 40px; left:0; width: 100%; height: 2px; background: #aaf;}
/* Login page */
.login_page {margin: 0; padding: 0; background: #aaf; height: 100vh; overflow: hidden;}
.center{
position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -40% );
width: 500px; height: 400px;
background: white;
border-radius: 2px;
}
.center h1 {
text-align: center;
border-bottom: 1px solid silver;
}
.center form {
padding: 0 60px;
box-sizing: border-box;
}
form .txt_field{
position: relative;
border-bottom: 2px solid #adadad;
margin: 30px 0;
}
.txt_field input { width: 100%; padding: 0 5px; height: 40px; font-size: 16px; border: none;
background: none;
outline: none;}
.txt_field label { position: absolute; top: 50%; left: 5px; color:#adadad; transform: translateY(-50%);
font-size: 16px; pointer-events: none;transition: .5s; }
.txt_field span::before{ content:''; position: absolute; top: 40px; left:0; width: 100%; height: 2px; background: #aaf;}
.txt_field input:focus ~ label,
.txt_field input:valid ~ label { top: -5px; color: #aaf; }
+36
View File
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<title>System Settings</title>
</head>
<body>
<nav id="sidebar"></nav>
<div style="margin-left:16%;padding:1px 16px;height:1000px;">
<div id="ports"></div>
<h1>System Settings</h1>
<div class="row">
<div class="lcol"> <label for="ip">IP address:</label></div>
<div class="rcol"> <input id="ip" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
</div>
<div class="row">
<div class="lcol"> <label for="netmask">Netmask:</label></div>
<div class="rcol"><input id="netmask" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
</div>
<div class="row">
<div class="lcol"> <label for="gw">Gateway:</label></div>
<div class="rcol"><input id="gw" class="ip" type="text" minlength="7" maxlength="15" size="15"/></div>
</div>
<br/><br/>
When updating the above settings, remember to point your browser to the new IP afterwards:<br/>
<input style="width:40%;" class="action" id="ip_sub" onclick="ipSub();" type="button" value="Update Settings"><br/>
<br/><br/>
Save all current settings to Flash:<br/>
<input style="width:40%;" class="action" id="flash_sub" onclick="flashSave();" type="button" value="Save Settings to Flash">
</div>
<script src="/config.js"></script>
<script src="/system.js"></script>
<script src="/navigation.js"></script>
</body>
</html>
+76
View File
@@ -0,0 +1,76 @@
var systemInterval = Number();
const ips = ["ip", "netmask", "gw"];
function checkIp(ip) {
const ipv4 = /^(\d{1,3}\.){3}\d{1,3}$/;
if (!ipv4.test(ip)) {alert(`Invalid ip:${ip}`); return false };
return true;
}
async function ipSub() {
for (let i=0;i<3;i++) {
if (!checkIp(document.getElementById(ips[i]).value))
return;
}
for (let i=0; i<3;i++){
var cmd = ips[i]+' '+document.getElementById(ips[i]).value;
try {
const response = await fetch('/cmd', {
method: 'POST',
body: cmd
});
console.log('Completed!', response);
fetchIP();
} catch(err) {
console.error(`Error: ${err}`);
}
}
}
async function sendConfig(c) {
const form = new FormData();
form.append("MAX_FILE_SIZE", "4096");
form.append("configuration", new Blob([c], {type: "application/octet-stream"}));
try {
const response = await fetch('/config', {
method: 'POST',
body: form
});
console.log('Completed!', response);
} catch(err) {
console.error(`Error: ${err}`);
}
}
async function flashSave() {
fetchConfig().then((s) => {
parseConf(s);
fetchCmdLog().then((s) => {
parseConf(s);
var body = "";
for (const x of configuration) { body = body + x + "\n"; }
console.log("CONFIGURATION to save: ", body);
sendConfig(body);
});
});
}
function fetchIP() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const s = JSON.parse(xhttp.responseText);
console.log("IP: ", s);
document.getElementById("ip").value=s.ip_address;
document.getElementById("netmask").value=s.ip_netmask;
document.getElementById("gw").value=s.ip_gateway;
clearInterval(systemInterval);
}
}
xhttp.open("GET", `/information.json`, true);
xhttp.send();
}
window.addEventListener("load", function() {
systemInterval = setInterval(fetchIP, 1000);
});
+4 -4
View File
@@ -6,13 +6,13 @@
</head> </head>
<body> <body>
<nav id="sidebar"></nav> <nav id="sidebar"></nav>
<div style="margin-left:16%;padding:1px 16px;height:1000px;"> <div style="margin-left:16%;padding:1px 16px;height:1000px;width:40%;">
<div id="ports"></div>
<h1>Firmware Update</h1> <h1>Firmware Update</h1>
<form enctype="multipart/form-data" action="/upload" method="POST"> <form enctype="multipart/form-data" action="/upload" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" /> <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
Choose a firmware update file to upload: <input name="uploadedfile" type="file" accept=".bin" /><br /> Choose a firmware update file to upload: <br/> <br/>
<input type="submit" value="Upload File" /> <input name="uploadedfile" type="file" accept=".bin" /><br />
<input style="margin-top:3em" type="submit" value="Upload File" />
</form> </form>
<script src="/navigation.js"></script> <script src="/navigation.js"></script>
</body> </body>
+154 -9
View File
@@ -2,11 +2,15 @@
#include "httpd.h" #include "httpd.h"
#include "page_impl.h" #include "page_impl.h"
#include "../rtl837x_common.h" #include "../rtl837x_common.h"
#include "../rtl837x_regs.h"
#include "../cmd_parser.h" #include "../cmd_parser.h"
#include "../rtl837x_flash.h" #include "../rtl837x_flash.h"
#include "uip.h" #include "uip.h"
#include "../html_data.h" #include "../html_data.h"
#define SESSION_ID_LENGTH 12
#define SESSION_TIMEOUT 200
// Upload Firmware to 1M // Upload Firmware to 1M
#define FIRMWARE_UPLOAD_START 0x100000 #define FIRMWARE_UPLOAD_START 0x100000
@@ -18,6 +22,8 @@
#pragma codeseg BANK1 #pragma codeseg BANK1
#pragma constseg BANK1 #pragma constseg BANK1
extern volatile __xdata uint8_t sfr_data[4];
extern __code uint8_t * __code hex;
extern __code struct f_data f_data[]; extern __code struct f_data f_data[];
extern __code char * __code mime_strings[]; extern __code char * __code mime_strings[];
extern __xdata struct flash_region_t flash_region; extern __xdata struct flash_region_t flash_region;
@@ -33,16 +39,27 @@ __xdata uint16_t slen;
__xdata uint16_t o_idx; __xdata uint16_t o_idx;
__xdata uint16_t mpos; __xdata uint16_t mpos;
__xdata uint16_t len_left; __xdata uint16_t len_left;
__xdata uint16_t cont_len;
__xdata uint32_t cont_addr;
// HTTP header properties // HTTP header properties
__xdata uint8_t boundary[72]; __xdata uint8_t boundary[72];
__xdata uint8_t *content_type = 0; __xdata uint8_t *content_type = 0;
__xdata uint8_t *session = 0;
// Global variables holding POST state // Global variables holding POST state
__xdata uint16_t bindex; // Current index into the boundary __xdata uint16_t bindex; // Current index into the boundary
__xdata uint8_t verify_crc;
__xdata uint32_t max_upload;
__xdata uint16_t short_parsed; __xdata uint16_t short_parsed;
__xdata char passwd[21];
__xdata char session_id[SESSION_ID_LENGTH + 1];
__xdata uint8_t authenticated;
__xdata uint32_t now;
__xdata uint8_t *timeptr;
__xdata uint32_t last_session_use;
#define TSTATE_NONE 0 #define TSTATE_NONE 0
#define TSTATE_TX 1 #define TSTATE_TX 1
#define TSTATE_ACKED 2 #define TSTATE_ACKED 2
@@ -161,6 +178,19 @@ void send_bad_request(void)
} }
void send_to_login(void)
{
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\n" \
"Location: login.html\r\n\r\n");
}
void send_unauthorized(void)
{
slen = strtox(outbuf, "HTTP/1.1 401 Unauthorized\r\n\r\n");
}
__xdata uint8_t *skip_boundary(__xdata uint8_t *p) __xdata uint8_t *skip_boundary(__xdata uint8_t *p)
{ {
while (*p) { while (*p) {
@@ -175,6 +205,8 @@ __xdata uint8_t *skip_boundary(__xdata uint8_t *p)
__xdata uint8_t *scan_header(__xdata uint8_t *p) __xdata uint8_t *scan_header(__xdata uint8_t *p)
{ {
content_type = 0; content_type = 0;
session = 0;
authenticated = 0;
while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') { while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') {
write_char(*p); write_char(*p);
@@ -182,9 +214,11 @@ __xdata uint8_t *scan_header(__xdata uint8_t *p)
break; break;
if (is_word(p, "\nContent-Type:")) if (is_word(p, "\nContent-Type:"))
content_type = p + 15; content_type = p + 15;
else if (is_word(p, "\nCookie:"))
session = p + 17;
} }
if (content_type && is_word(content_type, "multipart/form-data; boundary")) { if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
print_string("\nFound multiplart\n"); print_string("\nFound multipart\n");
content_type += 30; content_type += 30;
uint8_t i = 0; uint8_t i = 0;
while (content_type[i] != '\r' && content_type[i] != '\n') { while (content_type[i] != '\r' && content_type[i] != '\n') {
@@ -198,10 +232,37 @@ __xdata uint8_t *scan_header(__xdata uint8_t *p)
boundary[3] = '-'; boundary[3] = '-';
boundary[i + 4] = 0; boundary[i + 4] = 0;
} }
read_reg_timer(&now);
if (session) {
if (now - last_session_use > SESSION_TIMEOUT) {
print_string("Session expired\n");
} else {
if (is_word_x(session, session_id))
authenticated = 1;
else
print_string("Invalid session cookie!\n");
}
}
return p; return p;
} }
void gen_random_bytes(__xdata uint8_t *b, uint8_t bytes)
{
__xdata uint8_t i = 0;
while (bytes) {
if (!i)
get_random_32();
b[--bytes] = itohex(sfr_data[i]);
if (!bytes) { break; }
b[--bytes] = itohex(sfr_data[i] >> 4 | sfr_data[i] << 4);
i = (i + 1) & 0x3;
}
}
/* /*
* Reads post data from the http stream and writes it into flash memory * Reads post data from the http stream and writes it into flash memory
* Input: the current position in the TCP buffer (uip_appdata) * Input: the current position in the TCP buffer (uip_appdata)
@@ -230,6 +291,7 @@ uint8_t stream_upload(uint16_t bptr)
uptr += write_len; uptr += write_len;
write_len = 0; write_len = 0;
// TODO: This is a bit premature, what about a nice web-page saying the device will reset??? // TODO: This is a bit premature, what about a nice web-page saying the device will reset???
if (verify_crc) {
print_string("CRC16: "); print_short(crc_final); write_char('\n'); print_string("CRC16: "); print_short(crc_final); write_char('\n');
if (crc_final == 0xb001) { if (crc_final == 0xb001) {
print_string("Checksum OK."); print_string("Checksum OK.");
@@ -238,6 +300,12 @@ uint8_t stream_upload(uint16_t bptr)
} }
print_string("Upload to flash done, will reset!\n"); print_string("Upload to flash done, will reset!\n");
reset_chip(); reset_chip();
}
// Make sure there is a 0 at the end of the uploaded data
flash_buf[0] = 0;
flash_region.addr = uptr;
flash_region.len = 1;
flash_write_bytes(flash_buf);
if (bptr >= uip_len) if (bptr >= uip_len)
return 0; return 0;
return 1; return 1;
@@ -302,13 +370,38 @@ void handle_post(void)
if (is_word(request_path, "cmd")) { if (is_word(request_path, "cmd")) {
register uint8_t i = 0; register uint8_t i = 0;
p += 4; p += 4;
if (!authenticated) {
send_unauthorized();
return;
}
while (*p && *p != '\n' && *p != '\r') while (*p && *p != '\n' && *p != '\r')
cmd_buffer[i++] = *p++; cmd_buffer[i++] = *p++;
cmd_buffer[i] = '\0'; cmd_buffer[i] = '\0';
if (i) if (i)
cmd_available = 1; cmd_available = 1;
} else if (is_word(request_path, "upload")) { } else if (is_word(request_path, "login")) {
print_string("POST upload request\n"); print_string("POST login\n");
p += 8; // Read also over "pwd="
if (is_word_x(p, passwd)) {
print_string("Password accepted!\n");
read_reg_timer(&last_session_use);
gen_random_bytes(session_id, SESSION_ID_LENGTH);
session_id[SESSION_ID_LENGTH] = '\0';
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nLocation: index.html\r\n" \
"Set-Cookie: session=");
for (register uint8_t i = 0; i < SESSION_ID_LENGTH; i++)
outbuf[slen++] = session_id[i];
slen += strtox(outbuf + slen, "; SameSite=Strict\r\n\r\n");
} else {
slen = strtox(outbuf, "HTTP/1.1 302 Found\r\nLocation: login.html\r\n\r\n");
}
return;
} else if (is_word(request_path, "upload") || is_word(request_path, "config")) {
print_string("POST upload/config request\n");
if (!authenticated) {
send_unauthorized();
return;
}
if (!boundary[0]) { if (!boundary[0]) {
print_string("Bad request, no boundary!\n"); print_string("Bad request, no boundary!\n");
send_bad_request(); send_bad_request();
@@ -328,7 +421,18 @@ void handle_post(void)
print_string("Have content octets\n"); print_string("Have content octets\n");
p += 4; // Skip \r\n\r\n sequence at end of preamble of part p += 4; // Skip \r\n\r\n sequence at end of preamble of part
if (is_word(request_path, "upload")) {
uptr = FIRMWARE_UPLOAD_START; uptr = FIRMWARE_UPLOAD_START;
verify_crc = 1;
max_upload = 1024576;
} else {
print_string("Configuration upload, erasing config mem!\n");
uptr = CONFIG_START;
verify_crc = 0;
max_upload = 2048;
flash_region.addr = CONFIG_START;
flash_sector_erase();
}
crc_value = 0; crc_value = 0;
bindex = 0; bindex = 0;
write_len = 0; write_len = 0;
@@ -386,17 +490,34 @@ void httpd_appcall(void)
if (slen > uip_mss()) { if (slen > uip_mss()) {
print_string("Sending A: "); print_short(slen); write_char('\n'); print_string("Sending A: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, uip_mss()); uip_send(outbuf + o_idx, uip_mss());
print_string("Sending A done\n");
s->tstate = TSTATE_TX; s->tstate = TSTATE_TX;
} else if (slen > 0) { } else if (slen > 0) {
print_string("Sending B: "); print_short(slen); write_char('\n'); print_string("Sending B: "); print_short(slen); write_char('\n');
uip_send(outbuf + o_idx, slen); uip_send(outbuf + o_idx, slen);
print_string("Sending B done\n"); s->tstate = TSTATE_TX;
} else if (cont_len) {
print_string("CONT cont_len: "); print_short(cont_len);
slen = cont_len > uip_mss() ? uip_mss() : cont_len;
if (slen > TCP_OUTBUF_SIZE)
slen = TCP_OUTBUF_SIZE;
flash_region.addr = cont_addr;
flash_region.len = slen;
flash_read_bulk(outbuf);
uip_send(outbuf, slen);
cont_len -= slen;
cont_addr += slen;
s->tstate = TSTATE_TX; s->tstate = TSTATE_TX;
} }
} else if (uip_newdata() && s->tstate == TSTATE_POST) { } else if (uip_newdata() && s->tstate == TSTATE_POST) {
// Check here maxupload by subtracting uip_len and close socekt if fails!
if (max_upload - uip_len > 0) {
stream_upload(0); stream_upload(0);
} else {
send_bad_request();
goto do_send;
}
} else if (uip_newdata() && s->tstate != TSTATE_TX) { } else if (uip_newdata() && s->tstate != TSTATE_TX) {
cont_len = 0;
write_char('<'); print_short(uip_len); write_char('\n'); write_char('<'); print_short(uip_len); write_char('\n');
__xdata uint8_t *p = uip_appdata; __xdata uint8_t *p = uip_appdata;
// Mark end of request header with \0 // Mark end of request header with \0
@@ -418,6 +539,7 @@ void httpd_appcall(void)
if (is_word(p, "GET")) if (is_word(p, "GET"))
print_string("GET request "); print_string("GET request ");
p += 4; p += 4;
scan_header(p);
__xdata uint8_t *q = p; __xdata uint8_t *q = p;
while (!is_separator(*p)) while (!is_separator(*p))
p++; p++;
@@ -429,6 +551,11 @@ void httpd_appcall(void)
entry = find_entry(q); entry = find_entry(q);
print_string("Entry is: "); print_byte(entry); write_char('\n'); print_string("Entry is: "); print_byte(entry); write_char('\n');
if (entry == 0xff) { if (entry == 0xff) {
if (!authenticated) {
print_string("Not authorized!\n");
send_unauthorized();
goto do_send;
}
print_string("Not file entry\n"); print_string("Not file entry\n");
if (!strcmp(q, "/status.json")) { if (!strcmp(q, "/status.json")) {
send_status(); send_status();
@@ -443,16 +570,34 @@ void httpd_appcall(void)
send_eee(); send_eee();
} else if (is_word(q, "/mirror.json")) { } else if (is_word(q, "/mirror.json")) {
send_mirror(); send_mirror();
} else if (is_word(q, "/config")) {
send_config();
} else if (is_word(q, "/cmd_log")) {
send_cmd_log();
} else { } else {
send_not_found(); send_not_found();
} }
} else { } else {
print_string("Have entry\n"); print_string("Have entry, authenticated: "); print_byte(authenticated); write_char('\n');
if (!authenticated && !(f_data[entry].start == FDATA_START_login_html
|| f_data[entry].start == FDATA_START_style_css)) {
send_to_login();
goto do_send;
}
// A web-page is actively accessed, we can reset session time-out
reg_read_m(RTL837X_REG_SEC_COUNTER);
timeptr = (uint8_t*)&last_session_use; // last_session_use is Little endian
timeptr[0] = sfr_data[3]; timeptr[1] = sfr_data[2]; timeptr[2] = sfr_data[1]; timeptr[3] = sfr_data[0];
slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: "); slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: ");
slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]); slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]);
slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=2592000\r\n\r\n"); slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=60, must-revalidate\r\n\r\n");
len_left = f_data[entry].len; len_left = f_data[entry].len;
if (len_left > (TCP_OUTBUF_SIZE - slen)) {
cont_len = len_left - (TCP_OUTBUF_SIZE - slen);
len_left = TCP_OUTBUF_SIZE - slen;
cont_addr = f_data[entry].start + len_left;
}
print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n');
flash_region.addr = f_data[entry].start; flash_region.addr = f_data[entry].start;
flash_region.len = len_left; flash_region.len = len_left;
+53 -15
View File
@@ -4,17 +4,21 @@
#include "../rtl837x_common.h" #include "../rtl837x_common.h"
#include "../rtl837x_regs.h" #include "../rtl837x_regs.h"
#include "../rtl837x_port.h" #include "../rtl837x_port.h"
#include "../rtl837x_flash.h"
#include "uip.h" #include "uip.h"
#include "../html_data.h" #include "../html_data.h"
#include <stdint.h> #include <stdint.h>
#include "../phy.h" #include "../phy.h"
#include "../version.h" #include "../version.h"
#include "page_impl.h"
#pragma codeseg BANK1 #pragma codeseg BANK1
#pragma constseg BANK1 #pragma constseg BANK1
extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE];
extern __xdata uint16_t slen; extern __xdata uint16_t slen;
extern __xdata uint16_t cont_len;
extern __xdata uint32_t cont_addr;
extern __code uint8_t * __code hex; extern __code uint8_t * __code hex;
extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
extern __code struct uip_eth_addr uip_ethaddr; extern __code struct uip_eth_addr uip_ethaddr;
@@ -30,22 +34,13 @@ extern __xdata uint8_t isRTL8373;
extern __xdata uint8_t sfp_pins_last; extern __xdata uint8_t sfp_pins_last;
extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
extern __xdata uint8_t cmd_history[CMD_HISTORY_SIZE];
extern __xdata uint16_t cmd_history_ptr;
extern __xdata struct flash_region_t flash_region;
__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"; __code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n";
__code uint8_t * __code HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
/* Convert only the lower nibble to ascii HEX char.
For convenience the upper nibble is masked out.
*/
inline char itohex(uint8_t val) {
// Ignore upper nibble for convenience.
val &= 0x0f;
val -= 10;
// 10 or above
if ((int8_t)val >= 0)
val += ('a' - '0' - 10);
return val + ('0' + 10);
}
// Convert uint8_t to ascii HEX char push on html-buffer. // Convert uint8_t to ascii HEX char push on html-buffer.
void charhex_to_html(char c) void charhex_to_html(char c)
@@ -371,3 +366,46 @@ void send_status(void)
char_to_html(']'); char_to_html(']');
} }
} }
void send_config(void)
{
print_string("send_config called\n");
__xdata uint32_t pos = CONFIG_START; // 70000 , 6c000 / 0xc000 = 9
extern __xdata uint16_t len_left = CONFIG_LEN;
slen = strtox(outbuf, HTTP_RESPONCE_TXT);
while (read_flash((CONFIG_START-CODE0_SIZE) / CODE_BANK_SIZE + 1,
(__code uint8_t *) (((CONFIG_START + len_left - CODE0_SIZE) % CODE_BANK_SIZE) + CODE0_SIZE + len_left)) == 0xff) {
print_short(len_left);
len_left--;
}
len_left++;
if (len_left > (TCP_OUTBUF_SIZE - slen)) {
cont_len = len_left - (TCP_OUTBUF_SIZE - slen);
len_left = TCP_OUTBUF_SIZE - slen;
cont_addr = len_left;
}
flash_region.addr = CONFIG_START;
flash_region.len = len_left;
flash_read_bulk(outbuf + slen);
slen += len_left;
}
void send_cmd_log(void)
{
print_string("send_cmd_log called\n");
slen = strtox(outbuf, HTTP_RESPONCE_TXT);
__xdata uint16_t p = (cmd_history_ptr + 1) & CMD_HISTORY_MASK;
__xdata uint8_t found_begin = 0;
print_string("History ptr: ");
print_short(cmd_history_ptr); write_char('\n');
while (p != cmd_history_ptr) {
if (!cmd_history[p] || cmd_history[p] == '\n')
found_begin = 1;
if (found_begin && cmd_history[p])
outbuf[slen++] = cmd_history[p];
p = (p + 1) & CMD_HISTORY_MASK;
}
}
+18 -1
View File
@@ -3,9 +3,26 @@
void send_counters(char port); void send_counters(char port);
void send_status(void); void send_status(void);
void send_vlan(register uint16_t vlan); void send_vlan(uint16_t vlan);
void send_basic_info(void); void send_basic_info(void);
void send_eee(void); void send_eee(void);
void send_mirror(void); void send_mirror(void);
void send_config(void);
void send_cmd_log(void);
/* Convert only the lower nibble to ascii HEX char.
For convenience the upper nibble is masked out.
*/
inline char itohex(uint8_t val) {
// Ignore upper nibble for convenience.
val &= 0x0f;
val -= 10;
// 10 or above
if ((int8_t)val >= 0)
val += ('a' - '0' - 10);
return val + ('0' + 10);
}
#endif #endif
+12 -1
View File
@@ -47,6 +47,15 @@
#define IS_SFP(port) (i == maxPort || i == 3) #define IS_SFP(port) (i == maxPort || i == 3)
#endif #endif
#define CONFIG_START 0x70000
#define CONFIG_LEN 0x1000
#define CODE0_SIZE 0x4000
#define CODE_BANK_SIZE 0xc000
// Constants for the circular command buffer, the size must be 2^n
#define CMD_HISTORY_SIZE 0x400
#define CMD_HISTORY_MASK (CMD_HISTORY_SIZE - 1)
/** /**
* Representation of a 48-bit Ethernet address. * Representation of a 48-bit Ethernet address.
*/ */
@@ -94,6 +103,8 @@ uint16_t strlen_x(register __xdata const char *s);
uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s); uint16_t strtox(register __xdata uint8_t *dst, register __code const char *s);
void tcpip_output(void); void tcpip_output(void);
void print_string_x(__xdata char *p); void print_string_x(__xdata char *p);
uint8_t read_flash(uint8_t bank, __code uint8_t *addr);
void get_random_32(void);
void read_reg_timer(uint32_t * tmr);
#endif #endif
+7
View File
@@ -170,6 +170,13 @@
#define EEE_1000 0x04 #define EEE_1000 0x04
#define EEE_2G5 0x10 #define EEE_2G5 0x10
/*
* RANDOM
*/
#define RTL837X_RLDP_RLPP 0x106C
#define RLDP_RND_EN 3
#define RTL837X_RAND_NUM0 0x107C
#define RTL837X_RAND_NUM1 0x1080
#ifdef REGDBG #ifdef REGDBG
+26
View File
@@ -402,6 +402,18 @@ void sfr_set_zero(void) {
} }
} }
/*
* Create 32 random number in sfr_data
*/
void get_random_32(void)
{
// In order to get a new random numner, this bit has to be set each time!
reg_bit_set(RTL837X_RLDP_RLPP, RLDP_RND_EN);
reg_read_m(RTL837X_RAND_NUM0);
}
/* /*
* Transfer Network Interface RX data from the ASIC to the 8051 XMEM * Transfer Network Interface RX data from the ASIC to the 8051 XMEM
* data will be stored in the rx_header structure * data will be stored in the rx_header structure
@@ -590,6 +602,20 @@ void cpy_4(__xdata uint8_t dest[], __xdata uint8_t source[])
} }
void read_reg_timer(uint32_t * tmr)
{
uint8_t * val = (uint8_t *)tmr;
SFR_REG_ADDR_U16 = RTL837X_REG_SEC_COUNTER;
SFR_EXEC_GO = SFR_EXEC_READ_REG;
do {
} while (SFR_EXEC_STATUS != 0);
*val++ = SFR_DATA_0;
*val++ = SFR_DATA_8;
*val++ = SFR_DATA_16;
*val = SFR_DATA_24;
}
void sds_config_mac(uint8_t sds, uint8_t mode) void sds_config_mac(uint8_t sds, uint8_t mode)
{ {
reg_read_m(RTL837X_REG_SDS_MODES); reg_read_m(RTL837X_REG_SDS_MODES);
+164 -13
View File
@@ -4,14 +4,20 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <time.h> #include <time.h>
#include "httpd_sim.h" #include "httpd_sim.h"
#include <json.h> #include <json.h>
#include <signal.h> #include <signal.h>
#include "../version.h" #include "../version.h"
#define SESSION_ID "1234567890ab"
#define PASSWORD "1234"
#define SESSION_TIMEOUT 20
#define PORTS 6 #define PORTS 6
time_t last_called; time_t last_called;
time_t last_session_use;
uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS]; uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS];
char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20]; char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20];
@@ -20,6 +26,12 @@ char upload_buffer[4194304]; // 4MB
char *content_type = NULL; char *content_type = NULL;
char boundary[72]; char boundary[72];
char cmd_history[1024][256];
uint16_t cmd_ptr = 0;
char *uploaded_config = NULL;
int uploaded_config_len;
const char *session = NULL;
bool authenticated = false;
char is_word(char *c, char *d) char is_word(char *c, char *d)
{ {
@@ -101,8 +113,10 @@ void send_status(int s)
struct json_object *ports, *v; struct json_object *ports, *v;
const char *jstring; const char *jstring;
char *header = "HTTP/1.1 200 OK\r\n" char *header = "HTTP/1.1 200 OK\r\n"
"Cache-Control: no-cache\r\n"
"Content-Type: application/json; charset=UTF-8\r\n\r\n"; "Content-Type: application/json; charset=UTF-8\r\n\r\n";
printf("Sending status.\n");
time_t now = time(NULL); time_t now = time(NULL);
now = last_called ? last_called + 1 : now; // Make sure we don't divide by 0 for rates now = last_called ? last_called + 1 : now; // Make sure we don't divide by 0 for rates
@@ -202,6 +216,32 @@ void send_mirror(int s)
} }
void send_cmd_log(int s)
{
char *header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n\r\n";
write(s, header, strlen(header));
for (int i = 0; i < cmd_ptr; i++) {
write(s, cmd_history[i], strlen(cmd_history[i]));
write(s, "\n", 1);
printf("%d: %s\n", i, cmd_history[i]);
}
}
void send_config(int s)
{
char *header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n\r\n";
printf("Sending uploaded config\n");
write(s, header, strlen(header));
printf("Uploaded config len: %d\n", uploaded_config_len);
printf(">%s<", uploaded_config);
write(s, uploaded_config, uploaded_config_len);
}
struct Server serverConstructor(int port, void (*launch)(struct Server *server)) { struct Server serverConstructor(int port, void (*launch)(struct Server *server)) {
struct Server server; struct Server server;
@@ -253,13 +293,30 @@ void send_bad_request(int socket) {
} }
void send_to_login(int socket) {
char *response = "HTTP/1.1 302 Found\r\n"
"Location: login.html\r\n\r\n";
write(socket, response, strlen(response));
}
void send_unauthorized(int socket) {
char *response = "HTTP/1.1 401 Unauthorized\r\n\r\n";
write(socket, response, strlen(response));
}
char *scan_header(char *p) char *scan_header(char *p)
{ {
session = 0;
authenticated = false;
while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') { while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') {
if (!*p++) if (!*p++)
break; break;
if (*p == '\n' && is_word(p + 1, "Content-Type:")) if (is_word(p, "\nContent-Type:"))
content_type = p + 15; content_type = p + 15;
else if (is_word(p, "\nCookie:"))
session = p + 17;
} }
if (content_type && is_word(content_type, "multipart/form-data; boundary")) { if (content_type && is_word(content_type, "multipart/form-data; boundary")) {
printf("Found multiplart\n"); printf("Found multiplart\n");
@@ -275,6 +332,19 @@ char *scan_header(char *p)
boundary[i + 2] = 0; boundary[i + 2] = 0;
} }
time_t now = time(NULL);
if (session) {
printf("Session: >%s<. time now: %ld last %ld\n", session, now, last_session_use);
if (now - last_session_use > SESSION_TIMEOUT) {
printf("Session expired\n");
} else {
if (!strncmp(session, SESSION_ID, 12))
authenticated = true;
else
printf("Invalid session cookie!\n");
}
}
printf("Time now: %ld last %ld\n", now, last_session_use);
return p; return p;
} }
@@ -289,6 +359,11 @@ char *skip_boundary(char *p)
return p; return p;
} }
void print_cmd_history(void)
{
for (int i = 0; i < cmd_ptr; i++)
printf("%d: %s\n", i, cmd_history[i]);
}
void launch(struct Server *server) void launch(struct Server *server)
{ {
@@ -313,33 +388,66 @@ void launch(struct Server *server)
puts(buffer); puts(buffer);
if (is_word(buffer, "GET")) { if (is_word(buffer, "GET")) {
printf("GET request\n"); scan_header(buffer);
if (!strncmp(&buffer[4], "/status.json", 12)) { if (!strncmp(&buffer[4], "/status.json", 12)) {
printf("Status request\n"); printf("Status request\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_status(new_socket); send_status(new_socket);
goto done; goto done;
} } else if (!strncmp(&buffer[4], "/eee.json", 9)) {
if (!strncmp(&buffer[4], "/eee.json", 9)) {
printf("EEE request\n"); printf("EEE request\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_eee(new_socket); send_eee(new_socket);
goto done; goto done;
} } else if (!strncmp(&buffer[4], "/information.json", 17)) {
if (!strncmp(&buffer[4], "/information.json", 12)) {
printf("Status request\n"); printf("Status request\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_basic_info(new_socket); send_basic_info(new_socket);
goto done; goto done;
} } else if (!strncmp(&buffer[4], "/mirror.json", 12)) {
if (!strncmp(&buffer[4], "/mirror.json", 12)) {
printf("Mirror request\n"); printf("Mirror request\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_mirror(new_socket); send_mirror(new_socket);
goto done; goto done;
} } else if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) {
if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) {
int vlan = atoi(&buffer[19]); int vlan = atoi(&buffer[19]);
printf("VLAN request for %d\n", vlan); printf("VLAN request for %d\n", vlan);
if (!authenticated)
send_unauthorized(new_socket);
else
send_vlan(new_socket, vlan); send_vlan(new_socket, vlan);
goto done; goto done;
} else if (!strncmp(&buffer[4], "/cmd_log", 8)) {
printf("Request cmd_log\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_cmd_log(new_socket);
goto done;
} else if (!strncmp(&buffer[4], "/config ", 8) && uploaded_config) {
printf("Request current config.\n");
if (!authenticated)
send_unauthorized(new_socket);
else
send_config(new_socket);
goto done;
} }
if (!authenticated && !(!strncmp(&buffer[4], "/login.html", 11) || !strncmp(&buffer[4], "/style.css", 10))) {
send_to_login(new_socket);
goto done;
}
// A web-page is actively accessed, we can reset session time-out
last_session_use = time(NULL);
int i = 0; int i = 0;
while (!isspace(buffer[4 + i])) while (!isspace(buffer[4 + i]))
i++; i++;
@@ -389,10 +497,44 @@ void launch(struct Server *server)
send_bad_request(new_socket); send_bad_request(new_socket);
goto done; goto done;
} }
if (!authenticated && !is_word(&buffer[5], "/login")) {
send_unauthorized(new_socket);
goto done;
}
printf("Bytes read %ld\n", bytesRead); printf("Bytes read %ld\n", bytesRead);
if (is_word(&buffer[5], "/upload")) { if (is_word(&buffer[5], "/cmd")) {
printf("POST upload request\n"); printf("POST cmd\n");
printf("CMD: %s\n", p + 4);
strcpy(cmd_history[cmd_ptr], p + 4);
cmd_ptr++;
print_cmd_history();
char *response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n\r\n"
"<!DOCTYPE html> <html><head><title>Upload OK</title></head>"
"<body><h1>Command executed successully</h1></html>";
write(new_socket, response, strlen(response));
goto done;
} else if (is_word(&buffer[5], "/login")) {
printf("POST login\n");
p += 4;
p += 4; // Read also over "pwd="
char *response;
if (is_word(p, PASSWORD)) {
printf("Password accepted!\n");
response = "HTTP/1.1 302 Found\r\n"
"Location: index.html\r\n"
"Set-Cookie: session=" SESSION_ID "; SameSite=Strict\r\n";
} else {
response = "HTTP/1.1 302 Found\r\n"
"Location: login.html\r\n\r\n";
}
write(new_socket, response, strlen(response));
goto done;
} else if (is_word(&buffer[5], "/upload") || is_word(&buffer[5], "/config")) {
printf("POST upload/config request\n");
bool config_upload = false;
if (is_word(&buffer[5], "/config"))
config_upload = true;
if (!boundary[0]) { if (!boundary[0]) {
printf("Bad request, no boundary!\n"); printf("Bad request, no boundary!\n");
send_bad_request(new_socket); send_bad_request(new_socket);
@@ -409,6 +551,7 @@ void launch(struct Server *server)
} while (!is_word(content_type, "application/octet-stream")); } while (!is_word(content_type, "application/octet-stream"));
printf("Have content: >%s<\n", content_type); printf("Have content: >%s<\n", content_type);
p += 4; // Skip \r\n\r\n after content type
char *uptr = upload_buffer; char *uptr = upload_buffer;
int bindex = 0; int bindex = 0;
int bptr = p - buffer; int bptr = p - buffer;
@@ -441,10 +584,18 @@ void launch(struct Server *server)
"<!DOCTYPE html> <html><head><title>Upload OK</title></head>" "<!DOCTYPE html> <html><head><title>Upload OK</title></head>"
"<body><h1>File uploaded successully</h1></html>"; "<body><h1>File uploaded successully</h1></html>";
write(new_socket, response, strlen(response)); write(new_socket, response, strlen(response));
if (config_upload) {
uploaded_config_len = (uptr - upload_buffer);
if (uploaded_config)
free (uploaded_config);
uploaded_config = malloc(uploaded_config_len + 1);
memcpy(uploaded_config, upload_buffer, uploaded_config_len);
}
goto done; goto done;
} }
} }
char *response = "HTTP/1.1 200 OK\r\n" char *response = "HTTP/1.1 200 OK\r\n"
"Cache-Control: max-age=60, must-revalidate\r\n"
"Content-Type: "; "Content-Type: ";
write(new_socket, response, strlen(response)); write(new_socket, response, strlen(response));
+1 -1
View File
@@ -3,7 +3,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#define BUFFER_SIZE 2400 #define BUFFER_SIZE 24000
struct Server { struct Server {
int domain; int domain;