mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-11-03 20:07:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			503 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			503 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From d5484e69a2476ff3bea5d402d06ed3c68d2ef24d Mon Sep 17 00:00:00 2001
 | 
						|
From: John Crispin <john@phrozen.org>
 | 
						|
Date: Wed, 6 Nov 2024 12:28:41 +0100
 | 
						|
Subject: [PATCH] netifd: add various backports
 | 
						|
 | 
						|
Signed-off-by: John Crispin <john@phrozen.org>
 | 
						|
---
 | 
						|
 .../netifd/patches/100-backport_fixes.patch   | 482 ++++++++++++++++++
 | 
						|
 1 file changed, 482 insertions(+)
 | 
						|
 create mode 100644 package/network/config/netifd/patches/100-backport_fixes.patch
 | 
						|
 | 
						|
diff --git a/package/network/config/netifd/patches/100-backport_fixes.patch b/package/network/config/netifd/patches/100-backport_fixes.patch
 | 
						|
new file mode 100644
 | 
						|
index 0000000000..0442beb053
 | 
						|
--- /dev/null
 | 
						|
+++ b/package/network/config/netifd/patches/100-backport_fixes.patch
 | 
						|
@@ -0,0 +1,482 @@
 | 
						|
+--- a/device.c
 | 
						|
++++ b/device.c
 | 
						|
+@@ -166,12 +166,19 @@ static int set_device_state(struct devic
 | 
						|
+ 		dev->orig_settings.flags &= dev->settings.flags;
 | 
						|
+ 		system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
 | 
						|
+ 
 | 
						|
+-		system_if_up(dev);
 | 
						|
++		if (!dev->external)
 | 
						|
++			system_if_up(dev);
 | 
						|
+ 
 | 
						|
+ 		system_if_apply_settings_after_up(dev, &dev->settings);
 | 
						|
+ 	} else {
 | 
						|
+-		system_if_down(dev);
 | 
						|
++		if (!dev->external)
 | 
						|
++			system_if_down(dev);
 | 
						|
+ 		system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
 | 
						|
++
 | 
						|
++		/* Restore any settings present in UCI which may have
 | 
						|
++		 * failed to apply so that they will be re-attempted
 | 
						|
++		 * the next time the device is brought up */
 | 
						|
++		dev->settings.flags |= dev->settings.valid_flags;
 | 
						|
+ 	}
 | 
						|
+ 
 | 
						|
+ 	return 0;
 | 
						|
+@@ -571,6 +578,9 @@ device_init_settings(struct device *dev,
 | 
						|
+ 		s->flags |= DEV_OPT_EEE;
 | 
						|
+ 	}
 | 
						|
+ 
 | 
						|
++	/* Remember the settings present in UCI */
 | 
						|
++	s->valid_flags = s->flags;
 | 
						|
++
 | 
						|
+ 	cur = tb[DEV_ATTR_AUTH_VLAN];
 | 
						|
+ 	free(dev->config_auth_vlans);
 | 
						|
+ 	dev->config_auth_vlans = cur ? blob_memdup(cur) : NULL;
 | 
						|
+@@ -609,11 +619,15 @@ static int device_broadcast_cb(void *ctx
 | 
						|
+ 	return 0;
 | 
						|
+ }
 | 
						|
+ 
 | 
						|
+-void device_broadcast_event(struct device *dev, enum device_event ev)
 | 
						|
++static const char *device_event_name(enum device_event ev)
 | 
						|
