1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <linux/rfkill.h>
10 #include "sd-daemon.h"
11 #include "sd-device.h"
13 #include "alloc-util.h"
14 #include "device-util.h"
20 #include "main-func.h"
22 #include "parse-util.h"
23 #include "reboot-util.h"
24 #include "string-table.h"
25 #include "string-util.h"
26 #include "udev-util.h"
29 /* Note that any write is delayed until exit and the rfkill state will not be
30 * stored for rfkill indices that disappear after a change. */
31 #define EXIT_USEC (5 * USEC_PER_SEC)
33 typedef struct write_queue_item
{
34 LIST_FIELDS(struct write_queue_item
, queue
);
40 typedef struct Context
{
41 LIST_HEAD(write_queue_item
, write_queue
);
45 static struct write_queue_item
* write_queue_item_free(struct write_queue_item
*item
) {
53 static const char* const rfkill_type_table
[NUM_RFKILL_TYPES
] = {
54 [RFKILL_TYPE_ALL
] = "all",
55 [RFKILL_TYPE_WLAN
] = "wlan",
56 [RFKILL_TYPE_BLUETOOTH
] = "bluetooth",
57 [RFKILL_TYPE_UWB
] = "uwb",
58 [RFKILL_TYPE_WIMAX
] = "wimax",
59 [RFKILL_TYPE_WWAN
] = "wwan",
60 [RFKILL_TYPE_GPS
] = "gps",
61 [RFKILL_TYPE_FM
] = "fm",
62 [RFKILL_TYPE_NFC
] = "nfc",
65 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(rfkill_type
, int);
67 static int find_device(
68 const struct rfkill_event
*event
,
70 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
71 _cleanup_free_
char *sysname
= NULL
;
78 if (asprintf(&sysname
, "rfkill%i", event
->idx
) < 0)
81 r
= sd_device_new_from_subsystem_sysname(&device
, "rfkill", sysname
);
83 return log_full_errno(IN_SET(r
, -ENOENT
, -ENXIO
, -ENODEV
) ? LOG_DEBUG
: LOG_ERR
, r
,
84 "Failed to open device '%s': %m", sysname
);
86 r
= sd_device_get_sysattr_value(device
, "name", &name
);
88 return log_device_debug_errno(device
, r
, "Device has no name, ignoring: %m");
90 log_device_debug(device
, "Operating on rfkill device '%s'.", name
);
92 *ret
= TAKE_PTR(device
);
96 static int determine_state_file(
97 const struct rfkill_event
*event
,
100 _cleanup_(sd_device_unrefp
) sd_device
*d
= NULL
, *device
= NULL
;
101 const char *path_id
, *type
;
108 r
= find_device(event
, &d
);
112 r
= device_wait_for_initialization(d
, "rfkill", USEC_INFINITY
, &device
);
116 assert_se(type
= rfkill_type_to_string(event
->type
));
118 if (sd_device_get_property_value(device
, "ID_PATH", &path_id
) >= 0) {
119 _cleanup_free_
char *escaped_path_id
= NULL
;
121 escaped_path_id
= cescape(path_id
);
122 if (!escaped_path_id
)
125 state_file
= strjoin("/var/lib/systemd/rfkill/", escaped_path_id
, ":", type
);
127 state_file
= strjoin("/var/lib/systemd/rfkill/", type
);
136 static int load_state(Context
*c
, const struct rfkill_event
*event
) {
137 _cleanup_free_
char *state_file
= NULL
, *value
= NULL
;
141 assert(c
->rfkill_fd
>= 0);
144 if (shall_restore_state() == 0)
147 r
= determine_state_file(event
, &state_file
);
151 r
= read_one_line_file(state_file
, &value
);
152 if (IN_SET(r
, -ENOENT
, 0)) {
153 /* No state file or it's truncated? Then save the current state */
155 r
= write_string_file(state_file
, one_zero(event
->soft
), WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
|WRITE_STRING_FILE_MKDIR_0755
);
157 return log_error_errno(r
, "Failed to write state file %s: %m", state_file
);
159 log_debug("Saved state '%s' to %s.", one_zero(event
->soft
), state_file
);
163 return log_error_errno(r
, "Failed to read state file %s: %m", state_file
);
165 b
= parse_boolean(value
);
167 return log_error_errno(b
, "Failed to parse state file %s: %m", state_file
);
169 struct rfkill_event we
= {
171 .op
= RFKILL_OP_CHANGE
,
174 assert_cc(offsetof(struct rfkill_event
, op
) < RFKILL_EVENT_SIZE_V1
);
175 assert_cc(offsetof(struct rfkill_event
, soft
) < RFKILL_EVENT_SIZE_V1
);
177 ssize_t l
= write(c
->rfkill_fd
, &we
, sizeof we
);
179 return log_error_errno(errno
, "Failed to restore rfkill state for %i: %m", event
->idx
);
180 if ((size_t)l
< RFKILL_EVENT_SIZE_V1
) /* l cannot be < 0 here. Cast to fix -Werror=sign-compare */
181 return log_error_errno(SYNTHETIC_ERRNO(EIO
),
182 "Couldn't write rfkill event structure, too short (wrote %zd of %zu bytes).",
184 log_debug("Writing struct rfkill_event successful (%zd of %zu bytes).", l
, sizeof we
);
186 log_debug("Loaded state '%s' from %s.", one_zero(b
), state_file
);
190 static void save_state_queue_remove(Context
*c
, int idx
, const char *state_file
) {
193 LIST_FOREACH(queue
, item
, c
->write_queue
)
194 if ((state_file
&& streq(item
->file
, state_file
)) || idx
== item
->rfkill_idx
) {
195 log_debug("Canceled previous save state of '%s' to %s.", one_zero(item
->state
), item
->file
);
196 LIST_REMOVE(queue
, c
->write_queue
, item
);
197 write_queue_item_free(item
);
201 static int save_state_queue(Context
*c
, const struct rfkill_event
*event
) {
202 _cleanup_free_
char *state_file
= NULL
;
203 struct write_queue_item
*item
;
207 assert(c
->rfkill_fd
>= 0);
210 r
= determine_state_file(event
, &state_file
);
214 save_state_queue_remove(c
, event
->idx
, state_file
);
216 item
= new0(struct write_queue_item
, 1);
220 item
->file
= TAKE_PTR(state_file
);
221 item
->rfkill_idx
= event
->idx
;
222 item
->state
= event
->soft
;
224 LIST_APPEND(queue
, c
->write_queue
, item
);
229 static int save_state_cancel(Context
*c
, const struct rfkill_event
*event
) {
230 _cleanup_free_
char *state_file
= NULL
;
234 assert(c
->rfkill_fd
>= 0);
237 r
= determine_state_file(event
, &state_file
);
238 save_state_queue_remove(c
, event
->idx
, state_file
);
245 static int save_state_write_one(struct write_queue_item
*item
) {
248 r
= write_string_file(item
->file
, one_zero(item
->state
), WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
|WRITE_STRING_FILE_MKDIR_0755
);
250 return log_error_errno(r
, "Failed to write state file %s: %m", item
->file
);
252 log_debug("Saved state '%s' to %s.", one_zero(item
->state
), item
->file
);
256 static void context_save_and_clear(Context
*c
) {
257 struct write_queue_item
*i
;
261 while ((i
= c
->write_queue
)) {
262 LIST_REMOVE(queue
, c
->write_queue
, i
);
263 (void) save_state_write_one(i
);
264 write_queue_item_free(i
);
267 safe_close(c
->rfkill_fd
);
270 static int run(int argc
, char *argv
[]) {
271 _cleanup_(context_save_and_clear
) Context c
= { .rfkill_fd
= -1 };
276 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "This program requires no arguments.");
282 n
= sd_listen_fds(false);
284 return log_error_errno(n
, "Failed to determine whether we got any file descriptors passed: %m");
286 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Got too many file descriptors.");
289 c
.rfkill_fd
= open("/dev/rfkill", O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NONBLOCK
);
290 if (c
.rfkill_fd
< 0) {
291 if (errno
== ENOENT
) {
292 log_debug_errno(errno
, "Missing rfkill subsystem, or no device present, exiting.");
296 return log_error_errno(errno
, "Failed to open /dev/rfkill: %m");
299 c
.rfkill_fd
= SD_LISTEN_FDS_START
;
301 r
= fd_nonblock(c
.rfkill_fd
, 1);
303 return log_error_errno(r
, "Failed to make /dev/rfkill socket non-blocking: %m");
307 struct rfkill_event event
= {};
309 ssize_t l
= read(c
.rfkill_fd
, &event
, sizeof event
);
312 return log_error_errno(errno
, "Failed to read from /dev/rfkill: %m");
315 /* Notify manager that we are now finished with processing whatever was
317 r
= sd_notify(false, "READY=1");
319 log_warning_errno(r
, "Failed to send readiness notification, ignoring: %m");
324 /* Hang around for a bit, maybe there's more coming */
326 r
= fd_wait_for_event(c
.rfkill_fd
, POLLIN
, EXIT_USEC
);
330 return log_error_errno(r
, "Failed to poll() on device: %m");
334 log_debug("All events read and idle, exiting.");
338 if ((size_t)l
< RFKILL_EVENT_SIZE_V1
) /* l cannot be < 0 here. Cast to fix -Werror=sign-compare */
339 return log_error_errno(SYNTHETIC_ERRNO(EIO
), "Short read of struct rfkill_event: (%zd < %zu)",
340 l
, (size_t) RFKILL_EVENT_SIZE_V1
); /* Casting necessary to make compiling with different kernel versions happy */
341 log_debug("Reading struct rfkill_event: got %zd bytes.", l
);
343 /* The event structure has more fields. We only care about the first few, so it's OK if we
344 * don't read the full structure. */
345 assert_cc(offsetof(struct rfkill_event
, op
) < RFKILL_EVENT_SIZE_V1
);
346 assert_cc(offsetof(struct rfkill_event
, type
) < RFKILL_EVENT_SIZE_V1
);
348 const char *type
= rfkill_type_to_string(event
.type
);
350 log_debug("An rfkill device of unknown type %i discovered, ignoring.", event
.type
);
357 log_debug("A new rfkill device has been added with index %i and type %s.", event
.idx
, type
);
358 (void) load_state(&c
, &event
);
362 log_debug("An rfkill device has been removed with index %i and type %s", event
.idx
, type
);
363 (void) save_state_cancel(&c
, &event
);
366 case RFKILL_OP_CHANGE
:
367 log_debug("An rfkill device has changed state with index %i and type %s", event
.idx
, type
);
368 (void) save_state_queue(&c
, &event
);
372 log_debug("Unknown event %i from /dev/rfkill for index %i and type %s, ignoring.", event
.op
, event
.idx
, type
);
380 DEFINE_MAIN_FUNCTION(run
);