diff --git a/board/common/rootfs/etc/finit.d/available/hostapd@.conf b/board/common/rootfs/etc/finit.d/available/hostapd@.conf deleted file mode 100644 index 638c5c61..00000000 --- a/board/common/rootfs/etc/finit.d/available/hostapd@.conf +++ /dev/null @@ -1,3 +0,0 @@ -service name:hostapd :%i \ - [2345] hostapd -P/var/run/hostapd-%i.pid /etc/hostapd-%i.conf \ - -- Wi-Fi Access Point @%i diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index 28c6ae2b..f8d847d8 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #define XPATH_BASE_ "/ietf-hardware:hardware" #define HOSTAPD_CONF "/etc/hostapd-%s.conf" #define HOSTAPD_CONF_NEXT HOSTAPD_CONF"+" +#define HOSTAPD_SERVICE "/etc/finit.d/available/hostapd.conf" #define GPSD_CONF "/etc/finit.d/available/gpsd.conf" #define GPSD_CONF_NEXT GPSD_CONF"+" #define GPSD_MAX_DEVICES 4 @@ -1177,6 +1179,7 @@ int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct l struct lyd_node *difs = NULL, *dif = NULL; int rc = SR_ERR_OK; int gps_changed = 0; + int wifi_changed = 0; if (!lydx_find_xpathf(diff, XPATH_BASE_)) return SR_ERR_OK; @@ -1238,34 +1241,25 @@ int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct l wifi_find_interfaces_on_radio(interfaces_diff, name, &wifi_iface_list, &wifi_iface_count); if (wifi_iface_count > 0) { - bool running, enabled; - ap = lydx_get_descendant(wifi_iface_list[0], "interface", "wifi", "access-point", NULL); if (ap && lydx_get_op(ap) != LYDX_OP_DELETE) { - /* AP mode - activate hostapd for radio */ snprintf(src, sizeof(src), HOSTAPD_CONF_NEXT, name); snprintf(dst, sizeof(dst), HOSTAPD_CONF, name); - running = !systemf("initctl -bfq status hostapd:%s", name); - enabled = fexistf(HOSTAPD_CONF_NEXT, name); - - if (enabled) { + if (fexistf(HOSTAPD_CONF_NEXT, name)) { (void)rename(src, dst); ap_interfaces++; - - if (running) - finit_reloadf("hostapd@%s", name); - else - finit_enablef("hostapd@%s", name); } } } if (!ap_interfaces) { - finit_disablef("hostapd@%s", name); erasef(HOSTAPD_CONF, name); erasef(HOSTAPD_CONF_NEXT, name); } free(wifi_iface_list); + /* All radios share one hostapd process; the service is + * (re)generated after the component loop below. */ + wifi_changed = 1; continue; default: continue; @@ -1361,6 +1355,45 @@ int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct l break; } } + + /* + * All AP radios run in a single hostapd process so that + * cross-radio directives (e.g. no_probe_resp_if_seen_on for band + * steering) resolve: those only consult interfaces managed by the + * same process. Regenerate the combined service from every staged + * /etc/hostapd-.conf and (re)start it. A restart re-reads + * all radio configs, so band edits and radio add/remove both apply. + */ + if (wifi_changed && event == SR_EV_DONE) { + glob_t gl = { 0 }; + + if (glob("/etc/hostapd-*.conf", 0, NULL, &gl) == 0 && gl.gl_pathc > 0) { + FILE *fp; + + fp = fopen(HOSTAPD_SERVICE, "w"); + if (!fp) { + ERRNO("Could not open " HOSTAPD_SERVICE); + rc = SR_ERR_INTERNAL; + } else { + size_t i; + + fprintf(fp, "# Generated by confd, do not edit.\n"); + fprintf(fp, "service name:hostapd \\\n"); + fprintf(fp, "\t[2345] hostapd -P /run/hostapd.pid"); + for (i = 0; i < gl.gl_pathc; i++) + fprintf(fp, " %s", gl.gl_pathv[i]); + fprintf(fp, " \\\n\t-- Wi-Fi Access Points\n"); + fclose(fp); + + finit_enable("hostapd"); + finit_reload("hostapd"); + } + } else { + unlink(HOSTAPD_SERVICE); + finit_disable("hostapd"); + } + globfree(&gl); + } err: return rc;