confd: wifi: Refactor radio setup (access point)

Use common function for configure main SSID and
bss SSID.
This commit is contained in:
Mattias Walström
2026-01-24 09:51:02 +01:00
parent 0432d7f9b6
commit a471cdf770
+93 -149
View File
@@ -231,30 +231,22 @@ static int wifi_find_radio_aps(struct lyd_node *cifs, const char *radio_name,
return 0;
}
/* Generate BSS section for secondary AP (multi-SSID) */
static int wifi_gen_bss_section(FILE *hostapd, struct lyd_node *cifs, const char *ifname, struct lyd_node *config)
/* Helper: Write SSID and security configuration (shared between primary and BSS) */
static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd_node *config, bool is_bss)
{
const char *ssid, *hidden, *security_mode, *secret_name, *secret;
struct lyd_node *cif, *wifi, *ap, *security, *secret_node;
struct lyd_node *wifi, *ap, *security, *secret_node;
const char *ifname;
char bssid[18];
/* Find the interface node for this BSS */
LYX_LIST_FOR_EACH(cifs, cif, "interface") {
const char *name = lydx_get_cattr(cif, "name");
if (strcmp(name, ifname) == 0)
break;
}
if (!cif) {
ERROR("Failed to find interface %s for BSS section", ifname);
return SR_ERR_INVAL_ARG;
}
ifname = lydx_get_cattr(cif, "name");
wifi = lydx_get_child(cif, "wifi");
ap = lydx_get_child(wifi, "access-point");
fprintf(hostapd, "\n# BSS %s\n", ifname);
fprintf(hostapd, "bss=%s\n", ifname);
if (is_bss) {
fprintf(hostapd, "\n# BSS %s\n", ifname);
fprintf(hostapd, "bss=%s\n", ifname);
}
/* Set BSSID if custom MAC is configured */
if (!interface_get_phys_addr(cif, bssid))
@@ -270,6 +262,7 @@ static int wifi_gen_bss_section(FILE *hostapd, struct lyd_node *cifs, const char
fprintf(hostapd, "ignore_broadcast_ssid=1\n");
fprintf(hostapd, "wmm_enabled=1\n");
/* Security configuration */
security = lydx_get_child(ap, "security");
security_mode = lydx_get_cattr(security, "mode");
@@ -319,119 +312,25 @@ static int wifi_gen_bss_section(FILE *hostapd, struct lyd_node *cifs, const char
}
fprintf(hostapd, "ieee80211w=1\n");
}
return 0;
}
/* Generate hostapd config for all APs on a radio (multi-SSID support) */
static int wifi_gen_aps_on_radio(const char *radio_name, struct lyd_node *cifs,
struct lyd_node *radio_node, struct lyd_node *config)
/* Helper: Write radio-specific configuration */
static void wifi_gen_radio_config(FILE *hostapd, struct lyd_node *radio_node)
{
const char *ssid, *hidden, *security_mode, *secret_name, *secret;
struct lyd_node *primary_cif, *cif;
struct lyd_node *primary_wifi, *primary_ap;
struct lyd_node *security, *secret_node;
const char *country, *channel, *band;
const char *primary_ifname;
char hostapd_conf[256];
char **ap_list = NULL;
FILE *hostapd = NULL;
bool ax_enabled;
int ap_count = 0;
char bssid[18];
int i;
int rc = SR_ERR_OK;
wifi_find_radio_aps(cifs, radio_name, &ap_list, &ap_count);
if (ap_count == 0) {
DEBUG("No APs found on radio %s", radio_name);
goto cleanup;
}
DEBUG("Generating hostapd config for radio %s (%d APs)", radio_name, ap_count);
primary_ifname = ap_list[0];
primary_cif = NULL;
LYX_LIST_FOR_EACH(cifs, cif, "interface") {
if (!strcmp(lydx_get_cattr(cif, "name"), primary_ifname)) {
primary_cif = cif;
break;
}
}
if (!primary_cif) {
ERROR("Failed to find primary AP interface %s", primary_ifname);
rc = SR_ERR_INVAL_ARG;
goto cleanup;
}
primary_wifi = lydx_get_child(primary_cif, "wifi");
primary_ap = lydx_get_child(primary_wifi, "access-point");
/* Get AP configuration */
ssid = lydx_get_cattr(primary_ap, "ssid");
hidden = lydx_get_cattr(primary_ap, "hidden");
security = lydx_get_child(primary_ap, "security");
security_mode = lydx_get_cattr(security, "mode");
secret_name = lydx_get_cattr(security, "secret");
secret = NULL;
/* Get radio configuration */
country = lydx_get_cattr(radio_node, "country-code");
band = lydx_get_cattr(radio_node, "band");
channel = lydx_get_cattr(radio_node, "channel");
ax_enabled = lydx_get_bool(radio_node, "enable-80211ax");
/* Get secret from keystore if not open network */
if (secret_name && strcmp(security_mode, "open") != 0) {
secret_node = lydx_get_xpathf(config,
"/keystore/symmetric-keys/symmetric-key[name='%s']/symmetric-key",
secret_name);
if (secret_node) {
secret = lyd_get_value(secret_node);
}
}
snprintf(hostapd_conf, sizeof(hostapd_conf), HOSTAPD_CONF_NEXT, radio_name);
hostapd = fopen(hostapd_conf, "w");
if (!hostapd) {
ERROR("Failed to create hostapd config: %s", hostapd_conf);
rc = SR_ERR_INTERNAL;
goto cleanup;
}
fprintf(hostapd, "# Generated by Infix confd - WiFi Radio %s\n", radio_name);
fprintf(hostapd, "# Primary BSS: %s", primary_ifname);
if (ap_count > 1)
fprintf(hostapd, " (%d total APs)\n\n", ap_count);
else
fprintf(hostapd, "\n\n");
fprintf(hostapd, "interface=%s\n", primary_ifname);
fprintf(hostapd, "driver=nl80211\n");
fprintf(hostapd, "ctrl_interface=/run/hostapd\n");
/* Set BSSID if custom MAC is configured */
if (!interface_get_phys_addr(primary_cif, bssid))
fprintf(hostapd, "bssid=%s\n", bssid);
fprintf(hostapd, "\n");
fprintf(hostapd, "ssid=%s\n", ssid);
if (hidden && !strcmp(hidden, "true"))
fprintf(hostapd, "ignore_broadcast_ssid=1\n");
fprintf(hostapd, "\n");
if (country)
fprintf(hostapd, "country_code=%s\n", country);
/* Enable 802.11d (regulatory domain) and 802.11h (spectrum management/DFS) */
fprintf(hostapd, "ieee80211d=1\n");
fprintf(hostapd, "ieee80211h=1\n");
fprintf(hostapd, "wmm_enabled=1\n");
/* Band and channel configuration */
if (band) {
@@ -467,23 +366,19 @@ static int wifi_gen_aps_on_radio(const char *radio_name, struct lyd_node *cifs,
fprintf(hostapd, "channel=%s\n", channel);
}
}
}
if (band) {
/* 802.11n/ac/ax configuration */
if (!strcmp(band, "2.4GHz")) {
/* 2.4GHz: Enable 802.11n (HT), optionally 802.11ax */
fprintf(hostapd, "ieee80211n=1\n");
if (ax_enabled) {
if (ax_enabled)
fprintf(hostapd, "ieee80211ax=1\n");
}
} else if (!strcmp(band, "5GHz")) {
/* 5GHz: Enable 802.11n and 802.11ac, optionally 802.11ax */
fprintf(hostapd, "ieee80211n=1\n");
fprintf(hostapd, "ieee80211ac=1\n");
if (ax_enabled) {
if (ax_enabled)
fprintf(hostapd, "ieee80211ax=1\n");
}
} else if (!strcmp(band, "6GHz")) {
/* 6GHz: Enable 802.11ax (required for 6GHz) */
fprintf(hostapd, "ieee80211n=1\n");
@@ -492,43 +387,92 @@ static int wifi_gen_aps_on_radio(const char *radio_name, struct lyd_node *cifs,
}
}
fprintf(hostapd, "\n");
}
/* Security configuration */
if (!strcmp(security_mode, "open")) {
fprintf(hostapd, "# Open network (no encryption)\n");
fprintf(hostapd, "auth_algs=1\n");
} else if (!strcmp(security_mode, "wpa2-personal")) {
fprintf(hostapd, "# WPA2-Personal\n");
fprintf(hostapd, "wpa=2\n");
fprintf(hostapd, "wpa_key_mgmt=WPA-PSK\n");
fprintf(hostapd, "wpa_pairwise=CCMP\n");
fprintf(hostapd, "wpa_passphrase=%s\n", secret);
} else if (!strcmp(security_mode, "wpa3-personal")) {
fprintf(hostapd, "# WPA3-Personal\n");
fprintf(hostapd, "wpa=2\n");
fprintf(hostapd, "wpa_key_mgmt=SAE\n");
fprintf(hostapd, "rsn_pairwise=CCMP\n");
fprintf(hostapd, "sae_password=%s\n", secret);
fprintf(hostapd, "ieee80211w=2\n");
} else if (!strcmp(security_mode, "wpa2-wpa3-personal")) {
fprintf(hostapd, "# WPA2/WPA3 Mixed Mode\n");
fprintf(hostapd, "wpa=2\n");
fprintf(hostapd, "wpa_key_mgmt=WPA-PSK SAE\n");
fprintf(hostapd, "rsn_pairwise=CCMP\n");
fprintf(hostapd, "wpa_passphrase=%s\n", secret);
fprintf(hostapd, "sae_password=%s\n", secret);
fprintf(hostapd, "ieee80211w=1\n");
/* Generate hostapd config for all APs on a radio (multi-SSID support) */
static int wifi_gen_aps_on_radio(const char *radio_name, struct lyd_node *cifs,
struct lyd_node *radio_node, struct lyd_node *config)
{
struct lyd_node *primary_cif, *cif;
const char *primary_ifname;
char hostapd_conf[256];
char **ap_list = NULL;
FILE *hostapd = NULL;
int ap_count = 0;
int rc = SR_ERR_OK;
int i;
wifi_find_radio_aps(cifs, radio_name, &ap_list, &ap_count);
if (ap_count == 0) {
DEBUG("No APs found on radio %s", radio_name);
goto cleanup;
}
DEBUG("Generating hostapd config for radio %s (%d APs)", radio_name, ap_count);
primary_ifname = ap_list[0];
primary_cif = NULL;
LYX_LIST_FOR_EACH(cifs, cif, "interface") {
if (!strcmp(lydx_get_cattr(cif, "name"), primary_ifname)) {
primary_cif = cif;
break;
}
}
if (!primary_cif) {
ERROR("Failed to find primary AP interface %s", primary_ifname);
rc = SR_ERR_INVAL_ARG;
goto cleanup;
}
snprintf(hostapd_conf, sizeof(hostapd_conf), HOSTAPD_CONF_NEXT, radio_name);
hostapd = fopen(hostapd_conf, "w");
if (!hostapd) {
ERROR("Failed to create hostapd config: %s", hostapd_conf);
rc = SR_ERR_INTERNAL;
goto cleanup;
}
fprintf(hostapd, "# Generated by Infix confd - WiFi Radio %s\n", radio_name);
fprintf(hostapd, "# Primary BSS: %s", primary_ifname);
if (ap_count > 1)
fprintf(hostapd, " (%d total APs)\n\n", ap_count);
else
fprintf(hostapd, "\n\n");
fprintf(hostapd, "interface=%s\n", primary_ifname);
fprintf(hostapd, "driver=nl80211\n");
fprintf(hostapd, "ctrl_interface=/run/hostapd\n\n");
/* Primary AP SSID and security configuration */
wifi_gen_ssid_config(hostapd, primary_cif, config, false);
fprintf(hostapd, "\n");
/* Radio-specific configuration */
wifi_gen_radio_config(hostapd, radio_node);
/* Add BSS sections for secondary APs (multi-SSID) */
for (i = 1; i < ap_count; i++) {
DEBUG("Adding BSS section for secondary AP %s", ap_list[i]);
rc = wifi_gen_bss_section(hostapd, cifs, ap_list[i], config);
if (rc != SR_ERR_OK) {
ERROR("Failed to generate BSS section for %s", ap_list[i]);
struct lyd_node *bss_cif = NULL;
LYX_LIST_FOR_EACH(cifs, cif, "interface") {
if (!strcmp(lydx_get_cattr(cif, "name"), ap_list[i])) {
bss_cif = cif;
break;
}
}
if (!bss_cif) {
ERROR("Failed to find interface %s for BSS section", ap_list[i]);
fclose(hostapd);
rc = SR_ERR_INVAL_ARG;
goto cleanup;
}
DEBUG("Adding BSS section for secondary AP %s", ap_list[i]);
wifi_gen_ssid_config(hostapd, bss_cif, config, true);
}
fclose(hostapd);