diff --git a/README.md b/README.md index 81b62eb8..81fd8dda 100644 --- a/README.md +++ b/README.md @@ -344,6 +344,7 @@ netmask zzz.zzz.zzz.zzz = Network mask of the switch port x name xxx = Name xxx the port number x port z 1g = Set 1g speed for port z igmp on/off = Turn IGMP on or off +session xxxx = Web session timeout in seconds (default 200) ``` [To be continue] diff --git a/cmd_parser.c b/cmd_parser.c index 103efa6d..c0c549dc 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -43,6 +43,8 @@ extern __xdata struct flash_region_t flash_region; extern __xdata char passwd[21]; +extern __xdata uint16_t session_timeout; + extern __xdata struct dhcp_state dhcp_state; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; @@ -1613,6 +1615,25 @@ void parse_syslog(void) } } +void parse_session(void) +{ + if (cmd_words_len >= 2) { + /* atoi_short() returns zero for no digits and for a value past + * 65535; a zero-second timeout is not useful either, so both + * tests are needed. */ + if (!atoi_short(cmd_words_b[1]) || !atoi_results_short) { + print_string("Must be 1-65535 s\n"); + return; + } + session_timeout = atoi_results_short; + } + /* Also the confirmation after setting: one message for both. */ + print_string("Session timeout: "); + itoa_short(session_timeout); + print_string(" s\n"); +} + + // Parse command into words // cmd_words_len contains the number of words found. // cmd_words_b[] contains only start of a word offset. @@ -1919,6 +1940,8 @@ void cmd_parser(void) __banked } } else if (cmd_compare(0, "ingress")) { parse_ingress(); + } else if (cmd_compare(0, "session")) { + parse_session(); } else { cmd_error("Unknown command\n"); diff --git a/html/app.js b/html/app.js index 0ac3b64a..527075c9 100644 --- a/html/app.js +++ b/html/app.js @@ -72,6 +72,7 @@ bw_exceed:"When exceeded",bw_fc:"Flow control",bw_drop:"Drop", bw_in_err:"Ingress limit must be 0.016-10000 Mbit/s",bw_out_err:"Egress limit must be 0.016-10000 Mbit/s", sy_network:"Network",sy_dhcp:"Use DHCP",sy_dhcp_t:"Request address via DHCP",sy_services:"Services", sy_igmp:"IGMP snooping",sy_sysip:"server IP",sy_server:"Server",sy_port:"Port", +sy_sesstmo:"Session timeout (s)",sy_sesstmo_err:"Session timeout must be 1-65535 s", sy_services_note:"Service state reflects the startup config; runtime state is not readable.", sy_password:"Admin password",sy_newpw:"New password",sy_repeat:"Repeat",sy_pwapply:"Change password", sy_pw_note:"Takes effect immediately; save to flash to keep it after reboot.",sy_console:"Console", @@ -184,6 +185,7 @@ bw_exceed:"超過時の動作",bw_fc:"フロー制御",bw_drop:"破棄", bw_in_err:"入力制限は 0.016〜10000 Mbit/s の範囲で指定してください",bw_out_err:"出力制限は 0.016〜10000 Mbit/s の範囲で指定してください", sy_network:"ネットワーク",sy_dhcp:"DHCP を使用",sy_dhcp_t:"DHCP でアドレスを取得",sy_services:"サービス", sy_igmp:"IGMP スヌーピング",sy_sysip:"サーバー IP",sy_server:"サーバー",sy_port:"ポート", +sy_sesstmo:"セッションタイムアウト (秒)",sy_sesstmo_err:"セッションタイムアウトは 1〜65535 秒で指定してください", sy_services_note:"サービスの状態は起動設定を反映しています。実行時の状態は読み取れません。", sy_password:"管理者パスワード",sy_newpw:"新しいパスワード",sy_repeat:"再入力",sy_pwapply:"パスワードを変更", sy_pw_note:"即時に反映されます。再起動後も保持するにはフラッシュに保存してください。",sy_console:"コンソール", @@ -296,6 +298,7 @@ bw_exceed:"超限动作",bw_fc:"流量控制",bw_drop:"丢弃", bw_in_err:"入方向限速范围为 0.016-10000 Mbit/s",bw_out_err:"出方向限速范围为 0.016-10000 Mbit/s", sy_network:"网络",sy_dhcp:"使用 DHCP",sy_dhcp_t:"通过 DHCP 获取地址",sy_services:"服务", sy_igmp:"IGMP 侦听",sy_sysip:"服务器 IP",sy_server:"服务器",sy_port:"端口", +sy_sesstmo:"会话超时(秒)",sy_sesstmo_err:"会话超时必须为 1-65535 秒", sy_services_note:"服务状态反映启动配置;运行时状态无法读取。", sy_password:"管理员密码",sy_newpw:"新密码",sy_repeat:"重复输入",sy_pwapply:"修改密码", sy_pw_note:"立即生效;如需重启后保留请保存到 Flash。",sy_console:"控制台", @@ -408,6 +411,7 @@ bw_exceed:"Al excederse",bw_fc:"Control de flujo",bw_drop:"Descartar", bw_in_err:"El límite de entrada debe estar entre 0.016 y 10000 Mbit/s",bw_out_err:"El límite de salida debe estar entre 0.016 y 10000 Mbit/s", sy_network:"Red",sy_dhcp:"Usar DHCP",sy_dhcp_t:"Solicitar dirección mediante DHCP",sy_services:"Servicios", sy_igmp:"IGMP snooping",sy_sysip:"IP del servidor",sy_server:"Servidor",sy_port:"Puerto", +sy_sesstmo:"Tiempo de sesión (s)",sy_sesstmo_err:"El tiempo de sesión debe estar entre 1 y 65535 s", sy_services_note:"El estado del servicio refleja la configuración de inicio; el estado en ejecución no es legible.", sy_password:"Contraseña de administrador",sy_newpw:"Nueva contraseña",sy_repeat:"Repetir",sy_pwapply:"Cambiar contraseña", sy_pw_note:"Toma efecto inmediatamente; guarda en flash para conservarla tras el reinicio.",sy_console:"Consola", @@ -541,6 +545,7 @@ var CONF_CMDS=[ /^ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^ip\s+dhcp$/, /^gw\s+(\d{1,3}\.){3}\d{1,3}$/,/^netmask\s+(\d{1,3}\.){3}\d{1,3}$/, /^syslog\s+(on|off)$/,/^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^syslog\s+port\s+\d{1,5}$/, + /^session\s+\d{1,5}$/, /^passwd\s+\S+$/,/^hostname\s+\S{1,23}$/, /^vlan\s+\d{1,4}\s+d$/,/^vlan\s+\d{1,4}\s+mgmt$/, /^vlan\s+\d{1,4}(\s+[a-zA-Z]\w*)?(\s+\d{1,2}t?)+$/, @@ -1624,6 +1629,7 @@ function sysLoad(){ var sl=(S.info.syslog_server||"").split(":"); if(sl[0]&&sl[0]!=="0.0.0.0")$("sy-sysip").value=sl[0]; if(sl[1])$("sy-sysport").value=sl[1]; + if(S.info.session_timeout)$("sy-sesstmo").value=S.info.session_timeout; }).catch(function(){}); cfgReload(); } @@ -1676,6 +1682,11 @@ $("sy-syslog").addEventListener("change",function(){ }else cmds.push("syslog off"); postCmds(cmds).catch(function(){}); }); +$("sy-sesstmo").addEventListener("change",function(){ + var v=+this.value; + if(!(v>=1&&v<=65535)){toast(t("sy_sesstmo_err"),"err");sysLoad();return;} + postCmd("session "+v).catch(function(){sysLoad()}); +}); $("sy-pwapply").addEventListener("click",function(){ var a=$("sy-pw1").value,b=$("sy-pw2").value; if(a.length<1||a.length>20){toast(t("sy_pw_len"),"err");return;} @@ -1739,7 +1750,7 @@ tabHooks.system={enter:sysLoad}; var CONF_OVERWRITE=[ /^ip\b/,/^gw\b/,/^netmask\b/,/^hostname\b/, - /^syslog\s+ip\b/,/^syslog\s+port\b/,/^passwd\b/, + /^syslog\s+ip\b/,/^syslog\s+port\b/,/^passwd\b/,/^session\b/, /^vlan\s+\d{1,4}\s+mgmt$/,/^vlan\s+\d{1,4}(?!\s+mgmt\b)/, /^pvid\s+\d{1,2}\b/, /^port\s+\d{1,2}(?!\s+name\b)/,/^port\s+\d{1,2}\s+name\b/, diff --git a/html/index.html b/html/index.html index 6402285b..1bb3e7cc 100644 --- a/html/index.html +++ b/html/index.html @@ -375,6 +375,8 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent} Port +

Service state reflects the startup config; runtime state is not readable.

Admin password

diff --git a/httpd/httpd.c b/httpd/httpd.c index 85408e7b..c4ac485a 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -12,7 +12,11 @@ #include "debug.h" #define SESSION_ID_LENGTH 12 -#define SESSION_TIMEOUT 200 +#define SESSION_TIMEOUT_DEFAULT 200 + +/* Seconds of inactivity after which a session cookie stops validating. + * Configurable with the "session" command, see cmd_parser.c. */ +__xdata uint16_t session_timeout = SESSION_TIMEOUT_DEFAULT; #define CMARK_S 6 @@ -342,7 +346,7 @@ __xdata uint8_t *scan_header(__xdata uint8_t * __xdata p) read_reg_timer(&now); if (session && session_id[0]) { - if (now - last_session_use > SESSION_TIMEOUT) { + if (now - last_session_use > session_timeout) { dbg_string("Session expired\n"); } else { if (is_word_x(session, session_id)) { diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 073709cd..ac5118a4 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -28,6 +28,7 @@ extern __code const struct machine machine; extern __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; extern __xdata uint16_t slen; extern __xdata uint16_t management_vlan; +extern __xdata uint16_t session_timeout; extern __xdata uint16_t cont_len; extern __xdata uint32_t cont_addr; extern __code const uint8_t * __code const hex; @@ -114,12 +115,14 @@ void itoa_html(uint8_t v) char_to_html('0' + (v % 10)); } -void itoa16_html(uint16_t v) /* sufficient for VLAN IDs (max 4094) */ +void itoa16_html(uint16_t v) /* up to five digits (65535) */ { uint8_t print_zeros = 0; uint8_t d; - d = v / 1000; + d = v / 10000; if (d) { char_to_html('0' + d); print_zeros = 1; } + d = (v / 1000) % 10; + if (d || print_zeros) { char_to_html('0' + d); print_zeros = 1; } d = (v / 100) % 10; if (d || print_zeros) { char_to_html('0' + d); print_zeros = 1; } d = (v / 10) % 10; @@ -258,7 +261,9 @@ void send_basic_info(void) itoa_html(syslog_state.server_ip[2]); char_to_html('.'); itoa_html(syslog_state.server_ip[3]); char_to_html(':'); itoa16_html(syslog_state.server_port); - slen += strtox(outbuf + slen, "\",\"mac_address\":\""); + slen += strtox(outbuf + slen, "\",\"session_timeout\":"); + itoa16_html(session_timeout); + slen += strtox(outbuf + slen, ",\"mac_address\":\""); byte_to_html(uip_ethaddr.addr[0]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[1]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[2]); char_to_html(':'); diff --git a/httpd/page_impl.h b/httpd/page_impl.h index 0f171042..b3bcdfd9 100644 --- a/httpd/page_impl.h +++ b/httpd/page_impl.h @@ -5,6 +5,8 @@ extern __code const uint8_t * __code const HTTP_RESPONCE_TXT; +void itoa16_html(uint16_t v); + bool send_counters(uint8_t phys_port); void send_status(void); void send_vlan(uint16_t vlan); diff --git a/test/support.c b/test/support.c index 1270554f..191f8a5a 100644 --- a/test/support.c +++ b/test/support.c @@ -27,6 +27,7 @@ uint8_t cmd_available; uint8_t err_status; uint8_t cmd_history[CMD_HISTORY_SIZE]; uint16_t cmd_history_ptr; +__xdata uint16_t session_timeout = 200; /* httpd global, referenced by page_impl.c */ /* editor-internal read pointer (defined in cmd_editor.c, external linkage) */ extern __xdata uint8_t l;