iPXE
Data Structures | Defines | Functions | Variables
net80211.c File Reference

802.11 device management More...

#include <string.h>
#include <byteswap.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ipxe/settings.h>
#include <ipxe/if_arp.h>
#include <ipxe/ethernet.h>
#include <ipxe/ieee80211.h>
#include <ipxe/netdevice.h>
#include <ipxe/net80211.h>
#include <ipxe/sec80211.h>
#include <ipxe/timer.h>
#include <ipxe/nap.h>
#include <ipxe/errortab.h>
#include <ipxe/net80211_err.h>

Go to the source code of this file.

Data Structures

struct  net80211_rx_info
 Information associated with a received management packet. More...
struct  net80211_probe_ctx
 Context for a probe operation. More...
struct  net80211_assoc_ctx
 Context for the association task. More...

Defines

#define NET80211_PROBE_GATHER   1
 Seconds to wait after finding a network, to possibly find better APs for it.
#define NET80211_PROBE_GATHER_ALL   2
 Seconds to wait after finding a network, to possibly find other networks.
#define NET80211_PROBE_TIMEOUT   6
 Seconds to allow a probe to take if no network has been found.
#define ASSOC_TIMEOUT   TICKS_PER_SEC
 Number of ticks to wait for replies to association management frames.
#define ASSOC_RETRIES   2
 Number of times to try sending a particular association management frame.
#define LQ_SMOOTH   7
 Smoothing factor (1-7) for link quality calculation.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
__weak int sec80211_detect (struct io_buffer *iob __unused, enum net80211_security_proto *secprot __unused, enum net80211_crypto_alg *crypt __unused)
 Detect secure 802.11 network when security support is not available.
static int net80211_netdev_open (struct net_device *netdev)
 Open 802.11 device and start association.
static void net80211_netdev_close (struct net_device *netdev)
 Close 802.11 device.
static int net80211_netdev_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet on 802.11 device.
static void net80211_netdev_poll (struct net_device *netdev)
 Poll 802.11 device for received packets and completed transmissions.
static void net80211_netdev_irq (struct net_device *netdev, int enable)
 Enable or disable interrupts for 802.11 device.
static int net80211_ll_push (struct net_device *netdev, struct io_buffer *iobuf, const void *ll_dest, const void *ll_source, uint16_t net_proto)
 Add 802.11 link-layer header.
