The below are my thoughts about a week into the coding season. They may change without warning. This is not meant to be a complete API guide; there are comments in the header files for that. Update: As of Week 5 these have been updated for accuracy, if not completeness.
802.11 drivers should “feel” like regular NIC drivers. They'll need to handle more things, because wireless networking is more complex than wired, but the programming interface should be similar. 802.11 has a lot of MAC-layer processing, though, so there needs to be a shim between the driver layer and the ll_protocol push/pull. I chose to implement this by creating a net80211_device
, and having the 802.11 MAC layer set up a normal net_device
to wrap it.
The operations for a net80211_device
are the same as those of a net_device
, with one addition: config()
. The config
call is used to ask the driver to update any hardware-level settings for wireless-specific issues like channel, transmission rate, association settings (what network are we connected to?), and physical-layer issues like ERP parameters. (When associating with an 802.11g network, we might get something in the association response packet that tells us how to configure our timings and such; the card needs to hear about that.)
On initialization (the driver probe()
routine), each wireless driver provides some information about the capabilities and quirks of its hardware in order to register its net80211_device
. This information is stored in a net80211_hw_info
structure, and its contents are mostly self-explanatory. The MAC layer uses it to know what to advertise when associating with a network, how to interpret the card's status, and how to set up the wrapping net_device
(proper MAC address).
When the 802.11 netdev is first open, after driver initialization is complete, an auto-association process is started that does all of the following in sequence. They can be done separately from that based on user commands.
First, it's necessary to find out what network you want to associate with. To that end, net80211_probe_start()
will start scanning for networks, and process received data whenever net80211_probe_step()
is called. The handler should call net80211_probe_finish_all()
or net80211_probe_finish_best()
to retrieve a list of all networks, or the best-signal network, that were returned by the probe and matched the SSID filter supplied, if any. The probe
call will attempt a passive search (scanning for beacons), but can be configured to search actively (sending probe requests) for networks on the 2.4GHz band by setting the netX/active-scan
gPXE setting. The net80211_probe_finish_*
calls return net80211_wlan
structures listing the detected network parameters; either a list or a single structure. The returned structure(s) need to be freed by calling net80211_free_wlan()
or net80211_free_wlanlist()
after they have been used for association.
The actual association is performed by passing that net80211_wlan
structure in sequence to net80211_prepare_assoc()
, net80211_send_auth()
, net80211_send_assoc()
, and crypto handshaking:
net80211_prepare_assoc()
sets device parameters like channel and transmission rate based on the contents of the beacon packet received and recorded in the wlan structure. There is a variant, net80211_prepare_probe()
, that creates a sensible default list without knowing beacon information, to be used for either passive or active scanning. (The passive default includes more channels, because it's always safe to listen on a channel but local regulations may prohibit sending on it.)net80211_send_auth()
sends an authentication packet, using either Open System or Shared Key authentication. It sets the NET80211_WORKING
flag in dev→state
and returns immediately. As further packets in the authentication sequence are received, they are responded to automatically. When authentication either succeeds or fails, the NET80211_WORKING
flag is unset. On success, NET80211_AUTHENTICATED
is set; on failure, the 802.11 status code is stored in the low byte of dev→state
.net80211_send_assoc()
sends an association request packet; authentication must have previously succeeded. It operates similarly to net80211_authenticate
, setting the WORKING
flag until a reply is received, and setting NET80211_ASSOCIATED
if the association was successful or storing the status code if it was not.net_protocol
API. Not implemented yet.
To be continued…