+ {
 | 
						|
+ 	static const char * const event_names[] = {
 | 
						|
+ 		[DEV_EVENT_ADD] = "add",
 | 
						|
+ 		[DEV_EVENT_REMOVE] = "remove",
 | 
						|
++		[DEV_EVENT_UPDATE_IFNAME] = "update_ifname",
 | 
						|
++		[DEV_EVENT_UPDATE_IFINDEX] = "update_ifindex",
 | 
						|
++		[DEV_EVENT_SETUP] = "setup",
 | 
						|
++		[DEV_EVENT_TEARDOWN] = "teardown",
 | 
						|
+ 		[DEV_EVENT_UP] = "up",
 | 
						|
+ 		[DEV_EVENT_DOWN] = "down",
 | 
						|
+ 		[DEV_EVENT_AUTH_UP] = "auth_up",
 | 
						|
+@@ -621,12 +635,37 @@ void device_broadcast_event(struct devic
 | 
						|
+ 		[DEV_EVENT_LINK_DOWN] = "link_down",
 | 
						|
+ 		[DEV_EVENT_TOPO_CHANGE] = "topo_change",
 | 
						|
+ 	};
 | 
						|
++
 | 
						|
++	if (ev >= ARRAY_SIZE(event_names) || !event_names[ev])
 | 
						|
++		return "unknown";
 | 
						|
++
 | 
						|
++	return event_names[ev];
 | 
						|
++}
 | 
						|
++
 | 
						|
++void device_broadcast_event(struct device *dev, enum device_event ev)
 | 
						|
++{
 | 
						|
++	const char *ev_name;
 | 
						|
+ 	int dev_ev = ev;
 | 
						|
+ 
 | 
						|
+ 	safe_list_for_each(&dev->aliases, device_broadcast_cb, &dev_ev);
 | 
						|
+ 	safe_list_for_each(&dev->users, device_broadcast_cb, &dev_ev);
 | 
						|
+ 
 | 
						|
+-	if (ev >= ARRAY_SIZE(event_names) || !event_names[ev] || !dev->ifname[0])
 | 
						|
++	switch (ev) {
 | 
						|
++	case DEV_EVENT_ADD:
 | 
						|
++	case DEV_EVENT_REMOVE:
 | 
						|
++	case DEV_EVENT_UP:
 | 
						|
++	case DEV_EVENT_DOWN:
 | 
						|
++	case DEV_EVENT_AUTH_UP:
 | 
						|
++	case DEV_EVENT_LINK_UP:
 | 
						|
++	case DEV_EVENT_LINK_DOWN:
 | 
						|
++	case DEV_EVENT_TOPO_CHANGE:
 | 
						|
++		break;
 | 
						|
++	default:
 | 
						|
++		return;
 | 
						|
++	}
 | 
						|
++
 | 
						|
++	ev_name = device_event_name(ev);
 | 
						|
++	if (!dev->ifname[0])
 | 
						|
+ 		return;
 | 
						|
+ 
 | 
						|
+ 	blob_buf_init(&b, 0);
 | 
						|
+@@ -635,7 +674,7 @@ void device_broadcast_event(struct devic
 | 
						|
+ 	blobmsg_add_u8(&b, "present", dev->present);
 | 
						|
+ 	blobmsg_add_u8(&b, "active", dev->active);
 | 
						|
+ 	blobmsg_add_u8(&b, "link_active", dev->link_active);
 | 
						|
+-	netifd_ubus_device_notify(event_names[ev], b.head, -1);
 | 
						|
++	netifd_ubus_device_notify(ev_name, b.head, -1);
 | 
						|
+ }
 | 
						|
+ 
 | 
						|
+ static void
 | 
						|
+@@ -689,17 +728,7 @@ int device_claim(struct device_user *dep
 | 
						|
+ 
 | 
						|
+ 	device_broadcast_event(dev, DEV_EVENT_SETUP);
 | 
						|
+ 	device_fill_default_settings(dev);
 | 
						|
+-	if (dev->external) {
 | 
						|
+-		/* Get ifindex for external claimed devices so a valid   */
 | 
						|
+-		/* ifindex is in place avoiding possible race conditions */
 | 
						|
+-		device_set_ifindex(dev, system_if_resolve(dev));
 | 
						|
+-		if (!dev->ifindex)
 | 
						|
+-			ret = -1;
 | 
						|
+-
 | 
						|
+-		system_if_get_settings(dev, &dev->orig_settings);
 | 
						|
+-	} else
 | 
						|
+-		ret = dev->set_state(dev, true);
 | 
						|
+-
 | 
						|
++	ret = dev->set_state(dev, true);
 | 
						|
+ 	if (ret == 0)
 | 
						|
+ 		device_broadcast_event(dev, DEV_EVENT_UP);
 | 
						|
+ 	else {
 | 
						|
+@@ -727,8 +756,7 @@ void device_release(struct device_user *
 | 
						|
+ 		return;
 | 
						|
+ 
 | 
						|
+ 	device_broadcast_event(dev, DEV_EVENT_TEARDOWN);
 | 
						|
+-	if (!dev->external)
 | 
						|
+-		dev->set_state(dev, false);
 | 
						|
++	dev->set_state(dev, false);
 | 
						|
+ 
 | 
						|
+ 	if (dev->active)
 | 
						|
+ 		return;
 | 
						|
+@@ -810,9 +838,6 @@ device_create_default(const char *name,
 | 
						|
+ 	}
 | 
						|
+ 
 | 
						|
+ 	dev->default_config = true;
 | 
						|
+-	if (external)
 | 
						|
+-		system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
 | 
						|
+-
 | 
						|
+ 	device_check_state(dev);
 | 
						|
+ 
 | 
						|
+ 	return dev;
 | 
						|
+@@ -841,7 +866,6 @@ __device_get(const char *name, int creat
 | 
						|
+ 
 | 
						|
+ 	if (dev) {
 | 
						|
+ 		if (create > 1 && !dev->external) {
 | 
						|
+-			system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
 | 
						|
+ 			dev->external = true;
 | 
						|
+ 			device_set_present(dev, true);
 | 
						|
+ 		}
 | 
						|
+@@ -1164,11 +1188,6 @@ device_apply_config(struct device *dev,
 | 
						|
+ 	enum dev_change_type change;
 | 
						|
+ 
 | 
						|
+ 	change = device_set_config(dev, type, config);
 | 
						|
+-	if (dev->external) {
 | 
						|
+-		system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
 | 
						|
+-		change = DEV_CONFIG_APPLIED;
 | 
						|
+-	}
 | 
						|
+-
 | 
						|
+ 	switch (change) {
 | 
						|
+ 		case DEV_CONFIG_RESTART:
 | 
						|
+ 		case DEV_CONFIG_APPLIED:
 | 
						|
+@@ -1180,7 +1199,7 @@ device_apply_config(struct device *dev,
 | 
						|
+ 				int ret = 0;
 | 
						|
+ 
 | 
						|
+ 				device_set_present(dev, false);
 | 
						|
+-				if (dev->active && !dev->external) {
 | 
						|
++				if (dev->active) {
 | 
						|
+ 					ret = dev->set_state(dev, false);
 | 
						|
+ 					if (!ret)
 | 
						|
+ 						ret = dev->set_state(dev, true);
 | 
						|
+--- a/interface.c
 | 
						|
++++ b/interface.c
 | 
						|
+@@ -1078,11 +1078,17 @@ interface_add_link(struct interface *ifa
 | 
						|
+ {
 | 
						|
+ 	struct device *mdev = iface->main_dev.dev;
 | 
						|
+ 
 | 
						|
+-	if (mdev == dev)
 | 
						|
++	if (mdev == dev) {
 | 
						|
++		if (iface->state != IFS_UP) {
 | 
						|
++			interface_set_available(iface, false);
 | 
						|
++			if (dev->present)
 | 
						|
++				interface_set_available(iface, true);
 | 
						|
++		}
 | 
						|
+ 		return 0;
 | 
						|
++	}
 | 
						|
+ 
 | 
						|
+ 	if (iface->main_dev.hotplug)
 | 
						|
+-		device_remove_user(&iface->main_dev);
 | 
						|
++		interface_set_main_dev(iface, NULL);
 | 
						|
+ 
 | 
						|
+ 	if (mdev) {
 | 
						|
+ 		if (mdev->hotplug_ops)
 | 
						|
+--- a/wireless.c
 | 
						|
++++ b/wireless.c
 | 
						|
+@@ -138,7 +138,7 @@ static void
 | 
						|
+ put_container(struct blob_buf *buf, struct blob_attr *attr, const char *name)
 | 
						|
+ {
 | 
						|
+ 	void *c = blobmsg_open_table(buf, name);
 | 
						|
+-	blob_put_raw(buf, blob_data(attr), blob_len(attr));
 | 
						|
++	blob_put_raw(buf, blobmsg_data(attr), blobmsg_len(attr));
 | 
						|
+ 	blobmsg_close_table(buf, c);
 | 
						|
+ }
 | 
						|
+ 
 | 
						|
+@@ -337,12 +337,39 @@ static void wireless_device_set_mcast_to
 | 
						|
+ 	dev->settings.flags |= DEV_OPT_MULTICAST_TO_UNICAST;
 | 
						|
+ }
 | 
						|
+ 
 | 
						|
++static void wireless_check_interface(struct blob_attr *list, int *enabled, int *ifindex)
 | 
						|
++{
 | 
						|
++	struct interface *iface;
 | 
						|
++	struct blob_attr *cur;
 | 
						|
++	size_t rem;
 | 
						|
++
 | 
						|
++	blobmsg_for_each_attr(cur, list, rem) {
 | 
						|
++		struct device *mdev;
 | 
						|
++
 | 
						|
++		iface = vlist_find(&interfaces, blobmsg_get_string(cur), iface, node);
 | 
						|
++		if (!iface)
 | 
						|
++			continue;
 | 
						|
++
 | 
						|
++		if (iface->autostart)
 | 
						|
++			*enabled = 1;
 | 
						|
++		else if (*enabled != 1)
 | 
						|
++			*enabled = 0;
 | 
						|
++
 | 
						|
++		mdev = iface->main_dev.dev;
 | 
						|
++		if (!mdev || !mdev->hotplug_ops)
 | 
						|
++			continue;
 | 
						|
++
 | 
						|
++		*ifindex = mdev->ifindex;
 | 
						|
++	}
 | 
						|
++}
 | 
						|
++
 | 
						|
+ static void wireless_interface_handle_link(struct wireless_interface *vif, const char *ifname, bool up)
 | 
						|
+ {
 | 
						|
+ 	struct interface *iface;
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 	const char *network;
 | 
						|
+ 	struct device *dev;
 | 
						|
++	int enabled = -1;
 | 
						|
+ 	size_t rem;
 | 
						|
+ 
 | 
						|
+ 	if (!vif->network || !vif->ifname)
 | 
						|
+@@ -372,6 +399,7 @@ static void wireless_interface_handle_li
 | 
						|
+ 	dev->bpdu_filter = dev->wireless_ap;
 | 
						|
+ 
 | 
						|
+ out:
 | 
						|
++	wireless_check_interface(vif->network, &enabled, &vif->network_ifindex);
 | 
						|
+ 	blobmsg_for_each_attr(cur, vif->network, rem) {
 | 
						|
+ 		network = blobmsg_data(cur);
 | 
						|
+ 
 | 
						|
+@@ -388,6 +416,7 @@ static void wireless_vlan_handle_link(st
 | 
						|
+ 	struct interface *iface;
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 	const char *network;
 | 
						|
++	int enabled = -1;
 | 
						|
+ 	size_t rem;
 | 
						|
+ 
 | 
						|
+ 	if (!vlan->network || !vlan->ifname)
 | 
						|
+@@ -406,6 +435,7 @@ static void wireless_vlan_handle_link(st
 | 
						|
+ 		}
 | 
						|
+ 	}
 | 
						|
+ 
 | 
						|
++	wireless_check_interface(vlan->network, &enabled, &vlan->network_ifindex);
 | 
						|
+ 	blobmsg_for_each_attr(cur, vlan->network, rem) {
 | 
						|
+ 		network = blobmsg_data(cur);
 | 
						|
+ 
 | 
						|
+@@ -838,7 +868,7 @@ wireless_interface_init_config(struct wi
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 
 | 
						|
+ 	vif->network = NULL;
 | 
						|
+-	blobmsg_parse(vif_policy, __VIF_ATTR_MAX, tb, blob_data(vif->config), blob_len(vif->config));
 | 
						|
++	blobmsg_parse_attr(vif_policy, __VIF_ATTR_MAX, tb, vif->config);
 | 
						|
+ 
 | 
						|
+ 	if ((cur = tb[VIF_ATTR_NETWORK]))
 | 
						|
+ 		vif->network = cur;
 | 
						|
+@@ -922,7 +952,7 @@ wireless_vlan_init_config(struct wireles
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 
 | 
						|
+ 	vlan->network = NULL;
 | 
						|
+-	blobmsg_parse(vlan_policy, __VLAN_ATTR_MAX, tb, blob_data(vlan->config), blob_len(vlan->config));
 | 
						|
++	blobmsg_parse_attr(vlan_policy, __VLAN_ATTR_MAX, tb, vlan->config);
 | 
						|
+ 
 | 
						|
+ 	if ((cur = tb[VLAN_ATTR_NETWORK]))
 | 
						|
+ 		vlan->network = cur;
 | 
						|
+@@ -1079,7 +1109,7 @@ wireless_device_create(struct wireless_d
 | 
						|
+ 	struct blob_attr *tb[__WDEV_ATTR_MAX];
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(wdev_policy, __WDEV_ATTR_MAX, tb, blob_data(data), blob_len(data));
 | 
						|
++	blobmsg_parse_attr(wdev_policy, __WDEV_ATTR_MAX, tb, data);
 | 
						|
+ 
 | 
						|
+ 	wdev = calloc_a(sizeof(*wdev), &name_buf, strlen(name) + 1);
 | 
						|
+ 
 | 
						|
+@@ -1128,7 +1158,7 @@ wireless_station_create(struct wireless_
 | 
						|
+ 	char *name_buf;
 | 
						|
+ 	char name[8];
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(sta_policy, __STA_ATTR_MAX, tb, blob_data(data), blob_len(data));
 | 
						|
++	blobmsg_parse_attr(sta_policy, __STA_ATTR_MAX, tb, data);
 | 
						|
+ 
 | 
						|
+ 	cur = tb[STA_ATTR_DISABLED];
 | 
						|
+ 	if (cur && blobmsg_get_bool(cur))
 | 
						|
+@@ -1168,7 +1198,7 @@ wireless_vlan_create(struct wireless_int
 | 
						|
+ 	char *name_buf;
 | 
						|
+ 	char name[8];
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(vlan_policy, __VLAN_ATTR_MAX, tb, blob_data(data), blob_len(data));
 | 
						|
++	blobmsg_parse_attr(vlan_policy, __VLAN_ATTR_MAX, tb, data);
 | 
						|
+ 
 | 
						|
+ 	cur = tb[VLAN_ATTR_DISABLED];
 | 
						|
+ 	if (cur && blobmsg_get_bool(cur))
 | 
						|
+@@ -1208,7 +1238,7 @@ struct wireless_interface* wireless_inte
 | 
						|
+ 	char *name_buf;
 | 
						|
+ 	char name[8];
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(vif_policy, __VIF_ATTR_MAX, tb, blob_data(data), blob_len(data));
 | 
						|
++	blobmsg_parse_attr(vif_policy, __VIF_ATTR_MAX, tb, data);
 | 
						|
+ 
 | 
						|
+ 	cur = tb[VIF_ATTR_DISABLED];
 | 
						|
+ 	if (cur && blobmsg_get_bool(cur))
 | 
						|
+@@ -1232,7 +1262,15 @@ struct wireless_interface* wireless_inte
 | 
						|
+ 
 | 
						|
+ 	vlist_add(&wdev->interfaces, &vif->node, vif->name);
 | 
						|
+ 
 | 
						|
+-	return vlist_find(&wdev->interfaces, name, vif, node);
 | 
						|
++	vif = vlist_find(&wdev->interfaces, name, vif, node);
 | 
						|
++	if (!vif)
 | 
						|
++		return NULL;
 | 
						|
++
 | 
						|
++	vif->vlan_idx = vif->sta_idx = 0;
 | 
						|
++	vlist_update(&vif->vlans);
 | 
						|
++	vlist_update(&vif->stations);
 | 
						|
++
 | 
						|
++	return vif;
 | 
						|
+ }
 | 
						|
+ 
 | 
						|
+ /* ubus callback network.wireless.status, runs for every interface */
 | 
						|
+@@ -1321,8 +1359,7 @@ wireless_interface_set_data(struct wirel
 | 
						|
+ 	struct blob_attr *tb[__VIF_DATA_MAX];
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(data_policy, __VIF_DATA_MAX, tb,
 | 
						|
+-		      blobmsg_data(vif->data), blobmsg_data_len(vif->data));
 | 
						|
++	blobmsg_parse_attr(data_policy, __VIF_DATA_MAX, tb, vif->data);
 | 
						|
+ 
 | 
						|
+ 	if ((cur = tb[VIF_DATA_IFNAME]))
 | 
						|
+ 		vif->ifname = blobmsg_data(cur);
 | 
						|
+@@ -1342,8 +1379,7 @@ wireless_vlan_set_data(struct wireless_v
 | 
						|
+ 	struct blob_attr *tb[__VLAN_DATA_MAX];
 | 
						|
+ 	struct blob_attr *cur;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(data_policy, __VLAN_DATA_MAX, tb,
 | 
						|
+-		      blobmsg_data(vlan->data), blobmsg_data_len(vlan->data));
 | 
						|
++	blobmsg_parse_attr(data_policy, __VLAN_DATA_MAX, tb, vlan->data);
 | 
						|
+ 
 | 
						|
+ 	if ((cur = tb[VLAN_DATA_IFNAME]))
 | 
						|
+ 		vlan->ifname = blobmsg_data(cur);
 | 
						|
+@@ -1374,7 +1410,7 @@ wireless_device_add_process(struct wirel
 | 
						|
+ 	if (!data)
 | 
						|
+ 		return UBUS_STATUS_INVALID_ARGUMENT;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(proc_policy, __PROC_ATTR_MAX, tb, blobmsg_data(data), blobmsg_data_len(data));
 | 
						|
++	blobmsg_parse_attr(proc_policy, __PROC_ATTR_MAX, tb, data);
 | 
						|
+ 	if (!tb[PROC_ATTR_PID] || !tb[PROC_ATTR_EXE])
 | 
						|
+ 		return UBUS_STATUS_INVALID_ARGUMENT;
 | 
						|
+ 
 | 
						|
+@@ -1420,7 +1456,7 @@ wireless_device_process_kill_all(struct
 | 
						|
+ 	bool immediate = false;
 | 
						|
+ 	int signal = SIGTERM;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(kill_policy, __KILL_ATTR_MAX, tb, blobmsg_data(data), blobmsg_data_len(data));
 | 
						|
++	blobmsg_parse_attr(kill_policy, __KILL_ATTR_MAX, tb, data);
 | 
						|
+ 
 | 
						|
+ 	if ((cur = tb[KILL_ATTR_SIGNAL]))
 | 
						|
+ 		signal = blobmsg_get_u32(cur);
 | 
						|
+@@ -1451,7 +1487,7 @@ wireless_device_set_retry(struct wireles
 | 
						|
+ 	};
 | 
						|
+ 	struct blob_attr *val;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(&retry_policy, 1, &val, blobmsg_data(data), blobmsg_data_len(data));
 | 
						|
++	blobmsg_parse_attr(&retry_policy, 1, &val, data);
 | 
						|
+ 	if (val)
 | 
						|
+ 		wdev->retry = blobmsg_get_u32(val);
 | 
						|
+ 	else
 | 
						|
+@@ -1492,7 +1528,7 @@ wireless_device_notify(struct wireless_d
 | 
						|
+ 	struct blob_attr *tb[__NOTIFY_MAX];
 | 
						|
+ 	struct blob_attr *cur, **pdata;
 | 
						|
+ 
 | 
						|
+-	blobmsg_parse(notify_policy, __NOTIFY_MAX, tb, blob_data(data), blob_len(data));
 | 
						|
++	blobmsg_parse_attr(notify_policy, __NOTIFY_MAX, tb, data);
 | 
						|
+ 
 | 
						|
+ 	if (!tb[NOTIFY_ATTR_COMMAND])
 | 
						|
+ 		return UBUS_STATUS_INVALID_ARGUMENT;
 | 
						|
+@@ -1555,33 +1591,41 @@ wireless_device_notify(struct wireless_d
 | 
						|
+ }
 | 
						|
+ 
 | 
						|
+ static void
 | 
						|
++wdev_vlan_check_network_enabled(struct wireless_device *wdev,
 | 
						|
++				struct wireless_interface *vif)
 | 
						|
++{
 | 
						|
++	struct wireless_vlan *vlan;
 | 
						|
++
 | 
						|
++	vlist_for_each_element(&vif->vlans, vlan, node) {
 | 
						|
++		int enabled = -1, ifindex = -1;
 | 
						|
++
 | 
						|
++		wireless_check_interface(vlan->network, &enabled, &ifindex);
 | 
						|
++
 | 
						|
++		if (wdev->state != IFS_UP || vlan->network_ifindex == ifindex)
 | 
						|
++			continue;
 | 
						|
++
 | 
						|
++		vlan->network_ifindex = ifindex;
 | 
						|
++		wdev->config_update = true;
 | 
						|
++	}
 | 
						|
++}
 | 
						|
++
 | 
						|
++static void
 | 
						|
+ wdev_check_network_enabled(struct wireless_device *wdev)
 | 
						|
+ {
 | 
						|
+ 	struct wireless_interface *vif;
 | 
						|
+-	struct interface *iface;
 | 
						|
+-	struct blob_attr *cur;
 | 
						|
+-	size_t rem;
 | 
						|
+ 
 | 
						|
+ 	vlist_for_each_element(&wdev->interfaces, vif, node) {
 | 
						|
+-		int enabled = -1;
 | 
						|
++		int enabled = -1, ifindex = -1;
 | 
						|
+ 
 | 
						|
+-		blobmsg_for_each_attr(cur, vif->network, rem) {
 | 
						|
+-			iface = vlist_find(&interfaces, blobmsg_get_string(cur), iface, node);
 | 
						|
+-			if (!iface)
 | 
						|
+-				continue;
 | 
						|
++		wireless_check_interface(vif->network, &enabled, &ifindex);
 | 
						|
++		wdev_vlan_check_network_enabled(wdev, vif);
 | 
						|
+ 
 | 
						|
+-			if (iface->autostart) {
 | 
						|
+-				enabled = 1;
 | 
						|
+-				break;
 | 
						|
+-			}
 | 
						|
+-			if (enabled != 1)
 | 
						|
+-				enabled = 0;
 | 
						|
+-		}
 | 
						|
+-
 | 
						|
+-		if (vif->disabled == !enabled)
 | 
						|
++		if (vif->disabled == !enabled &&
 | 
						|
++		    (wdev->state != IFS_UP || vif->network_ifindex == ifindex))
 | 
						|
+ 			continue;
 | 
						|
+ 
 | 
						|
+ 		vif->disabled = !enabled;
 | 
						|
++		vif->network_ifindex = ifindex;
 | 
						|
+ 		wdev->config_update = true;
 | 
						|
+ 	}
 | 
						|
+ }
 | 
						|
+@@ -1639,10 +1683,8 @@ void wireless_device_hotplug_event(const
 | 
						|
+ 			return;
 | 
						|
+ 
 | 
						|
+ 		len = s - name;
 | 
						|
+-	} else if (!device_find(name)) {
 | 
						|
+-		len = strlen(name);
 | 
						|
+ 	} else {
 | 
						|
+-		return;
 | 
						|
++		len = strlen(name);
 | 
						|
+ 	}
 | 
						|
+ 
 | 
						|
+ 	vlist_for_each_element(&wireless_devices, wdev, node) {
 | 
						|
+--- a/wireless.h
 | 
						|
++++ b/wireless.h
 | 
						|
+@@ -96,6 +96,8 @@ struct wireless_interface {
 | 
						|
+ 	int vlan_idx;
 | 
						|
+ 	int sta_idx;
 | 
						|
+ 	bool disabled;
 | 
						|
++
 | 
						|
++	int network_ifindex;
 | 
						|
+ };
 | 
						|
+ 
 | 
						|
+ struct wireless_vlan {
 | 
						|
+@@ -112,6 +114,8 @@ struct wireless_vlan {
 | 
						|
+ 	int multicast_to_unicast;
 | 
						|
+ 	bool isolate;
 | 
						|
+ 	bool bridge_isolate;
 | 
						|
++
 | 
						|
++	int network_ifindex;
 | 
						|
+ };
 | 
						|
+ 
 | 
						|
+ struct wireless_station {
 | 
						|
-- 
 | 
						|
2.34.1
 | 
						|
 |