static int net80211_ll_pull (struct net_device *netdev, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
static void net80211_add_channels (struct net80211_device *dev, int start, int len, int txpower)
 Add channels to 802.11 device.
static void net80211_filter_hw_channels (struct net80211_device *dev)
 Filter 802.11 device channels for hardware capabilities.
static void net80211_set_rtscts_rate (struct net80211_device *dev)
 Pick TX rate for RTS/CTS packets based on data rate.
static int net80211_process_capab (struct net80211_device *dev, u16 capab)
 Update 802.11 device state to reflect received capabilities field.
static int net80211_process_ie (struct net80211_device *dev, union ieee80211_ie *ie, void *ie_end)
 Update 802.11 device state to reflect received information elements.
static union ieee80211_ienet80211_marshal_request_info (struct net80211_device *dev, union ieee80211_ie *ie)
 Create information elements for outgoing probe or association packet.
static void net80211_step_associate (struct net80211_device *dev)
 Step 802.11 association process.
static void net80211_handle_auth (struct net80211_device *dev, struct io_buffer *iob)
 Handle receipt of 802.11 authentication frame.
static void net80211_handle_assoc_reply (struct net80211_device *dev, struct io_buffer *iob)
 Handle receipt of 802.11 association reply frame.
static int net80211_send_disassoc (struct net80211_device *dev, int reason, int deauth)
 Send 802.11 disassociation frame.
static void net80211_handle_mgmt (struct net80211_device *dev, struct io_buffer *iob, int signal)
 Handle receipt of 802.11 management frame.
static void net80211_free_frags (struct net80211_device *dev, int fcid)
 Free buffers used by 802.11 fragment cache entry.
static struct io_buffernet80211_accum_frags (struct net80211_device *dev, int fcid, int nfrags, int size)
 Accumulate 802.11 fragments into one I/O buffer.
static void net80211_rx_frag (struct net80211_device *dev, struct io_buffer *iob, int signal)
 Handle receipt of 802.11 fragment.
static int net80211_check_settings_update (void)
 Check for 802.11 SSID or key updates.
struct setting
net80211_ssid_setting 
__setting (SETTING_NETDEV_EXTRA, ssid)
 The network name to associate with.
struct setting
net80211_active_setting 
__setting (SETTING_NETDEV_EXTRA, active-scan)
 Whether to use active scanning.
struct setting net80211_key_setting __setting (SETTING_NETDEV_EXTRA, key)
 The cryptographic key to use.
static int net80211_rate_is_erp (u16 rate)
 Determine whether a transmission rate uses ERP/OFDM.
u16 net80211_duration (struct net80211_device *dev, int bytes, u16 rate)
 Calculate one frame's contribution to 802.11 duration field.
static int net80211_ll_pull (struct net_device *netdev __unused, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
 Remove 802.11 link-layer header.
struct net80211_devicenet80211_get (struct net_device *netdev)
 Get 802.11 device from wrapping network device.
int net80211_keep_mgmt (struct net80211_device *dev, int enable)
 Set state of 802.11 device keeping management frames.
struct io_buffernet80211_mgmt_dequeue (struct net80211_device *dev, int *signal)
 Get 802.11 management frame.
int net80211_tx_mgmt (struct net80211_device *dev, u16 fc, u8 dest[6], struct io_buffer *iob)
 Transmit 802.11 management frame.
struct net80211_devicenet80211_alloc (size_t priv_size)
 Allocate 802.11 device.
int net80211_register (struct net80211_device *dev, struct net80211_device_operations *ops, struct net80211_hw_info *hw)
 Register 802.11 device with network stack.
void net80211_unregister (struct net80211_device *dev)
 Unregister 802.11 device from network stack.
void net80211_free (struct net80211_device *dev)
 Free 802.11 device.
static void net80211_set_state (struct net80211_device *dev, short clear, short set, u16 status)
 Set state of 802.11 device.
struct net80211_probe_ctxnet80211_probe_start (struct net80211_device *dev, const char *essid, int active)
 Begin probe of 802.11 networks.
int net80211_probe_step (struct net80211_probe_ctx *ctx)
 Continue probe of 802.11 networks.
struct net80211_wlannet80211_probe_finish_best (struct net80211_probe_ctx *ctx)
 Finish probe of 802.11 networks, returning best-signal network found.
struct list_headnet80211_probe_finish_all (struct net80211_probe_ctx *ctx)
 Finish probe of 802.11 networks, returning all networks found.
void net80211_free_wlan (struct net80211_wlan *wlan)
 Free WLAN structure.
void net80211_free_wlanlist (struct list_head *list)
 Free list of WLAN structures.
void net80211_autoassociate (struct net80211_device *dev)
 Start 802.11 association process.
void net80211_set_rate_idx (struct net80211_device *dev, int rate)
 Set data transmission rate for 802.11 device.
int net80211_change_channel (struct net80211_device *dev, int channel)
 Configure 802.11 device to transmit on a certain channel.
int net80211_prepare_probe (struct net80211_device *dev, int band, int active)
 Prepare 802.11 device channel and rate set for scanning.
int net80211_prepare_assoc (struct net80211_device *dev, struct net80211_wlan *wlan)
 Prepare 802.11 device channel and rate set for communication.
int net80211_send_auth (struct net80211_device *dev, struct net80211_wlan *wlan, int method)
 Send 802.11 initial authentication frame.
int net80211_send_assoc (struct net80211_device *dev, struct net80211_wlan *wlan)
 Send 802.11 association frame.
void net80211_deauthenticate (struct net80211_device *dev, int rc)
 Deauthenticate from current network and try again.
static void net80211_update_link_quality (struct net80211_device *dev, struct io_buffer *iob)
 Update link quality information based on received beacon.
void net80211_rx (struct net80211_device *dev, struct io_buffer *iob, int signal, u16 rate)
 Handle receipt of 802.11 frame.
void net80211_rx_err (struct net80211_device *dev, struct io_buffer *iob, int rc)
 Indicate an error in receiving a packet.
void net80211_tx_complete (struct net80211_device *dev, struct io_buffer *iob, int retries, int rc)
 Indicate the completed transmission of a packet.
 REQUIRING_SYMBOL (net80211_ll_protocol)
 REQUIRE_OBJECT (config_net80211)

Variables

static struct list_head net80211_devices = LIST_HEAD_INIT ( net80211_devices )
 List of 802.11 devices.
static struct
net80211_device_operations 
net80211_null_ops
 Set of device operations that does nothing.
struct settings_applicator
net80211_applicator 
__settings_applicator
 802.11 settings applicator
static struct net_device_operations net80211_netdev_ops
 Network device operations for a wrapped 802.11 device.
static struct ll_protocol
net80211_ll_protocol 
__ll_protocol
 802.11 link-layer protocol
static struct process_descriptor net80211_process_desc
 802.11 association process descriptor
struct errortab
common_wireless_errors[] 
__errortab
 Common 802.11 errors.

Detailed Description

802.11 device management

Definition in file net80211.c.


Define Documentation

#define NET80211_PROBE_GATHER   1

Seconds to wait after finding a network, to possibly find better APs for it.

This is used when a specific SSID to scan for is specified.

Definition at line 1259 of file net80211.c.

Referenced by net80211_probe_step().

#define NET80211_PROBE_GATHER_ALL   2

Seconds to wait after finding a network, to possibly find other networks.

This is used when an empty SSID is specified, to scan for all networks.

Definition at line 1266 of file net80211.c.

Referenced by net80211_probe_step().

#define NET80211_PROBE_TIMEOUT   6

Seconds to allow a probe to take if no network has been found.

Definition at line 1269 of file net80211.c.

Referenced by net80211_probe_step().

Number of ticks to wait for replies to association management frames.

Definition at line 1636 of file net80211.c.

Referenced by net80211_step_associate().

#define ASSOC_RETRIES   2

Number of times to try sending a particular association management frame.

Definition at line 1639 of file net80211.c.

Referenced by net80211_step_associate().

#define LQ_SMOOTH   7

Smoothing factor (1-7) for link quality calculation.

Definition at line 2401 of file net80211.c.

Referenced by net80211_update_link_quality().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
__weak int sec80211_detect ( struct io_buffer *iob  __unused,
enum net80211_security_proto *secprot  __unused,
enum net80211_crypto_alg *crypt  __unused 
)

Detect secure 802.11 network when security support is not available.

Returns:
-ENOTSUP, always.

Definition at line 112 of file net80211.c.

References ENOTSUP.

Referenced by net80211_probe_step().

                                                                        {
        return -ENOTSUP;
}
static int net80211_rate_is_erp ( u16  rate) [inline, static]

Determine whether a transmission rate uses ERP/OFDM.

Parameters:
rateRate in 100 kbps units
Return values:
is_erpTRUE if the rate is an ERP/OFDM rate

802.11b supports rates of 1.0, 2.0, 5.5, and 11.0 Mbps; any other rate than these on the 2.4GHz spectrum is an ERP (802.11g) rate.

Definition at line 399 of file net80211.c.

Referenced by net80211_duration().

{
        if ( rate == 10 || rate == 20 || rate == 55 || rate == 110 )
                return 0;
        return 1;
}
static int net80211_ll_pull ( struct net_device *netdev  __unused,
struct io_buffer iobuf,
const void **  ll_dest,
const void **  ll_source,
uint16_t net_proto,
unsigned int *  flags 
) [static]

Remove 802.11 link-layer header.

Parameters:
netdevWrapping network device
iobufI/O buffer
Return values:
ll_destLink-layer destination address
ll_sourceLink-layer source
net_protoNetwork-layer protocol, in network byte order
flagsPacket flags
rcReturn status code

This expects and removes both the 802.11 frame header and the 802.2 LLC/SNAP header that are used on data packets.

Definition at line 537 of file net80211.c.

References ieee80211_frame::addr1, ieee80211_frame::addr3, ieee80211_llc_snap_header::ctrl, io_buffer::data, DBGC, ieee80211_llc_snap_header::dsap, EINVAL_PKT_LLC_HEADER, EINVAL_PKT_NOT_DATA, EINVAL_PKT_NOT_FROMDS, EINVAL_PKT_TOO_SHORT, EINVAL_PKT_VERSION, ieee80211_llc_snap_header::ethertype, ieee80211_frame::fc, hdr, IEEE80211_FC_FROMDS, IEEE80211_FC_SUBTYPE, IEEE80211_FC_TODS, IEEE80211_FC_TYPE, IEEE80211_FC_VERSION, IEEE80211_LLC_CTRL, IEEE80211_LLC_DSAP, IEEE80211_LLC_HEADER_LEN, IEEE80211_LLC_SSAP, IEEE80211_STYPE_DATA, IEEE80211_THIS_VERSION, IEEE80211_TYP_FRAME_HEADER_LEN, IEEE80211_TYPE_DATA, iob_len(), iob_pull, is_broadcast_ether_addr(), is_multicast_ether_addr(), LL_BROADCAST, LL_MULTICAST, netdev, ieee80211_llc_snap_header::oui, net_device::priv, and ieee80211_llc_snap_header::ssap.

{
        struct ieee80211_frame *hdr = iobuf->data;
        struct ieee80211_llc_snap_header *lhdr =
                ( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;

        /* Bunch of sanity checks */
        if ( iob_len ( iobuf ) < IEEE80211_TYP_FRAME_HEADER_LEN +
             IEEE80211_LLC_HEADER_LEN ) {
                DBGC ( netdev->priv, "802.11 %p packet too short (%zd bytes)\n",
                       netdev->priv, iob_len ( iobuf ) );
                return -EINVAL_PKT_TOO_SHORT;
        }

        if ( ( hdr->fc & IEEE80211_FC_VERSION ) != IEEE80211_THIS_VERSION ) {
                DBGC ( netdev->priv, "802.11 %p packet invalid version %04x\n",
                       netdev->priv, hdr->fc & IEEE80211_FC_VERSION );
                return -EINVAL_PKT_VERSION;
        }

        if ( ( hdr->fc & IEEE80211_FC_TYPE ) != IEEE80211_TYPE_DATA ||
             ( hdr->fc & IEEE80211_FC_SUBTYPE ) != IEEE80211_STYPE_DATA ) {
                DBGC ( netdev->priv, "802.11 %p packet not data/data (fc=%04x)\n",
                       netdev->priv, hdr->fc );
                return -EINVAL_PKT_NOT_DATA;
        }

        if ( ( hdr->fc & ( IEEE80211_FC_TODS | IEEE80211_FC_FROMDS ) ) !=
             IEEE80211_FC_FROMDS ) {
                DBGC ( netdev->priv, "802.11 %p packet not from DS (fc=%04x)\n",
                       netdev->priv, hdr->fc );
                return -EINVAL_PKT_NOT_FROMDS;
        }

        if ( lhdr->dsap != IEEE80211_LLC_DSAP || lhdr->ssap != IEEE80211_LLC_SSAP ||
             lhdr->ctrl != IEEE80211_LLC_CTRL || lhdr->oui[0] || lhdr->oui[1] ||
             lhdr->oui[2] ) {
                DBGC ( netdev->priv, "802.11 %p LLC header is not plain EtherType "
                       "encapsulator: %02x->%02x [%02x] %02x:%02x:%02x %04x\n",
                       netdev->priv, lhdr->dsap, lhdr->ssap, lhdr->ctrl,
                       lhdr->oui[0], lhdr->oui[1], lhdr->oui[2], lhdr->ethertype );
                return -EINVAL_PKT_LLC_HEADER;
        }

        iob_pull ( iobuf, sizeof ( *hdr ) + sizeof ( *lhdr ) );

        *ll_dest = hdr->addr1;
        *ll_source = hdr->addr3;
        *net_proto = lhdr->ethertype;
        *flags = ( ( is_multicast_ether_addr ( hdr->addr1 ) ?
                     LL_MULTICAST : 0 ) |
                   ( is_broadcast_ether_addr ( hdr->addr1 ) ?
                     LL_BROADCAST : 0 ) );
        return 0;
}
int net80211_tx_mgmt ( struct net80211_device dev,
u16  fc,
u8  dest[6],
struct io_buffer iob 
)

Transmit 802.11 management frame.

Parameters:
dev802.11 device
fcFrame Control flags for management frame
destDestination access point
iobI/O buffer
Return values:
rcReturn status code

The fc argument must contain at least an IEEE 802.11 management subtype number (e.g. IEEE80211_STYPE_PROBE_REQ). If it contains IEEE80211_FC_PROTECTED, the frame will be encrypted prior to transmission.

It is required that iob have at least 24 bytes of headroom reserved before its data start.

Definition at line 706 of file net80211.c.

References ieee80211_frame::addr1, ieee80211_frame::addr2, ieee80211_frame::addr3, net80211_device::crypto, ieee80211_frame::duration, EINVAL_CRYPTO_REQUEST, net80211_crypto::encrypt, ETH_ALEN, ieee80211_frame::fc, free_iob(), hdr, IEEE80211_FC_PROTECTED, IEEE80211_MAKESEQ, IEEE80211_THIS_VERSION, IEEE80211_TYP_FRAME_HEADER_LEN, IEEE80211_TYPE_MGMT, iob_push, net80211_device::last_tx_seqnr, net_device::ll_addr, memcpy(), net80211_duration(), net80211_device::netdev, netdev_tx(), net80211_device::rate, net80211_device::rates, and ieee80211_frame::seq.

Referenced by net80211_probe_step(), net80211_send_assoc(), net80211_send_auth(), and net80211_send_disassoc().

{
        struct ieee80211_frame *hdr = iob_push ( iob,
                                                 IEEE80211_TYP_FRAME_HEADER_LEN );

        hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_MGMT |
            ( fc & ~IEEE80211_FC_PROTECTED );
        hdr->duration = net80211_duration ( dev, 10, dev->rates[dev->rate] );
        hdr->seq = IEEE80211_MAKESEQ ( ++dev->last_tx_seqnr, 0 );

        memcpy ( hdr->addr1, dest, ETH_ALEN );  /* DA = RA */
        memcpy ( hdr->addr2, dev->netdev->ll_addr, ETH_ALEN );  /* SA = TA */
        memcpy ( hdr->addr3, dest, ETH_ALEN );  /* BSSID */

        if ( fc & IEEE80211_FC_PROTECTED ) {
                if ( ! dev->crypto )
                        return -EINVAL_CRYPTO_REQUEST;

                struct io_buffer *eiob = dev->crypto->encrypt ( dev->crypto,
                                                                iob );
                free_iob ( iob );
                iob = eiob;
        }

        return netdev_tx ( dev->netdev, iob );
}
static void net80211_set_state ( struct net80211_device dev,
short  clear,
short  set,
u16  status 
) [inline, static]

Set state of 802.11 device.

Parameters:
dev802.11 device
clearBitmask of flags to clear
setBitmask of flags to set
statusStatus or reason code for most recent operation

If status represents a reason code, it should be OR'ed with NET80211_IS_REASON.

Clearing authentication also clears association; clearing association also clears security handshaking state. Clearing association removes the link-up flag from the wrapping net_device, but setting it does not automatically set the flag; that is left to the judgment of higher-level code.

Definition at line 866 of file net80211.c.

References net80211_device::assoc_rc, net80211_device_operations::config, E80211_REASON, E80211_STATUS, NET80211_ASSOCIATED, NET80211_AUTHENTICATED, NET80211_CFG_ASSOC, NET80211_CRYPTO_SYNCED, NET80211_IS_REASON, NET80211_PROBED, NET80211_STATUS_MASK, net80211_device::netdev, netdev_link_down(), netdev_link_err(), net80211_device::op, and net80211_device::state.

Referenced by net80211_autoassociate(), net80211_handle_assoc_reply(), net80211_handle_auth(), net80211_handle_mgmt(), net80211_prepare_assoc(), net80211_send_assoc(), net80211_send_auth(), and net80211_send_disassoc().

{
        /* The conditions in this function are deliberately formulated
           to be decidable at compile-time in most cases. Since clear
           and set are generally passed as constants, the body of this
           function can be reduced down to a few statements by the
           compiler. */

        const int statmsk = NET80211_STATUS_MASK | NET80211_IS_REASON;

        if ( clear & NET80211_PROBED )
                clear |= NET80211_AUTHENTICATED;

        if ( clear & NET80211_AUTHENTICATED )
                clear |= NET80211_ASSOCIATED;

        if ( clear & NET80211_ASSOCIATED )
                clear |= NET80211_CRYPTO_SYNCED;

        dev->state = ( dev->state & ~clear ) | set;
        dev->state = ( dev->state & ~statmsk ) | ( status & statmsk );

        if ( clear & NET80211_ASSOCIATED )
                netdev_link_down ( dev->netdev );

        if ( ( clear | set ) & NET80211_ASSOCIATED )
                dev->op->config ( dev, NET80211_CFG_ASSOC );

        if ( status != 0 ) {
                if ( status & NET80211_IS_REASON )
                        dev->assoc_rc = -E80211_REASON ( status );
                else
                        dev->assoc_rc = -E80211_STATUS ( status );
                netdev_link_err ( dev->netdev, dev->assoc_rc );
        }
}
static void net80211_update_link_quality ( struct net80211_device dev,
struct io_buffer iob 
) [static]

Update link quality information based on received beacon.

Parameters:
dev802.11 device
iobI/O buffer containing beacon
Return values:
rcReturn status code

Definition at line 2410 of file net80211.c.

References io_buffer::data, ieee80211_frame::data, hdr, ieee80211_beacon, net80211_device::last_beacon_timestamp, LQ_SMOOTH, NET80211_ASSOCIATED, net80211_device::rx_beacon_interval, and net80211_device::state.

Referenced by net80211_handle_mgmt().

{
        struct ieee80211_frame *hdr = iob->data;
        struct ieee80211_beacon *beacon;
        u32 dt, rxi;

        if ( ! ( dev->state & NET80211_ASSOCIATED ) )
                return;

        beacon = ( struct ieee80211_beacon * ) hdr->data;
        dt = ( u32 ) ( beacon->timestamp - dev->last_beacon_timestamp );
        rxi = dev->rx_beacon_interval;

        rxi = ( LQ_SMOOTH * rxi ) + ( ( 8 - LQ_SMOOTH ) * dt );
        dev->rx_beacon_interval = rxi >> 3;

        dev->last_beacon_timestamp = beacon->timestamp;
}
REQUIRING_SYMBOL ( net80211_ll_protocol  )
REQUIRE_OBJECT ( config_net80211  )

Variable Documentation

List of 802.11 devices.

Definition at line 47 of file net80211.c.

Set of device operations that does nothing.

Definition at line 50 of file net80211.c.

Referenced by net80211_alloc(), net80211_netdev_open(), and net80211_unregister().

Initial value:

Network device operations for a wrapped 802.11 device.

Definition at line 379 of file net80211.c.

struct ll_protocol net80211_ll_protocol __ll_protocol [static]
Initial value:
 {
        .name = "802.11",
        .push = net80211_ll_push,
        .pull = net80211_ll_pull,
        .init_addr = eth_init_addr,
        .ntoa = eth_ntoa,
        .mc_hash = eth_mc_hash,
        .eth_addr = eth_eth_addr,
        .eui64 = eth_eui64,
        .ll_proto = htons ( ARPHRD_ETHER ),     
        .hw_addr_len = ETH_ALEN,
        .ll_addr_len = ETH_ALEN,
        .ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN +
                                IEEE80211_LLC_HEADER_LEN,
}

802.11 link-layer protocol

Definition at line 597 of file net80211.c.

Initial value:

802.11 association process descriptor

Definition at line 738 of file net80211.c.

struct errortab common_wireless_errors [] __errortab