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