1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <net/ethernet.h>
#include <linux/nl80211.h>
#include "sd-bus.h"
#include "log.h"
#include "netlink-util.h"
#include "wifi-util.h"
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
sd_genl_family family;
int r;
assert(genl);
assert(ifindex > 0);
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
if (r < 0)
return log_debug_errno(r, "Failed to create generic netlink message: %m");
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex);
if (r < 0)
return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
r = sd_netlink_call(genl, m, 0, &reply);
if (r == -ENODEV) {
/* For obsolete WEXT driver. */
log_debug_errno(r, "Failed to request information about wifi interface %d. "
"The device doesn't seem to have nl80211 interface. Ignoring.",
ifindex);
goto nodata;
}
if (r < 0)
return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex);
if (!reply)
goto nodata;
r = sd_netlink_message_get_errno(reply);
if (r < 0)
return log_debug_errno(r, "Failed to get information about wifi interface %d: %m", ifindex);
r = sd_genl_message_get_family(genl, reply, &family);
if (r < 0)
return log_debug_errno(r, "Failed to determine genl family: %m");
if (family != SD_GENL_NL80211) {
log_debug("Received message of unexpected genl family %u, ignoring.", family);
goto nodata;
}
if (iftype) {
uint32_t t;
r = sd_netlink_message_read_u32(reply, NL80211_ATTR_IFTYPE, &t);
if (r < 0)
return log_debug_errno(r, "Failed to get NL80211_ATTR_IFTYPE attribute: %m");
*iftype = t;
}
if (ssid) {
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, ssid);
if (r == -ENODATA)
goto nodata;
if (r < 0)
return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m");
}
return 1;
nodata:
if (iftype)
*iftype = 0;
if (ssid)
*ssid = NULL;
return 0;
}
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
sd_genl_family family;
int r;
assert(genl);
assert(ifindex > 0);
assert(bssid);
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
if (r < 0)
return log_debug_errno(r, "Failed to create generic netlink message: %m");
r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
if (r < 0)
return log_debug_errno(r, "Failed to set dump flag: %m");
r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex);
if (r < 0)
return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m");
r = sd_netlink_call(genl, m, 0, &reply);
if (r < 0)
return log_debug_errno(r, "Failed to request information about wifi station: %m");
if (!reply)
goto nodata;
r = sd_netlink_message_get_errno(reply);
if (r < 0)
return log_debug_errno(r, "Failed to get information about wifi station: %m");
r = sd_genl_message_get_family(genl, reply, &family);
if (r < 0)
return log_debug_errno(r, "Failed to determine genl family: %m");
if (family != SD_GENL_NL80211) {
log_debug("Received message of unexpected genl family %u, ignoring.", family);
goto nodata;
}
r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, bssid);
if (r == -ENODATA)
goto nodata;
if (r < 0)
return log_debug_errno(r, "Failed to get NL80211_ATTR_MAC attribute: %m");
return 1;
nodata:
*bssid = (struct ether_addr) {};
return 0;
}
|