]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
b492aea0 | 2 | |
b492aea0 | 3 | #include "log.h" |
abad436d | 4 | #include "string-table.h" |
56fdc16d | 5 | #include "string-util.h" |
b492aea0 ZJS |
6 | #include "wifi-util.h" |
7 | ||
ae2b86de | 8 | int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *ret_iftype, char **ret_ssid) { |
b492aea0 | 9 | _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; |
ae2b86de | 10 | _cleanup_free_ char *ssid = NULL; |
56fdc16d | 11 | const char *family; |
ae2b86de | 12 | uint32_t iftype; |
f3e235ff | 13 | size_t len; |
b492aea0 ZJS |
14 | int r; |
15 | ||
cc17c4c9 YW |
16 | assert(genl); |
17 | assert(ifindex > 0); | |
18 | ||
56fdc16d | 19 | r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_INTERFACE, &m); |
b492aea0 ZJS |
20 | if (r < 0) |
21 | return log_debug_errno(r, "Failed to create generic netlink message: %m"); | |
22 | ||
23 | r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex); | |
24 | if (r < 0) | |
25 | return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m"); | |
26 | ||
27 | r = sd_netlink_call(genl, m, 0, &reply); | |
cc17c4c9 YW |
28 | if (r == -ENODEV) { |
29 | /* For obsolete WEXT driver. */ | |
30 | log_debug_errno(r, "Failed to request information about wifi interface %d. " | |
31 | "The device doesn't seem to have nl80211 interface. Ignoring.", | |
32 | ifindex); | |
33 | goto nodata; | |
34 | } | |
b492aea0 ZJS |
35 | if (r < 0) |
36 | return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex); | |
a66a402d | 37 | if (!reply) { |
66205cb3 | 38 | log_debug("No reply received to request for information about wifi interface %d, ignoring.", ifindex); |
cc17c4c9 | 39 | goto nodata; |
a66a402d | 40 | } |
b492aea0 ZJS |
41 | |
42 | r = sd_netlink_message_get_errno(reply); | |
43 | if (r < 0) | |
44 | return log_debug_errno(r, "Failed to get information about wifi interface %d: %m", ifindex); | |
45 | ||
56fdc16d | 46 | r = sd_genl_message_get_family_name(genl, reply, &family); |
b492aea0 ZJS |
47 | if (r < 0) |
48 | return log_debug_errno(r, "Failed to determine genl family: %m"); | |
56fdc16d YW |
49 | if (!streq(family, NL80211_GENL_NAME)) { |
50 | log_debug("Received message of unexpected genl family '%s', ignoring.", family); | |
cc17c4c9 | 51 | goto nodata; |
b492aea0 ZJS |
52 | } |
53 | ||
ae2b86de YW |
54 | r = sd_netlink_message_read_u32(reply, NL80211_ATTR_IFTYPE, &iftype); |
55 | if (r < 0) | |
56 | return log_debug_errno(r, "Failed to get NL80211_ATTR_IFTYPE attribute: %m"); | |
78404d22 | 57 | |
f3e235ff | 58 | r = sd_netlink_message_read_data_suffix0(reply, NL80211_ATTR_SSID, &len, (void**) &ssid); |
ae2b86de YW |
59 | if (r < 0 && r != -ENODATA) |
60 | return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m"); | |
f3e235ff YW |
61 | if (r >= 0) { |
62 | if (len == 0) { | |
63 | log_debug("SSID has zero length, ignoring the received SSID."); | |
64 | ssid = mfree(ssid); | |
65 | } else if (strlen_ptr(ssid) != len) { | |
66 | log_debug("SSID contains NUL character(s), ignoring the received SSID."); | |
67 | ssid = mfree(ssid); | |
68 | } | |
69 | } | |
78404d22 | 70 | |
ae2b86de YW |
71 | if (ret_iftype) |
72 | *ret_iftype = iftype; | |
73 | ||
74 | if (ret_ssid) | |
75 | *ret_ssid = TAKE_PTR(ssid); | |
b492aea0 | 76 | |
cc17c4c9 YW |
77 | return 1; |
78 | ||
79 | nodata: | |
ae2b86de YW |
80 | if (ret_iftype) |
81 | *ret_iftype = 0; | |
82 | if (ret_ssid) | |
83 | *ret_ssid = NULL; | |
cc17c4c9 | 84 | return 0; |
b492aea0 ZJS |
85 | } |
86 | ||
ae2b86de | 87 | int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *ret_bssid) { |
b492aea0 | 88 | _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; |
56fdc16d | 89 | const char *family; |
b492aea0 ZJS |
90 | int r; |
91 | ||
cc17c4c9 YW |
92 | assert(genl); |
93 | assert(ifindex > 0); | |
ae2b86de | 94 | assert(ret_bssid); |
cc17c4c9 | 95 | |
56fdc16d | 96 | r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_STATION, &m); |
b492aea0 ZJS |
97 | if (r < 0) |
98 | return log_debug_errno(r, "Failed to create generic netlink message: %m"); | |
99 | ||
100 | r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); | |
101 | if (r < 0) | |
102 | return log_debug_errno(r, "Failed to set dump flag: %m"); | |
103 | ||
104 | r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex); | |
105 | if (r < 0) | |
106 | return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m"); | |
107 | ||
108 | r = sd_netlink_call(genl, m, 0, &reply); | |
109 | if (r < 0) | |
110 | return log_debug_errno(r, "Failed to request information about wifi station: %m"); | |
a66a402d | 111 | if (!reply) { |
66205cb3 | 112 | log_debug("No reply received to request for information about wifi station, ignoring."); |
cc17c4c9 | 113 | goto nodata; |
a66a402d | 114 | } |
b492aea0 ZJS |
115 | |
116 | r = sd_netlink_message_get_errno(reply); | |
117 | if (r < 0) | |
118 | return log_debug_errno(r, "Failed to get information about wifi station: %m"); | |
119 | ||
56fdc16d | 120 | r = sd_genl_message_get_family_name(genl, reply, &family); |
b492aea0 ZJS |
121 | if (r < 0) |
122 | return log_debug_errno(r, "Failed to determine genl family: %m"); | |
56fdc16d YW |
123 | if (!streq(family, NL80211_GENL_NAME)) { |
124 | log_debug("Received message of unexpected genl family '%s', ignoring.", family); | |
cc17c4c9 | 125 | goto nodata; |
b492aea0 ZJS |
126 | } |
127 | ||
ae2b86de | 128 | r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, ret_bssid); |
cc17c4c9 YW |
129 | if (r == -ENODATA) |
130 | goto nodata; | |
131 | if (r < 0) | |
b492aea0 ZJS |
132 | return log_debug_errno(r, "Failed to get NL80211_ATTR_MAC attribute: %m"); |
133 | ||
cc17c4c9 YW |
134 | return 1; |
135 | ||
136 | nodata: | |
ae2b86de | 137 | *ret_bssid = ETHER_ADDR_NULL; |
cc17c4c9 | 138 | return 0; |
b492aea0 | 139 | } |
abad436d YW |
140 | |
141 | static const char * const nl80211_iftype_table[NUM_NL80211_IFTYPES] = { | |
142 | [NL80211_IFTYPE_ADHOC] = "ad-hoc", | |
143 | [NL80211_IFTYPE_STATION] = "station", | |
144 | [NL80211_IFTYPE_AP] = "ap", | |
145 | [NL80211_IFTYPE_AP_VLAN] = "ap-vlan", | |
146 | [NL80211_IFTYPE_WDS] = "wds", | |
147 | [NL80211_IFTYPE_MONITOR] = "monitor", | |
148 | [NL80211_IFTYPE_MESH_POINT] = "mesh-point", | |
149 | [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client", | |
150 | [NL80211_IFTYPE_P2P_GO] = "p2p-go", | |
151 | [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device", | |
152 | [NL80211_IFTYPE_OCB] = "ocb", | |
153 | [NL80211_IFTYPE_NAN] = "nan", | |
154 | }; | |
155 | ||
156 | DEFINE_STRING_TABLE_LOOKUP_TO_STRING(nl80211_iftype, enum nl80211_iftype); |