diff --git a/user/cgi_network.c b/user/cgi_network.c index 6ed9d40..e417dd7 100644 --- a/user/cgi_network.c +++ b/user/cgi_network.c @@ -49,6 +49,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData) // ---- AP DHCP server lease time ---- +#define XSTRUCT wificonf #define X XSET_CGI_FUNC XTABLE_WIFI #undef X @@ -98,6 +99,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplNetwork(HttpdConnData *connData, char *toke strcpy(buff, ""); // fallback +#define XSTRUCT wificonf #define X XGET_CGI_FUNC XTABLE_WIFI #undef X diff --git a/user/cgi_system.c b/user/cgi_system.c index d23d20b..3f939a7 100755 --- a/user/cgi_system.c +++ b/user/cgi_system.c @@ -12,6 +12,9 @@ #define SET_REDIR_SUC "/cfg/system" #define SET_REDIR_ERR SET_REDIR_SUC"?err=" +// Select which struct we want to use for X tables +#define XSTRUCT sysconf + static ETSTimer tmr; static void ICACHE_FLASH_ATTR tmrCb(void *arg) @@ -95,106 +98,77 @@ cgiSystemCfgSetParams(HttpdConnData *connData) memcpy(admin_backup, &persist.admin, sizeof(AdminConfigBlock)); memcpy(sysconf_backup, sysconf, sizeof(SystemConfigBundle)); + // flags for the template builder + bool admin = false, tpl = false; do { - if (!GET_ARG("pw")) { - break; // if no PW in GET, not trying to configure anything protected - } - - if (!streq(buff, persist.admin.pw)) { - warn("Bad admin pw!"); - redir_url += sprintf(redir_url, "pw,"); - break; - } - - // authenticated OK - if (GET_ARG("pwlock")) { - cgi_dbg("pwlock: %s", buff); - int pwlock = atoi(buff); - if (pwlock < 0 || pwlock >= PWLOCK_MAX) { - cgi_warn("Bad pwlock %s", buff); - redir_url += sprintf(redir_url, "pwlock,"); - break; + // Check admin PW + if (GET_ARG("pw")) { + if (!streq(buff, persist.admin.pw)) { + warn("Bad admin pw!"); + redir_url += sprintf(redir_url, "pw,"); + break; // Abort + } else { + admin = true; } - - sysconf->pwlock = (enum pwlock) pwlock; } - if (GET_ARG("access_pw")) { - cgi_dbg("access_pw: %s", buff); - + // Changing admin PW + if (admin && GET_ARG("admin_pw")) { if (strlen(buff)) { - strcpy(buff2, buff); - if (!GET_ARG("access_pw2")) { - cgi_warn("Missing repeated access_pw %s", buff); - redir_url += sprintf(redir_url, "access_pw2,"); - break; - } - - if (!streq(buff, buff2)) { - cgi_warn("Bad repeated access_pw %s", buff); - redir_url += sprintf(redir_url, "access_pw2,"); - break; - } - - if (strlen(buff) >= 64) { - cgi_warn("Too long access_pw %s", buff); - redir_url += sprintf(redir_url, "access_pw,"); - break; - } - - cgi_dbg("Changing access PW!"); - strncpy(sysconf->access_pw, buff, 64); - } - } - - if (GET_ARG("access_name")) { - cgi_dbg("access_name: %s", buff); - - if (!strlen(buff) || strlen(buff) >= 32) { - cgi_warn("Too long access_name %s", buff); - redir_url += sprintf(redir_url, "access_name,"); - break; - } - - strncpy(sysconf->access_name, buff, 32); - } - - if (GET_ARG("admin_pw")) { - cgi_dbg("admin_pw: %s", buff); + cgi_dbg("admin_pw: %s", buff); - if (strlen(buff)) { strcpy(buff2, buff); if (!GET_ARG("admin_pw2")) { cgi_warn("Missing repeated admin_pw %s", buff); redir_url += sprintf(redir_url, "admin_pw2,"); - break; + break; // Abort } if (!streq(buff, buff2)) { cgi_warn("Bad repeated admin_pw %s", buff); redir_url += sprintf(redir_url, "admin_pw2,"); - break; + break; // Abort } if (strlen(buff) >= 64) { cgi_warn("Too long admin_pw %s", buff); redir_url += sprintf(redir_url, "admin_pw,"); - break; + break; // Abort } cgi_dbg("Changing admin PW!"); strncpy(persist.admin.pw, buff, 64); + + break; // this is the only field in this form } } - } while (0); - if (GET_ARG("overclock")) { - cgi_dbg("overclock = %s", buff); - int enable = atoi(buff); - if (sysconf->overclock != enable) { - sysconf->overclock = (bool)enable; + // Reject filled but unconfirmed access PW + if (admin && GET_ARG("access_pw")) { + if (strlen(buff)) { + cgi_dbg("access_pw: %s", buff); + + strcpy(buff2, buff); + if (!GET_ARG("access_pw2")) { + cgi_warn("Missing repeated access_pw %s", buff); + redir_url += sprintf(redir_url, "access_pw2,"); + break; // Abort + } + + if (!streq(buff, buff2)) { + cgi_warn("Bad repeated access_pw %s", buff); + redir_url += sprintf(redir_url, "access_pw2,"); + break; // Abort + } + } } - } + + // Settings in the system config block +#define X XSET_CGI_FUNC + XTABLE_SYSCONF +#undef X + + } while (0); (void)redir_url; @@ -236,13 +210,13 @@ tplSystemCfg(HttpdConnData *connData, char *token, void **arg) strcpy(buff, ""); // fallback - if (streq(token, "pwlock")) { - sprintf(buff, "%d", sysconf->pwlock); - } - else if (streq(token, "access_name")) { - sprintf(buff, "%s", sysconf->access_name); - } - else if (streq(token, "def_access_name")) { + const bool admin = false, tpl=true; + +#define X XGET_CGI_FUNC + XTABLE_SYSCONF +#undef X + + if (streq(token, "def_access_name")) { sprintf(buff, "%s", DEF_ACCESS_NAME); } else if (streq(token, "def_access_pw")) { @@ -251,9 +225,6 @@ tplSystemCfg(HttpdConnData *connData, char *token, void **arg) else if (streq(token, "def_admin_pw")) { sprintf(buff, "%s", DEFAULT_ADMIN_PW); } - else if (streq(token, "overclock")) { - sprintf(buff, "%d", sysconf->overclock); - } tplSend(connData, buff, -1); return HTTPD_CGI_DONE; diff --git a/user/cgi_wifi.c b/user/cgi_wifi.c index 41be75d..fe09fda 100644 --- a/user/cgi_wifi.c +++ b/user/cgi_wifi.c @@ -324,6 +324,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) bool sta_turned_on = false; bool sta_ssid_pw_changed = false; +#define XSTRUCT wificonf #define X XSET_CGI_FUNC XTABLE_WIFI #undef X @@ -414,6 +415,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, strcpy(buff, ""); // fallback +#define XSTRUCT wificonf #define X XGET_CGI_FUNC XTABLE_WIFI #undef X diff --git a/user/config_xmacros.c b/user/config_xmacros.c index 55105f8..d52f6cf 100644 --- a/user/config_xmacros.c +++ b/user/config_xmacros.c @@ -81,7 +81,7 @@ xset_u8(const char *name, u8 *field, const char *buff, const void *arg) } enum xset_result ICACHE_FLASH_ATTR -xset_string(const char *name, char *field, const char *buff, const void *arg) +xset_string(const char *name, s8 **field, const char *buff, const void *arg) { cgi_dbg("Setting %s = %s", name, buff); u32 maxlen = (u32) arg; @@ -97,3 +97,22 @@ xset_string(const char *name, char *field, const char *buff, const void *arg) } return XSET_UNCHANGED; } + + +enum xset_result ICACHE_FLASH_ATTR +xset_ustring(const char *name, u8 **field, const char *buff, const void *arg) +{ + cgi_dbg("Setting %s = %s", name, buff); + u32 maxlen = (u32) arg; + + if (arg > 0 && (u32)strlen(buff) > maxlen) { + cgi_warn("String too long, max %d", maxlen); + return XSET_FAIL; + } + + if (!streq((char *)field, buff)) { + strncpy_safe(field, buff, (u32)arg); + return XSET_SET; + } + return XSET_UNCHANGED; +} diff --git a/user/config_xmacros.h b/user/config_xmacros.h index 9da5daf..53495b0 100644 --- a/user/config_xmacros.h +++ b/user/config_xmacros.h @@ -64,7 +64,8 @@ enum xset_result xset_u8(const char *name, u8 *field, const char *buff, const vo /** * @param arg - max string length */ -enum xset_result xset_string(const char *name, char *field, const char *buff, const void *arg); +enum xset_result xset_string(const char *name, s8 **field, const char *buff, const void *arg); +enum xset_result xset_ustring(const char *name, u8 **field, const char *buff, const void *arg); /** * Helper template macro for CGI functions that load GET args to structs using XTABLE @@ -72,17 +73,20 @@ enum xset_result xset_string(const char *name, char *field, const char *buff, co * If 'name' is found in connData->getArgs, xset() is called. * If the result is SET, xnotify() is fired. Else, 'name,' is appended to the redir_url buffer. */ -#define XSET_CGI_FUNC(type, name, suffix, deref, xget, cast, xset, xsarg, xnotify) \ - if (GET_ARG(#name)) { \ - enum xset_result res = xset(#name, cast &wificonf->name, buff, (const void*) (xsarg)); \ +#define XSET_CGI_FUNC(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \ + if ((allow) && GET_ARG(#name)) { \ + enum xset_result res = xset(#name, cast &XSTRUCT->name, buff, (const void*) (xsarg)); \ if (res == XSET_SET) { xnotify(); } \ else if (res == XSET_FAIL) { redir_url += sprintf(redir_url, #name","); } \ } -#define XGET_CGI_FUNC(type, name, suffix, deref, xget, cast, xset, xsarg, xnotify) \ - if (streq(token, #name)) xget(buff, deref wificonf->name); +#define XGET_CGI_FUNC(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \ + if ((allow) && streq(token, #name)) xget(buff, deref XSTRUCT->name); -#define XSTRUCT_FIELD(type, name, suffix, deref, xget, cast, xset, xsarg, xnotify) \ +#define XSTRUCT_FIELD(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \ type name suffix; +#define XDUMP_FIELD(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \ + { xget(buff, deref XSTRUCT->name); dbg(#name " = %s", buff); } + #endif //ESPTERM_CONFIG_XMACROS_H diff --git a/user/routes.c b/user/routes.c index 4b6b502..895133e 100644 --- a/user/routes.c +++ b/user/routes.c @@ -23,8 +23,8 @@ static int ICACHE_FLASH_ATTR wifiPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) { if (no == 0) { - os_strcpy(user, sysconf->access_name); - os_strcpy(pass, sysconf->access_pw); + os_strcpy(user, (const char *) sysconf->access_name); + os_strcpy(pass, (const char *) sysconf->access_pw); return 1; } if (no == 1) { diff --git a/user/syscfg.c b/user/syscfg.c index cd22d77..9a2a6f2 100644 --- a/user/syscfg.c +++ b/user/syscfg.c @@ -6,12 +6,112 @@ #include "persist.h" #include "uart_driver.h" #include "serial.h" +#include "cgi_logging.h" SystemConfigBundle * const sysconf = &persist.current.sysconf; +enum xset_result ICACHE_FLASH_ATTR +xset_sys_baudrate(const char *name, u32 *field, const char *buff, const void *arg) +{ + cgi_dbg("Setting %s = %s", name, buff); + int baud = atoi(buff); + if (baud == BIT_RATE_300 || + baud == BIT_RATE_600 || + baud == BIT_RATE_1200 || + baud == BIT_RATE_2400 || + baud == BIT_RATE_4800 || + baud == BIT_RATE_9600 || + baud == BIT_RATE_19200 || + baud == BIT_RATE_38400 || + baud == BIT_RATE_57600 || + baud == BIT_RATE_74880 || + baud == BIT_RATE_115200 || + baud == BIT_RATE_230400 || + baud == BIT_RATE_460800 || + baud == BIT_RATE_921600 || + baud == BIT_RATE_1843200 || + baud == BIT_RATE_3686400) { + if (*field != baud) { + *field = (u32) baud; + return XSET_SET; + } + return XSET_UNCHANGED; + } else { + cgi_warn("Bad baud rate %s", buff); + return XSET_FAIL; + } +} + +enum xset_result ICACHE_FLASH_ATTR +xset_sys_parity(const char *name, u8 *field, const char *buff, const void *arg) +{ + cgi_dbg("Setting %s = %s", name, buff); + int parity = atoi(buff); + if (parity >= 0 && parity <= 2) { + if (*field != parity) { + *field = (UartParityMode) parity; + return XSET_SET; + } + return XSET_UNCHANGED; + } else { + cgi_warn("Bad parity %s", buff); + return XSET_FAIL; + } +} + +enum xset_result ICACHE_FLASH_ATTR +xset_sys_stopbits(const char *name, u8 *field, const char *buff, const void *arg) +{ + cgi_dbg("Setting %s = %s", name, buff); + int stopbits = atoi(buff); + if (stopbits >= 1 && stopbits <= 3) { + if (*field != stopbits) { + *field = (UartParityMode) stopbits; + return XSET_SET; + } + return XSET_UNCHANGED; + } else { + cgi_warn("Bad stopbits %s", buff); + return XSET_FAIL; + } +} + +enum xset_result ICACHE_FLASH_ATTR +xset_sys_pwlock(const char *name, u8 *field, const char *buff, const void *arg) +{ + cgi_dbg("Setting %s = %s", name, buff); + + int pwlock = atoi(buff); + if (pwlock >= 0 && pwlock < PWLOCK_MAX) { + if (*field != pwlock) { + *field = (enum pwlock) pwlock; + return XSET_SET; + } + return XSET_UNCHANGED; + } else { + cgi_warn("Bad pwlock %s", buff); + return XSET_FAIL; + } +} + +enum xset_result ICACHE_FLASH_ATTR +xset_sys_accesspw(const char *name, u8 **field, const char *buff, const void *arg) +{ + // Do not overwrite pw if empty + if (strlen(buff) == 0) return XSET_UNCHANGED; + return xset_ustring(name, field, buff, arg); +} + + void ICACHE_FLASH_ATTR sysconf_apply_settings(void) { +// char buff[64]; +//#define XSTRUCT sysconf +//#define X XDUMP_FIELD +// XTABLE_SYSCONF +//#undef X + bool changed = false; if (sysconf->config_version < 1) { dbg("Upgrading syscfg to v 1"); @@ -40,7 +140,7 @@ sysconf_restore_defaults(void) sysconf->config_version = SYSCONF_VERSION; sysconf->access_pw[0] = 0; sysconf->pwlock = PWLOCK_NONE; - strcpy(sysconf->access_pw, DEF_ACCESS_PW); - strcpy(sysconf->access_name, DEF_ACCESS_NAME); + strcpy((char *)sysconf->access_pw, DEF_ACCESS_PW); + strcpy((char *)sysconf->access_name, DEF_ACCESS_NAME); sysconf->overclock = false; } diff --git a/user/syscfg.h b/user/syscfg.h index e316b68..70ea94b 100644 --- a/user/syscfg.h +++ b/user/syscfg.h @@ -6,6 +6,7 @@ #define ESP_VT100_FIRMWARE_SYSCFG_H #include +#include "config_xmacros.h" // Size designed for the wifi config structure // Must be constant to avoid corrupting user config after upgrade @@ -24,15 +25,36 @@ enum pwlock { PWLOCK_MAX = 5, }; + +//....Type................Name..Suffix...............Deref..XGET........Allow..Cast..XSET.........................NOTIFY +// Deref is used to pass the field to xget. Cast is used to convert the &'d field to what xset wants (needed for static arrays) +#define XTABLE_SYSCONF \ + X(u32, uart_baudrate, /**/, /**/, xget_dec, 1, /**/, xset_sys_baudrate, NULL, xnoop) \ + X(u8, uart_parity, /**/, /**/, xget_dec, 1, /**/, xset_sys_parity, NULL, xnoop) \ + X(u8, uart_stopbits, /**/, /**/, xget_dec, 1, /**/, xset_sys_stopbits, NULL, xnoop) \ + \ + X(u8, config_version, /**/, /**/, xget_dec, 0, /**/, xset_u8, NULL, xnoop) \ + \ + X(u8, pwlock, /**/, /**/, xget_dec, admin|tpl, /**/, xset_sys_pwlock, NULL, xnoop) \ + X(u8, access_pw, [64], /**/, xget_ustring, admin, (u8**), xset_sys_accesspw, NULL, xnoop) \ + X(u8, access_name, [32], /**/, xget_ustring, admin|tpl, (u8**), xset_ustring, NULL, xnoop) \ + \ + X(bool, overclock, /**/, /**/, xget_bool, 1, /**/, xset_bool, NULL, xnoop) \ + + typedef struct { - u32 uart_baudrate; - u8 uart_parity; - u8 uart_stopbits; - u8 config_version; - enum pwlock pwlock : 8; // page access lock - char access_pw[64]; // access password - char access_name[32]; // access name - bool overclock; +#define X XSTRUCT_FIELD + XTABLE_SYSCONF +#undef X + +// u32 uart_baudrate; +// u8 uart_parity; +// u8 uart_stopbits; +// u8 config_version; +// enum pwlock pwlock : 8; // page access lock +// char access_pw[64]; // access password +// char access_name[32]; // access name +// bool overclock; } SystemConfigBundle; extern SystemConfigBundle * const sysconf; @@ -41,4 +63,10 @@ void sysconf_apply_settings(void); void sysconf_restore_defaults(void); +enum xset_result xset_sys_baudrate(const char *name, u32 *field, const char *buff, const void *arg); +enum xset_result xset_sys_parity(const char *name, u8 *field, const char *buff, const void *arg); +enum xset_result xset_sys_stopbits(const char *name, u8 *field, const char *buff, const void *arg); +enum xset_result xset_sys_pwlock(const char *name, u8 *field, const char *buff, const void *arg); +enum xset_result xset_sys_accesspw(const char *name, u8 **field, const char *buff, const void *arg); + #endif //ESP_VT100_FIRMWARE_SYSCFG_H diff --git a/user/wifimgr.c b/user/wifimgr.c index 46d028a..b0376c9 100644 --- a/user/wifimgr.c +++ b/user/wifimgr.c @@ -300,6 +300,12 @@ wifimgr_apply_settings(void) { wifi_info("[WiFi] Initializing..."); +// char buff[64]; +//#define XSTRUCT wificonf +//#define X XDUMP_FIELD +// XTABLE_WIFICONF +//#undef X + // !!! Update to current version !!! // Force wifi cycle diff --git a/user/wifimgr.h b/user/wifimgr.h index 2302571..5e0952f 100644 --- a/user/wifimgr.h +++ b/user/wifimgr.h @@ -23,37 +23,37 @@ #define wifimgr_notify_ap() { wifi_change_flags.ap = true; } #define wifimgr_notify_sta() { wifi_change_flags.ap = true; } -//....Type................Name..Suffix...............Deref..XGET.........Cast..XSET.........................NOTIFY +//....Type................Name..Suffix...............Deref..XGET.......Allow..Cast..XSET.........................NOTIFY // Deref is used to pass the field to xget. Cast is used to convert the &'d field to what xset wants (needed for static arrays) #define XTABLE_WIFI \ - X(u8, opmode, /**/, /**/, xget_dec, /**/, xset_wifi_opmode, NULL, xnoop) \ + X(u8, opmode, /**/, /**/, xget_dec, 1, /**/, xset_wifi_opmode, NULL, xnoop) \ \ - X(u8, tpw, /**/, /**/, xget_dec, /**/, xset_wifi_tpw, NULL, wifimgr_notify_ap) \ - X(u8, ap_channel, /**/, /**/, xget_dec, /**/, xset_wifi_ap_channel, NULL, wifimgr_notify_ap) \ - X(u8, ap_ssid, [SSID_LEN], /**/, xget_ustring, (u8**), xset_wifi_ssid, 1, wifimgr_notify_ap) \ - X(u8, ap_password, [PASSWORD_LEN], /**/, xget_ustring, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_ap) \ - X(bool, ap_hidden, /**/, /**/, xget_bool, /**/, xset_bool, NULL, wifimgr_notify_ap) \ + X(u8, tpw, /**/, /**/, xget_dec, 1, /**/, xset_wifi_tpw, NULL, wifimgr_notify_ap) \ + X(u8, ap_channel, /**/, /**/, xget_dec, 1, /**/, xset_wifi_ap_channel, NULL, wifimgr_notify_ap) \ + X(u8, ap_ssid, [SSID_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_ssid, 1, wifimgr_notify_ap) \ + X(u8, ap_password, [PASSWORD_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_ap) \ + X(bool, ap_hidden, /**/, /**/, xget_bool, 1, /**/, xset_bool, NULL, wifimgr_notify_ap) \ \ - X(u16, ap_dhcp_time, /**/, /**/, xget_dec, /**/, xset_wifi_lease_time, NULL, wifimgr_notify_ap) \ - X(u32, unused1, /**/, /**/, xget_dummy, /**/, xset_dummy, NULL, xnoop) \ - X(struct ip_addr, ap_dhcp_start, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap) \ - X(struct ip_addr, ap_dhcp_end, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap) \ + X(u16, ap_dhcp_time, /**/, /**/, xget_dec, 1, /**/, xset_wifi_lease_time, NULL, wifimgr_notify_ap) \ + X(u32, unused1, /**/, /**/, xget_dummy, 0, /**/, xset_dummy, NULL, xnoop) \ + X(struct ip_addr, ap_dhcp_start, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \ + X(struct ip_addr, ap_dhcp_end, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \ \ - X(struct ip_addr, ap_addr_ip, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap) \ - X(struct ip_addr, ap_addr_mask, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap) \ + X(struct ip_addr, ap_addr_ip, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \ + X(struct ip_addr, ap_addr_mask, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \ \ \ - X(u32, unused2, /**/, /**/, xget_dummy, /**/, xset_dummy, NULL, xnoop) \ - X(u8, sta_ssid, [SSID_LEN], /**/, xget_ustring, (u8**), xset_wifi_ssid, 0, wifimgr_notify_sta) \ - X(u8, sta_password, [PASSWORD_LEN], /**/, xget_ustring, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_sta) \ - X(bool, sta_dhcp_enable, /**/, /**/, xget_bool, /**/, xset_bool, NULL, wifimgr_notify_sta) \ + X(u32, unused2, /**/, /**/, xget_dummy, 0, /**/, xset_dummy, NULL, xnoop) \ + X(u8, sta_ssid, [SSID_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_ssid, 0, wifimgr_notify_sta) \ + X(u8, sta_password, [PASSWORD_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_sta) \ + X(bool, sta_dhcp_enable, /**/, /**/, xget_bool, 1, /**/, xset_bool, NULL, wifimgr_notify_sta) \ \ - X(struct ip_addr, sta_addr_ip, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_sta) \ - X(struct ip_addr, sta_addr_mask, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_sta) \ - X(struct ip_addr, sta_addr_gw, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_sta) \ + X(struct ip_addr, sta_addr_ip, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_sta) \ + X(struct ip_addr, sta_addr_mask, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_sta) \ + X(struct ip_addr, sta_addr_gw, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_sta) \ \ \ - X(u8, config_version, /**/, /**/, xget_dec, /**/, xset_u8, NULL, xnoop) + X(u8, config_version, /**/, /**/, xget_dec, 0, /**/, xset_u8, NULL, xnoop) // unused1 - replaces 'enabled' bit from old dhcps_lease struct // unused2 - gap after 'ap_gw' which isn't used and doesn't make sense