diff --git a/CONFIGURE.md b/CONFIGURE.md index e7457c3..626b9b5 100644 --- a/CONFIGURE.md +++ b/CONFIGURE.md @@ -288,3 +288,16 @@ grep 'CONFIG-H:' `find . -type f -name "*.[ch]"`|sed 's/^.*CONFIG-.: *\(.*\)$/|\ |Parameter|Purpose|Notes [Default is bracketed]| |---------|-------|-----| |hostapd_dir|Path to hostapd runtime information|[/var/run/hostapd]| +|steering_ssid|SSID that DAWN is allowed to manage (repeatable; empty = all)|[]| + +By default DAWN manages every BSS it discovers under `hostapd_dir`. To limit +DAWN to a subset of your networks, add one `list steering_ssid ''` entry +per SSID you want managed. Any BSS whose SSID is not listed is left entirely +alone: DAWN never subscribes to it, so it neither steers/kicks its clients nor +shares their measurements with peer APs. When no `steering_ssid` is configured +the list is empty and the historic "manage everything" behaviour is preserved. + + config hostapd + option hostapd_dir '/var/run/hostapd' + list steering_ssid 'MyMainNetwork' + list steering_ssid 'MyRoamingNetwork' diff --git a/dawn-config b/dawn-config index 603038b..d58807d 100644 --- a/dawn-config +++ b/dawn-config @@ -16,6 +16,10 @@ config network config hostapd option hostapd_dir '/var/run/hostapd' + # Optional: restrict DAWN to specific SSIDs. Repeat for each managed + # SSID. If no steering_ssid is listed, DAWN manages every BSS (default). + #list steering_ssid 'MyMainNetwork' + #list steering_ssid 'MyRoamingNetwork' config times option con_timeout '60' diff --git a/src/include/dawn_uci.h b/src/include/dawn_uci.h index 83e01d5..6288e31 100644 --- a/src/include/dawn_uci.h +++ b/src/include/dawn_uci.h @@ -46,6 +46,18 @@ struct network_config_s uci_get_dawn_network(); */ bool uci_get_dawn_hostapd_dir(); +/** + * Load the optional allow-list of SSIDs that DAWN may manage from the config + * file. When no 'steering_ssid' entries are present DAWN manages every BSS. + */ +void uci_get_dawn_steering_ssids(); + +/** + * Test whether a given SSID is in the configured steering allow-list. + * @return true if the SSID may be managed (always true when the list is empty). + */ +bool dawn_ssid_is_managed(const char *ssid); + int uci_set_network(char* uci_cmd); /** diff --git a/src/main.c b/src/main.c index 8b3e71a..87a6718 100644 --- a/src/main.c +++ b/src/main.c @@ -114,6 +114,7 @@ int main(int argc, char **argv) { timeout_config = time_config; // TODO: Refactor... uci_get_dawn_hostapd_dir(); + uci_get_dawn_steering_ssids(); init_mutex(); diff --git a/src/utils/dawn_uci.c b/src/utils/dawn_uci.c index 5ea0f97..d130602 100644 --- a/src/utils/dawn_uci.c +++ b/src/utils/dawn_uci.c @@ -468,6 +468,65 @@ bool uci_get_dawn_hostapd_dir() { return false; } +// Optional allow-list of SSIDs that DAWN is permitted to manage. When the +// list is empty DAWN keeps its default behaviour of managing every BSS it +// finds, so the feature is opt-in and backwards compatible. +struct steering_ssid_s { + char ssid[SSID_MAX_LEN + 1]; + struct steering_ssid_s *next; +}; + +static struct steering_ssid_s *steering_ssid_list = NULL; + +void uci_get_dawn_steering_ssids() { + dawnlog_debug_func("Entering..."); + + // Drop any previously loaded list (e.g. on config reload) + while (steering_ssid_list) { + struct steering_ssid_s *tmp = steering_ssid_list; + steering_ssid_list = steering_ssid_list->next; + dawn_free(tmp); + } + + struct uci_element *e; + uci_foreach_element(&uci_pkg->sections, e) + { + struct uci_section *s = uci_to_section(e); + + if (strcmp(s->type, "hostapd") == 0) { + // CONFIG-H: steering_ssid|SSID that DAWN is allowed to manage (repeatable; empty = all)|[] + struct uci_option *o = uci_lookup_option(uci_ctx, s, "steering_ssid"); + if (o && o->type == UCI_TYPE_LIST) { + struct uci_element *le; + uci_foreach_element(&o->v.list, le) + { + struct steering_ssid_s *entry = dawn_calloc(1, sizeof(struct steering_ssid_s)); + if (!entry) + continue; + strncpy(entry->ssid, le->name, SSID_MAX_LEN); + entry->ssid[SSID_MAX_LEN] = '\0'; + entry->next = steering_ssid_list; + steering_ssid_list = entry; + } + } + return; + } + } +} + +bool dawn_ssid_is_managed(const char *ssid) { + // Empty allow-list => manage everything (default DAWN behaviour) + if (steering_ssid_list == NULL) + return true; + + for (struct steering_ssid_s *e = steering_ssid_list; e; e = e->next) { + if (strncmp(e->ssid, ssid, SSID_MAX_LEN) == 0) + return true; + } + + return false; +} + int uci_reset() { dawnlog_debug_func("Entering..."); diff --git a/src/utils/ubus.c b/src/utils/ubus.c index 94fe0a0..8e7b679 100644 --- a/src/utils/ubus.c +++ b/src/utils/ubus.c @@ -1818,6 +1818,20 @@ void subscribe_to_new_interfaces(const char *hostapd_sock_path) { break; } } + // Honour the optional steering_ssid allow-list: if we can read the + // BSS's SSID and it is not permitted, leave the interface entirely + // unmanaged (no subscription, no probes, not shared with peers). + // Fail open: if the SSID cannot be determined, manage it as before. + if (do_subscribe) { + char iface_ssid[SSID_MAX_LEN + 1] = {0}; + get_ssid(entry->d_name, iface_ssid, SSID_MAX_LEN); + if (iface_ssid[0] != '\0' && !dawn_ssid_is_managed(iface_ssid)) { + dawnlog_info("[SUBSCRIBING] Skipping %s: SSID '%s' not in steering_ssid list\n", + entry->d_name, iface_ssid); + do_subscribe = false; + } + } + if (do_subscribe) { subscriber_to_interface(entry->d_name); }