| .. | .. |
|---|
| 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. */ |
|---|