summaryrefslogtreecommitdiffstats
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/gpxe/errfile.h1
-rw-r--r--src/include/gpxe/ieee80211.h1174
-rw-r--r--src/include/gpxe/net80211.h983
-rw-r--r--src/include/gpxe/rc80211.h19
4 files changed, 2177 insertions, 0 deletions
diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h
index d3155324..e777ecb1 100644
--- a/src/include/gpxe/errfile.h
+++ b/src/include/gpxe/errfile.h
@@ -148,6 +148,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_ib_pathrec ( ERRFILE_NET | 0x001c0000 )
#define ERRFILE_ib_mcast ( ERRFILE_NET | 0x001d0000 )
#define ERRFILE_ib_cm ( ERRFILE_NET | 0x001e0000 )
+#define ERRFILE_net80211 ( ERRFILE_NET | 0x001f0000 )
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
diff --git a/src/include/gpxe/ieee80211.h b/src/include/gpxe/ieee80211.h
new file mode 100644
index 00000000..e2d25191
--- /dev/null
+++ b/src/include/gpxe/ieee80211.h
@@ -0,0 +1,1174 @@
+#ifndef _GPXE_IEEE80211_H
+#define _GPXE_IEEE80211_H
+
+#include <gpxe/if_ether.h> /* for ETH_ALEN */
+
+/** @file
+ * Constants and data structures defined in IEEE 802.11, subsetted
+ * according to what gPXE knows how to use.
+ */
+
+FILE_LICENCE(GPL2_OR_LATER);
+
+/* ---------- Maximum lengths of things ---------- */
+
+/**
+ * @defgroup ieee80211_maxlen Maximum lengths in the 802.11 protocol
+ * @{
+ */
+
+/** Maximum length of frame payload
+ *
+ * This does not include cryptographic overhead, which can be up to 20
+ * bytes, but it DOES include the 802.2 LLC/SNAP headers that are used
+ * on data frames (but not management frames).
+ */
+#define IEEE80211_MAX_DATA_LEN 2304
+
+/** Length of LLC/SNAP headers on data frames */
+#define IEEE80211_LLC_HEADER_LEN 8
+
+/** Maximum cryptographic overhead before encrypted data */
+#define IEEE80211_MAX_CRYPTO_HEADER 8
+
+/** Maximum cryptographic overhead after encrypted data */
+#define IEEE80211_MAX_CRYPTO_TRAILER 12
+
+/** Total maximum cryptographic overhead */
+#define IEEE80211_MAX_CRYPTO_OVERHEAD 20
+
+/** Bytes of network-layer data that can go into a regular data frame */
+#define IEEE80211_MAX_FRAME_DATA 2296
+
+/** Frame header length for frames we might work with
+ *
+ * QoS adds a two-byte field on top of this, and APs communicating
+ * with each other in Wireless Distribution System (WDS) mode add an
+ * extra 6-byte MAC address field, but we do not work with such
+ * frames.
+ */
+#define IEEE80211_TYP_FRAME_HEADER_LEN 24
+
+/** Theoretical maximum frame header length
+ *
+ * This includes the QoS and WDS Addr4 fields that we should never
+ * see.
+ */
+#define IEEE80211_MAX_FRAME_HEADER_LEN 32
+
+/** Maximum combined frame length
+ *
+ * The biggest frame will include 32 frame header bytes, 20 bytes of
+ * crypto overhead, and 2304 data bytes.
+ */
+#define IEEE80211_MAX_FRAME_LEN 2356
+
+/** Maximum length of an ESSID */
+#define IEEE80211_MAX_SSID_LEN 32
+
+/** @} */
+
+
+/* ---------- Frame Control defines ---------- */
+
+/**
+ * @defgroup ieee80211_fc 802.11 Frame Control field bits
+ * @{
+ */
+
+/** 802.11 Frame Control field, Version bitmask */
+#define IEEE80211_FC_VERSION 0x0003
+
+/** Expected value of Version bits in Frame Control */
+#define IEEE80211_THIS_VERSION 0x0000
+
+
+/** 802.11 Frame Control field, Frame Type bitmask */
+#define IEEE80211_FC_TYPE 0x000C
+
+/** Type value for management (layer-2) frames */
+#define IEEE80211_TYPE_MGMT 0x0000
+
+/** Type value for control (layer-1, hardware-managed) frames */
+#define IEEE80211_TYPE_CTRL 0x0004
+
+/** Type value for data frames */
+#define IEEE80211_TYPE_DATA 0x0008
+
+
+/** 802.11 Frame Control field, Frame Subtype bitmask */
+#define IEEE80211_FC_SUBTYPE 0x00F0
+
+/** Subtype value for association-request management frames
+ *
+ * Association request frames are sent after authentication from the
+ * client to the Access Point to establish the client as part of the
+ * Access Point's network.
+ */
+#define IEEE80211_STYPE_ASSOC_REQ 0x0000
+
+/** Subtype value for association-response management frames
+ *
+ * Association response frames are sent by the Access Point to confirm
+ * or deny the association requested in an association request frame.
+ */
+#define IEEE80211_STYPE_ASSOC_RESP 0x0010
+
+/** Subtype value for reassociation-request management frames
+ *
+ * Reassociation request frames are sent by clients wishing to change
+ * from one Access Point to another while roaming within the same
+ * extended network (same ESSID).
+ */
+#define IEEE80211_STYPE_REASSOC_REQ 0x0020
+
+/** Subtype value for reassociation-response management frames
+ *
+ * Reassociation response frames are sent by the Access Point to
+ * confirm or deny the swap requested in a reassociation request
+ * frame.
+ */
+#define IEEE80211_STYPE_REASSOC_RESP 0x0030
+
+/** Subtype value for probe-request management frames
+ *
+ * Probe request frames are sent by clients to request that all Access
+ * Points on the sending channel, or all belonging to a particular
+ * ESSID, identify themselves by BSSID, supported transfer rates, RF
+ * configuration, and other capabilities.
+ */
+#define IEEE80211_STYPE_PROBE_REQ 0x0040
+
+/** Subtype value for probe-response management frames
+ *
+ * Probe response frames are sent by Access Points in response to
+ * probe request frames, providing the requested information.
+ */
+#define IEEE80211_STYPE_PROBE_RESP 0x0050
+
+/** Subtype value for beacon management frames
+ *
+ * Beacon frames are sent by Access Points at regular intervals,
+ * usually ten per second, on the channel on which they communicate.
+ * They can be used to probe passively for access points on a channel
+ * where local regulatory restrictions prohibit active scanning, or
+ * due to their regularity as a mechanism to determine the fraction of
+ * packets that are being dropped.
+ */
+#define IEEE80211_STYPE_BEACON 0x0080
+
+/** Subtype value for disassociation management frames
+ *
+ * Disassociation frames are sent by either a client or an Access
+ * Point to unequivocally terminate the association between the two.
+ * They may be sent by clients upon leaving the network, or by an
+ * Access Point upon reconfiguration, among other reasons; they are
+ * usually more "polite" than deauthentication frames.
+ */
+#define IEEE80211_STYPE_DISASSOC 0x00A0
+
+/** Subtype value for authentication management frames
+ *
+ * Authentication frames are exchanged between a client and an Access
+ * Point before association may be performed. Confusingly, in the most
+ * common authentication method (Open System) no security tokens are
+ * exchanged at all. Modern 802.11 security handshaking takes place
+ * after association.
+ */
+#define IEEE80211_STYPE_AUTH 0x00B0
+
+/** Subtype value for deauthentication management frames
+ *
+ * Deauthentication frames are sent by either a client or an Access
+ * Point to terminate the authentication (and therefore also the
+ * association) between the two. They are generally more forceful than
+ * disassociation frames, sent for such reasons as a failure to
+ * set up security properly after associating.
+ */
+#define IEEE80211_STYPE_DEAUTH 0x00C0
+
+/** Subtype value for action management frames
+ *
+ * Action frames are used to implement spectrum management and QoS
+ * features that gPXE currently does not support.
+ */
+#define IEEE80211_STYPE_ACTION 0x00D0
+
+
+/** Subtype value for RTS (request to send) control frames */
+#define IEEE80211_STYPE_RTS 0x00B0
+
+/** Subtype value for CTS (clear to send) control frames */
+#define IEEE80211_STYPE_CTS 0x00C0
+
+/** Subtype value for ACK (acknowledgement) control frames */
+#define IEEE80211_STYPE_ACK 0x00D0
+
+
+/** Subtype value for ordinary data frames, with no QoS or CF add-ons */
+#define IEEE80211_STYPE_DATA 0x0000
+
+/** Subtype value for data frames containing no data */
+#define IEEE80211_STYPE_NODATA 0x0040
+
+
+/** 802.11 Frame Control field: To Data System flag
+ *
+ * This is set on data frames sent to an Access Point.
+ */
+#define IEEE80211_FC_TODS 0x0100
+
+/** 802.11 Frame Control field: From Data System flag
+ *
+ * This is set on data frames sent from an Access Point. If both TODS
+ * and FROMDS are set, the frame header is a 4-address format used for
+ * inter-Access Point communication.
+ */
+#define IEEE80211_FC_FROMDS 0x0200
+
+/** 802.11 Frame Control field: More Fragments flag */
+#define IEEE80211_FC_MORE_FRAG 0x0400
+
+/** 802.11 Frame Control field: Retransmission flag */
+#define IEEE80211_FC_RETRY 0x0800
+
+/** 802.11 Frame Control field: Power Managed flag
+ *
+ * This is set on any frame sent by a low-power station that will go
+ * into a power-saving mode immediately after this frame. Access
+ * Points are not allowed to act as low-power stations.
+ */
+#define IEEE80211_FC_PWR_MGMT 0x1000
+
+/** 802.11 Frame Control field: More Data flag
+ *
+ * This is set on any frame sent by a station that has more data
+ * queued to be sent than is in the frame.
+ */
+#define IEEE80211_FC_MORE_DATA 0x2000
+
+/** 802.11 Frame Control field: Protected flag
+ *
+ * This is set on frames in which data is encrypted (by any method).
+ */
+#define IEEE80211_FC_PROTECTED 0x4000
+
+/** 802.11 Frame Control field: Ordered flag [?] */
+#define IEEE80211_FC_ORDER 0x8000
+
+/** @} */
+
+
+/* ---------- Sequence Control defines ---------- */
+
+/**
+ * @defgroup ieee80211_seq 802.11 Sequence Control field handling
+ * @{
+ */
+
+/** Extract sequence number from 802.11 Sequence Control field */
+#define IEEE80211_SEQNR( seq ) ( ( seq ) >> 4 )
+
+/** Extract fragment number from 802.11 Sequence Control field */
+#define IEEE80211_FRAG( seq ) ( ( seq ) & 0x000F )
+
+/** Make 802.11 Sequence Control field from sequence and fragment numbers */
+#define IEEE80211_MAKESEQ( seqnr, frag ) \
+ ( ( ( ( seqnr ) & 0xFFF ) << 4 ) | ( ( frag ) & 0xF ) )
+
+/** @} */
+
+
+/* ---------- Frame header formats ---------- */
+
+/**
+ * @defgroup ieee80211_hdr 802.11 frame header formats
+ * @{
+ */
+
+/** An 802.11 data or management frame without QoS or WDS header fields */
+struct ieee80211_frame
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+ u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */
+ u8 addr3[ETH_ALEN]; /**< Address 3 (often "forward to") */
+ u16 seq; /**< 802.11 Sequence Control field */
+ u8 data[0]; /**< Beginning of frame data */
+} __attribute__((packed));
+
+/** The 802.2 LLC/SNAP header sent before actual data in a data frame
+ *
+ * This header is not acknowledged in the 802.11 standard at all; it
+ * is treated just like data for MAC-layer purposes, including
+ * fragmentation and encryption. It is actually two headers
+ * concatenated: a three-byte 802.2 LLC header indicating Subnetwork
+ * Accesss Protocol (SNAP) in both source and destination Service
+ * Access Point (SAP) fields, and a five-byte SNAP header indicating a
+ * zero OUI and two-byte Ethernet protocol type field.
+ *
+ * Thus, an eight-byte header in which six of the bytes are redundant.
+ * Lovely, isn't it?
+ */
+struct ieee80211_llc_snap_header
+{
+ /* LLC part: */
+ u8 dsap; /**< Destination SAP ID */
+ u8 ssap; /**< Source SAP ID */
+ u8 ctrl; /**< Control information */
+
+ /* SNAP part: */
+ u8 oui[3]; /**< Organization code, usually 0 */
+ u16 ethertype; /**< Ethernet Type field */
+} __attribute__((packed));
+
+/** Value for DSAP field in 802.2 LLC header for 802.11 frames: SNAP */
+#define IEEE80211_LLC_DSAP 0xAA
+
+/** Value for SSAP field in 802.2 LLC header for 802.11 frames: SNAP */
+#define IEEE80211_LLC_SSAP 0xAA
+
+/** Value for control field in 802.2 LLC header for 802.11 frames
+ *
+ * "Unnumbered Information".
+ */
+#define IEEE80211_LLC_CTRL 0x03
+
+
+/** 16-byte RTS frame format, with abbreviated header */
+struct ieee80211_rts
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+ u8 addr2[ETH_ALEN]; /**< Address 2 (immediate sender) */
+} __attribute__((packed));
+
+/** Length of 802.11 RTS control frame */
+#define IEEE80211_RTS_LEN 16
+
+/** 10-byte CTS or ACK frame format, with abbreviated header */
+struct ieee80211_cts_or_ack
+{
+ u16 fc; /**< 802.11 Frame Control field */
+ u16 duration; /**< Microseconds to reserve link */
+ u8 addr1[ETH_ALEN]; /**< Address 1 (immediate receiver) */
+} __attribute__((packed));
+
+#define ieee80211_cts ieee80211_cts_or_ack
+#define ieee80211_ack ieee80211_cts_or_ack
+
+/** Length of 802.11 CTS control frame */
+#define IEEE80211_CTS_LEN 10
+
+/** Length of 802.11 ACK control frame */
+#define IEEE80211_ACK_LEN 10
+
+/** @} */
+
+
+/* ---------- Capability bits, status and reason codes ---------- */
+
+/**
+ * @defgroup ieee80211_capab 802.11 management frame capability field bits
+ * @{
+ */
+
+/** Set if using an Access Point (managed mode) */
+#define IEEE80211_CAPAB_MANAGED 0x0001
+
+/** Set if operating in IBSS (no-AP, "Ad-Hoc") mode */
+#define IEEE80211_CAPAB_ADHOC 0x0002
+
+/** Set if we support Contention-Free Period operation */
+#define IEEE80211_CAPAB_CFPOLL 0x0004
+
+/** Set if we wish to be polled for Contention-Free operation */
+#define IEEE80211_CAPAB_CFPR 0x0008
+
+/** Set if the network is encrypted (by any method) */
+#define IEEE80211_CAPAB_PRIVACY 0x0010
+
+/** Set if PHY supports short preambles on 802.11b */
+#define IEEE80211_CAPAB_SHORT_PMBL 0x0020
+
+/** Set if PHY supports PBCC modulation */
+#define IEEE80211_CAPAB_PBCC 0x0040
+
+/** Set if we support Channel Agility */
+#define IEEE80211_CAPAB_CHAN_AGILITY 0x0080
+
+/** Set if we support spectrum management (DFS and TPC) on the 5GHz band */
+#define IEEE80211_CAPAB_SPECTRUM_MGMT 0x0100
+
+/** Set if we support Quality of Service enhancements */
+#define IEEE80211_CAPAB_QOS 0x0200
+
+/** Set if PHY supports short slot time on 802.11g */
+#define IEEE80211_CAPAB_SHORT_SLOT 0x0400
+
+/** Set if PHY supports APSD option */
+#define IEEE80211_CAPAB_APSD 0x0800
+
+/** Set if PHY supports DSSS/OFDM modulation (one way of 802.11 b/g mixing) */
+#define IEEE80211_CAPAB_DSSS_OFDM 0x2000
+
+/** Set if we support delayed block ACK */
+#define IEEE80211_CAPAB_DELAYED_BACK 0x4000
+
+/** Set if we support immediate block ACK */
+#define IEEE80211_CAPAB_IMMED_BACK 0x8000
+
+/** @} */
+
+
+/**
+ * @defgroup ieee80211_status 802.11 status codes
+ *
+ * These are returned to indicate an immediate denial of
+ * authentication or association. In gPXE, the lower 5 bits of the
+ * status code are encoded into the file-unique portion of an error
+ * code, the ERRFILE portion is always @c ERRFILE_net80211, and the
+ * POSIX error code is @c ECONNREFUSED for status 0-31 or @c
+ * EHOSTUNREACH for status 32-63.
+ *
+ * For a complete table with non-abbreviated error messages, see IEEE
+ * Std 802.11-2007, Table 7-23, p.94.
+ *
+ * @{
+ */
+
+#define IEEE80211_STATUS_SUCCESS 0
+#define IEEE80211_STATUS_FAILURE 1
+#define IEEE80211_STATUS_CAPAB_UNSUPP 10
+#define IEEE80211_STATUS_REASSOC_INVALID 11
+#define IEEE80211_STATUS_ASSOC_DENIED 12
+#define IEEE80211_STATUS_AUTH_ALGO_UNSUPP 13
+#define IEEE80211_STATUS_AUTH_SEQ_INVALID 14
+#define IEEE80211_STATUS_AUTH_CHALL_INVALID 15
+#define IEEE80211_STATUS_AUTH_TIMEOUT 16
+#define IEEE80211_STATUS_ASSOC_NO_ROOM 17
+#define IEEE80211_STATUS_ASSOC_NEED_RATE 18
+#define IEEE80211_STATUS_ASSOC_NEED_SHORT_PMBL 19
+#define IEEE80211_STATUS_ASSOC_NEED_PBCC 20
+#define IEEE80211_STATUS_ASSOC_NEED_CHAN_AGILITY 21
+#define IEEE80211_STATUS_ASSOC_NEED_SPECTRUM_MGMT 22
+#define IEEE80211_STATUS_ASSOC_BAD_POWER 23
+#define IEEE80211_STATUS_ASSOC_BAD_CHANNELS 24
+#define IEEE80211_STATUS_ASSOC_NEED_SHORT_SLOT 25
+#define IEEE80211_STATUS_ASSOC_NEED_DSSS_OFDM 26
+#define IEEE80211_STATUS_QOS_FAILURE 32
+#define IEEE80211_STATUS_QOS_NO_ROOM 33
+#define IEEE80211_STATUS_LINK_IS_HORRIBLE 34
+#define IEEE80211_STATUS_ASSOC_NEED_QOS 35
+#define IEEE80211_STATUS_REQUEST_DECLINED 37
+#define IEEE80211_STATUS_REQUEST_INVALID 38
+#define IEEE80211_STATUS_TS_NOT_CREATED_AGAIN 39
+#define IEEE80211_STATUS_INVALID_IE 40
+#define IEEE80211_STATUS_GROUP_CIPHER_INVALID 41
+#define IEEE80211_STATUS_PAIR_CIPHER_INVALID 42
+#define IEEE80211_STATUS_AKMP_INVALID 43
+#define IEEE80211_STATUS_RSN_VERSION_UNSUPP 44
+#define IEEE80211_STATUS_RSN_CAPAB_INVALID 45
+#define IEEE80211_STATUS_CIPHER_REJECTED 46
+#define IEEE80211_STATUS_TS_NOT_CREATED_WAIT 47
+#define IEEE80211_STATUS_DIRECT_LINK_FORBIDDEN 48
+#define IEEE80211_STATUS_DEST_NOT_PRESENT 49
+#define IEEE80211_STATUS_DEST_NOT_QOS 50
+#define IEEE80211_STATUS_ASSOC_LISTEN_TOO_HIGH 51
+
+/** @} */
+
+
+
+/**
+ * @defgroup ieee80211_reason 802.11 reason codes
+ *
+ * These are returned to indicate the reason for a deauthentication or
+ * disassociation sent (usually) after authentication or association
+ * had succeeded. In gPXE, the lower 5 bits of the reason code are
+ * encoded into the file-unique portion of an error code, the ERRFILE
+ * portion is always @c ERRFILE_net80211, and the POSIX error code is
+ * @c ECONNRESET for reason 0-31 or @c ENETRESET for reason 32-63.
+ *
+ * For a complete table with non-abbreviated error messages, see IEEE
+ * Std 802.11-2007, Table 7-22, p.92.
+ *
+ * @{
+ */
+
+#define IEEE80211_REASON_NONE 0
+#define IEEE80211_REASON_UNSPECIFIED 1
+#define IEEE80211_REASON_AUTH_NO_LONGER_VALID 2
+#define IEEE80211_REASON_LEAVING 3
+#define IEEE80211_REASON_INACTIVITY 4
+#define IEEE80211_REASON_OUT_OF_RESOURCES 5
+#define IEEE80211_REASON_NEED_AUTH 6
+#define IEEE80211_REASON_NEED_ASSOC 7
+#define IEEE80211_REASON_LEAVING_TO_ROAM 8
+#define IEEE80211_REASON_REASSOC_INVALID 9
+#define IEEE80211_REASON_BAD_POWER 10
+#define IEEE80211_REASON_BAD_CHANNELS 11
+#define IEEE80211_REASON_INVALID_IE 13
+#define IEEE80211_REASON_MIC_FAILURE 14
+#define IEEE80211_REASON_4WAY_TIMEOUT 15
+#define IEEE80211_REASON_GROUPKEY_TIMEOUT 16
+#define IEEE80211_REASON_4WAY_INVALID 17
+#define IEEE80211_REASON_GROUP_CIPHER_INVALID 18
+#define IEEE80211_REASON_PAIR_CIPHER_INVALID 19
+#define IEEE80211_REASON_AKMP_INVALID 20
+#define IEEE80211_REASON_RSN_VERSION_INVALID 21
+#define IEEE80211_REASON_RSN_CAPAB_INVALID 22
+#define IEEE80211_REASON_8021X_FAILURE 23
+#define IEEE80211_REASON_CIPHER_REJECTED 24
+#define IEEE80211_REASON_QOS_UNSPECIFIED 32
+#define IEEE80211_REASON_QOS_OUT_OF_RESOURCES 33
+#define IEEE80211_REASON_LINK_IS_HORRIBLE 34
+#define IEEE80211_REASON_INVALID_TXOP 35
+#define IEEE80211_REASON_REQUESTED_LEAVING 36
+#define IEEE80211_REASON_REQUESTED_NO_USE 37
+#define IEEE80211_REASON_REQUESTED_NEED_SETUP 38
+#define IEEE80211_REASON_REQUESTED_TIMEOUT 39
+#define IEEE80211_REASON_CIPHER_UNSUPPORTED 45
+
+/** @} */
+
+/* ---------- Information element declarations ---------- */
+
+/**
+ * @defgroup ieee80211_ie 802.11 information elements
+ *
+ * Many management frames include a section that amounts to a
+ * concatenation of these information elements, so that the sender can
+ * choose which information to send and the receiver can ignore the
+ * parts it doesn't understand. Each IE contains a two-byte header,
+ * one byte ID and one byte length, followed by IE-specific data. The
+ * length does not include the two-byte header. Information elements
+ * are required to be sorted by ID, but gPXE does not require that in
+ * those it receives.
+ *
+ * This group also includes a few inline functions to simplify common
+ * tasks in IE processing.
+ *
+ * @{
+ */
+
+/** Generic 802.11 information element header */
+struct ieee80211_ie_header {
+ u8 id; /**< Information element ID */
+ u8 len; /**< Information element length */
+} __attribute__ ((packed));
+
+
+/** 802.11 SSID information element */
+struct ieee80211_ie_ssid {
+ u8 id; /**< SSID ID: 0 */
+ u8 len; /**< SSID length */
+ char ssid[0]; /**< SSID data, not NUL-terminated */
+} __attribute__ ((packed));
+
+/** Information element ID for SSID information element */
+#define IEEE80211_IE_SSID 0
+
+
+/** 802.11 rates information element
+ *
+ * The first 8 rates go in an IE of type RATES (1), and any more rates
+ * go in one of type EXT_RATES (50). Each rate is a byte with the low
+ * 7 bits equal to the rate in units of 500 kbps, and the high bit set
+ * if and only if the rate is "basic" (must be supported by all
+ * connected stations).
+ */
+struct ieee80211_ie_rates {
+ u8 id; /**< Rates ID: 1 or 50 */
+ u8 len; /**< Number of rates */
+ u8 rates[0]; /**< Rates data, one rate per byte */
+} __attribute__ ((packed));
+
+/** Information element ID for rates information element */
+#define IEEE80211_IE_RATES 1
+
+/** Information element ID for extended rates information element */
+#define IEEE80211_IE_EXT_RATES 50
+
+
+/** 802.11 Direct Spectrum parameter information element
+ *
+ * This just contains the channel number. It has the fancy name
+ * because IEEE 802.11 also defines a frequency-hopping PHY that
+ * changes channels at regular intervals following a predetermined
+ * pattern; in practice nobody uses the FH PHY.
+ */
+struct ieee80211_ie_ds_param {
+ u8 id; /**< DS parameter ID: 3 */
+ u8 len; /**< DS parameter length: 1 */
+ u8 current_channel; /**< Current channel number, 1-14 */
+} __attribute__ ((packed));
+
+/** Information element ID for Direct Spectrum parameter information element */
+#define IEEE80211_IE_DS_PARAM 3
+
+
+/** 802.11 Country information element regulatory extension triplet */
+struct ieee80211_ie_country_ext_triplet {
+ u8 reg_ext_id; /**< Regulatory extension ID */
+ u8 reg_class_id; /**< Regulatory class ID */
+ u8 coverage_class; /**< Coverage class */
+} __attribute__ ((packed));
+
+/** 802.11 Country information element regulatory band triplet */
+struct ieee80211_ie_country_band_triplet {
+ u8 first_channel; /**< Channel number for first channel in band */
+ u8 nr_channels; /**< Number of contiguous channels in band */
+ u8 max_txpower; /**< Maximum TX power in dBm */
+} __attribute__ ((packed));
+
+/** 802.11 Country information element regulatory triplet
+ *
+ * It is a band triplet if the first byte is 200 or less, and a
+ * regulatory extension triplet otherwise.
+ */
+union ieee80211_ie_country_triplet {
+ /** Differentiator between band and ext triplets */
+ u8 first;
+
+ /** Information about a band of channels */
+ struct ieee80211_ie_country_band_triplet band;
+
+ /** Regulatory extension information */
+ struct ieee80211_ie_country_ext_triplet ext;
+};
+
+/** 802.11 Country information element
+ *
+ * This contains some data about RF regulations.
+ */
+struct ieee80211_ie_country {
+ u8 id; /**< Country information ID: 7 */
+ u8 len; /**< Country information length: varies */
+ char name[2]; /**< ISO Alpha2 country code */
+ char in_out; /**< 'I' for indoor, 'O' for outdoor */
+
+ /** List of regulatory triplets */
+ union ieee80211_ie_country_triplet triplet[0];
+} __attribute__ ((packed));
+
+/** Information element ID for Country information element */
+#define IEEE80211_IE_COUNTRY 7
+
+
+/** 802.11 Request information element
+ *
+ * This contains a list of information element types we would like to
+ * be included in probe response frames.
+ */
+struct ieee80211_ie_request {
+ u8 id; /**< Request ID: 10 */
+ u8 len; /**< Number of IEs requested */
+ u8 request[0]; /**< List of IEs requested */
+} __attribute__ ((packed));
+
+/** Information element ID for Request information element */
+#define IEEE80211_IE_REQUEST 10
+
+
+/** 802.11 Challenge Text information element
+ *
+ * This is used in authentication frames under Shared Key
+ * authentication.
+ */
+struct ieee80211_ie_challenge_text {
+ u8 id; /**< Challenge Text ID: 16 */
+ u8 len; /**< Challenge Text length: usually 128 */
+ u8 challenge_text[0]; /**< Challenge Text data */
+} __attribute__ ((packed));
+
+/** Information element ID for Challenge Text information element */
+#define IEEE80211_IE_CHALLENGE_TEXT 16
+
+
+/** 802.11 Power Constraint information element
+ *
+ * This is used to specify an additional power limitation on top of
+ * the Country requirements.
+ */
+struct ieee80211_ie_power_constraint {
+ u8 id; /**< Power Constraint ID: 52 */
+ u8 len; /**< Power Constraint length: 1 */
+ u8 power_constraint; /**< Decrease in allowed TX power, dBm */
+} __attribute__ ((packed));
+
+/** Information element ID for Power Constraint information element */
+#define IEEE80211_IE_POWER_CONSTRAINT 52
+
+
+/** 802.11 Power Capability information element
+ *
+ * This is used in association request frames to indicate the extremes
+ * of our TX power abilities. It is required only if we indicate
+ * support for spectrum management.
+ */
+struct ieee80211_ie_power_capab {
+ u8 id; /**< Power Capability ID: 33 */
+ u8 len; /**< Power Capability length: 2 */
+ u8 min_txpower; /**< Minimum possible TX power, dBm */
+ u8 max_txpower; /**< Maximum possible TX power, dBm */
+} __attribute__ ((packed));
+
+/** Information element ID for Power Capability information element */
+#define IEEE80211_IE_POWER_CAPAB 33
+
+
+/** 802.11 Channels information element channel band tuple */
+struct ieee80211_ie_channels_channel_band {
+ u8 first_channel; /**< Channel number of first channel in band */
+ u8 nr_channels; /**< Number of channels in band */
+} __attribute__ ((packed));
+
+/** 802.11 Channels information element
+ *
+ * This is used in association frames to indicate the channels we can
+ * use. It is required only if we indicate support for spectrum
+ * management.
+ */
+struct ieee80211_ie_channels {
+ u8 id; /**< Channels ID: 36 */
+ u8 len; /**< Channels length: 2 */
+
+ /** List of (start, length) channel bands we can use */
+ struct ieee80211_ie_channels_channel_band channels[0];
+} __attribute__ ((packed));
+
+/** Information element ID for Channels information element */
+#define IEEE80211_IE_CHANNELS 36
+
+
+/** 802.11 ERP Information information element
+ *
+ * This is used to communicate some PHY-level flags.
+ */
+struct ieee80211_ie_erp_info {
+ u8 id; /**< ERP Information ID: 42 */
+ u8 len; /**< ERP Information length: 1 */
+ u8 erp_info; /**< ERP flags */
+} __attribute__ ((packed));
+
+/** Information element ID for ERP Information information element */
+#define IEEE80211_IE_ERP_INFO 42
+
+/** ERP information element: Flag set if 802.11b stations are present */
+#define IEEE80211_ERP_NONERP_PRESENT 0x01
+
+/** ERP information element: Flag set if CTS protection must be used */
+#define IEEE80211_ERP_USE_PROTECTION 0x02
+
+/** ERP information element: Flag set if long preambles must be used */
+#define IEEE80211_ERP_BARKER_LONG 0x04
+
+
+/** 802.11 Robust Security Network ("WPA") information element
+ *
+ * Showing once again a striking clarity of design, the IEEE folks put
+ * dynamically-sized data in the middle of this structure. As such,
+ * the below structure definition is only a guideline; the
+ * @c IEEE80211_RSN_FIELD, @c IEEE80211_RSN_CIPHER, and
+ * @c IEEE80211_RSN_AUTHTYPE macros should be used to access any
+ * data.
+ *
+ * Also inspired was IEEE's choice of 16-bit fields to count the
+ * number of 4-byte elements in a structure with a maximum length of
+ * 255 bytes.
+ *
+ * Many fields reference a cipher or authentication-type ID; this is a
+ * three-byte OUI followed by one byte identifying the cipher with
+ * respect to that OUI. For all standard ciphers the OUI is 00:0F:AC.
+ *
+ * The authentication types referenced in this structure have nothing
+ * to do with 802.11 authentication frames or the @c algorithm field
+ * within them.
+ */
+struct ieee80211_ie_rsn {
+ /** Information element ID */
+ u8 id;
+
+ /** Information element length */
+ u8 len;
+
+ /** RSN information element version */
+ u16 version;
+
+ /** Cipher ID for the cipher used in multicast/broadcast frames */
+ u8 group_cipher[4];
+
+ /** Number of unicast ciphers supported */
+ u16 pairwise_count;
+
+ /** List of cipher IDs for supported unicast frame ciphers */
+ u8 pairwise_cipher[4];
+
+ /** Number of authentication types supported */
+ u16 akm_count;
+
+ /** List of authentication type IDs for supported types */
+ u8 akm_list[4];
+
+ /** Security capabilities field. */
+ u16 rsn_capab;
+
+ /** Number of PMKIDs included (present only in association frames) */
+ u16 pmkid_count;
+
+ /** List of PMKIDs included, each a 16-byte SHA1 hash */
+ u8 pmkid_list[0];
+} __attribute__((packed));
+
+/** Information element ID for Robust Security Network information element */
+#define IEEE80211_IE_RSN 48
+
+/** OUI for standard ciphers in RSN information element */
+#define IEEE80211_RSN_OUI "\x00\x0F\xAC"
+
+/** Extract RSN IE version field */
+#define IEEE80211_RSN_FIELD_version( rsnp ) ( (rsnp)->version )
+
+/** Extract RSN IE group_cipher field */
+#define IEEE80211_RSN_FIELD_group_cipher( rsnp ) ( (rsnp)->group_cipher )
+
+/** Extract RSN IE pairwise_count field */
+#define IEEE80211_RSN_FIELD_pairwise_count( rsnp ) ( (rsnp)->pairwise_count )
+
+/** Extract RSN IE akm_count field */
+#define IEEE80211_RSN_FIELD_akm_count( rsnp ) \
+ ( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
+ 4*( ( rsnp )->pairwise_count - 1 ) ) )->akm_count )
+
+/** Extract RSN IE rsn_capab field */
+#define IEEE80211_RSN_FIELD_rsn_capab( rsnp ) \
+ ( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
+ 4*( ( rsnp )->pairwise_count - 1 ) + \
+ 4*( ( rsnp )->akm_count - 1 ) ) )->rsn_capab )
+
+/** Extract RSN IE pmkid_count field */
+#define IEEE80211_RSN_FIELD_pmkid_count( rsnp ) \
+ ( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
+ 4*( ( rsnp )->pairwise_count - 1 ) + \
+ 4*( ( rsnp )->akm_count - 1 ) ) )->pmkid_count )
+
+/** Extract field from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v field Name of field to extract
+ * @ret val Lvalue of the requested field
+ *
+ * You must fill the fields of the structure in order for this to work
+ * properly.
+ */
+#define IEEE80211_RSN_FIELD( rsnp, field ) \
+ IEEE80211_RSN_FIELD_ ## field ( rsnp )
+
+/** Get pointer to pairwise cipher from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v cipher Index of pairwise cipher to extract
+ * @ret ptr Pointer to requested cipher
+ */
+#define IEEE80211_RSN_CIPHER( rsnp, cipher ) \
+ ( ( rsnp )->pairwise_cipher + 4 * ( cipher ) )
+
+/** Get pointer to authentication type from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v akm Index of authentication type to extract
+ * @ret ptr Pointer to requested authentication type
+ *
+ * The @c pairwise_count field must be correct.
+ */
+#define IEEE80211_RSN_AUTHTYPE( rsnp, akm ) \
+ ( ( rsnp )->akm_list + 4 * ( ( rsnp )->pairwise_count - 1 ) + 4 * ( akm ) )
+
+/** Get pointer to PMKID from RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @v idx Index of PMKID to extract
+ * @ret ptr Pointer to requested PMKID
+ *
+ * The @c pairwise_count and @c akm_count fields must be correct.
+ */
+#define IEEE80211_RSN_PMKID( rsnp, idx ) \
+ ( ( rsnp )->pmkid_list + 4 * ( ( rsnp )->pairwise_count - 1 ) + \
+ 4 * ( ( rsnp )->akm_count - 1 ) + 16 * ( idx ) )
+
+/** Verify size of RSN information element
+ *
+ * @v rsnp Pointer to RSN information element
+ * @ret ok TRUE if count fields are consistent with length field
+ *
+ * It is important to drop any RSN IE that does not pass this function
+ * before using the @c IEEE80211_RSN_FIELD, @c IEEE80211_RSN_CIPHER,
+ * and @c IEEE80211_RSN_AUTHTYPE macros, to avoid potential security
+ * compromise due to a malformed RSN IE.
+ *
+ * This function does not consider the possibility of some PMKIDs
+ * included in the RSN IE, because PMKIDs are only included in RSN IEs
+ * sent in association request frames, and we should never receive an
+ * association request frame. An RSN IE that includes PMKIDs will
+ * always fail this check.
+ */
+static inline int ieee80211_rsn_check ( struct ieee80211_ie_rsn *rsnp ) {
+ if ( rsnp->len < 12 + 4 * rsnp->pairwise_count )
+ return 0;
+ return ( rsnp->len == 12 + 4 * ( rsnp->pairwise_count +
+ IEEE80211_RSN_FIELD ( rsnp, akm_count ) ) );
+}
+
+/** Calculate necessary size of RSN information element
+ *
+ * @v npair Number of pairwise ciphers supported
+ * @v nauth Number of authentication types supported
+ * @v npmkid Number of PMKIDs to include
+ * @ret size Necessary size of RSN IE, including header bytes
+ */
+static inline size_t ieee80211_rsn_size ( int npair, int nauth, int npmkid ) {
+ return 16 + 4 * ( npair + nauth ) + 16 * npmkid;
+}
+
+/** 802.11 RSN IE: expected version number */
+#define IEEE80211_RSN_VERSION 1
+
+/** 802.11 RSN IE: fourth byte of cipher type for 40-bit WEP */
+#define IEEE80211_RSN_CTYPE_WEP40 1
+
+/** 802.11 RSN IE: fourth byte of cipher type for 104-bit WEP */
+#define IEEE80211_RSN_CTYPE_WEP104 5
+
+/** 802.11 RSN IE: fourth byte of cipher type for TKIP ("WPA") */
+#define IEEE80211_RSN_CTYPE_TKIP 2
+
+/** 802.11 RSN IE: fourth byte of cipher type for CCMP ("WPA2") */
+#define IEEE80211_RSN_CTYPE_CCMP 4
+
+/** 802.11 RSN IE: fourth byte of cipher type for "use group"
+ *
+ * This can only appear as a pairwise cipher, and means unicast frames
+ * should be encrypted in the same way as broadcast/multicast frames.
+ */
+#define IEEE80211_RSN_CTYPE_USEGROUP 0
+
+/** 802.11 RSN IE: fourth byte of auth method type for using an 802.1X server */
+#define IEEE80211_RSN_ATYPE_8021X 1
+
+/** 802.11 RSN IE: fourth byte of auth method type for using a pre-shared key */
+#define IEEE80211_RSN_ATYPE_PSK 2
+
+/** 802.11 RSN IE capabilities: AP supports pre-authentication */
+#define IEEE80211_RSN_CAPAB_PREAUTH 0x001
+
+/** 802.11 RSN IE capabilities: Node has conflict between TKIP and WEP
+ *
+ * This is a legacy issue; APs always set it to 0, and gPXE sets it to
+ * 0.
+ */
+#define IEEE80211_RSN_CAPAB_NO_PAIRWISE 0x002
+
+/** 802.11 RSN IE capabilities: Number of PTKSA replay counters
+ *
+ * A value of 0 means one replay counter, 1 means two, 2 means four,
+ * and 3 means sixteen.
+ */
+#define IEEE80211_RSN_CAPAB_PTKSA_REPLAY 0x00C
+
+/** 802.11 RSN IE capabilities: Number of GTKSA replay counters
+ *
+ * A value of 0 means one replay counter, 1 means two, 2 means four,
+ * and 3 means sixteen.
+ */
+#define IEEE80211_RSN_CAPAB_GTKSA_REPLAY 0x030
+
+/** 802.11 RSN IE capabilities: PeerKey Handshaking is suported */
+#define IEEE80211_RSN_CAPAB_PEERKEY 0x200
+
+
+
+/** Any 802.11 information element
+ *
+ * This is formatted for ease of use, so IEs with complex structures
+ * get referenced in full, while those with only one byte of data or a
+ * simple array are pulled in to avoid a layer of indirection like
+ * ie->channels.channels[0].
+ */
+union ieee80211_ie
+{
+ /** Generic and simple information element info */
+ struct {
+ u8 id; /**< Information element ID */
+ u8 len; /**< Information element data length */
+ union {
+ char ssid[0]; /**< SSID text */
+ u8 rates[0]; /**< Rates data */
+ u8 request[0]; /**< Request list */
+ u8 challenge_text[0]; /**< Challenge text data */
+ u8 power_constraint; /**< Power constraint, dBm */
+ u8 erp_info; /**< ERP information flags */
+ /** List of channels */
+ struct ieee80211_ie_channels_channel_band channels[0];
+ };
+ };
+
+ /** DS parameter set */
+ struct ieee80211_ie_ds_param ds_param;
+
+ /** Country information */
+ struct ieee80211_ie_country country;
+
+ /** Power capability */
+ struct ieee80211_ie_power_capab power_capab;
+
+ /** Security information */
+ struct ieee80211_ie_rsn rsn;
+};
+
+/** Advance to next 802.11 information element
+ *
+ * @v ie Current information element pointer
+ * @v end Pointer to first byte not in information element space
+ * @ret next Pointer to next information element, or NULL if no more
+ *
+ * When processing received IEs, @a end should be set to the I/O
+ * buffer tail pointer; when marshalling IEs for sending, @a end
+ * should be NULL.
+ */
+static inline union ieee80211_ie * ieee80211_next_ie ( union ieee80211_ie *ie,
+ void *end )
+{
+ void *next_ie_byte = ( void * ) ie + ie->len + 2;
+ union ieee80211_ie *next_ie = next_ie_byte;
+
+ if ( ! end )
+ return next_ie;
+
+ if ( next_ie_byte < end && next_ie_byte + next_ie->len <= end )
+ return next_ie;
+
+ return NULL;
+}
+
+/** @} */
+
+
+/* ---------- Management frame data formats ---------- */
+
+/**
+ * @defgroup ieee80211_mgmt_data Management frame data payloads
+ * @{
+ */
+
+/** Beacon or probe response frame data */
+struct ieee80211_beacon_or_probe_resp
+{
+ /** 802.11 TSFT value at frame send */
+ u64 timestamp;
+
+ /** Interval at which beacons are sent, in units of 1024 us */
+ u16 beacon_interval;
+
+ /** Capability flags */
+ u16 capability;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+#define ieee80211_beacon ieee80211_beacon_or_probe_resp
+#define ieee80211_probe_resp ieee80211_beacon_or_probe_resp
+
+/** Disassociation or deauthentication frame data */
+struct ieee80211_disassoc_or_deauth
+{
+ /** Reason code */
+ u16 reason;
+} __attribute__((packed));
+
+#define ieee80211_disassoc ieee80211_disassoc_or_deauth
+#define ieee80211_deauth ieee80211_disassoc_or_deauth
+
+/** Association request frame data */
+struct ieee80211_assoc_req
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Interval at which we wake up, in units of the beacon interval */
+ u16 listen_interval;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Association or reassociation response frame data */
+struct ieee80211_assoc_or_reassoc_resp
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Status code */
+ u16 status;
+
+ /** Association ID */
+ u16 aid;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+#define ieee80211_assoc_resp ieee80211_assoc_or_reassoc_resp
+#define ieee80211_reassoc_resp ieee80211_assoc_or_reassoc_resp
+
+/** Reassociation request frame data */
+struct ieee80211_reassoc_req
+{
+ /** Capability flags */
+ u16 capability;
+
+ /** Interval at which we wake up, in units of the beacon interval */
+ u16 listen_interval;
+
+ /** MAC address of current Access Point */
+ u8 current_addr[ETH_ALEN];
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Probe request frame data */
+struct ieee80211_probe_req
+{
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Authentication frame data */
+struct ieee80211_auth
+{
+ /** Authentication algorithm (Open System or Shared Key) */
+ u16 algorithm;
+
+ /** Sequence number of this frame; first from client to AP is 1 */
+ u16 tx_seq;
+
+ /** Status code */
+ u16 status;
+
+ /** List of information elements */
+ union ieee80211_ie info_element[0];
+} __attribute__((packed));
+
+/** Open System authentication algorithm */
+#define IEEE80211_AUTH_OPEN_SYSTEM 0
+
+/** Shared Key authentication algorithm */
+#define IEEE80211_AUTH_SHARED_KEY 1
+
+/** @} */
+
+#endif
diff --git a/src/include/gpxe/net80211.h b/src/include/gpxe/net80211.h
new file mode 100644
index 00000000..a1bddd5d
--- /dev/null
+++ b/src/include/gpxe/net80211.h
@@ -0,0 +1,983 @@
+#ifndef _GPXE_NET80211_H
+#define _GPXE_NET80211_H
+
+#include <gpxe/process.h>
+#include <gpxe/ieee80211.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/rc80211.h>
+
+/** @file
+ *
+ * The gPXE 802.11 MAC layer.
+ */
+
+/*
+ * Major things NOT YET supported:
+ * - any type of security
+ * - 802.11n
+ *
+ * Major things that probably will NEVER be supported, barring a
+ * compelling use case and/or corporate sponsorship:
+ * - QoS
+ * - 802.1X authentication ("WPA Enterprise")
+ * - Contention-free periods
+ * - "ad-hoc" networks (IBSS), monitor mode, host AP mode
+ * - hidden networks on the 5GHz band due to regulatory issues
+ * - spectrum management on the 5GHz band (TPC and DFS), as required
+ * in some non-US regulatory domains
+ * - Clause 14 PHYs (Frequency-Hopping Spread Spectrum on 2.4GHz)
+ * and Clause 16 PHYs (infrared) - I'm not aware of any real-world
+ * use of these.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/* All 802.11 devices are handled using a generic "802.11 device"
+ net_device, with a link in its `priv' field to a net80211_device
+ which we use to handle 802.11-specific details. */
+
+
+/** @defgroup net80211_band RF bands on which an 802.11 device can transmit */
+/** @{ */
+
+/** The 2.4 GHz ISM band, unlicensed in most countries */
+#define NET80211_BAND_2GHZ (1 << 0)
+/** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */
+#define NET80211_BAND_5GHZ (1 << 1)
+
+/** @} */
+
+
+/** @defgroup net80211_mode 802.11 operation modes supported by hardware */
+/** @{ */
+
+/** 802.11a: 54 Mbps operation using OFDM signaling on the 5GHz band */
+#define NET80211_MODE_A (1 << 0)
+
+/** 802.11b: 1-11 Mbps operation using DSSS/CCK signaling on the 2.4GHz band */
+#define NET80211_MODE_B (1 << 1)
+
+/** 802.11g: 54 Mbps operation using ERP/OFDM signaling on the 2.4GHz band */
+#define NET80211_MODE_G (1 << 2)
+
+/** 802.11n: High-rate operation using MIMO technology on 2.4GHz or 5GHz */
+#define NET80211_MODE_N (1 << 3)
+
+/** @} */
+
+
+/** @defgroup net80211_cfg Constants for the net80211 config callback */
+/** @{ */
+
+/** Channel choice (@c dev->channel) or regulatory parameters have changed */
+#define NET80211_CFG_CHANNEL (1 << 0)
+
+/** Requested transmission rate (@c dev->rate) has changed */
+#define NET80211_CFG_RATE (1 << 1)
+
+/** Association has been established with a new BSS (@c dev->bssid) */
+#define NET80211_CFG_ASSOC (1 << 2)
+
+/** Low-level link parameters (short preamble, protection, etc) have changed */
+#define NET80211_CFG_PHY_PARAMS (1 << 3)
+
+/** @} */
+
+
+/** An 802.11 security handshaking protocol */
+enum net80211_security_proto {
+ /** No security handshaking
+ *
+ * This might be used with an open network or with WEP, as
+ * WEP does not have a cryptographic handshaking phase.
+ */
+ NET80211_SECPROT_NONE = 0,
+
+ /** Pre-shared key handshaking
+ *
+ * This implements the "WPA Personal" handshake. 802.1X
+ * authentication is not performed -- the user supplies a
+ * pre-shared key directly -- but there is a 4-way handshake
+ * between client and AP to verify that both have the same key
+ * without revealing the contents of that key.
+ */
+ NET80211_SECPROT_PSK = 1,
+
+ /** Full EAP 802.1X handshaking
+ *
+ * This implements the "WPA Enterprise" handshake, connecting
+ * to an 802.1X authentication server to provide credentials
+ * and receive a pairwise master key (PMK), which is then used
+ * in the same 4-way handshake as the PSK method.
+ */
+ NET80211_SECPROT_EAP = 2,
+};
+
+
+/** An 802.11 data encryption algorithm */
+enum net80211_crypto_alg {
+ /** No security, an "Open" network */
+ NET80211_CRYPT_NONE = 0,
+
+ /** Network protected with WEP (awful RC4-based system)
+ *
+ * WEP uses a naive application of RC4, with a monotonically
+ * increasing initialization vector that is prepended to the
+ * key to initialize the RC4 keystream. It is highly insecure
+ * and can be completely cracked or subverted using automated,
+ * robust, freely available tools (aircrack-ng) in minutes.
+ *
+ * 40-bit and 104-bit WEP are differentiated only by the size
+ * of the key. They may be advertised as 64-bit and 128-bit,
+ * counting the non-random IV as part of the key bits.
+ */
+ NET80211_CRYPT_WEP = 1,
+
+ /** Network protected with TKIP (better RC4-based system)
+ *
+ * Usually known by its trade name of WPA (Wi-Fi Protected
+ * Access), TKIP implements a message integrity code (MIC)
+ * called Michael, a timestamp counter for replay prevention,
+ * and a key mixing function that together remove almost all
+ * the security problems with WEP. Countermeasures are
+ * implemented to prevent high data-rate attacks.
+ *
+ * There exists one known attack on TKIP, that allows one to
+ * send between 7 and 15 arbitrary short data packets on a
+ * QoS-enabled network given about an hour of data
+ * gathering. Since gPXE does not support QoS for 802.11
+ * networks, this is not a threat to us. The only other method
+ * is a brute-force passphrase attack.
+ */
+ NET80211_CRYPT_TKIP = 2,
+
+ /** Network protected with CCMP (AES-based system)
+ *
+ * Often called WPA2 in commerce, or RSNA (Robust Security
+ * Network Architecture) in the 802.11 standard, CCMP is
+ * highly secure and does not have any known attack vectors.
+ * Since it is based on a block cipher, the statistical
+ * correlation and "chopchop" attacks used with great success
+ * against WEP and minor success against TKIP fail.
+ */
+ NET80211_CRYPT_CCMP = 3,
+};
+
+
+/** @defgroup net80211_state Bits for the 802.11 association state field */
+/** @{ */
+
+/** An error code indicating the failure mode, or 0 if successful */
+#define NET80211_STATUS_MASK 0x7F
+
+/** Whether the error code provided is a "reason" code, not a "status" code */
+#define NET80211_IS_REASON 0x80
+
+/** Whether we have found the network we will be associating with */
+#define NET80211_PROBED (1 << 8)
+
+/** Whether we have successfully authenticated with the network
+ *
+ * This usually has nothing to do with actual security; it is a
+ * holdover from older 802.11 implementation ideas.
+ */
+#define NET80211_AUTHENTICATED (1 << 9)
+
+/** Whether we have successfully associated with the network */
+#define NET80211_ASSOCIATED (1 << 10)
+
+/** Whether we have completed security handshaking with the network
+ *
+ * Once this is set, we can send data packets. For that reason this
+ * bit is set even in cases where no security handshaking is
+ * required.
+ */
+#define NET80211_CRYPTO_SYNCED (1 << 11)
+
+/** Whether the auto-association task is running */
+#define NET80211_WORKING (1 << 12)
+
+/** Whether the auto-association task is waiting for a reply from the AP */
+#define NET80211_WAITING (1 << 13)
+
+/** Whether the auto-association task should be suppressed
+ *
+ * This is set by the `iwlist' command so that it can open the device
+ * without starting another probe process that will interfere with its
+ * own.
+ */
+#define NET80211_NO_ASSOC (1 << 14)
+
+/** Whether this association was performed using a broadcast SSID
+ *
+ * If the user opened this device without netX/ssid set, the device's
+ * SSID will be set to that of the network it chooses to associate
+ * with, but the netX/ssid setting will remain blank. If we don't
+ * remember that we started from no specified SSID, it will appear
+ * every time settings are updated (e.g. after DHCP) that we need to
+ * reassociate due to the difference between the set SSID and our own.
+ */
+#define NET80211_AUTO_SSID (1 << 15)
+
+
+/** @} */
+
+
+/** @defgroup net80211_phy 802.11 physical layer flags */
+/** @{ */
+
+/** Whether to use RTS/CTS or CTS-to-self protection for transmissions
+ *
+ * Since the RTS or CTS is transmitted using 802.11b signaling, and
+ * includes a field indicating the amount of time that will be used by
+ * transmission of the following packet, this serves as an effective
+ * protection mechanism to avoid 802.11b clients interfering with
+ * 802.11g clients on mixed networks.
+ */
+#define NET80211_PHY_USE_PROTECTION (1 << 1)
+
+/** Whether to use 802.11b short preamble operation
+ *
+ * Short-preamble operation can moderately increase throughput on
+ * 802.11b networks operating between 2Mbps and 11Mbps. It is
+ * irrelevant for 802.11g data rates, since they use a different
+ * modulation scheme.
+ */
+#define NET80211_PHY_USE_SHORT_PREAMBLE (1 << 2)
+
+/** Whether to use 802.11g short slot operation
+ *
+ * This affects a low-level timing parameter of 802.11g transmissions.
+ */
+#define NET80211_PHY_USE_SHORT_SLOT (1 << 3)
+
+/** @} */
+
+
+/** The maximum number of TX rates we allow to be configured simultaneously */
+#define NET80211_MAX_RATES 16
+
+/** The maximum number of channels we allow to be configured simultaneously */
+#define NET80211_MAX_CHANNELS 32
+
+/** Seconds we'll wait to get all fragments of a packet */
+#define NET80211_FRAG_TIMEOUT 2
+
+/** The number of fragments we can receive at once
+ *
+ * The 802.11 standard requires that this be at least 3.
+ */
+#define NET80211_NR_CONCURRENT_FRAGS 3
+
+/** Maximum TX power to allow (dBm), if we don't get a regulatory hint */
+#define NET80211_REG_TXPOWER 20
+
+
+struct net80211_device;
+
+/** Operations that must be implemented by an 802.11 driver */
+struct net80211_device_operations {
+ /** Open 802.11 device
+ *
+ * @v dev 802.11 device
+ * @ret rc Return status code
+ *
+ * This method should allocate RX I/O buffers and enable the
+ * hardware to start transmitting and receiving packets on the
+ * channels its net80211_register() call indicated it could
+ * handle. It does not need to tune the antenna to receive
+ * packets on any particular channel.
+ */
+ int ( * open ) ( struct net80211_device *dev );
+
+ /** Close 802.11 network device
+ *
+ * @v dev 802.11 device
+ *
+ * This method should stop the flow of packets, and call
+ * net80211_tx_complete() for any packets remaining in the
+ * device's TX queue.
+ */
+ void ( * close ) ( struct net80211_device *dev );
+
+ /** Transmit packet on 802.11 network device
+ *
+ * @v dev 802.11 device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware to initiate
+ * transmission of the I/O buffer, using the channel and rate
+ * most recently indicated by an appropriate call to the
+ * @c config callback. The 802.11 layer guarantees that said
+ * channel and rate will be the same as those currently
+ * reflected in the fields of @a dev.
+ *
+ * If this method returns success, the I/O buffer remains
+ * owned by the network layer's TX queue, and the driver must
+ * eventually call net80211_tx_complete() to free the buffer
+ * whether transmission succeeded or not. If this method
+ * returns failure, it will be interpreted as "failure to
+ * enqueue buffer" and the I/O buffer will be immediately
+ * released.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * transmit ) ( struct net80211_device *dev,
+ struct io_buffer *iobuf );
+
+ /** Poll for completed and received packets
+ *
+ * @v dev 802.11 device
+ *
+ * This method should cause the hardware to check for
+ * completed transmissions and received packets. Any received
+ * packets should be delivered via net80211_rx(), and
+ * completed transmissions should be indicated using
+ * net80211_tx_complete().
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ void ( * poll ) ( struct net80211_device *dev );
+
+ /** Enable or disable interrupts
+ *
+ * @v dev 802.11 device
+ * @v enable If TRUE, interrupts should be enabled
+ */
+ void ( * irq ) ( struct net80211_device *dev, int enable );
+
+ /** Update hardware state to match 802.11 layer state
+ *
+ * @v dev 802.11 device
+ * @v changed Set of flags indicating what may have changed
+ * @ret rc Return status code
+ *
+ * This method should cause the hardware state to be
+ * reinitialized from the state indicated in fields of
+ * net80211_device, in the areas indicated by bits set in
+ * @a changed. If the hardware is unable to do so, this method
+ * may return an appropriate error indication.
+ *
+ * This method is guaranteed to be called only when the device
+ * is open.
+ */
+ int ( * config ) ( struct net80211_device *dev, int changed );
+};
+
+/** An 802.11 RF channel. */
+struct net80211_channel
+{
+ /** The band with which this channel is associated */
+ u8 band;
+
+ /** A channel number interpreted according to the band
+ *
+ * The 2.4GHz band uses channel numbers from 1-13 at 5MHz
+ * intervals such that channel 1 is 2407 MHz; channel 14,
+ * legal for use only in Japan, is defined separately as 2484
+ * MHz. Adjacent channels will overlap, since 802.11
+ * transmissions use a 20 MHz (4-channel) bandwidth. Most
+ * commonly, channels 1, 6, and 11 are used.
+ *
+ * The 5GHz band uses channel numbers derived directly from
+ * the frequency; channel 0 is 5000 MHz, and channels are
+ * always spaced 5 MHz apart. Channel numbers over 180 are
+ * relative to 4GHz instead of 5GHz, but these are rarely
+ * seen. Most channels are not legal for use.
+ */
+ u8 channel_nr;
+
+ /** The center frequency for this channel
+ *
+ * Currently a bandwidth of 20 MHz is assumed.
+ */
+ u16 center_freq;
+
+ /** Maximum allowable transmit power, in dBm
+ *
+ * This should be interpreted as EIRP, the power supplied to
+ * an ideal isotropic antenna in order to achieve the same
+ * average signal intensity as the real hardware at a
+ * particular distance.
+ *
+ * Currently no provision is made for directional antennas.
+ */
+ u8 maxpower;
+};
+
+/** Information on the capabilities of an 802.11 hardware device
+ *
+ * In its probe callback, an 802.11 driver must read hardware
+ * registers to determine the appropriate contents of this structure,
+ * fill it, and pass it to net80211_register() so that the 802.11
+ * layer knows how to treat the hardware and what to advertise as
+ * supported to access points.
+ */
+struct net80211_hw_info
+{
+ /** Default hardware MAC address.
+ *
+ * The user may change this by setting the @c netX/mac setting
+ * before the driver's open function is called; in that case
+ * the driver must set the hardware MAC address to the address
+ * contained in the wrapping net_device's ll_addr field, or if
+ * that is impossible, set that ll_addr field back to the
+ * unchangeable hardware MAC address.
+ */
+ u8 hwaddr[ETH_ALEN];
+
+ /** A bitwise OR of the 802.11x modes supported by this device */
+ int modes;
+
+ /** A bitwise OR of the bands on which this device can communicate */
+ int bands;
+
+ /** A set of flags indicating peculiarities of this device. */
+ enum {
+ /** Received frames include a frame check sequence. */
+ NET80211_HW_RX_HAS_FCS = (1 << 1),
+
+ /** Hardware doesn't support 2.4GHz short preambles
+ *
+ * This is only relevant for 802.11b operation above
+ * 2Mbps. All 802.11g devices support short preambles.
+ */
+ NET80211_HW_NO_SHORT_PREAMBLE = (1 << 2),
+
+ /** Hardware doesn't support 802.11g short slot operation */
+ NET80211_HW_NO_SHORT_SLOT = (1 << 3),
+ } flags;
+
+ /** Signal strength information that can be provided by the device
+ *
+ * Signal strength is passed to net80211_rx(), primarily to
+ * allow determination of the closest access point for a
+ * multi-AP network. The units are provided for completeness
+ * of status displays.
+ */
+ enum {
+ /** No signal strength information supported */
+ NET80211_SIGNAL_NONE = 0,
+ /** Signal strength in arbitrary units */
+ NET80211_SIGNAL_ARBITRARY,
+ /** Signal strength in decibels relative to arbitrary base */
+ NET80211_SIGNAL_DB,
+ /** Signal strength in decibels relative to 1mW */
+ NET80211_SIGNAL_DBM,
+ } signal_type;
+
+ /** Maximum signal in arbitrary cases
+ *
+ * If signal_type is NET80211_SIGNAL_ARBITRARY or
+ * NET80211_SIGNAL_DB, the driver should report it on a scale
+ * from 0 to signal_max.
+ */
+ unsigned signal_max;
+
+ /** List of transmission rates supported by the card
+ *
+ * Rates should be in 100kbps increments (e.g. 11 Mbps would
+ * be represented as the number 110).
+ */
+ u16 supported_rates[NET80211_MAX_RATES];
+
+ /** Number of supported rates */
+ int nr_supported_rates;
+
+ /** Estimate of the time required to change channels, in microseconds
+ *
+ * If this is not known, a guess on the order of a few
+ * milliseconds (value of 1000-5000) is reasonable.
+ */
+ unsigned channel_change_time;
+};
+
+/** Structure tracking received fragments for a packet
+ *
+ * We set up a fragment cache entry when we receive a packet marked as
+ * fragment 0 with the "more fragments" bit set in its frame control
+ * header. We are required by the 802.11 standard to track 3
+ * fragmented packets arriving simultaneously; if we receive more we
+ * may drop some. Upon receipt of a new fragment-0 packet, if no entry
+ * is available or expired, we take over the most @e recent entry for
+ * the new packet, since we don't want to starve old entries from ever
+ * finishing at all. If we get a fragment after the zeroth with no
+ * cache entry for its packet, we drop it.
+ */
+struct net80211_frag_cache
+{
+ /** Whether this cache entry is in use */
+ u8 in_use;
+
+ /** Sequence number of this MSDU (packet) */
+ u16 seqnr;
+
+ /** Timestamp from point at which first fragment was collected */
+ u32 start_ticks;
+
+ /** Buffers for each fragment */
+ struct io_buffer *iob[16];
+};
+
+/** Interface to an 802.11 cryptographic algorithm
+ *
+ * Cryptographic algorithms define a net80211_crypto structure
+ * statically, using a gPXE linker table to make it available to the
+ * 802.11 layer. When the algorithm needs to be used, the 802.11 code
+ * will allocate a copy of the static definition plus whatever space
+ * the algorithm has requested for private state, and point
+ * net80211_device::crypto at it.
+ */
+struct net80211_crypto
+{
+ /** The cryptographic algorithm implemented */
+ enum net80211_crypto_alg algorithm;
+
+ /** Initialize cryptographic algorithm using a given key
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v key Pointer to key bytes
+ * @v keylen Number of key bytes
+ * @ret rc Return status code
+ *
+ * This method is passed the communication key provided by the
+ * security handshake handler, which will already be in the
+ * low-level form required.
+ */
+ int ( * initialize ) ( struct net80211_crypto *crypto, u8 *key,
+ int keylen );
+
+ /** Encrypt a frame using the cryptographic algorithm
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v iob I/O buffer
+ * @ret eiob Newly allocated I/O buffer with encrypted packet
+ *
+ * This method is called to encrypt a single frame. It is
+ * guaranteed that initialize() will have completed
+ * successfully before this method is called.
+ *
+ * The frame passed already has an 802.11 header prepended,
+ * but the PROTECTED bit in the frame control field will not
+ * be set; this method is responsible for setting it. The
+ * returned I/O buffer should contain a complete copy of @a
+ * iob, including the 802.11 header, but with the PROTECTED
+ * bit set, the data encrypted, and whatever encryption
+ * headers/trailers are necessary added.
+ *
+ * This method should never free the passed I/O buffer.
+ *
+ * Return NULL if the packet could not be encrypted, due to
+ * memory limitations or otherwise.
+ */
+ struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto,
+ struct io_buffer *iob );
+
+ /** Decrypt a frame using the cryptographic algorithm
+ *
+ * @v crypto 802.11 cryptographic algorithm
+ * @v eiob Encrypted I/O buffer
+ * @ret iob Newly allocated I/O buffer with decrypted packet
+ *
+ * This method is called to decrypt a single frame. It is
+ * guaranteed that initialize() will have completed
+ * successfully before this method is called.
+ *
+ * Decryption follows the reverse of the pattern used for
+ * encryption: this method must copy the 802.11 header into
+ * the returned packet, decrypt the data stream, remove any
+ * encryption header or trailer, and clear the PROTECTED bit
+ * in the frame control header.
+ *
+ * This method should never free the passed I/O buffer.
+ *
+ * Return NULL if memory was not available for decryption, if
+ * a consistency or integrity check on the decrypted frame
+ * failed, or if the decrypted frame should not be processed
+ * by the network stack for any other reason.
+ */
+ struct io_buffer * ( * decrypt ) ( struct net80211_crypto *crypto,
+ struct io_buffer *iob );
+
+ /** Length of private data requested to be allocated */
+ int priv_len;
+
+ /** Private data for the algorithm to store key and state info */
+ void *priv;
+};
+
+
+struct net80211_probe_ctx;
+struct net80211_assoc_ctx;
+
+
+/** Structure encapsulating the complete state of an 802.11 device
+ *
+ * An 802.11 device is always wrapped by a network device, and this
+ * network device is always pointed to by the @a netdev field. In
+ * general, operations should never be performed by 802.11 code using
+ * netdev functions directly. It is usually the case that the 802.11
+ * layer might need to do some processing or bookkeeping on top of
+ * what the netdevice code will do.
+ */
+struct net80211_device
+{
+ /** The net_device that wraps us. */
+ struct net_device *netdev;
+
+ /** List of 802.11 devices. */
+ struct list_head list;
+
+ /** 802.11 device operations */
+ struct net80211_device_operations *op;
+
+ /** Driver private data */
+ void *priv;
+
+ /** Information about the hardware, provided to net80211_register() */
+ struct net80211_hw_info *hw;
+
+ /* ---------- Channel and rate fields ---------- */
+
+ /** A list of all possible channels we might use */
+ struct net80211_channel channels[NET80211_MAX_CHANNELS];
+
+ /** The number of channels in the channels array */
+ u8 nr_channels;
+
+ /** The channel currently in use, as an index into the channels array */
+ u8 channel;
+
+ /** A list of all possible TX rates we might use
+ *
+ * Rates are in units of 100 kbps.
+ */
+ u16 rates[NET80211_MAX_RATES];
+
+ /** The number of transmission rates in the rates array */
+ u8 nr_rates;
+
+ /** The rate currently in use, as an index into the rates array */
+ u8 rate;
+
+ /** The rate to use for RTS/CTS transmissions
+ *
+ * This is always the fastest basic rate that is not faster
+ * than the data rate in use. Also an index into the rates array.
+ */
+ u8 rtscts_rate;
+
+ /** Bitmask of basic rates
+ *
+ * If bit N is set in this value, with the LSB considered to
+ * be bit 0, then rate N in the rates array is a "basic" rate.
+ *
+ * We don't decide which rates are "basic"; our AP does, and
+ * we respect its wishes. We need to be able to identify basic
+ * rates in order to calculate the duration of a CTS packet
+ * used for 802.11 g/b interoperability.
+ */
+ u32 basic_rates;
+
+ /* ---------- Association fields ---------- */
+
+ /** The asynchronous association process.
+ *
+ * When an 802.11 netdev is opened, or when the user changes
+ * the SSID setting on an open 802.11 device, an
+ * autoassociation task is started by net80211_autoassocate()
+ * to associate with the new best network. The association is
+ * asynchronous, but no packets can be transmitted until it is
+ * complete. If it is successful, the wrapping net_device is
+ * set as "link up". If it fails, @c assoc_rc will be set with
+ * an error indication.
+ */
+ struct process proc_assoc;
+
+ /** Network with which we are associating
+ *
+ * This will be NULL when we are not actively in the process
+ * of associating with a network we have already successfully
+ * probed for.
+ */
+ struct net80211_wlan *associating;
+
+ /** Context for the association process
+ *
+ * This is a probe_ctx if the @c PROBED flag is not set in @c
+ * state, and an assoc_ctx otherwise.
+ */
+ union {
+ struct net80211_probe_ctx *probe;
+ struct net80211_assoc_ctx *assoc;
+ } ctx;
+
+ /** State of our association to the network
+ *
+ * Since the association process happens asynchronously, it's
+ * necessary to have some channel of communication so the
+ * driver can say "I got an association reply and we're OK" or
+ * similar. This variable provides that link. It is a bitmask
+ * of any of NET80211_PROBED, NET80211_AUTHENTICATED,
+ * NET80211_ASSOCIATED, NET80211_CRYPTO_SYNCED to indicate how
+ * far along in associating we are; NET80211_WORKING if the
+ * association task is running; and NET80211_WAITING if a
+ * packet has been sent that we're waiting for a reply to. We
+ * can only be crypto-synced if we're associated, we can
+ * only be associated if we're authenticated, we can only be
+ * authenticated if we've probed.
+ *
+ * If an association process fails (that is, we receive a
+ * packet with an error indication), the error code is copied
+ * into bits 6-0 of this variable and bit 7 is set to specify
+ * what type of error code it is. An AP can provide either a
+ * "status code" (0-51 are defined) explaining why it refused
+ * an association immediately, or a "reason code" (0-45 are
+ * defined) explaining why it canceled an association after it
+ * had originally OK'ed it. Status and reason codes serve
+ * similar functions, but they use separate error message
+ * tables. A gPXE-formatted return status code (negative) is
+ * placed in @c assoc_rc.
+ *
+ * If the failure to associate is indicated by a status code,
+ * the NET80211_IS_REASON bit will be clear; if it is
+ * indicated by a reason code, the bit will be set. If we were
+ * successful, both zero status and zero reason mean success,
+ * so there is no ambiguity.
+ *
+ * To prevent association when opening the device, user code
+ * can set the NET80211_NO_ASSOC bit. The final bit in this
+ * variable, NET80211_AUTO_SSID, is used to remember whether
+ * we picked our SSID through automated probing as opposed to
+ * user specification; the distinction becomes relevant in the
+ * settings applicator.
+ */
+ u16 state;
+
+ /** Return status code associated with @c state */
+ int assoc_rc;
+
+ /* ---------- Parameters of currently associated network ---------- */
+
+ /** 802.11 cryptographic algorithm for our current network
+ *
+ * For an open network, this will be set to NULL.
+ */
+ struct net80211_crypto *crypto;
+
+ /** MAC address of the access point most recently associated */
+ u8 bssid[ETH_ALEN];
+
+ /** SSID of the access point we are or will be associated with
+ *
+ * Although the SSID field in 802.11 packets is generally not
+ * NUL-terminated, here and in net80211_wlan we add a NUL for
+ * convenience.
+ */
+ char essid[IEEE80211_MAX_SSID_LEN+1];
+
+ /** Association ID given to us by the AP */
+ u16 aid;
+
+ /** TSFT value for last beacon received, microseconds */
+ u64 last_beacon_timestamp;
+
+ /** Time between AP sending beacons, microseconds */
+ u32 tx_beacon_interval;
+
+ /** Smoothed average time between beacons, microseconds */
+ u32 rx_beacon_interval;
+
+ /* ---------- Physical layer information ---------- */
+
+ /** Physical layer options
+ *
+ * These control the use of CTS protection, short preambles,
+ * and short-slot operation.
+ */
+ int phy_flags;
+
+ /** Signal strength of last received packet */
+ int last_signal;
+
+ /** Rate control state */
+ struct rc80211_ctx *rctl;
+
+ /* ---------- Packet handling state ---------- */
+
+ /** Fragment reassembly state */
+ struct net80211_frag_cache frags[NET80211_NR_CONCURRENT_FRAGS];
+
+ /** The sequence number of the last packet we sent */
+ u16 last_tx_seqnr;
+
+ /** Packet duplication elimination state
+ *
+ * We are only required to handle immediate duplicates for
+ * each direct sender, and since we can only have one direct
+ * sender (the AP), we need only keep the sequence control
+ * field from the most recent packet we've received. Thus,
+ * this field stores the last sequence control field we've
+ * received for a packet from the AP.
+ */
+ u16 last_rx_seq;
+
+ /** RX management packet queue
+ *
+ * Sometimes we want to keep probe, beacon, and action packets
+ * that we receive, such as when we're scanning for networks.
+ * Ordinarily we drop them because they are sent at a large
+ * volume (ten beacons per second per AP, broadcast) and we
+ * have no need of them except when we're scanning.
+ *
+ * When keep_mgmt is TRUE, received probe, beacon, and action
+ * management packets will be stored in this queue.
+ */
+ struct list_head mgmt_queue;
+
+ /** RX management packet info queue
+ *
+ * We need to keep track of the signal strength for management
+ * packets we're keeping, because that provides the only way
+ * to distinguish between multiple APs for the same network.
+ * Since we can't extend io_buffer to store signal, this field
+ * heads a linked list of "RX packet info" structures that
+ * contain that signal strength field. Its entries always
+ * parallel the entries in mgmt_queue, because the two queues
+ * are always added to or removed from in parallel.
+ */
+ struct list_head mgmt_info_queue;
+
+ /** Whether to store management packets
+ *
+ * Received beacon, probe, and action packets will be added to
+ * mgmt_queue (and their signal strengths added to
+ * mgmt_info_queue) only when this variable is TRUE. It should
+ * be set by net80211_keep_mgmt() (which returns the old
+ * value) only when calling code is prepared to poll the
+ * management queue frequently, because packets will otherwise
+ * pile up and exhaust memory.
+ */
+ int keep_mgmt;
+};
+
+/** Structure representing a probed network.
+ *
+ * This is returned from the net80211_probe_finish functions and
+ * passed to the low-level association functions. At least essid,
+ * bssid, channel, beacon, and security must be filled in if you want
+ * to build this structure manually.
+ */
+struct net80211_wlan
+{
+ /** The human-readable ESSID (network name)
+ *
+ * Although the 802.11 SSID field is generally not
+ * NUL-terminated, the gPXE code adds an extra NUL (and
+ * expects one in this structure) for convenience.
+ */
+ char essid[IEEE80211_MAX_SSID_LEN+1];
+
+ /** MAC address of the strongest-signal access point for this ESSID */
+ u8 bssid[ETH_ALEN];
+
+ /** Signal strength of beacon frame from that access point */
+ int signal;
+
+ /** The channel on which that access point communicates
+ *
+ * This is a raw channel number (net80211_channel::channel_nr),
+ * so that it will not be affected by reconfiguration of the
+ * device channels array.
+ */
+ int channel;
+
+ /** The complete beacon or probe-response frame received */
+ struct io_buffer *beacon;
+
+ /** Security handshaking method used on the network */
+ enum net80211_security_proto handshaking;
+
+ /** Cryptographic algorithm used on the network */
+ enum net80211_crypto_alg crypto;
+
+ /** Link to allow chaining multiple structures into a list to
+ be returned from net80211_probe_finish_all(). */
+ struct list_head list;
+};
+
+
+/**
+ * @defgroup net80211_probe 802.11 network location API
+ * @{
+ */
+int net80211_prepare_probe ( struct net80211_device *dev, int band,
+ int active );
+struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev,
+ const char *essid,
+ int active );
+int net80211_probe_step ( struct net80211_probe_ctx *ctx );
+struct net80211_wlan *
+net80211_probe_finish_best ( struct net80211_probe_ctx *ctx );
+struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx );
+
+void net80211_free_wlan ( struct net80211_wlan *wlan );
+void net80211_free_wlanlist ( struct list_head *list );
+/** @} */
+
+
+/**
+ * @defgroup net80211_mgmt 802.11 network management API
+ * @{
+ */
+struct net80211_device * net80211_get ( struct net_device *netdev );
+void net80211_autoassociate ( struct net80211_device *dev );
+
+int net80211_change_channel ( struct net80211_device *dev, int channel );
+void net80211_set_rate_idx ( struct net80211_device *dev, int rate );
+
+int net80211_keep_mgmt ( struct net80211_device *dev, int enable );
+struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev,
+ int *signal );
+int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc,
+ u8 bssid[ETH_ALEN], struct io_buffer *iob );
+/** @} */
+
+
+/**
+ * @defgroup net80211_assoc 802.11 network association API
+ * @{
+ */
+int net80211_prepare_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan );
+int net80211_send_auth ( struct net80211_device *dev,
+ struct net80211_wlan *wlan, int method );
+int net80211_send_assoc ( struct net80211_device *dev,
+ struct net80211_wlan *wlan );
+/** @} */
+
+
+/**
+ * @defgroup net80211_driver 802.11 driver interface API
+ * @{
+ */
+struct net80211_device *net80211_alloc ( size_t priv_size );
+int net80211_register ( struct net80211_device *dev,
+ struct net80211_device_operations *ops,
+ struct net80211_hw_info *hw );
+void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
+ int signal, u16 rate );
+void net80211_rx_err ( struct net80211_device *dev,
+ struct io_buffer *iob, int rc );
+void net80211_tx_complete ( struct net80211_device *dev,
+ struct io_buffer *iob, int retries, int rc );
+void net80211_unregister ( struct net80211_device *dev );
+void net80211_free ( struct net80211_device *dev );
+/** @} */
+
+
+#endif
diff --git a/src/include/gpxe/rc80211.h b/src/include/gpxe/rc80211.h
new file mode 100644
index 00000000..0856896c
--- /dev/null
+++ b/src/include/gpxe/rc80211.h
@@ -0,0 +1,19 @@
+#ifndef _GPXE_RC80211_H
+#define _GPXE_RC80211_H
+
+/** @file
+ *
+ * Rate-control algorithm prototype for 802.11.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct net80211_device;
+struct rc80211_ctx;
+
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev );
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc );
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate );
+void rc80211_free ( struct rc80211_ctx *ctx );
+
+#endif /* _GPXE_RC80211_H */