From d5484e69a2476ff3bea5d402d06ed3c68d2ef24d Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 6 Nov 2024 12:28:41 +0100 Subject: [PATCH] netifd: add various backports Signed-off-by: John Crispin --- .../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