diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index 8bbff3fa..17c38ce3 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -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);