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