summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2023-09-15 18:30:04 +0000
committerFelix Fietkau2023-09-15 18:30:05 +0000
commitafcd3825dad9b6a6712fbf6ed8e4434819a34009 (patch)
treef41ae0effbd04b086f10094d827f0e6a83b2d5f1
parent88a3a9e2be07c5a5521d336f8dab485a089a346c (diff)
downloadnetifd-afcd3825dad9b6a6712fbf6ed8e4434819a34009.tar.gz
wireless: dynamically enable/disable virtual interfaces base on network interface autostart
This allows disabling individual interfaces with ifup/ifdown calls Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--config.c2
-rw-r--r--interface.c3
-rw-r--r--wireless.c68
-rw-r--r--wireless.h4
4 files changed, 72 insertions, 5 deletions
diff --git a/config.c b/config.c
index 8f4a383..dbf4425 100644
--- a/config.c
+++ b/config.c
@@ -784,7 +784,7 @@ config_init_all(void)
vlist_flush(&interfaces);
interface_refresh_assignments(false);
interface_start_pending();
- wireless_start_pending();
+ wireless_start_pending(0);
return ret;
}
diff --git a/interface.c b/interface.c
index 66e0e80..a18e872 100644
--- a/interface.c
+++ b/interface.c
@@ -25,6 +25,7 @@
#include "ubus.h"
#include "config.h"
#include "system.h"
+#include "wireless.h"
struct vlist_tree interfaces;
static LIST_HEAD(iface_all_users);
@@ -1125,6 +1126,7 @@ interface_set_up(struct interface *iface)
const char *error = NULL;
iface->autostart = true;
+ wireless_check_network_enabled();
if (iface->state != IFS_DOWN)
return;
@@ -1157,6 +1159,7 @@ interface_set_down(struct interface *iface)
__interface_set_down(iface, false);
} else {
iface->autostart = false;
+ wireless_check_network_enabled();
__interface_set_down(iface, false);
}
}
diff --git a/wireless.c b/wireless.c
index 958080e..a21bf54 100644
--- a/wireless.c
+++ b/wireless.c
@@ -198,6 +198,9 @@ prepare_config(struct wireless_device *wdev, struct blob_buf *buf, bool up)
l = blobmsg_open_table(&b, "interfaces");
vlist_for_each_element(&wdev->interfaces, vif, node) {
+ if (vif->disabled)
+ continue;
+
i = blobmsg_open_table(&b, vif->name);
vif_config_add_bridge(&b, vif->network, up);
put_container(&b, vif->config, "config");
@@ -1522,19 +1525,78 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
return 0;
}
-/* called on startup and by netifd reload() */
-void
-wireless_start_pending(void)
+static void
+wdev_check_network_enabled(struct wireless_device *wdev)
+{
+ struct wireless_interface *vif;
+ struct interface *iface;
+ struct blob_attr *cur;
+ int rem;
+
+ vlist_for_each_element(&wdev->interfaces, vif, node) {
+ int enabled = -1;
+
+ blobmsg_for_each_attr(cur, vif->network, rem) {
+ iface = vlist_find(&interfaces, blobmsg_get_string(cur), iface, node);
+ if (!iface)
+ continue;
+
+ if (iface->autostart) {
+ enabled = 1;
+ break;
+ }
+ if (enabled != 1)
+ enabled = 0;
+ }
+
+ if (vif->disabled == !enabled)
+ continue;
+
+ vif->disabled = !enabled;
+ wdev->config_update = true;
+ }
+}
+
+static void
+__wireless_start_pending(struct uloop_timeout *t)
{
struct wireless_device *wdev;
vlist_for_each_element(&wireless_devices, wdev, node) {
+ wdev_check_network_enabled(wdev);
if (wdev->config_update)
wdev_set_config_state(wdev, IFC_RELOAD);
__wireless_device_set_up(wdev, 0);
}
}
+void wireless_start_pending(int timeout)
+{
+ static struct uloop_timeout timer = {
+ .cb = __wireless_start_pending
+ };
+
+ if (timeout) {
+ uloop_timeout_set(&timer, timeout);
+ return;
+ }
+
+ uloop_timeout_cancel(&timer);
+ timer.cb(&timer);
+}
+
+void wireless_check_network_enabled(void)
+{
+ struct wireless_device *wdev;
+
+ vlist_for_each_element(&wireless_devices, wdev, node) {
+ wdev_check_network_enabled(wdev);
+
+ if (wdev->config_update)
+ wireless_start_pending(1000);
+ }
+}
+
void wireless_device_hotplug_event(const char *name, bool add)
{
struct wireless_interface *vif;
diff --git a/wireless.h b/wireless.h
index eaf75f7..f8bbd2f 100644
--- a/wireless.h
+++ b/wireless.h
@@ -94,6 +94,7 @@ struct wireless_interface {
int multicast_to_unicast;
int vlan_idx;
int sta_idx;
+ bool disabled;
};
struct wireless_vlan {
@@ -142,7 +143,8 @@ void wireless_station_create(struct wireless_interface *vif, struct blob_attr *d
int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
struct ubus_request_data *req);
-void wireless_start_pending(void);
+void wireless_check_network_enabled(void);
+void wireless_start_pending(int timeout);
void wireless_init(void);
void wireless_device_hotplug_event(const char *name, bool add);