1 of 31

BUILD A VIRTUAL WIFI DRIVER FOR LINUX - VWIFI

By:吳恩緯 (EN-WEI WU)

2 of 31

Self Introduction

  • 成功大學資訊工程系
  • Linux 核心設計/實作 – vwifi
  • Google Summer of Code – write wifi driver for FreeBSD
  • Interested in IEEE 802.11

3 of 31

What is vwifi

  • Virtual Wi-Fi (simulator)
  • Lightweight, about 1000 lines of code
  • Created by Jserv
  • My final topic of lesson “Linux 核心設計/實作
  • a.k.a. owl (Our WireLess)

4 of 31

  • Build simple wireless environment

What can vwifi do

5 of 31

Why not mac80211_hwsim, why vwifi

6 of 31

Why not mac80211_hwsim, why vwifi

Probe request /

Probe response

7 of 31

Why not mac80211_hwsim, why vwifi

802.11 authentication

8 of 31

Why not mac80211_hwsim, why vwifi

Association request /

Association response

9 of 31

Why not mac80211_hwsim, why vwifi

802.1X authentication

10 of 31

Why not mac80211_hwsim, why vwifi

Just find AP and connect to it !

Lightweight !!

Fewer code

Fewer cost

11 of 31

Outline

  • Data frame flow and hooks
  • Wireless stack and hooks
  • Implementation of STA mode ops
  • Implementation of Hostap mode TX/RX

TX = transmit�RX = receive

What to implement

Implementation

12 of 31

DATA FRAME FLOW AND HOOKS

13 of 31

Data frame workflow (like Ethernet)

hooks

14 of 31

struct net_device

15 of 31

Register callbacks for net_device

static struct net_device_ops owl_ndev_ops = {

.ndo_open = owl_ndo_open,

.ndo_stop = owl_ndo_stop,

.ndo_start_xmit = owl_ndo_start_xmit,

.ndo_get_stats = owl_ndo_get_stats,

};

TX

16 of 31

WIRELESS STACK AND HOOKS

17 of 31

Different NIC category

FullMAC

SoftMAC

= MLME in hardware

= MLME in software

  • Low CPU load
  • Save power
  • Linux cfg80211 subsystem
  • Low cost on hardware
  • Update functionality on driver
  • Share many code with different drivers
  • Linux mac80211 subsystem

18 of 31

802.11 Management workflow

註: NL = netlink

hooks

19 of 31

Register callbacks for cfg80211

static struct cfg80211_ops owl_cfg_ops = {

.scan = owl_scan,

.connect = owl_connect,

.disconnect = owl_disconnect,

�.change_virtual_intf = owl_change_iface,

.start_ap = owl_start_ap,

.stop_ap = owl_stop_ap,

� .get_station = owl_get_station,

};

STA mode

AP mode

20 of 31

IMPLEMENTATION OF �STA MODE OPS

21 of 31

cfg80211 scan

  • Iterate through all APs
    1. Collect information of the AP
    2. Insert SSID into information element (IE)
    3. Call cfg80211_inform_bss_data() to inform kernel

22 of 31

static int owl_scan(struct wiphy *wiphy,

struct cfg80211_scan_request *request)

{

list_for_each_entry (ap, &owl->ap_list, ap_list) {

struct cfg80211_inform_bss data = {

.chan = /* ... */

.scan_width = NL80211_BSS_CHAN_WIDTH_20,

.signal = /* ... */

};

�u8 *ie = kmalloc(ap->ssid_len + 2, GFP_KERNEL);

ie[0] = WLAN_EID_SSID;

ie[1] = ap->ssid_len;

memcpy(ie + 2, ap->ssid, ap->ssid_len);

�bss = cfg80211_inform_bss_data(

vif->wdev.wiphy, &data, CFG80211_BSS_FTYPE_UNKNOWN, ap->bssid, tsf,

WLAN_CAPABILITY_ESS, 100, ie, ap->ssid_len + 2, GFP_KERNEL);

}

cfg80211_scan_done(vif->scan_request, &info);

}

23 of 31

cfg80211 connect

  • Iterate through all APs, if SSID match:
    1. Call cfg80211_connect_result() to inform

kernel of connection successful or not

    • Update vif status
    • Insert vif into bss_list

: vif = virtual interface

24 of 31

static int owl_connect(struct wiphy *wiphy,

struct net_device *dev,

struct cfg80211_connect_params *sme)

{

list_for_each_entry (ap, &owl->ap_list, ap_list) {

if (!memcmp(ap->ssid, vif->req_ssid, ap->ssid_len)) {

cfg80211_connect_result(vif->ndev, NULL,

NULL, 0, NULL, 0,

WLAN_STATUS_SUCCESS, GFP_KERNEL);

memcpy(vif->ssid, ap->ssid, ap->ssid_len);

memcpy(vif->bssid, ap->bssid, ETH_ALEN);

vif->sme_state = SME_CONNECTED;

vif->conn_time = jiffies;

vif->ap = ap;

list_add_tail(&vif->bss_list, &ap->bss_list);

return;

}

}

}

25 of 31

IMPLEMENTATION OF HOSTAP MODE TX/RX

26 of 31

TX on AP mode (may be relay)

  1. Get destination’s vif and check packet type, if:
    • Unicast: (destination MAC in packet) == (vif’s MAC))
    • Broadcast/multicast: send packet to every interface in BSS
  2. Put packet into destination’s vif’s RX queue

3. Call owl_rx() on destination vif to simulate RX interrupt

27 of 31

AP TX

AP RX

28 of 31

RX on AP mode (may need to relay)

  1. Check packet type, if:
    • Unicast: if the packet is not for us, goto TX (relay the packet); else, goto 2.
    • Broadcast/Unicast: goto TX (relay the packet), and goto 2.
  2. Pass packet to kernel

relay

relay

Packet is for us

Packet is for us

29 of 31

RX on AP mode

  • skb: will be sent to protocol stack
  • skb1: will be sent to another STA via TX

struct sk_buff *skb, *skb1 = NULL;

PS: skb represents packet

30 of 31

WELCOME TO CONTRIBUTE VWIFI

31 of 31

TODO List

  • Support adhoc (IBSS) mode
  • Beacon frame
  • Inter-guest communication