Translated all files to ENG (#5)
Reviewed-on: #5 Co-authored-by: Finn <fwaggoner@nmfpgt.de> Co-committed-by: Finn <fwaggoner@nmfpgt.de>
This commit was merged in pull request #5.
This commit is contained in:
+89
-89
@@ -1,50 +1,50 @@
|
||||
/*
|
||||
* openuf - inform.c
|
||||
*
|
||||
* Protocolo Inform de UniFi — implementación completa.
|
||||
* UniFi Inform Protocol — full implementation.
|
||||
*
|
||||
* ── CÓMO FUNCIONA ────────────────────────────────────────────────────
|
||||
* ── HOW IT WORKS ─────────────────────────────────────────────────────
|
||||
*
|
||||
* Cada 10 segundos el AP hace HTTP POST a http://<controller>:8080/inform
|
||||
* con un paquete binario TNBU que contiene JSON cifrado con AES-128-CBC.
|
||||
* Every 10 seconds the AP makes an HTTP POST to http://<controller>:8080/inform
|
||||
* with a binary TNBU packet containing JSON encrypted with AES-128-CBC.
|
||||
*
|
||||
* El controlador responde con otro paquete TNBU. El AP descifra, parsea
|
||||
* el JSON y ejecuta la acción (_type).
|
||||
* The controller responds with another TNBU packet. The AP decrypts, parses
|
||||
* the JSON, and executes the action (_type).
|
||||
*
|
||||
* ── PAQUETE BINARIO TNBU ─────────────────────────────────────────────
|
||||
* ── TNBU BINARY PACKET ───────────────────────────────────────────────
|
||||
*
|
||||
* Offset Bytes Campo
|
||||
* Offset Bytes Field
|
||||
* ------ ----- -----
|
||||
* 0 4 Magic "TNBU"
|
||||
* 4 4 Versión paquete (=0), uint32 BE
|
||||
* 8 6 MAC del AP
|
||||
* 14 2 Flags: bit0=cifrado, bit1=zlib
|
||||
* 16 16 IV de AES (cuando cifrado)
|
||||
* 32 4 Versión de datos (=1), uint32 BE
|
||||
* 36 4 Longitud del payload, uint32 BE
|
||||
* 40 N Payload JSON, cifrado con AES-128-CBC
|
||||
* 4 4 Packet version (=0), uint32 BE
|
||||
* 8 6 AP MAC address
|
||||
* 14 2 Flags: bit0=encrypted, bit1=zlib
|
||||
* 16 16 AES IV (when encrypted)
|
||||
* 32 4 Data version (=1), uint32 BE
|
||||
* 36 4 Payload length, uint32 BE
|
||||
* 40 N JSON payload, encrypted with AES-128-CBC
|
||||
*
|
||||
* ── CÓMO SE LEEN LOS PARÁMETROS ──────────────────────────────────────
|
||||
* ── HOW PARAMETERS ARE READ ──────────────────────────────────────────
|
||||
*
|
||||
* CPU: sysinfo_cpu_percent() → /proc/stat (delta 2 llamadas)
|
||||
* RAM: sysinfo_mem() → /proc/meminfo
|
||||
* Interfaces: sysinfo_iface() → /proc/net/dev + /sys/class/net/
|
||||
* Radios: sysinfo_radio() → iw dev <iface> info + survey
|
||||
* VAPs UCI: wlan_get_vap_table() → libuci wireless.*
|
||||
* Clientes WiFi: clients_build_sta_table() → iw dev <iface> station dump
|
||||
* Clientes IP: clients_mac_to_ip() → /proc/net/arp
|
||||
* Clientes nombre: clients_mac_to_hostname() → /tmp/dhcp.leases
|
||||
* LLDP vecinos: lldp_read_neighbors() → lldpctl -f json
|
||||
* CPU: sysinfo_cpu_percent() → /proc/stat (delta across 2 calls)
|
||||
* RAM: sysinfo_mem() → /proc/meminfo
|
||||
* Interfaces: sysinfo_iface() → /proc/net/dev + /sys/class/net/
|
||||
* Radios: sysinfo_radio() → iw dev <iface> info + survey
|
||||
* UCI VAPs: wlan_get_vap_table() → libuci wireless.*
|
||||
* WiFi clients: clients_build_sta_table() → iw dev <iface> station dump
|
||||
* IP clients: clients_mac_to_ip() → /proc/net/arp
|
||||
* Client names: clients_mac_to_hostname() → /tmp/dhcp.leases
|
||||
* LLDP neighbors: lldp_read_neighbors() → lldpctl -f json
|
||||
*
|
||||
* ── CICLO DE ADOPCIÓN ────────────────────────────────────────────────
|
||||
* ── ADOPTION CYCLE ───────────────────────────────────────────────────
|
||||
*
|
||||
* 1. AP envía inform con key=DEFAULT, default=true, state=1
|
||||
* 2. Controller responde: {_type:"cmd", cmd:"set-adopt",
|
||||
* key:"nuevaclave32hex", uri:"http://..."}
|
||||
* 3. AP guarda nueva clave + URL en state.json, adopted=true
|
||||
* 4. AP envía inform con nueva clave, state=4, default=false
|
||||
* 5. Controller responde: {_type:"setstate", radio_table:[...], vap_table:[...]}
|
||||
* 6. AP aplica config WiFi via wlan_apply_config() → libuci → wifi reload
|
||||
* 1. AP sends inform with key=DEFAULT, default=true, state=1
|
||||
* 2. Controller responds: {_type:"cmd", cmd:"set-adopt",
|
||||
* key:"new32hexkey", uri:"http://..."}
|
||||
* 3. AP saves the new key + URL to state.json, adopted=true
|
||||
* 4. AP sends inform with the new key, state=4, default=false
|
||||
* 5. Controller responds: {_type:"setstate", radio_table:[...], vap_table:[...]}
|
||||
* 6. AP applies WiFi config via wlan_apply_config() → libuci → wifi reload
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -95,10 +95,10 @@ static int valid_authkey(const char *key)
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
sys_stats — CPU y memoria del sistema
|
||||
sys_stats — CPU and memory of the system
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
El controlador muestra CPU y RAM en la vista del dispositivo.
|
||||
Leemos /proc/stat y /proc/meminfo directamente.
|
||||
The controller shows CPU and RAM in the device view.
|
||||
We read /proc/stat and /proc/meminfo directly.
|
||||
*/
|
||||
static struct json_object *build_sys_stats(void)
|
||||
{
|
||||
@@ -121,7 +121,7 @@ static struct json_object *build_sys_stats(void)
|
||||
json_object_object_add(o, "mem_buffer", json_object_new_int(0));
|
||||
}
|
||||
|
||||
/* CPU — delta respecto a llamada anterior (cada ~10s da buen promedio) */
|
||||
/* CPU — delta relative to the previous call (every ~10s gives a good average) */
|
||||
json_object_object_add(o, "cpu",
|
||||
json_object_new_int(sysinfo_cpu_percent()));
|
||||
|
||||
@@ -129,11 +129,11 @@ static struct json_object *build_sys_stats(void)
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
if_table — estadísticas de interfaces de red
|
||||
if_table — network interface statistics
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
Reportamos todos los puertos ethernet del modelo.
|
||||
Leemos /proc/net/dev para contadores y /sys/class/net/<iface>/
|
||||
para velocidad, duplex y estado del enlace.
|
||||
All Ethernet ports on the model are reported.
|
||||
/proc/net/dev is read for counters, and /sys/class/net/<iface>/
|
||||
for speed, duplex, and link status.
|
||||
*/
|
||||
static struct json_object *build_if_table(const uf_model_t *m,
|
||||
const openuf_state_t *st)
|
||||
@@ -184,10 +184,10 @@ static struct json_object *build_if_table(const uf_model_t *m,
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
radio_table — definición estática del hardware de radio
|
||||
radio_table — static definition of the radio hardware
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
Describe las capacidades físicas de cada radio al controlador.
|
||||
El controlador usa esto para saber qué frecuencias y modos soporta.
|
||||
Describes the physical capabilities of each radio to the controller.
|
||||
The controller uses this to know which frequencies and modes it supports.
|
||||
*/
|
||||
static void build_radio_table(struct json_object *root,
|
||||
const uf_model_t *m)
|
||||
@@ -215,12 +215,12 @@ static void build_radio_table(struct json_object *root,
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
radio_table_stats — estadísticas dinámicas de canal
|
||||
radio_table_stats — dynamic channel statistics
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
Leemos en tiempo real la utilización del canal con:
|
||||
iw dev wlan0 survey dump → active/busy/tx/rx time
|
||||
iw dev wlan0 info → canal actual, potencia
|
||||
El controlador muestra estos datos en la vista de RF.
|
||||
Channel utilization is read in real time using:
|
||||
iw dev wlan0 survey dump → active/busy/tx/rx time
|
||||
iw dev wlan0 info → current channel, power
|
||||
The controller displays this data in the RF view.
|
||||
*/
|
||||
static struct json_object *build_radio_table_stats(const uf_model_t *m)
|
||||
{
|
||||
@@ -229,13 +229,13 @@ static struct json_object *build_radio_table_stats(const uf_model_t *m)
|
||||
for (int i = 0; i < m->radio_map_len; i++) {
|
||||
const uf_radio_map_t *rm = &m->radio_map[i];
|
||||
|
||||
/* Mapear "radio0" → "wlan0" por convención OpenWrt */
|
||||
/* Map "radio0" → "wlan0" by OpenWrt convention */
|
||||
char wlan_iface[32];
|
||||
int ridx = 0;
|
||||
sscanf(rm->device, "radio%d", &ridx);
|
||||
snprintf(wlan_iface, sizeof(wlan_iface), "wlan%d", ridx);
|
||||
|
||||
/* Nombre del radio en la tabla estática */
|
||||
/* Radio name in the static table */
|
||||
const char *radio_name = (i < m->radio_table_len)
|
||||
? m->radio_table[i].name : wlan_iface;
|
||||
int default_ch = (i < m->radio_table_len)
|
||||
@@ -272,10 +272,10 @@ static struct json_object *build_radio_table_stats(const uf_model_t *m)
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
port_table — estado real de los puertos ethernet
|
||||
port_table — Real/actual status of the ethernet ports
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
Leemos /sys/class/net/<iface>/speed y operstate para
|
||||
reflejar el estado real de cada puerto en el controlador.
|
||||
/sys/class/net/<iface>/speed and operstate are read to
|
||||
reflect the actual status of each port on the controller.
|
||||
*/
|
||||
static void build_port_table(struct json_object *root,
|
||||
const uf_model_t *m)
|
||||
@@ -328,24 +328,24 @@ static void build_eth_table(struct json_object *root, const uf_model_t *m)
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
vap_table — VAPs activas con clientes conectados (sta_table)
|
||||
vap_table — active VAPs with connected clients (sta_table)
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
Para cada VAP activa en UCI:
|
||||
1. Leemos estadísticas de la interfaz wlan con sysinfo_iface()
|
||||
2. Obtenemos el canal actual con sysinfo_radio()
|
||||
3. Enumeramos clientes con clients_build_sta_table()
|
||||
→ iw dev wlan0 station dump (señal, bitrate, bytes, uptime)
|
||||
For each active VAP in UCI:
|
||||
1. Interface statistics for the wlan are read with sysinfo_iface()
|
||||
2. The current channel is obtained with sysinfo_radio()
|
||||
3. Clients are enumerated with clients_build_sta_table()
|
||||
→ iw dev wlan0 station dump (signal, bitrate, bytes, uptime)
|
||||
→ /proc/net/arp (MAC → IP)
|
||||
→ /tmp/dhcp.leases (MAC → hostname)
|
||||
|
||||
El sta_table anidado es lo que el controlador usa para:
|
||||
- Mostrar clientes en el dashboard
|
||||
- Calcular estadísticas por cliente
|
||||
- Dibujar la topología de la red
|
||||
The nested sta_table is what the controller uses to:
|
||||
- Display clients on the dashboard
|
||||
- Calculate per-client statistics
|
||||
- Draw the network topology
|
||||
*/
|
||||
static struct json_object *build_vap_table(const uf_model_t *m)
|
||||
{
|
||||
/* Obtener lista de VAPs desde UCI */
|
||||
/* Get list of VAPs from UCI */
|
||||
struct json_object *uci_vaps = wlan_get_vap_table(m);
|
||||
int nvaps = json_object_array_length(uci_vaps);
|
||||
|
||||
@@ -374,7 +374,7 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
||||
if (json_object_object_get_ex(vap, "fast_roaming_enabled", &v))
|
||||
is_11r = json_object_get_boolean(v);
|
||||
|
||||
/* Mapear banda → interfaz wlan y canal actual */
|
||||
/* Map band → wlan interface and current channel */
|
||||
char wlan_iface[32] = "phy0-ap0";
|
||||
if (ifname && ifname[0])
|
||||
snprintf(wlan_iface, sizeof(wlan_iface), "%s", ifname);
|
||||
@@ -394,17 +394,17 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
||||
}
|
||||
}
|
||||
|
||||
/* Estadísticas de la interfaz inalámbrica */
|
||||
/* Wireless interface statistics */
|
||||
iface_stats_t iface_st;
|
||||
sysinfo_iface(wlan_iface, &iface_st);
|
||||
|
||||
/* Clientes conectados a esta VAP */
|
||||
/* Clients connected to this VAP */
|
||||
struct json_object *sta_tbl =
|
||||
clients_build_sta_table(wlan_iface, radio, channel, vap_name,
|
||||
vlan_id, is_11r);
|
||||
int num_sta = json_object_array_length(sta_tbl);
|
||||
|
||||
/* Calcular tx_power del radio correspondiente */
|
||||
/* Calculate tx_power of the corresponding radio */
|
||||
int tx_pwr = 20;
|
||||
radio_stats_t rs2;
|
||||
if (sysinfo_radio(wlan_iface, &rs2) == 0 && rs2.tx_power)
|
||||
@@ -452,7 +452,7 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
||||
json_object_new_string("user"));
|
||||
json_object_object_add(o, "ccq",
|
||||
json_object_new_int(0));
|
||||
/* sta_table anidado — clientes de ESTA VAP */
|
||||
/* Nested sta_table — clients of THIS VAP */
|
||||
json_object_object_add(o, "sta_table", sta_tbl);
|
||||
|
||||
json_object_array_add(arr, o);
|
||||
@@ -481,13 +481,13 @@ static struct json_object *collect_sta_table(struct json_object *vap_table)
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
build_payload — ensamblado completo del JSON inform
|
||||
build_payload — Complete assembly of the inform JSON
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
static char *build_payload(const openuf_state_t *st,
|
||||
const uf_model_t *m,
|
||||
long uptime)
|
||||
{
|
||||
/* MAC sin colones → serial (uppercase) */
|
||||
/* MAC without colons → serial (uppercase) */
|
||||
char mac_clean[32] = {0};
|
||||
{
|
||||
const char *s = st->mac; int j = 0;
|
||||
@@ -511,7 +511,7 @@ static char *build_payload(const openuf_state_t *st,
|
||||
|
||||
struct json_object *root = json_object_new_object();
|
||||
|
||||
/* ── Identidad del dispositivo ──────────────────────────────── */
|
||||
/* ── Device identity ──────────────────────────────── */
|
||||
json_object_object_add(root, "mac",
|
||||
json_object_new_string(st->mac));
|
||||
json_object_object_add(root, "serial",
|
||||
@@ -564,17 +564,17 @@ static char *build_payload(const openuf_state_t *st,
|
||||
/* ── CPU + RAM ──────────────────────────────────────────────── */
|
||||
json_object_object_add(root, "sys_stats", build_sys_stats());
|
||||
|
||||
/* ── Interfaces ethernet con contadores reales ──────────────── */
|
||||
/* ── Ethernet interfaces with real counters ──────────────── */
|
||||
json_object_object_add(root, "if_table", build_if_table(m, st));
|
||||
|
||||
/* ── Capacidades de radio (estático del modelo) ─────────────── */
|
||||
/* ── Radio capabilities (static, from the model) ─────────────── */
|
||||
build_radio_table(root, m);
|
||||
|
||||
/* ── Utilización de canal en tiempo real ────────────────────── */
|
||||
/* ── Real-time channel utilization ────────────────────── */
|
||||
json_object_object_add(root, "radio_table_stats",
|
||||
build_radio_table_stats(m));
|
||||
|
||||
/* ── Puertos ethernet con estado real ───────────────────────── */
|
||||
/* ── Ethernet ports with actual status ───────────────────────── */
|
||||
build_port_table(root, m);
|
||||
build_eth_table(root, m);
|
||||
|
||||
@@ -585,10 +585,10 @@ static char *build_payload(const openuf_state_t *st,
|
||||
json_object_object_add(root, "vap_table", vap_table);
|
||||
json_object_object_add(root, "sta_table", sta_table);
|
||||
|
||||
/* ── Vecinos LLDP para topología visual ─────────────────────── */
|
||||
/* ── LLDP neighbors for visual topology ─────────────────────── */
|
||||
json_object_object_add(root, "lldp_table", lldp_read_neighbors());
|
||||
|
||||
/* Contadores globales */
|
||||
/* Global counters */
|
||||
json_object_object_add(root, "bytes_r", json_object_new_int(0));
|
||||
json_object_object_add(root, "bytes_d", json_object_new_int(0));
|
||||
json_object_object_add(root, "num_sta", json_object_new_int(station_count));
|
||||
@@ -610,7 +610,7 @@ static char *build_payload(const openuf_state_t *st,
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
Paquete binario TNBU
|
||||
TNBU binary packet
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
static unsigned char *build_packet(const char *mac_hex,
|
||||
const char *key_hex,
|
||||
@@ -668,7 +668,7 @@ static unsigned char *build_packet(const char *mac_hex,
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
Parsear respuesta binaria del controlador
|
||||
Parse binary response from the controller
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
static char *parse_packet(const unsigned char *data, size_t data_len,
|
||||
const char *key_hex)
|
||||
@@ -717,13 +717,13 @@ static char *parse_packet(const unsigned char *data, size_t data_len,
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
Procesar comando JSON del controlador
|
||||
Process JSON command from the controller
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
_type == "noop" → no hacer nada
|
||||
_type == "noop" → do nothing
|
||||
_type == "cmd" → set-adopt / reboot / reset / locate
|
||||
_type == "setstate" → aplicar radio_table + vap_table via UCI
|
||||
_type == "setparam" → cambiar un parámetro individual
|
||||
_type == "setstate" → apply radio_table + vap_table via UCI
|
||||
_type == "setparam" → change a single parameter
|
||||
*/
|
||||
static void handle_response(openuf_state_t *st,
|
||||
const uf_model_t *model,
|
||||
@@ -896,7 +896,7 @@ static void handle_response(openuf_state_t *st,
|
||||
system("reboot &");
|
||||
|
||||
} else if (!strcmp(cmd, "locate")) {
|
||||
/* Parpadear LED — en OpenWrt: echo 1 > /sys/class/leds/.../trigger */
|
||||
/* Blink LED — on OpenWrt: echo 1 > /sys/class/leds/.../trigger */
|
||||
strcpy(action_out, "locate");
|
||||
} else {
|
||||
snprintf(action_out, 64, "cmd:%s", cmd);
|
||||
@@ -904,7 +904,7 @@ static void handle_response(openuf_state_t *st,
|
||||
return;
|
||||
}
|
||||
|
||||
/* ── setstate — configuración WiFi del controlador ──────────── */
|
||||
/* ── setstate — WiFi configuration from the controller ──────────── */
|
||||
if (!strcmp(type, "setstate")) {
|
||||
if (json_object_object_get_ex(resp, "cfgversion", &v))
|
||||
snprintf(st->cfgversion, sizeof(st->cfgversion),
|
||||
@@ -937,7 +937,7 @@ static void handle_response(openuf_state_t *st,
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
inform_send — función principal pública
|
||||
inform_send — main public function
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
int inform_send(openuf_state_t *st,
|
||||
const uf_model_t *model,
|
||||
@@ -961,7 +961,7 @@ int inform_send(openuf_state_t *st,
|
||||
LOG("Sending inform: adopted=%d, authkey=%.8s..., inform_url=%s",
|
||||
st->adopted, key_hex, st->inform_url);
|
||||
|
||||
/* MAC sin colones */
|
||||
/* MAC without colons */
|
||||
char mac_hex[32] = {0};
|
||||
{
|
||||
const char *s = st->mac; int j = 0;
|
||||
|
||||
Reference in New Issue
Block a user