M2: WLAN-Passwort muss leer (offenes Netz) oder 8..64 Zeichen lang sein
(400 "invalid password" bei 1..7 Zeichen). CMake prüft NINLIGHT_WIFI_PASSWORD
ebenso (0 oder 8..63 Zeichen) und der Zeichen-Blacklist-Check bekommt `;`
dazu.
M4: Ein Authorization-Wert, der länger als NL_TOKEN_LEN-1 (64) ist, wird
von nl_http_parse() nicht mehr stillschweigend abgeschnitten, sondern setzt
`auth_too_long` in nl_http_request_t; nl_api_handle() behandelt eine solche
Anfrage als unauthentifiziert (außer bei offenem Zugriff), damit ein
abgeschnittener Wert nie zufällig auf ein kürzeres Token passt.
M5: get_int() prüfte die (long)-Cast-Gleichheit vor dem Bereichscheck -
bei sehr großen oder NaN-Werten ist der Cast von double nach long
undefiniertes Verhalten. Bereichs- und NaN-Check laufen jetzt vor dem Cast.
T1: sdk/Platform/Drivers/internalflash/wm_internal_fls.c: tls_fls_init()
ignorierte den Rückgabewert von tls_os_sem_create(&s_fls2_lock, 1) - jetzt
eine TLS_DBGPRT_ERR-Meldung, falls das fehlschlägt (dokumentiert in
sdk/PATCHES.md).
Tests: test_api.c (Passwortlängen, auth_too_long, 1e300-Brightness),
test_http.c (auth_too_long wird gesetzt). Für M5 zeigt der Host-Test kein
sichtbares RED, weil der (double)->(long)-Cast auf dieser Plattform/diesem
Compiler keinen Crash auslöst (implementation-defined statt UB-Crash) - der
Fix wird trotzdem angewendet, da er auf dem Zielcompiler (arm-none-eabi 4.9)
nicht garantiert sicher ist.
C2: tls_wifi_softap_create() setzt das SOFTAP-Bit (IEEE80211_MODE_AP = 4)
in TLS_PARAM_ID_WPROTOCOL und schreibt es in den Flash; tls_wifi_softap_destroy()
löscht es nie wieder. Solange das Bit gesetzt bleibt, erstellt
sys_net_status_changed() (sdk/Platform/Sys/tls_sys.c:519-525) bei jedem
NETIF_IP_NET_UP über tls_auto_reconnect_softap() erneut den Onboarding-AP
mit den SDK-eigenen (öffentlichen Default-)Parametern - unabhängig vom
Auto-Connect-Flag. Nach jedem Onboarding/Fallback käme der AP
`ninlight-<mac4>` mit dem öffentlichen Default-Passwort bei jedem
Reconnect/Reboot zurück, offen fürs LAN (SDK-NAPT).
Verifiziert in sdk/Platform/Sys/tls_sys.c, sdk/Include/Platform/wm_params.h
und sdk/Platform/Common/Params/wm_param.c:
- TLS_PARAM_ID_WPROTOCOL (10) ist ein u8, TLS_PARAM_IEEE80211_SOFTAP == 4 ==
IEEE80211_MODE_AP (sdk/Include/WiFi/wm_wifi.h).
- tls_param_get()/tls_param_set(id, argv, to_flash) - genau die Signaturen
aus dem Finding.
- tls_param_to_default() (tls_param_load_factory_default() + param_to_flash())
arbeitet ausschließlich auf `struct tls_sys_param` (Wi-Fi/Netzwerk-Konfig);
es liest/schreibt nirgends die MAC-Adresse oder RF-Kalibrierdaten - die
liegen in einer komplett getrennten, efuse-gestützten FT_PARAM_ST-Struktur
in sdk/Platform/Drivers/efuse/wm_efuse.c. tls_param_to_default() ist damit
für den Werksreset sicher.
Fix (nl_wifi_w600.c):
1. clear_softap_param(): liest TLS_PARAM_ID_WPROTOCOL, löscht bei gesetztem
IEEE80211_MODE_AP-Bit und persistiert das (to_flash=TRUE). Aufgerufen in
nl_wifi_start() (vor allem anderen) und nach jedem tls_wifi_softap_destroy().
2. nl_wifi_start(): zerstört einen bereits vom SDK selbst erzeugten SoftAP
(tls_wifi_softap_get_state() != WM_WIFI_DISCONNECTED), bevor unsere eigene
State Machine startet.
3. Backstop im Netzwerk-Task: NETIF_WIFI_SOFTAP_SUCCESS, während die State
Machine sagt, der AP solle unten sein (s_sm.ap_up == false) -> AP wieder
zerstören und Param erneut löschen (geloggt).
4. Werksreset (nl_app_factory_reset, src/app_main.c): setzt zusätzlich
tls_param_to_default() (siehe Verifikation oben) und dokumentiert das
inline.
Nebenbei im selben Treiber erledigt, weil sie denselben Codepfad betreffen:
- M2: connect_station() loggt den Rückgabewert von tls_wifi_connect(), wenn
er nicht WM_SUCCESS ist.
- M3: start_ap() merkt sich einen fehlgeschlagenen tls_wifi_softap_create()
(`s_ap_create_pending`) und wiederholt ihn alle 5 s, solange die State
Machine den AP oben haben will.
Nicht host-testbar (bindet SDK-Header ein); über den Firmware-Build
verifiziert (baut sauber für evk, keine neuen Warnungen).
I2: SO_RCVTIMEO=5s war ein Timeout pro recv(), nicht für die gesamte
Anfrage. Ein Client, der 1 Byte alle 4,9 s schickt, konnte den einzigen
HTTP-Server-Task damit stundenlang belegen (Spec §7.2 will 5 s pro Header).
serve() rechnet jetzt eine absolute Deadline (nl_app_now_ms() + 5000 ms)
und setzt SO_RCVTIMEO vor jedem recv() auf die verbleibende Zeit (mindestens
1 ms); ist die Deadline überschritten, wird die Verbindung sofort verworfen.
Nicht host-testbar (nl_http_server.c bindet SDK-Sockets ein); über den
Firmware-Build verifiziert.
I1: fail_test() kehrte ohne gespeicherte Zugangsdaten stillschweigend nach
AP_ONBOARDING zurück, ohne den Stationsversuch zu trennen; ein danach doch
noch eintreffendes CONNECTED wurde in AP_ONBOARDING ignoriert, aber der
Treiber rief nl_mdns_on_ip_up() unabhängig vom Zustand auf - die Lampe
landete offen im LAN, ohne dass Zugangsdaten gespeichert wurden.
nl_wifi_actions_t bekommt ein neues Feld `disconnect`:
- fail_test() ohne Zugangsdaten setzt es (Timeout/Fehler beendet den
Stationsversuch).
- Ein CONNECTED-Event in AP_ONBOARDING gilt als Ausreißer eines bereits
gescheiterten Versuchs und wird ebenfalls getrennt (Zustand bleibt
unverändert).
- M1: nl_wifi_sm_onboard() trennt jetzt immer vor dem Testverbindungsaufbau,
damit veraltete Events eines vorherigen Versuchs nicht mehr zählen; der
Treiber (nl_wifi_request_onboard) meldet zusätzlich "wifi busy" (503),
solange bereits ein Onboarding-Test läuft.
Der Treiber (src/net/nl_wifi_w600.c) führt `disconnect` vor `connect` aus
und ruft nl_mdns_on_ip_up() nur noch, wenn der Zustand nach der Verarbeitung
tatsächlich STA_CONNECTED ist.
Tests (test_wifi_sm.c): Timeout/Fehler ohne Zugangsdaten -> disconnect;
CONNECTED während AP_ONBOARDING -> disconnect, Zustand unverändert;
erneutes Onboarding während laufendem Test -> disconnect vor dem neuen
connect.