.. | .. |
---|
14 | 14 | #include <linux/etherdevice.h> |
---|
15 | 15 | #include <linux/math64.h> |
---|
16 | 16 | #include <linux/module.h> |
---|
17 | | - |
---|
18 | | -#include <net/cfg80211.h> |
---|
19 | | -#include <net/rtnetlink.h> |
---|
20 | | -#include <linux/etherdevice.h> |
---|
21 | | -#include <linux/module.h> |
---|
22 | 17 | #include <net/virt_wifi.h> |
---|
23 | 18 | |
---|
24 | 19 | static struct wiphy *common_wiphy; |
---|
.. | .. |
---|
143 | 138 | /* Assigned at module init. Guaranteed locally-administered and unicast. */ |
---|
144 | 139 | static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {}; |
---|
145 | 140 | |
---|
| 141 | +static void virt_wifi_inform_bss(struct wiphy *wiphy) |
---|
| 142 | +{ |
---|
| 143 | + u64 tsf = div_u64(ktime_get_boottime_ns(), 1000); |
---|
| 144 | + struct cfg80211_bss *informed_bss; |
---|
| 145 | + static const struct { |
---|
| 146 | + u8 tag; |
---|
| 147 | + u8 len; |
---|
| 148 | + u8 ssid[8]; |
---|
| 149 | + } __packed ssid = { |
---|
| 150 | + .tag = WLAN_EID_SSID, |
---|
| 151 | + .len = 8, |
---|
| 152 | + .ssid = "VirtWifi", |
---|
| 153 | + }; |
---|
| 154 | + |
---|
| 155 | + informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz, |
---|
| 156 | + CFG80211_BSS_FTYPE_PRESP, |
---|
| 157 | + fake_router_bssid, tsf, |
---|
| 158 | + WLAN_CAPABILITY_ESS, 0, |
---|
| 159 | + (void *)&ssid, sizeof(ssid), |
---|
| 160 | + DBM_TO_MBM(-50), GFP_KERNEL); |
---|
| 161 | + cfg80211_put_bss(wiphy, informed_bss); |
---|
| 162 | +} |
---|
| 163 | + |
---|
146 | 164 | /* Called with the rtnl lock held. */ |
---|
147 | 165 | static int virt_wifi_scan(struct wiphy *wiphy, |
---|
148 | 166 | struct cfg80211_scan_request *request) |
---|
.. | .. |
---|
166 | 184 | /* Acquires and releases the rdev BSS lock. */ |
---|
167 | 185 | static void virt_wifi_scan_result(struct work_struct *work) |
---|
168 | 186 | { |
---|
169 | | - struct { |
---|
170 | | - u8 tag; |
---|
171 | | - u8 len; |
---|
172 | | - u8 ssid[8]; |
---|
173 | | - } __packed ssid = { |
---|
174 | | - .tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi", |
---|
175 | | - }; |
---|
176 | | - struct cfg80211_bss *informed_bss; |
---|
177 | 187 | struct virt_wifi_wiphy_priv *priv = |
---|
178 | 188 | container_of(work, struct virt_wifi_wiphy_priv, |
---|
179 | 189 | scan_result.work); |
---|
180 | 190 | struct wiphy *wiphy = priv_to_wiphy(priv); |
---|
181 | 191 | struct cfg80211_scan_info scan_info = { .aborted = false }; |
---|
182 | | - u64 tsf = div_u64(ktime_get_boot_ns(), 1000); |
---|
183 | 192 | |
---|
184 | | - informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz, |
---|
185 | | - CFG80211_BSS_FTYPE_PRESP, |
---|
186 | | - fake_router_bssid, tsf, |
---|
187 | | - WLAN_CAPABILITY_ESS, 0, |
---|
188 | | - (void *)&ssid, sizeof(ssid), |
---|
189 | | - DBM_TO_MBM(-50), GFP_KERNEL); |
---|
190 | | - cfg80211_put_bss(wiphy, informed_bss); |
---|
| 193 | + virt_wifi_inform_bss(wiphy); |
---|
191 | 194 | |
---|
192 | 195 | if(priv->network_simulation && |
---|
193 | 196 | priv->network_simulation->generate_virt_scan_result) { |
---|
.. | .. |
---|
241 | 244 | if (!could_schedule) |
---|
242 | 245 | return -EBUSY; |
---|
243 | 246 | |
---|
244 | | - if (sme->bssid) |
---|
| 247 | + if (sme->bssid) { |
---|
245 | 248 | ether_addr_copy(priv->connect_requested_bss, sme->bssid); |
---|
246 | | - else |
---|
| 249 | + } else { |
---|
| 250 | + virt_wifi_inform_bss(wiphy); |
---|
247 | 251 | eth_zero_addr(priv->connect_requested_bss); |
---|
| 252 | + } |
---|
248 | 253 | |
---|
249 | 254 | wiphy_debug(wiphy, "connect\n"); |
---|
250 | 255 | |
---|
.. | .. |
---|
257 | 262 | struct virt_wifi_netdev_priv *priv = |
---|
258 | 263 | container_of(work, struct virt_wifi_netdev_priv, connect.work); |
---|
259 | 264 | u8 *requested_bss = priv->connect_requested_bss; |
---|
260 | | - bool has_addr = !is_zero_ether_addr(requested_bss); |
---|
261 | 265 | bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid); |
---|
262 | 266 | u16 status = WLAN_STATUS_SUCCESS; |
---|
263 | 267 | |
---|
264 | | - if (!priv->is_up || (has_addr && !right_addr)) |
---|
| 268 | + if (is_zero_ether_addr(requested_bss)) |
---|
| 269 | + requested_bss = NULL; |
---|
| 270 | + |
---|
| 271 | + if (!priv->is_up || (requested_bss && !right_addr)) |
---|
265 | 272 | status = WLAN_STATUS_UNSPECIFIED_FAILURE; |
---|
266 | 273 | else |
---|
267 | 274 | priv->is_connected = true; |
---|
.. | .. |
---|
465 | 472 | return 0; |
---|
466 | 473 | } |
---|
467 | 474 | |
---|
| 475 | +static int virt_wifi_net_device_get_iflink(const struct net_device *dev) |
---|
| 476 | +{ |
---|
| 477 | + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); |
---|
| 478 | + |
---|
| 479 | + return priv->lowerdev->ifindex; |
---|
| 480 | +} |
---|
| 481 | + |
---|
468 | 482 | static const struct net_device_ops virt_wifi_ops = { |
---|
469 | 483 | .ndo_start_xmit = virt_wifi_start_xmit, |
---|
470 | | - .ndo_open = virt_wifi_net_device_open, |
---|
471 | | - .ndo_stop = virt_wifi_net_device_stop, |
---|
| 484 | + .ndo_open = virt_wifi_net_device_open, |
---|
| 485 | + .ndo_stop = virt_wifi_net_device_stop, |
---|
| 486 | + .ndo_get_iflink = virt_wifi_net_device_get_iflink, |
---|
472 | 487 | }; |
---|
473 | 488 | |
---|
474 | 489 | /* Invoked as part of rtnl lock release. */ |
---|