fixing adoption with invalid WiFi Name scheme
This commit is contained in:
+9
-2
@@ -239,7 +239,9 @@ int clients_read_wifi(const char *wlan_iface,
|
|||||||
struct json_object *clients_build_sta_table(const char *wlan_iface,
|
struct json_object *clients_build_sta_table(const char *wlan_iface,
|
||||||
const char *radio_band,
|
const char *radio_band,
|
||||||
int channel,
|
int channel,
|
||||||
const char *vap_name)
|
const char *vap_name,
|
||||||
|
int vlan_id,
|
||||||
|
int is_11r)
|
||||||
{
|
{
|
||||||
sta_info_t stas[MAX_STA];
|
sta_info_t stas[MAX_STA];
|
||||||
int n = clients_read_wifi(wlan_iface, radio_band, channel,
|
int n = clients_read_wifi(wlan_iface, radio_band, channel,
|
||||||
@@ -266,7 +268,12 @@ struct json_object *clients_build_sta_table(const char *wlan_iface,
|
|||||||
json_object_object_add(o, "channel", json_object_new_int(s->channel));
|
json_object_object_add(o, "channel", json_object_new_int(s->channel));
|
||||||
json_object_object_add(o, "vap_name", json_object_new_string(
|
json_object_object_add(o, "vap_name", json_object_new_string(
|
||||||
vap_name ? vap_name : wlan_iface));
|
vap_name ? vap_name : wlan_iface));
|
||||||
json_object_object_add(o, "is_11r", json_object_new_boolean(s->is_11r));
|
json_object_object_add(o, "is_11r", json_object_new_boolean(is_11r));
|
||||||
|
if (vlan_id > 0) {
|
||||||
|
json_object_object_add(o, "vlan", json_object_new_int(vlan_id));
|
||||||
|
json_object_object_add(o, "vlan_id", json_object_new_int(vlan_id));
|
||||||
|
}
|
||||||
|
json_object_object_add(o, "is_wired", json_object_new_boolean(false));
|
||||||
json_object_object_add(o, "ccq", json_object_new_int(s->ccq));
|
json_object_object_add(o, "ccq", json_object_new_int(s->ccq));
|
||||||
json_object_object_add(o, "idletime", json_object_new_int(0));
|
json_object_object_add(o, "idletime", json_object_new_int(0));
|
||||||
json_object_array_add(arr, o);
|
json_object_array_add(arr, o);
|
||||||
|
|||||||
+3
-1
@@ -72,7 +72,9 @@ int clients_read_wifi(const char *wlan_iface,
|
|||||||
struct json_object *clients_build_sta_table(const char *wlan_iface,
|
struct json_object *clients_build_sta_table(const char *wlan_iface,
|
||||||
const char *radio_band,
|
const char *radio_band,
|
||||||
int channel,
|
int channel,
|
||||||
const char *vap_name);
|
const char *vap_name,
|
||||||
|
int vlan_id,
|
||||||
|
int is_11r);
|
||||||
|
|
||||||
/* Busca IP en /proc/net/arp dado un MAC. */
|
/* Busca IP en /proc/net/arp dado un MAC. */
|
||||||
int clients_mac_to_ip(const char *mac, char *ip_out, size_t sz);
|
int clients_mac_to_ip(const char *mac, char *ip_out, size_t sz);
|
||||||
|
|||||||
+42
-6
@@ -360,21 +360,31 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
|||||||
const char *radio = "ng";
|
const char *radio = "ng";
|
||||||
const char *bssid = "00:00:00:00:00:00";
|
const char *bssid = "00:00:00:00:00:00";
|
||||||
const char *vap_id = NULL;
|
const char *vap_id = NULL;
|
||||||
|
const char *ifname = NULL;
|
||||||
|
int vlan_id = 0;
|
||||||
|
int is_11r = 0;
|
||||||
|
|
||||||
if (json_object_object_get_ex(vap, "essid", &v)) essid = json_object_get_string(v);
|
if (json_object_object_get_ex(vap, "essid", &v)) essid = json_object_get_string(v);
|
||||||
if (json_object_object_get_ex(vap, "name", &v)) vap_name = json_object_get_string(v);
|
if (json_object_object_get_ex(vap, "name", &v)) vap_name = json_object_get_string(v);
|
||||||
if (json_object_object_get_ex(vap, "radio", &v)) radio = json_object_get_string(v);
|
if (json_object_object_get_ex(vap, "radio", &v)) radio = json_object_get_string(v);
|
||||||
if (json_object_object_get_ex(vap, "bssid", &v)) bssid = json_object_get_string(v);
|
if (json_object_object_get_ex(vap, "bssid", &v)) bssid = json_object_get_string(v);
|
||||||
if (json_object_object_get_ex(vap, "id", &v)) vap_id = json_object_get_string(v);
|
if (json_object_object_get_ex(vap, "id", &v)) vap_id = json_object_get_string(v);
|
||||||
|
if (json_object_object_get_ex(vap, "ifname", &v)) ifname = json_object_get_string(v);
|
||||||
|
if (json_object_object_get_ex(vap, "vlan_id", &v)) vlan_id = json_object_get_int(v);
|
||||||
|
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 */
|
/* Mapear banda → interfaz wlan y canal actual */
|
||||||
char wlan_iface[32] = "wlan0";
|
char wlan_iface[32] = "phy0-ap0";
|
||||||
|
if (ifname && ifname[0])
|
||||||
|
snprintf(wlan_iface, sizeof(wlan_iface), "%s", ifname);
|
||||||
int channel = 6;
|
int channel = 6;
|
||||||
for (int j = 0; j < m->radio_map_len; j++) {
|
for (int j = 0; j < m->radio_map_len; j++) {
|
||||||
if (strcmp(m->radio_map[j].band, radio) == 0) {
|
if (strcmp(m->radio_map[j].band, radio) == 0) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
sscanf(m->radio_map[j].device, "radio%d", &idx);
|
sscanf(m->radio_map[j].device, "radio%d", &idx);
|
||||||
snprintf(wlan_iface, sizeof(wlan_iface), "wlan%d", idx);
|
if (!ifname || !ifname[0])
|
||||||
|
snprintf(wlan_iface, sizeof(wlan_iface), "phy%d-ap0", idx);
|
||||||
radio_stats_t rs;
|
radio_stats_t rs;
|
||||||
if (sysinfo_radio(wlan_iface, &rs) == 0 && rs.channel)
|
if (sysinfo_radio(wlan_iface, &rs) == 0 && rs.channel)
|
||||||
channel = rs.channel;
|
channel = rs.channel;
|
||||||
@@ -390,7 +400,8 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
|||||||
|
|
||||||
/* Clientes conectados a esta VAP */
|
/* Clientes conectados a esta VAP */
|
||||||
struct json_object *sta_tbl =
|
struct json_object *sta_tbl =
|
||||||
clients_build_sta_table(wlan_iface, radio, channel, vap_name);
|
clients_build_sta_table(wlan_iface, radio, channel, vap_name,
|
||||||
|
vlan_id, is_11r);
|
||||||
int num_sta = json_object_array_length(sta_tbl);
|
int num_sta = json_object_array_length(sta_tbl);
|
||||||
|
|
||||||
/* Calcular tx_power del radio correspondiente */
|
/* Calcular tx_power del radio correspondiente */
|
||||||
@@ -408,6 +419,8 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
|||||||
json_object_new_string(vap_name));
|
json_object_new_string(vap_name));
|
||||||
json_object_object_add(o, "radio",
|
json_object_object_add(o, "radio",
|
||||||
json_object_new_string(radio));
|
json_object_new_string(radio));
|
||||||
|
if (vlan_id > 0)
|
||||||
|
json_object_object_add(o, "vlan_id", json_object_new_int(vlan_id));
|
||||||
json_object_object_add(o, "up",
|
json_object_object_add(o, "up",
|
||||||
json_object_new_boolean(iface_st.up));
|
json_object_new_boolean(iface_st.up));
|
||||||
json_object_object_add(o, "channel",
|
json_object_object_add(o, "channel",
|
||||||
@@ -448,6 +461,25 @@ static struct json_object *build_vap_table(const uf_model_t *m)
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build the device-level station table UniFi uses for client ownership. */
|
||||||
|
static struct json_object *collect_sta_table(struct json_object *vap_table)
|
||||||
|
{
|
||||||
|
struct json_object *all = json_object_new_array();
|
||||||
|
int vap_count = json_object_array_length(vap_table);
|
||||||
|
for (int i = 0; i < vap_count; i++) {
|
||||||
|
struct json_object *vap = json_object_array_get_idx(vap_table, i);
|
||||||
|
struct json_object *stations;
|
||||||
|
if (!json_object_object_get_ex(vap, "sta_table", &stations) ||
|
||||||
|
!json_object_is_type(stations, json_type_array))
|
||||||
|
continue;
|
||||||
|
int count = json_object_array_length(stations);
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
json_object_array_add(all, json_object_get(
|
||||||
|
json_object_array_get_idx(stations, j)));
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
/* ═══════════════════════════════════════════════════════════════════
|
/* ═══════════════════════════════════════════════════════════════════
|
||||||
build_payload — ensamblado completo del JSON inform
|
build_payload — ensamblado completo del JSON inform
|
||||||
═══════════════════════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════════════════════ */
|
||||||
@@ -546,8 +578,12 @@ static char *build_payload(const openuf_state_t *st,
|
|||||||
build_port_table(root, m);
|
build_port_table(root, m);
|
||||||
build_eth_table(root, m);
|
build_eth_table(root, m);
|
||||||
|
|
||||||
/* ── VAPs con clientes WiFi (sta_table anidado) ─────────────── */
|
/* Publish both per-VAP and device-level station views. */
|
||||||
json_object_object_add(root, "vap_table", build_vap_table(m));
|
struct json_object *vap_table = build_vap_table(m);
|
||||||
|
struct json_object *sta_table = collect_sta_table(vap_table);
|
||||||
|
int station_count = json_object_array_length(sta_table);
|
||||||
|
json_object_object_add(root, "vap_table", vap_table);
|
||||||
|
json_object_object_add(root, "sta_table", sta_table);
|
||||||
|
|
||||||
/* ── Vecinos LLDP para topología visual ─────────────────────── */
|
/* ── Vecinos LLDP para topología visual ─────────────────────── */
|
||||||
json_object_object_add(root, "lldp_table", lldp_read_neighbors());
|
json_object_object_add(root, "lldp_table", lldp_read_neighbors());
|
||||||
@@ -555,7 +591,7 @@ static char *build_payload(const openuf_state_t *st,
|
|||||||
/* Contadores globales */
|
/* Contadores globales */
|
||||||
json_object_object_add(root, "bytes_r", json_object_new_int(0));
|
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, "bytes_d", json_object_new_int(0));
|
||||||
json_object_object_add(root, "num_sta", json_object_new_int(0));
|
json_object_object_add(root, "num_sta", json_object_new_int(station_count));
|
||||||
|
|
||||||
const char *s = json_object_to_json_string(root);
|
const char *s = json_object_to_json_string(root);
|
||||||
|
|
||||||
|
|||||||
+123
-41
@@ -122,6 +122,36 @@ static int valid_object_id(const char *id)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build one stable 802.11r mobility domain shared by every AP for an SSID. */
|
||||||
|
static void mobility_domain_for_ssid(const char *ssid, char out[5])
|
||||||
|
{
|
||||||
|
unsigned int hash = 2166136261u;
|
||||||
|
const unsigned char *p = (const unsigned char *)(ssid ? ssid : "");
|
||||||
|
while (*p) {
|
||||||
|
hash ^= *p++;
|
||||||
|
hash *= 16777619u;
|
||||||
|
}
|
||||||
|
snprintf(out, 5, "%04x", (hash ^ (hash >> 16)) & 0xffffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a UniFi boolean while accepting names used by controller versions. */
|
||||||
|
static int json_boolean_any(struct json_object *object,
|
||||||
|
const char *const *keys, size_t key_count)
|
||||||
|
{
|
||||||
|
struct json_object *value;
|
||||||
|
for (size_t i = 0; i < key_count; i++) {
|
||||||
|
if (!json_object_object_get_ex(object, keys[i], &value))
|
||||||
|
continue;
|
||||||
|
if (json_object_is_type(value, json_type_string)) {
|
||||||
|
const char *text = json_object_get_string(value);
|
||||||
|
return !strcasecmp(text, "enabled") || !strcasecmp(text, "true") ||
|
||||||
|
!strcasecmp(text, "on") || !strcmp(text, "1");
|
||||||
|
}
|
||||||
|
return json_object_get_boolean(value) ? 1 : 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Safe UCI section name (maximum 15 characters). */
|
/* Safe UCI section name (maximum 15 characters). */
|
||||||
static void safe_section_name(const char *ssid, char *out, size_t sz)
|
static void safe_section_name(const char *ssid, char *out, size_t sz)
|
||||||
{
|
{
|
||||||
@@ -483,13 +513,27 @@ static int apply_vap(struct uci_context *ctx,
|
|||||||
int vap_idx)
|
int vap_idx)
|
||||||
{
|
{
|
||||||
struct json_object *v;
|
struct json_object *v;
|
||||||
|
(void)mac_str;
|
||||||
const char *essid = "";
|
const char *essid = "";
|
||||||
const char *security = "wpa2psk";
|
const char *security = "wpa2psk";
|
||||||
const char *pass = "";
|
const char *pass = "";
|
||||||
|
|
||||||
if (json_object_object_get_ex(vap_json, "essid", &v)) essid = json_object_get_string(v);
|
if (json_object_object_get_ex(vap_json, "essid", &v)) essid = json_object_get_string(v);
|
||||||
if (json_object_object_get_ex(vap_json, "security", &v)) security = json_object_get_string(v);
|
if (json_object_object_get_ex(vap_json, "security", &v)) security = json_object_get_string(v);
|
||||||
if (json_object_object_get_ex(vap_json, "x_passphrase",&v)) pass = json_object_get_string(v);
|
if (json_object_object_get_ex(vap_json, "x_passphrase",&v)) pass = json_object_get_string(v);
|
||||||
|
|
||||||
|
/* Resolve the final network before creating the VAP; never fail open. */
|
||||||
|
int vid = 0;
|
||||||
|
char target_network[32] = "lan";
|
||||||
|
if (json_object_object_get_ex(vap_json, "vlan_id", &v))
|
||||||
|
vid = json_object_get_int(v);
|
||||||
|
if (vid > 0) {
|
||||||
|
if (ensure_vlan_network(vid) != 0) {
|
||||||
|
printf("[openuf] Failed to configure VLAN network %d\n", vid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(target_network, sizeof(target_network), "vlan%d", vid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Nombre de sección: openuf_<idx>_<ssid_safe> */
|
/* Nombre de sección: openuf_<idx>_<ssid_safe> */
|
||||||
char safe[16] = {0};
|
char safe[16] = {0};
|
||||||
@@ -505,7 +549,7 @@ static int apply_vap(struct uci_context *ctx,
|
|||||||
UCI_SET(ctx, "wireless", sec_name, "device", device_name);
|
UCI_SET(ctx, "wireless", sec_name, "device", device_name);
|
||||||
UCI_SET(ctx, "wireless", sec_name, "mode", "ap");
|
UCI_SET(ctx, "wireless", sec_name, "mode", "ap");
|
||||||
UCI_SET(ctx, "wireless", sec_name, "ssid", essid);
|
UCI_SET(ctx, "wireless", sec_name, "ssid", essid);
|
||||||
UCI_SET(ctx, "wireless", sec_name, "network", "lan");
|
UCI_SET(ctx, "wireless", sec_name, "network", target_network);
|
||||||
UCI_SET(ctx, "wireless", sec_name, "encryption", sec_to_uci(security));
|
UCI_SET(ctx, "wireless", sec_name, "encryption", sec_to_uci(security));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -567,25 +611,18 @@ static int apply_vap(struct uci_context *ctx,
|
|||||||
/* ── Fast Roaming (802.11r FT) ────────────────────────────────
|
/* ── Fast Roaming (802.11r FT) ────────────────────────────────
|
||||||
* Permite que los clientes se muevan entre APs sin re-autenticación
|
* Permite que los clientes se muevan entre APs sin re-autenticación
|
||||||
* completa. El handshake FT sólo tarda ~50ms vs ~200-300ms normal. */
|
* completa. El handshake FT sólo tarda ~50ms vs ~200-300ms normal. */
|
||||||
int ft = 0;
|
const char *ft_keys[] = {
|
||||||
if (json_object_object_get_ex(vap_json, "fast_roaming_enabled", &v))
|
"fast_roaming_enabled", "fast_roaming", "ft_enabled", "ieee80211r"
|
||||||
ft = json_object_get_boolean(v) ? 1 : 0;
|
};
|
||||||
|
int ft = json_boolean_any(vap_json, ft_keys,
|
||||||
|
sizeof(ft_keys) / sizeof(ft_keys[0]));
|
||||||
if (ft) {
|
if (ft) {
|
||||||
UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211r", 1);
|
char mdomain[5];
|
||||||
UCI_SET_INT(ctx, "wireless", sec_name, "ft_over_ds", 1);
|
mobility_domain_for_ssid(essid, mdomain);
|
||||||
|
UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211r", 1);
|
||||||
|
UCI_SET_INT(ctx, "wireless", sec_name, "ft_over_ds", 0);
|
||||||
UCI_SET_INT(ctx, "wireless", sec_name, "ft_psk_generate_local", 1);
|
UCI_SET_INT(ctx, "wireless", sec_name, "ft_psk_generate_local", 1);
|
||||||
/* mobility_domain: derivar de MAC del AP (2 bytes) */
|
/* Local key generation avoids external R0KH/R1KH dependencies. */
|
||||||
char mdomain[8] = {0};
|
|
||||||
if (mac_str && strlen(mac_str) >= 5) {
|
|
||||||
/* Usar bytes 0 y 1 de la MAC como dominio */
|
|
||||||
char b0[3]={mac_str[0],mac_str[1],0};
|
|
||||||
char b1[3]={mac_str[3],mac_str[4],0};
|
|
||||||
unsigned int v0=0,v1=0;
|
|
||||||
sscanf(b0,"%x",&v0); sscanf(b1,"%x",&v1);
|
|
||||||
snprintf(mdomain, sizeof(mdomain), "%02x%02x", v0, v1);
|
|
||||||
} else {
|
|
||||||
strcpy(mdomain, "1234");
|
|
||||||
}
|
|
||||||
UCI_SET(ctx, "wireless", sec_name, "mobility_domain", mdomain);
|
UCI_SET(ctx, "wireless", sec_name, "mobility_domain", mdomain);
|
||||||
} else {
|
} else {
|
||||||
UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211r", 0);
|
UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211r", 0);
|
||||||
@@ -609,22 +646,9 @@ static int apply_vap(struct uci_context *ctx,
|
|||||||
UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211v", 0);
|
UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211v", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── VLAN ──────────────────────────────────────────────────────
|
/* Record the controller VLAN for telemetry and diagnostics. */
|
||||||
* Si vlan_id ≠ 0, configurar la interfaz con VLAN tagging. */
|
if (vid > 0)
|
||||||
if (json_object_object_get_ex(vap_json, "vlan_id", &v)) {
|
UCI_SET_INT(ctx, "wireless", sec_name, "vlan_id", vid);
|
||||||
int vid = json_object_get_int(v);
|
|
||||||
if (vid > 0) {
|
|
||||||
if (ensure_vlan_network(vid) != 0) {
|
|
||||||
printf("[openuf] Failed to configure VLAN network %d\n", vid);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
UCI_SET_INT(ctx, "wireless", sec_name, "vlan_id", vid);
|
|
||||||
/* Establecer network a vlanXXX si existe */
|
|
||||||
char vlan_net[32];
|
|
||||||
snprintf(vlan_net, sizeof(vlan_net), "vlan%d", vid);
|
|
||||||
UCI_SET(ctx, "wireless", sec_name, "network", vlan_net);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reassert the binding last and reject incomplete UCI sections. */
|
/* Reassert the binding last and reject incomplete UCI sections. */
|
||||||
if (uci_set_required(ctx, pkg, sec_name, "device", device_name) != 0) {
|
if (uci_set_required(ctx, pkg, sec_name, "device", device_name) != 0) {
|
||||||
@@ -632,9 +656,14 @@ static int apply_vap(struct uci_context *ctx,
|
|||||||
essid, device_name);
|
essid, device_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (uci_set_required(ctx, pkg, sec_name, "network", target_network) != 0) {
|
||||||
|
printf("[openuf] Refusing unsafe VAP '%s': cannot bind to %s\n",
|
||||||
|
essid, target_network);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
printf("[openuf] VAP '%s' -> %s device=%s enc=%s ft=%d bs=%d pmf=%d\n",
|
printf("[openuf] VAP '%s' -> %s device=%s network=%s enc=%s ft=%d bs=%d pmf=%d\n",
|
||||||
essid, sec_name, device_name, sec_to_uci(security),
|
essid, sec_name, device_name, target_network, sec_to_uci(security),
|
||||||
ft, band_steer, pmf);
|
ft, band_steer, pmf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -868,6 +897,20 @@ int wlan_apply_system_cfg(const char *system_cfg,
|
|||||||
json_object_object_add(vap, "essid",
|
json_object_object_add(vap, "essid",
|
||||||
json_object_new_string(value));
|
json_object_new_string(value));
|
||||||
|
|
||||||
|
/* Preserve the WLAN ObjectId used to attach clients in topology. */
|
||||||
|
const char *id_suffixes[] = { "id", "_id", "wlanconf_id" };
|
||||||
|
for (size_t id_index = 0;
|
||||||
|
id_index < sizeof(id_suffixes) / sizeof(id_suffixes[0]);
|
||||||
|
id_index++) {
|
||||||
|
snprintf(key, sizeof(key), "aaa.%d.%s", i,
|
||||||
|
id_suffixes[id_index]);
|
||||||
|
if (system_cfg_get(system_cfg, key, value, sizeof(value)) &&
|
||||||
|
valid_object_id(value)) {
|
||||||
|
json_object_object_add(vap, "id", json_object_new_string(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(key, sizeof(key), "aaa.%d.status", i);
|
snprintf(key, sizeof(key), "aaa.%d.status", i);
|
||||||
if (system_cfg_get(system_cfg, key, value, sizeof(value)) &&
|
if (system_cfg_get(system_cfg, key, value, sizeof(value)) &&
|
||||||
strcmp(value, "enabled")) {
|
strcmp(value, "enabled")) {
|
||||||
@@ -950,6 +993,40 @@ int wlan_apply_system_cfg(const char *system_cfg,
|
|||||||
También intentamos leer el BSSID real de la interfaz wlan
|
También intentamos leer el BSSID real de la interfaz wlan
|
||||||
desde /sys/class/net/<iface>/address.
|
desde /sys/class/net/<iface>/address.
|
||||||
*/
|
*/
|
||||||
|
/* Resolve a configured VAP to the live interface reported by nl80211. */
|
||||||
|
static int find_runtime_vap(int phy_index, const char *ssid,
|
||||||
|
char *out, size_t out_size)
|
||||||
|
{
|
||||||
|
FILE *pipe = popen("iw dev 2>/dev/null", "r");
|
||||||
|
if (!pipe) return -1;
|
||||||
|
|
||||||
|
int phy = -1;
|
||||||
|
char candidate[32] = "";
|
||||||
|
char line[256];
|
||||||
|
while (fgets(line, sizeof(line), pipe)) {
|
||||||
|
int parsed_phy;
|
||||||
|
char value[128];
|
||||||
|
if (sscanf(line, "phy#%d", &parsed_phy) == 1) {
|
||||||
|
phy = parsed_phy;
|
||||||
|
candidate[0] = '\0';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sscanf(line, " Interface %31s", value) == 1) {
|
||||||
|
snprintf(candidate, sizeof(candidate), "%s", value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (phy == phy_index && candidate[0] &&
|
||||||
|
sscanf(line, " ssid %127[^\n]", value) == 1 &&
|
||||||
|
!strcmp(value, ssid)) {
|
||||||
|
snprintf(out, out_size, "%s", candidate);
|
||||||
|
pclose(pipe);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pclose(pipe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
struct json_object *wlan_get_vap_table(const uf_model_t *model)
|
struct json_object *wlan_get_vap_table(const uf_model_t *model)
|
||||||
{
|
{
|
||||||
struct json_object *arr = json_object_new_array();
|
struct json_object *arr = json_object_new_array();
|
||||||
@@ -981,6 +1058,7 @@ struct json_object *wlan_get_vap_table(const uf_model_t *model)
|
|||||||
const char *w11 = UCI_GET("ieee80211w");
|
const char *w11 = UCI_GET("ieee80211w");
|
||||||
const char *hidden = UCI_GET("hidden");
|
const char *hidden = UCI_GET("hidden");
|
||||||
const char *vap_id = UCI_GET("openuf_vap_id");
|
const char *vap_id = UCI_GET("openuf_vap_id");
|
||||||
|
const char *vlan = UCI_GET("vlan_id");
|
||||||
|
|
||||||
if (!ssid) ssid = "";
|
if (!ssid) ssid = "";
|
||||||
if (!device) device = "radio0";
|
if (!device) device = "radio0";
|
||||||
@@ -994,11 +1072,12 @@ struct json_object *wlan_get_vap_table(const uf_model_t *model)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nombre de la interfaz wlan (wlan0 para radio0, etc.) */
|
/* Resolve the actual netifd interface (for example phy1-ap0). */
|
||||||
char wlan_iface[32] = "wlan0";
|
char wlan_iface[32];
|
||||||
int ridx = 0;
|
int ridx = 0;
|
||||||
sscanf(device, "radio%d", &ridx);
|
sscanf(device, "radio%d", &ridx);
|
||||||
snprintf(wlan_iface, sizeof(wlan_iface), "wlan%d", ridx);
|
if (find_runtime_vap(ridx, ssid, wlan_iface, sizeof(wlan_iface)) != 0)
|
||||||
|
snprintf(wlan_iface, sizeof(wlan_iface), "phy%d-ap0", ridx);
|
||||||
|
|
||||||
/* Leer BSSID real desde sysfs */
|
/* Leer BSSID real desde sysfs */
|
||||||
char bssid[32] = "00:00:00:00:00:00";
|
char bssid[32] = "00:00:00:00:00:00";
|
||||||
@@ -1027,7 +1106,8 @@ struct json_object *wlan_get_vap_table(const uf_model_t *model)
|
|||||||
struct json_object *o = json_object_new_object();
|
struct json_object *o = json_object_new_object();
|
||||||
json_object_object_add(o, "essid", json_object_new_string(ssid));
|
json_object_object_add(o, "essid", json_object_new_string(ssid));
|
||||||
json_object_object_add(o, "bssid", json_object_new_string(bssid));
|
json_object_object_add(o, "bssid", json_object_new_string(bssid));
|
||||||
json_object_object_add(o, "name", json_object_new_string(sec->e.name));
|
json_object_object_add(o, "name", json_object_new_string(wlan_iface));
|
||||||
|
json_object_object_add(o, "ifname", json_object_new_string(wlan_iface));
|
||||||
json_object_object_add(o, "radio", json_object_new_string(radio_band));
|
json_object_object_add(o, "radio", json_object_new_string(radio_band));
|
||||||
json_object_object_add(o, "security", json_object_new_string(sec_to_unifi(enc)));
|
json_object_object_add(o, "security", json_object_new_string(sec_to_unifi(enc)));
|
||||||
json_object_object_add(o, "up", json_object_new_boolean(up));
|
json_object_object_add(o, "up", json_object_new_boolean(up));
|
||||||
@@ -1036,6 +1116,8 @@ struct json_object *wlan_get_vap_table(const uf_model_t *model)
|
|||||||
json_object_object_add(o, "band_steering", json_object_new_boolean(bs_on));
|
json_object_object_add(o, "band_steering", json_object_new_boolean(bs_on));
|
||||||
json_object_object_add(o, "pmf_mode", json_object_new_string(pmf));
|
json_object_object_add(o, "pmf_mode", json_object_new_string(pmf));
|
||||||
json_object_object_add(o, "num_sta", json_object_new_int(0));
|
json_object_object_add(o, "num_sta", json_object_new_int(0));
|
||||||
|
if (vlan && atoi(vlan) > 0)
|
||||||
|
json_object_object_add(o, "vlan_id", json_object_new_int(atoi(vlan)));
|
||||||
if (valid_object_id(vap_id))
|
if (valid_object_id(vap_id))
|
||||||
json_object_object_add(o, "id", json_object_new_string(vap_id));
|
json_object_object_add(o, "id", json_object_new_string(vap_id));
|
||||||
json_object_array_add(arr, o);
|
json_object_array_add(arr, o);
|
||||||
|
|||||||
Reference in New Issue
Block a user