]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: also assign rfkill device to Wiphy object
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 22 Jul 2022 00:46:52 +0000 (09:46 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 23 Jul 2022 11:55:03 +0000 (20:55 +0900)
Preparation for later commits.

src/network/networkd-manager.c
src/network/networkd-wiphy.c
src/network/networkd-wiphy.h

index 302ba729bd245e529be4b7f340bd9aeb88b355dd..265c7e62c67a1bb3d0df071bc4b3aa4d07cdab25 100644 (file)
@@ -190,6 +190,8 @@ static int manager_process_uevent(sd_device_monitor *monitor, sd_device *device,
                 r = manager_udev_process_link(m, device, action);
         else if (streq(s, "ieee80211"))
                 r = manager_udev_process_wiphy(m, device, action);
+        else if (streq(s, "rfkill"))
+                r = manager_udev_process_rfkill(m, device, action);
         else {
                 log_device_debug(device, "Received device with unexpected subsystem \"%s\", ignoring.", s);
                 return 0;
@@ -225,6 +227,10 @@ static int manager_connect_udev(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Could not add device monitor filter for ieee80211 subsystem: %m");
 
+        r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "rfkill", NULL);
+        if (r < 0)
+                return log_error_errno(r, "Could not add device monitor filter for rfkill subsystem: %m");
+
         r = sd_device_monitor_attach_event(m->device_monitor, m->event);
         if (r < 0)
                 return log_error_errno(r, "Failed to attach event to device monitor: %m");
index 113b67147924f0508abe8e0320865f95d3379859..1c258e24169bae3e88de3b7b8a955df569a73597 100644 (file)
@@ -7,6 +7,7 @@
 #include "networkd-manager.h"
 #include "networkd-wiphy.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "udev-util.h"
 #include "wifi-util.h"
 
@@ -21,6 +22,7 @@ Wiphy *wiphy_free(Wiphy *w) {
         }
 
         sd_device_unref(w->dev);
+        sd_device_unref(w->rfkill);
 
         free(w->name);
         return mfree(w);
@@ -163,6 +165,59 @@ static int wiphy_update_device(Wiphy *w) {
         return 0;
 }
 
+static int wiphy_update_rfkill(Wiphy *w) {
+        _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+        sd_device *rfkill;
+        int r;
+
+        assert(w);
+
+        if (!udev_available())
+                return 0;
+
+        w->rfkill = sd_device_unref(w->rfkill);
+
+        if (!w->dev)
+                return 0;
+
+        r = sd_device_enumerator_new(&e);
+        if (r < 0)
+                return r;
+
+        r = sd_device_enumerator_allow_uninitialized(e);
+        if (r < 0)
+                return r;
+
+        r = sd_device_enumerator_add_match_subsystem(e, "rfkill", true);
+        if (r < 0)
+                return r;
+
+        r = sd_device_enumerator_add_match_parent(e, w->dev);
+        if (r < 0)
+                return r;
+
+        rfkill = sd_device_enumerator_get_device_first(e);
+        if (!rfkill) {
+                /* rfkill device may not detected by the kernel yet, and may appear later. */
+                log_wiphy_debug_errno(w, SYNTHETIC_ERRNO(ENODEV), "No rfkill device found, ignoring.");
+                return 0;
+        }
+
+        if (sd_device_enumerator_get_device_next(e))
+                return log_wiphy_debug_errno(w, SYNTHETIC_ERRNO(EEXIST), "Multiple rfkill devices found.");
+
+        w->rfkill = sd_device_ref(rfkill);
+
+        if (DEBUG_LOGGING) {
+                const char *s = NULL;
+
+                (void) sd_device_get_syspath(rfkill, &s);
+                log_wiphy_debug(w, "Found rfkill device: %s", strna(s));
+        }
+
+        return 0;
+}
+
 static int wiphy_update(Wiphy *w) {
         int r;
 
@@ -172,6 +227,10 @@ static int wiphy_update(Wiphy *w) {
         if (r < 0)
                 return log_wiphy_debug_errno(w, r, "Failed to update wiphy device: %m");
 
+        r = wiphy_update_rfkill(w);
+        if (r < 0)
+                return log_wiphy_debug_errno(w, r, "Failed to update rfkill device: %m");
+
         return 0;
 }
 
@@ -284,3 +343,35 @@ int manager_udev_process_wiphy(Manager *m, sd_device *device, sd_device_action_t
 
         return device_unref_and_replace(w->dev, action == SD_DEVICE_REMOVE ? NULL : device);
 }
+
+int manager_udev_process_rfkill(Manager *m, sd_device *device, sd_device_action_t action) {
+        _cleanup_free_ char *parent_path = NULL, *parent_name = NULL;
+        const char *s;
+        Wiphy *w;
+        int r;
+
+        assert(m);
+        assert(device);
+
+        r = sd_device_get_syspath(device, &s);
+        if (r < 0)
+                return log_device_debug_errno(device, r, "Failed to get syspath: %m");
+
+        /* Do not use sd_device_get_parent() here, as this might be a 'remove' uevent. */
+        r = path_extract_directory(s, &parent_path);
+        if (r < 0)
+                return log_device_debug_errno(device, r, "Failed to get parent syspath: %m");
+
+        r = path_extract_filename(parent_path, &parent_name);
+        if (r < 0)
+                return log_device_debug_errno(device, r, "Failed to get parent name: %m");
+
+        r = wiphy_get_by_name(m, parent_name, &w);
+        if (r < 0) {
+                /* This error is not critical, as the corresponding genl message may be received later. */
+                log_device_debug_errno(device, r, "Failed to get Wiphy object: %m");
+                return 0;
+        }
+
+        return device_unref_and_replace(w->rfkill, action == SD_DEVICE_REMOVE ? NULL : device);
+}
index 9e8a3a5560bdc9bbf1a004d77b3a687c30c05135..5f0f47a2306db94e0fb3c7fa9a12fbc58fc62fee 100644 (file)
@@ -16,6 +16,7 @@ typedef struct Wiphy {
         char *name;
 
         sd_device *dev;
+        sd_device *rfkill;
 } Wiphy;
 
 Wiphy *wiphy_free(Wiphy *w);
@@ -26,6 +27,7 @@ int wiphy_get_by_name(Manager *manager, const char *name, Wiphy **ret);
 
 int manager_genl_process_nl80211_wiphy(sd_netlink *genl, sd_netlink_message *message, Manager *manager);
 int manager_udev_process_wiphy(Manager *m, sd_device *device, sd_device_action_t action);
+int manager_udev_process_rfkill(Manager *m, sd_device *device, sd_device_action_t action);
 
 #define log_wiphy_full_errno_zerook(w, level, error, ...)               \
         ({                                                              \