code:
/*-
 * Copyright (c) 2001 Atsushi Onoe
 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211.h 218927 2011-02-21 19:59:43Z bschmidt $
 */
#ifndef _NET80211_IEEE80211_H_
#define _NET80211_IEEE80211_H_

/*
 * 802.11 protocol definitions.
 */

#define	IEEE80211_ADDR_LEN	6		/* size of 802.11 address */
/* is 802.11 address multicast/broadcast? */
#define	IEEE80211_IS_MULTICAST(_a)	(*(_a) & 0x01)

typedef uint16_t ieee80211_seq;

/* IEEE 802.11 PLCP header */
struct ieee80211_plcp_hdr {
	uint16_t	i_sfd;
	uint8_t		i_signal;
	uint8_t		i_service;
	uint16_t	i_length;
	uint16_t	i_crc;
} __packed;

#define IEEE80211_PLCP_SFD      0xF3A0
#define IEEE80211_PLCP_SERVICE  0x00
#define IEEE80211_PLCP_SERVICE_LOCKED	0x04
#define IEEE80211_PLCL_SERVICE_PBCC	0x08
#define IEEE80211_PLCP_SERVICE_LENEXT5	0x20
#define IEEE80211_PLCP_SERVICE_LENEXT6	0x40
#define IEEE80211_PLCP_SERVICE_LENEXT7	0x80

/*
 * generic definitions for IEEE 802.11 frames
 */
struct ieee80211_frame {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_addr1[IEEE80211_ADDR_LEN];
	uint8_t		i_addr2[IEEE80211_ADDR_LEN];
	uint8_t		i_addr3[IEEE80211_ADDR_LEN];
	uint8_t		i_seq[2];
	/* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
	/* see below */
} __packed;

struct ieee80211_qosframe {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_addr1[IEEE80211_ADDR_LEN];
	uint8_t		i_addr2[IEEE80211_ADDR_LEN];
	uint8_t		i_addr3[IEEE80211_ADDR_LEN];
	uint8_t		i_seq[2];
	uint8_t		i_qos[2];
	/* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
	/* see below */
} __packed;

struct ieee80211_qoscntl {
	uint8_t		i_qos[2];
};

struct ieee80211_frame_addr4 {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_addr1[IEEE80211_ADDR_LEN];
	uint8_t		i_addr2[IEEE80211_ADDR_LEN];
	uint8_t		i_addr3[IEEE80211_ADDR_LEN];
	uint8_t		i_seq[2];
	uint8_t		i_addr4[IEEE80211_ADDR_LEN];
} __packed;

struct ieee80211_qosframe_addr4 {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_addr1[IEEE80211_ADDR_LEN];
	uint8_t		i_addr2[IEEE80211_ADDR_LEN];
	uint8_t		i_addr3[IEEE80211_ADDR_LEN];
	uint8_t		i_seq[2];
	uint8_t		i_addr4[IEEE80211_ADDR_LEN];
	uint8_t		i_qos[2];
} __packed;

#define	IEEE80211_FC0_VERSION_MASK		0x03
#define	IEEE80211_FC0_VERSION_SHIFT		0
#define	IEEE80211_FC0_VERSION_0			0x00
#define	IEEE80211_FC0_TYPE_MASK			0x0c
#define	IEEE80211_FC0_TYPE_SHIFT		2
#define	IEEE80211_FC0_TYPE_MGT			0x00
#define	IEEE80211_FC0_TYPE_CTL			0x04
#define	IEEE80211_FC0_TYPE_DATA			0x08

#define	IEEE80211_FC0_SUBTYPE_MASK		0xf0
#define	IEEE80211_FC0_SUBTYPE_SHIFT		4
/* for TYPE_MGT */
#define	IEEE80211_FC0_SUBTYPE_ASSOC_REQ		0x00
#define	IEEE80211_FC0_SUBTYPE_ASSOC_RESP	0x10
#define	IEEE80211_FC0_SUBTYPE_REASSOC_REQ	0x20
#define	IEEE80211_FC0_SUBTYPE_REASSOC_RESP	0x30
#define	IEEE80211_FC0_SUBTYPE_PROBE_REQ		0x40
#define	IEEE80211_FC0_SUBTYPE_PROBE_RESP	0x50
#define	IEEE80211_FC0_SUBTYPE_BEACON		0x80
#define	IEEE80211_FC0_SUBTYPE_ATIM		0x90
#define	IEEE80211_FC0_SUBTYPE_DISASSOC		0xa0
#define	IEEE80211_FC0_SUBTYPE_AUTH		0xb0
#define	IEEE80211_FC0_SUBTYPE_DEAUTH		0xc0
#define	IEEE80211_FC0_SUBTYPE_ACTION		0xd0
#define	IEEE80211_FC0_SUBTYPE_ACTION_NOACK	0xe0
/* for TYPE_CTL */
#define	IEEE80211_FC0_SUBTYPE_BAR		0x80
#define	IEEE80211_FC0_SUBTYPE_BA		0x90
#define	IEEE80211_FC0_SUBTYPE_PS_POLL		0xa0
#define	IEEE80211_FC0_SUBTYPE_RTS		0xb0
#define	IEEE80211_FC0_SUBTYPE_CTS		0xc0
#define	IEEE80211_FC0_SUBTYPE_ACK		0xd0
#define	IEEE80211_FC0_SUBTYPE_CF_END		0xe0
#define	IEEE80211_FC0_SUBTYPE_CF_END_ACK	0xf0
/* for TYPE_DATA (bit combination) */
#define	IEEE80211_FC0_SUBTYPE_DATA		0x00
#define	IEEE80211_FC0_SUBTYPE_CF_ACK		0x10
#define	IEEE80211_FC0_SUBTYPE_CF_POLL		0x20
#define	IEEE80211_FC0_SUBTYPE_CF_ACPL		0x30
#define	IEEE80211_FC0_SUBTYPE_NODATA		0x40
#define	IEEE80211_FC0_SUBTYPE_CFACK		0x50
#define	IEEE80211_FC0_SUBTYPE_CFPOLL		0x60
#define	IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK	0x70
#define	IEEE80211_FC0_SUBTYPE_QOS		0x80
#define	IEEE80211_FC0_SUBTYPE_QOS_NULL		0xc0

#define	IEEE80211_FC1_DIR_MASK			0x03
#define	IEEE80211_FC1_DIR_NODS			0x00	/* STA->STA */
#define	IEEE80211_FC1_DIR_TODS			0x01	/* STA->AP  */
#define	IEEE80211_FC1_DIR_FROMDS		0x02	/* AP ->STA */
#define	IEEE80211_FC1_DIR_DSTODS		0x03	/* AP ->AP  */

#define	IEEE80211_IS_DSTODS(wh) \
	(((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)

#define	IEEE80211_FC1_MORE_FRAG			0x04
#define	IEEE80211_FC1_RETRY			0x08
#define	IEEE80211_FC1_PWR_MGT			0x10
#define	IEEE80211_FC1_MORE_DATA			0x20
#define	IEEE80211_FC1_WEP			0x40
#define	IEEE80211_FC1_ORDER			0x80

#define	IEEE80211_SEQ_FRAG_MASK			0x000f
#define	IEEE80211_SEQ_FRAG_SHIFT		0
#define	IEEE80211_SEQ_SEQ_MASK			0xfff0
#define	IEEE80211_SEQ_SEQ_SHIFT			4
#define	IEEE80211_SEQ_RANGE			4096

#define	IEEE80211_SEQ_ADD(seq, incr) \
	(((seq) + (incr)) & (IEEE80211_SEQ_RANGE-1))
#define	IEEE80211_SEQ_INC(seq)	IEEE80211_SEQ_ADD(seq,1)
#define	IEEE80211_SEQ_SUB(a, b) \
	(((a) + IEEE80211_SEQ_RANGE - (b)) & (IEEE80211_SEQ_RANGE-1))

#define	IEEE80211_SEQ_BA_RANGE			2048	/* 2^11 */
#define	IEEE80211_SEQ_BA_BEFORE(a, b) \
	(IEEE80211_SEQ_SUB(b, a+1) < IEEE80211_SEQ_BA_RANGE-1)

#define	IEEE80211_NWID_LEN			32
#define	IEEE80211_MESHID_LEN			32

#define	IEEE80211_QOS_TXOP			0x00ff
/* bit 8 is reserved */
#define	IEEE80211_QOS_AMSDU			0x80
#define	IEEE80211_QOS_AMSDU_S			7
#define	IEEE80211_QOS_ACKPOLICY			0x60
#define	IEEE80211_QOS_ACKPOLICY_S		5
#define	IEEE80211_QOS_ACKPOLICY_NOACK		0x20	/* No ACK required */
#define	IEEE80211_QOS_ACKPOLICY_BA		0x60	/* Block ACK */
#define	IEEE80211_QOS_EOSP			0x10	/* EndOfService Period*/
#define	IEEE80211_QOS_EOSP_S			4
#define	IEEE80211_QOS_TID			0x0f

/* does frame have QoS sequence control data */
#define	IEEE80211_QOS_HAS_SEQ(wh) \
	(((wh)->i_fc[0] & \
	  (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \
	  (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))

/*
 * WME/802.11e information element.
 */
struct ieee80211_wme_info {
	uint8_t		wme_id;		/* IEEE80211_ELEMID_VENDOR */
	uint8_t		wme_len;	/* length in bytes */
	uint8_t		wme_oui[3];	/* 0x00, 0x50, 0xf2 */
	uint8_t		wme_type;	/* OUI type */
	uint8_t		wme_subtype;	/* OUI subtype */
	uint8_t		wme_version;	/* spec revision */
	uint8_t		wme_info;	/* QoS info */
} __packed;

/*
 * WME/802.11e Tspec Element
 */
struct ieee80211_wme_tspec {
	uint8_t		ts_id;
	uint8_t		ts_len;
	uint8_t		ts_oui[3];
	uint8_t		ts_oui_type;
	uint8_t		ts_oui_subtype;
	uint8_t		ts_version;
	uint8_t		ts_tsinfo[3];
	uint8_t		ts_nom_msdu[2];
	uint8_t		ts_max_msdu[2];
	uint8_t		ts_min_svc[4];
	uint8_t		ts_max_svc[4];
	uint8_t		ts_inactv_intv[4];
	uint8_t		ts_susp_intv[4];
	uint8_t		ts_start_svc[4];
	uint8_t		ts_min_rate[4];
	uint8_t		ts_mean_rate[4];
	uint8_t		ts_max_burst[4];
	uint8_t		ts_min_phy[4];
	uint8_t		ts_peak_rate[4];
	uint8_t		ts_delay[4];
	uint8_t		ts_surplus[2];
	uint8_t		ts_medium_time[2];
} __packed;

/*
 * WME AC parameter field
 */
struct ieee80211_wme_acparams {
	uint8_t		acp_aci_aifsn;
	uint8_t		acp_logcwminmax;
	uint16_t	acp_txop;
} __packed;

#define WME_NUM_AC		4	/* 4 AC categories */
#define	WME_NUM_TID		16	/* 16 tids */

#define WME_PARAM_ACI		0x60	/* Mask for ACI field */
#define WME_PARAM_ACI_S		5	/* Shift for ACI field */
#define WME_PARAM_ACM		0x10	/* Mask for ACM bit */
#define WME_PARAM_ACM_S		4	/* Shift for ACM bit */
#define WME_PARAM_AIFSN		0x0f	/* Mask for aifsn field */
#define WME_PARAM_AIFSN_S	0	/* Shift for aifsn field */
#define WME_PARAM_LOGCWMIN	0x0f	/* Mask for CwMin field (in log) */
#define WME_PARAM_LOGCWMIN_S	0	/* Shift for CwMin field */
#define WME_PARAM_LOGCWMAX	0xf0	/* Mask for CwMax field (in log) */
#define WME_PARAM_LOGCWMAX_S	4	/* Shift for CwMax field */

#define WME_AC_TO_TID(_ac) (       \
	((_ac) == WME_AC_VO) ? 6 : \
	((_ac) == WME_AC_VI) ? 5 : \
	((_ac) == WME_AC_BK) ? 1 : \
	0)

#define TID_TO_WME_AC(_tid) (      \
	((_tid) == 0 || (_tid) == 3) ? WME_AC_BE : \
	((_tid) < 3) ? WME_AC_BK : \
	((_tid) < 6) ? WME_AC_VI : \
	WME_AC_VO)

/*
 * WME Parameter Element
 */
struct ieee80211_wme_param {
	uint8_t		param_id;
	uint8_t		param_len;
	uint8_t		param_oui[3];
	uint8_t		param_oui_type;
	uint8_t		param_oui_subtype;
	uint8_t		param_version;
	uint8_t		param_qosInfo;
#define	WME_QOSINFO_COUNT	0x0f	/* Mask for param count field */
	uint8_t		param_reserved;
	struct ieee80211_wme_acparams	params_acParams[WME_NUM_AC];
} __packed;

/*
 * Management Notification Frame
 */
struct ieee80211_mnf {
	uint8_t		mnf_category;
	uint8_t		mnf_action;
	uint8_t		mnf_dialog;
	uint8_t		mnf_status;
} __packed;
#define	MNF_SETUP_REQ	0
#define	MNF_SETUP_RESP	1
#define	MNF_TEARDOWN	2

/*
 * 802.11n Management Action Frames
 */
/* generic frame format */
struct ieee80211_action {
	uint8_t		ia_category;
	uint8_t		ia_action;
} __packed;

#define	IEEE80211_ACTION_CAT_SM		0	/* Spectrum Management */
#define	IEEE80211_ACTION_CAT_QOS	1	/* QoS */
#define	IEEE80211_ACTION_CAT_DLS	2	/* DLS */
#define	IEEE80211_ACTION_CAT_BA		3	/* BA */
#define	IEEE80211_ACTION_CAT_HT		7	/* HT */
#define	IEEE80211_ACTION_CAT_VENDOR	127	/* Vendor Specific */

#define	IEEE80211_ACTION_HT_TXCHWIDTH	0	/* recommended xmit chan width*/
#define	IEEE80211_ACTION_HT_MIMOPWRSAVE	1	/* MIMO power save */

/* HT - recommended transmission channel width */
struct ieee80211_action_ht_txchwidth {
	struct ieee80211_action	at_header;
	uint8_t		at_chwidth;
} __packed;

#define	IEEE80211_A_HT_TXCHWIDTH_20	0
#define	IEEE80211_A_HT_TXCHWIDTH_2040	1

/* HT - MIMO Power Save (NB: D2.04) */
struct ieee80211_action_ht_mimopowersave {
	struct ieee80211_action am_header;
	uint8_t		am_control;
} __packed;

#define	IEEE80211_A_HT_MIMOPWRSAVE_ENA		0x01	/* PS enabled */
#define	IEEE80211_A_HT_MIMOPWRSAVE_MODE		0x02
#define	IEEE80211_A_HT_MIMOPWRSAVE_MODE_S	1
#define	IEEE80211_A_HT_MIMOPWRSAVE_DYNAMIC	0x02	/* Dynamic Mode */
#define	IEEE80211_A_HT_MIMOPWRSAVE_STATIC	0x00	/* no SM packets */
/* bits 2-7 reserved */

/* Block Ack actions */
#define IEEE80211_ACTION_BA_ADDBA_REQUEST       0   /* ADDBA request */
#define IEEE80211_ACTION_BA_ADDBA_RESPONSE      1   /* ADDBA response */
#define IEEE80211_ACTION_BA_DELBA	        2   /* DELBA */

/* Block Ack Parameter Set */
#define	IEEE80211_BAPS_BUFSIZ	0xffc0		/* buffer size */
#define	IEEE80211_BAPS_BUFSIZ_S	6
#define	IEEE80211_BAPS_TID	0x003c		/* TID */
#define	IEEE80211_BAPS_TID_S	2
#define	IEEE80211_BAPS_POLICY	0x0002		/* block ack policy */
#define	IEEE80211_BAPS_POLICY_S	1

#define	IEEE80211_BAPS_POLICY_DELAYED	(0<<IEEE80211_BAPS_POLICY_S)
#define	IEEE80211_BAPS_POLICY_IMMEDIATE	(1<<IEEE80211_BAPS_POLICY_S)

/* Block Ack Sequence Control */
#define	IEEE80211_BASEQ_START	0xfff0		/* starting seqnum */
#define	IEEE80211_BASEQ_START_S	4
#define	IEEE80211_BASEQ_FRAG	0x000f		/* fragment number */
#define	IEEE80211_BASEQ_FRAG_S	0

/* Delayed Block Ack Parameter Set */
#define	IEEE80211_DELBAPS_TID	0xf000		/* TID */
#define	IEEE80211_DELBAPS_TID_S	12
#define	IEEE80211_DELBAPS_INIT	0x0800		/* initiator */
#define	IEEE80211_DELBAPS_INIT_S 11

/* BA - ADDBA request */
struct ieee80211_action_ba_addbarequest {
	struct ieee80211_action rq_header;
	uint8_t		rq_dialogtoken;
	uint16_t	rq_baparamset;
	uint16_t	rq_batimeout;		/* in TUs */
	uint16_t	rq_baseqctl;
} __packed;

/* BA - ADDBA response */
struct ieee80211_action_ba_addbaresponse {
	struct ieee80211_action rs_header;
	uint8_t		rs_dialogtoken;
	uint16_t	rs_statuscode;
	uint16_t	rs_baparamset;
	uint16_t	rs_batimeout;		/* in TUs */
} __packed;

/* BA - DELBA */
struct ieee80211_action_ba_delba {
	struct ieee80211_action dl_header;
	uint16_t	dl_baparamset;
	uint16_t	dl_reasoncode;
} __packed;

/* BAR Control */
#define	IEEE80211_BAR_TID	0xf000		/* TID */
#define	IEEE80211_BAR_TID_S	12
#define	IEEE80211_BAR_COMP	0x0004		/* Compressed Bitmap */
#define	IEEE80211_BAR_MTID	0x0002		/* Multi-TID */
#define	IEEE80211_BAR_NOACK	0x0001		/* No-Ack policy */

/* BAR Starting Sequence Control */
#define	IEEE80211_BAR_SEQ_START	0xfff0		/* starting seqnum */
#define	IEEE80211_BAR_SEQ_START_S	4

struct ieee80211_ba_request {
	uint16_t	rq_barctl;
	uint16_t	rq_barseqctl;
} __packed;

/*
 * Control frames.
 */
struct ieee80211_frame_min {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_addr1[IEEE80211_ADDR_LEN];
	uint8_t		i_addr2[IEEE80211_ADDR_LEN];
	/* FCS */
} __packed;

struct ieee80211_frame_rts {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_ra[IEEE80211_ADDR_LEN];
	uint8_t		i_ta[IEEE80211_ADDR_LEN];
	/* FCS */
} __packed;

struct ieee80211_frame_cts {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_ra[IEEE80211_ADDR_LEN];
	/* FCS */
} __packed;

struct ieee80211_frame_ack {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_ra[IEEE80211_ADDR_LEN];
	/* FCS */
} __packed;

struct ieee80211_frame_pspoll {
	uint8_t		i_fc[2];
	uint8_t		i_aid[2];
	uint8_t		i_bssid[IEEE80211_ADDR_LEN];
	uint8_t		i_ta[IEEE80211_ADDR_LEN];
	/* FCS */
} __packed;

struct ieee80211_frame_cfend {		/* NB: also CF-End+CF-Ack */
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];	/* should be zero */
	uint8_t		i_ra[IEEE80211_ADDR_LEN];
	uint8_t		i_bssid[IEEE80211_ADDR_LEN];
	/* FCS */
} __packed;

struct ieee80211_frame_bar {
	uint8_t		i_fc[2];
	uint8_t		i_dur[2];
	uint8_t		i_ra[IEEE80211_ADDR_LEN];
	uint8_t		i_ta[IEEE80211_ADDR_LEN];
	uint16_t	i_ctl;
	uint16_t	i_seq;
	/* FCS */
} __packed;

/*
 * BEACON management packets
 *
 *	octet timestamp[8]
 *	octet beacon interval[2]
 *	octet capability information[2]
 *	information element
 *		octet elemid
 *		octet length
 *		octet information[length]
 */

#define	IEEE80211_BEACON_INTERVAL(beacon) \
	((beacon)[8] | ((beacon)[9] << 8))
#define	IEEE80211_BEACON_CAPABILITY(beacon) \
	((beacon)[10] | ((beacon)[11] << 8))

#define	IEEE80211_CAPINFO_ESS			0x0001
#define	IEEE80211_CAPINFO_IBSS			0x0002
#define	IEEE80211_CAPINFO_CF_POLLABLE		0x0004
#define	IEEE80211_CAPINFO_CF_POLLREQ		0x0008
#define	IEEE80211_CAPINFO_PRIVACY		0x0010
#define	IEEE80211_CAPINFO_SHORT_PREAMBLE	0x0020
#define	IEEE80211_CAPINFO_PBCC			0x0040
#define	IEEE80211_CAPINFO_CHNL_AGILITY		0x0080
#define	IEEE80211_CAPINFO_SPECTRUM_MGMT		0x0100
/* bit 9 is reserved */
#define	IEEE80211_CAPINFO_SHORT_SLOTTIME	0x0400
#define	IEEE80211_CAPINFO_RSN			0x0800
/* bit 12 is reserved */
#define	IEEE80211_CAPINFO_DSSSOFDM		0x2000
/* bits 14-15 are reserved */

#define	IEEE80211_CAPINFO_BITS \
	"\20\1ESS\2IBSS\3CF_POLLABLE\4CF_POLLREQ\5PRIVACY\6SHORT_PREAMBLE" \
	"\7PBCC\10CHNL_AGILITY\11SPECTRUM_MGMT\13SHORT_SLOTTIME\14RSN" \
	"\16DSSOFDM"

/*
 * 802.11i/WPA information element (maximally sized).
 */
struct ieee80211_ie_wpa {
	uint8_t		wpa_id;		/* IEEE80211_ELEMID_VENDOR */
	uint8_t		wpa_len;	/* length in bytes */
	uint8_t		wpa_oui[3];	/* 0x00, 0x50, 0xf2 */
	uint8_t		wpa_type;	/* OUI type */
	uint16_t	wpa_version;	/* spec revision */
	uint32_t	wpa_mcipher[1];	/* multicast/group key cipher */
	uint16_t	wpa_uciphercnt;	/* # pairwise key ciphers */
	uint32_t	wpa_uciphers[8];/* ciphers */
	uint16_t	wpa_authselcnt;	/* authentication selector cnt*/
	uint32_t	wpa_authsels[8];/* selectors */
	uint16_t	wpa_caps;	/* 802.11i capabilities */
	uint16_t	wpa_pmkidcnt;	/* 802.11i pmkid count */
	uint16_t	wpa_pmkids[8];	/* 802.11i pmkids */
} __packed;

/*
 * 802.11n HT Capability IE
 * NB: these reflect D1.10
 */
struct ieee80211_ie_htcap {
	uint8_t		hc_id;			/* element ID */
	uint8_t		hc_len;			/* length in bytes */
	uint16_t	hc_cap;			/* HT caps (see below) */
	uint8_t		hc_param;		/* HT params (see below) */
	uint8_t 	hc_mcsset[16]; 		/* supported MCS set */
	uint16_t	hc_extcap;		/* extended HT capabilities */
	uint32_t	hc_txbf;		/* txbf capabilities */
	uint8_t		hc_antenna;		/* antenna capabilities */
} __packed;

/* HT capability flags (ht_cap) */
#define	IEEE80211_HTCAP_LDPC		0x0001	/* LDPC supported */
#define	IEEE80211_HTCAP_CHWIDTH40	0x0002	/* 20/40 supported */
#define	IEEE80211_HTCAP_SMPS		0x000c	/* SM Power Save mode */
#define	IEEE80211_HTCAP_SMPS_OFF	0x000c	/* disabled */
#define	IEEE80211_HTCAP_SMPS_DYNAMIC	0x0004	/* send RTS first */
/* NB: SMPS value 2 is reserved */
#define	IEEE80211_HTCAP_SMPS_ENA	0x0000	/* enabled (static mode) */
#define	IEEE80211_HTCAP_GREENFIELD	0x0010	/* Greenfield supported */
#define	IEEE80211_HTCAP_SHORTGI20	0x0020	/* Short GI in 20MHz */
#define	IEEE80211_HTCAP_SHORTGI40	0x0040	/* Short GI in 40MHz */
#define	IEEE80211_HTCAP_TXSTBC		0x0080	/* STBC tx ok */
#define	IEEE80211_HTCAP_RXSTBC		0x0300  /* STBC rx support */
#define	IEEE80211_HTCAP_RXSTBC_S	8
#define	IEEE80211_HTCAP_RXSTBC_1STREAM	0x0100  /* 1 spatial stream */
#define	IEEE80211_HTCAP_RXSTBC_2STREAM	0x0200  /* 1-2 spatial streams*/
#define	IEEE80211_HTCAP_RXSTBC_3STREAM	0x0300  /* 1-3 spatial streams*/
#define	IEEE80211_HTCAP_DELBA		0x0400	/* HT DELBA supported */
#define	IEEE80211_HTCAP_MAXAMSDU	0x0800	/* max A-MSDU length */
#define	IEEE80211_HTCAP_MAXAMSDU_7935	0x0800	/* 7935 octets */
#define	IEEE80211_HTCAP_MAXAMSDU_3839	0x0000	/* 3839 octets */
#define	IEEE80211_HTCAP_DSSSCCK40	0x1000  /* DSSS/CCK in 40MHz */
#define	IEEE80211_HTCAP_PSMP		0x2000  /* PSMP supported */
#define	IEEE80211_HTCAP_40INTOLERANT	0x4000  /* 40MHz intolerant */
#define	IEEE80211_HTCAP_LSIGTXOPPROT	0x8000  /* L-SIG TXOP prot */

#define	IEEE80211_HTCAP_BITS \
	"\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \
	"\13DELBA\14AMSDU(7935)\15DSSSCCK40\16PSMP\1740INTOLERANT" \
	"\20LSIGTXOPPROT"

/* HT parameters (hc_param) */
#define	IEEE80211_HTCAP_MAXRXAMPDU	0x03	/* max rx A-MPDU factor */
#define	IEEE80211_HTCAP_MAXRXAMPDU_S	0
#define	IEEE80211_HTCAP_MAXRXAMPDU_8K	0
#define	IEEE80211_HTCAP_MAXRXAMPDU_16K	1
#define	IEEE80211_HTCAP_MAXRXAMPDU_32K	2
#define	IEEE80211_HTCAP_MAXRXAMPDU_64K	3
#define	IEEE80211_HTCAP_MPDUDENSITY	0x1c	/* min MPDU start spacing */
#define	IEEE80211_HTCAP_MPDUDENSITY_S	2
#define	IEEE80211_HTCAP_MPDUDENSITY_NA	0	/* no time restriction */
#define	IEEE80211_HTCAP_MPDUDENSITY_025	1	/* 1/4 us */
#define	IEEE80211_HTCAP_MPDUDENSITY_05	2	/* 1/2 us */
#define	IEEE80211_HTCAP_MPDUDENSITY_1	3	/* 1 us */
#define	IEEE80211_HTCAP_MPDUDENSITY_2	4	/* 2 us */
#define	IEEE80211_HTCAP_MPDUDENSITY_4	5	/* 4 us */
#define	IEEE80211_HTCAP_MPDUDENSITY_8	6	/* 8 us */
#define	IEEE80211_HTCAP_MPDUDENSITY_16	7	/* 16 us */

/* HT extended capabilities (hc_extcap) */
#define	IEEE80211_HTCAP_PCO		0x0001	/* PCO capable */
#define	IEEE80211_HTCAP_PCOTRANS	0x0006	/* PCO transition time */
#define	IEEE80211_HTCAP_PCOTRANS_S	1
#define	IEEE80211_HTCAP_PCOTRANS_04	0x0002	/* 400 us */
#define	IEEE80211_HTCAP_PCOTRANS_15	0x0004	/* 1.5 ms */
#define	IEEE80211_HTCAP_PCOTRANS_5	0x0006	/* 5 ms */
/* bits 3-7 reserved */
#define	IEEE80211_HTCAP_MCSFBACK	0x0300	/* MCS feedback */
#define	IEEE80211_HTCAP_MCSFBACK_S	8
#define	IEEE80211_HTCAP_MCSFBACK_NONE	0x0000	/* nothing provided */
#define	IEEE80211_HTCAP_MCSFBACK_UNSOL	0x0200	/* unsolicited feedback */
#define	IEEE80211_HTCAP_MCSFBACK_MRQ	0x0300	/* " "+respond to MRQ */
#define	IEEE80211_HTCAP_HTC		0x0400	/* +HTC support */
#define	IEEE80211_HTCAP_RDR		0x0800	/* reverse direction responder*/
/* bits 12-15 reserved */

/*
 * 802.11n HT Information IE
 */
struct ieee80211_ie_htinfo {
	uint8_t		hi_id;			/* element ID */
	uint8_t		hi_len;			/* length in bytes */
	uint8_t		hi_ctrlchannel;		/* primary channel */
	uint8_t		hi_byte1;		/* ht ie byte 1 */
	uint8_t		hi_byte2;		/* ht ie byte 2 */
	uint8_t		hi_byte3;		/* ht ie byte 3 */
	uint16_t	hi_byte45;		/* ht ie bytes 4+5 */
	uint8_t 	hi_basicmcsset[16]; 	/* basic MCS set */
} __packed;

/* byte1 */
#define	IEEE80211_HTINFO_2NDCHAN	0x03	/* secondary/ext chan offset */
#define	IEEE80211_HTINFO_2NDCHAN_S	0
#define	IEEE80211_HTINFO_2NDCHAN_NONE	0x00	/* no secondary/ext channel */
#define	IEEE80211_HTINFO_2NDCHAN_ABOVE	0x01	/* above private channel */
/* NB: 2 is reserved */
#define	IEEE80211_HTINFO_2NDCHAN_BELOW	0x03	/* below primary channel */
#define	IEEE80211_HTINFO_TXWIDTH	0x04	/* tx channel width */
#define	IEEE80211_HTINFO_TXWIDTH_20	0x00	/* 20MHz width */
#define	IEEE80211_HTINFO_TXWIDTH_2040	0x04	/* any supported width */
#define	IEEE80211_HTINFO_RIFSMODE	0x08	/* Reduced IFS (RIFS) use */
#define	IEEE80211_HTINFO_RIFSMODE_PROH	0x00	/* RIFS use prohibited */
#define	IEEE80211_HTINFO_RIFSMODE_PERM	0x08	/* RIFS use permitted */
#define	IEEE80211_HTINFO_PMSPONLY	0x10	/* PSMP required to associate */
#define	IEEE80211_HTINFO_SIGRAN		0xe0	/* shortest Service Interval */
#define	IEEE80211_HTINFO_SIGRAN_S	5
#define	IEEE80211_HTINFO_SIGRAN_5	0x00	/* 5 ms */
/* XXX add rest */

/* bytes 2+3 */
#define	IEEE80211_HTINFO_OPMODE		0x03	/* operating mode */
#define	IEEE80211_HTINFO_OPMODE_S	0
#define	IEEE80211_HTINFO_OPMODE_PURE	0x00	/* no protection */
#define	IEEE80211_HTINFO_OPMODE_PROTOPT	0x01	/* protection optional */
#define	IEEE80211_HTINFO_OPMODE_HT20PR	0x02	/* protection for HT20 sta's */
#define	IEEE80211_HTINFO_OPMODE_MIXED	0x03	/* protection for legacy sta's*/
#define	IEEE80211_HTINFO_NONGF_PRESENT	0x04	/* non-GF sta's present */
#define	IEEE80211_HTINFO_TXBL		0x08	/* transmit burst limit */
#define	IEEE80211_HTINFO_NONHT_PRESENT	0x10	/* non-HT sta's present */
/* bits 5-15 reserved */

/* bytes 4+5 */
#define	IEEE80211_HTINFO_2NDARYBEACON	0x01
#define	IEEE80211_HTINFO_LSIGTXOPPROT	0x02
#define	IEEE80211_HTINFO_PCO_ACTIVE	0x04
#define	IEEE80211_HTINFO_40MHZPHASE	0x08

/* byte5 */
#define	IEEE80211_HTINFO_BASIC_STBCMCS	0x7f
#define	IEEE80211_HTINFO_BASIC_STBCMCS_S 0
#define	IEEE80211_HTINFO_DUALPROTECTED	0x80

/*
 * Management information element payloads.
 */

enum {
	IEEE80211_ELEMID_SSID		= 0,
	IEEE80211_ELEMID_RATES		= 1,
	IEEE80211_ELEMID_FHPARMS	= 2,
	IEEE80211_ELEMID_DSPARMS	= 3,
	IEEE80211_ELEMID_CFPARMS	= 4,
	IEEE80211_ELEMID_TIM		= 5,
	IEEE80211_ELEMID_IBSSPARMS	= 6,
	IEEE80211_ELEMID_COUNTRY	= 7,
	IEEE80211_ELEMID_CHALLENGE	= 16,
	/* 17-31 reserved for challenge text extension */
	IEEE80211_ELEMID_PWRCNSTR	= 32,
	IEEE80211_ELEMID_PWRCAP		= 33,
	IEEE80211_ELEMID_TPCREQ		= 34,
	IEEE80211_ELEMID_TPCREP		= 35,
	IEEE80211_ELEMID_SUPPCHAN	= 36,
	IEEE80211_ELEMID_CSA		= 37,
	IEEE80211_ELEMID_MEASREQ	= 38,
	IEEE80211_ELEMID_MEASREP	= 39,
	IEEE80211_ELEMID_QUIET		= 40,
	IEEE80211_ELEMID_IBSSDFS	= 41,
	IEEE80211_ELEMID_ERP		= 42,
	IEEE80211_ELEMID_HTCAP		= 45,
	IEEE80211_ELEMID_RSN		= 48,
	IEEE80211_ELEMID_XRATES		= 50,
	IEEE80211_ELEMID_HTINFO		= 61,
	IEEE80211_ELEMID_TPC		= 150,
	IEEE80211_ELEMID_CCKM		= 156,
	IEEE80211_ELEMID_VENDOR		= 221,	/* vendor private */

	/*
	 * 802.11s IEs based on D3.03 spec and were not assigned by
	 * ANA. Beware changing them because some of them are being
	 * kept compatible with Linux.
	 */
	IEEE80211_ELEMID_MESHCONF	= 51,
	IEEE80211_ELEMID_MESHID		= 52,
	IEEE80211_ELEMID_MESHLINK	= 35,
	IEEE80211_ELEMID_MESHCNGST	= 36,
	IEEE80211_ELEMID_MESHPEER	= 55,
	IEEE80211_ELEMID_MESHCSA	= 38,
	IEEE80211_ELEMID_MESHTIM	= 39,
	IEEE80211_ELEMID_MESHAWAKEW	= 40,
	IEEE80211_ELEMID_MESHBEACONT	= 41,
	IEEE80211_ELEMID_MESHPANN	= 48,
	IEEE80211_ELEMID_MESHRANN	= 49,
	IEEE80211_ELEMID_MESHPREQ	= 68,
	IEEE80211_ELEMID_MESHPREP	= 69,
	IEEE80211_ELEMID_MESHPERR	= 70,
	IEEE80211_ELEMID_MESHPXU	= 53,
	IEEE80211_ELEMID_MESHPXUC	= 54,
	IEEE80211_ELEMID_MESHAH		= 60, /* Abbreviated Handshake */
};

struct ieee80211_tim_ie {
	uint8_t		tim_ie;			/* IEEE80211_ELEMID_TIM */
	uint8_t		tim_len;
	uint8_t		tim_count;		/* DTIM count */
	uint8_t		tim_period;		/* DTIM period */
	uint8_t		tim_bitctl;		/* bitmap control */
	uint8_t		tim_bitmap[1];		/* variable-length bitmap */
} __packed;

struct ieee80211_country_ie {
	uint8_t		ie;			/* IEEE80211_ELEMID_COUNTRY */
	uint8_t		len;
	uint8_t		cc[3];			/* ISO CC+(I)ndoor/(O)utdoor */
	struct {
		uint8_t schan;			/* starting channel */
		uint8_t nchan;			/* number channels */
		uint8_t maxtxpwr;		/* tx power cap */
	} __packed band[1];			/* sub bands (NB: var size) */
} __packed;

#define	IEEE80211_COUNTRY_MAX_BANDS	84	/* max possible bands */
#define	IEEE80211_COUNTRY_MAX_SIZE \
	(sizeof(struct ieee80211_country_ie) + 3*(IEEE80211_COUNTRY_MAX_BANDS-1))

/*
 * 802.11h Channel Switch Announcement (CSA).
 */
struct ieee80211_csa_ie {
	uint8_t		csa_ie;		/* IEEE80211_ELEMID_CHANSWITCHANN */
	uint8_t		csa_len;
	uint8_t		csa_mode;		/* Channel Switch Mode */
	uint8_t		csa_newchan;		/* New Channel Number */
	uint8_t		csa_count;		/* Channel Switch Count */
} __packed;

/*
 * Note the min acceptable CSA count is used to guard against
 * malicious CSA injection in station mode.  Defining this value
 * as other than 0 violates the 11h spec.
 */
#define	IEEE80211_CSA_COUNT_MIN	2
#define	IEEE80211_CSA_COUNT_MAX	255

/* rate set entries are in .5 Mb/s units, and potentially marked as basic */
#define	IEEE80211_RATE_BASIC		0x80
#define	IEEE80211_RATE_VAL		0x7f

/* EPR information element flags */
#define	IEEE80211_ERP_NON_ERP_PRESENT	0x01
#define	IEEE80211_ERP_USE_PROTECTION	0x02
#define	IEEE80211_ERP_LONG_PREAMBLE	0x04

#define	IEEE80211_ERP_BITS \
	"\20\1NON_ERP_PRESENT\2USE_PROTECTION\3LONG_PREAMBLE"

#define	ATH_OUI			0x7f0300	/* Atheros OUI */
#define	ATH_OUI_TYPE		0x01		/* Atheros protocol ie */

/* NB: Atheros allocated the OUI for this purpose ~2005 but beware ... */
#define	TDMA_OUI		ATH_OUI
#define	TDMA_OUI_TYPE		0x02		/* TDMA protocol ie */

#define	BCM_OUI			0x4c9000	/* Broadcom OUI */
#define	BCM_OUI_HTCAP		51		/* pre-draft HTCAP ie */
#define	BCM_OUI_HTINFO		52		/* pre-draft HTINFO ie */

#define	WPA_OUI			0xf25000
#define	WPA_OUI_TYPE		0x01
#define	WPA_VERSION		1		/* current supported version */

#define	WPA_CSE_NULL		0x00
#define	WPA_CSE_WEP40		0x01
#define	WPA_CSE_TKIP		0x02
#define	WPA_CSE_CCMP		0x04
#define	WPA_CSE_WEP104		0x05

#define	WPA_ASE_NONE		0x00
#define	WPA_ASE_8021X_UNSPEC	0x01
#define	WPA_ASE_8021X_PSK	0x02

#define	WPS_OUI_TYPE		0x04

#define	RSN_OUI			0xac0f00
#define	RSN_VERSION		1		/* current supported version */

#define	RSN_CSE_NULL		0x00
#define	RSN_CSE_WEP40		0x01
#define	RSN_CSE_TKIP		0x02
#define	RSN_CSE_WRAP		0x03
#define	RSN_CSE_CCMP		0x04
#define	RSN_CSE_WEP104		0x05

#define	RSN_ASE_NONE		0x00
#define	RSN_ASE_8021X_UNSPEC	0x01
#define	RSN_ASE_8021X_PSK	0x02

#define	RSN_CAP_PREAUTH		0x01

#define	WME_OUI			0xf25000
#define	WME_OUI_TYPE		0x02
#define	WME_INFO_OUI_SUBTYPE	0x00
#define	WME_PARAM_OUI_SUBTYPE	0x01
#define	WME_VERSION		1

/* WME stream classes */
#define	WME_AC_BE	0		/* best effort */
#define	WME_AC_BK	1		/* background */
#define	WME_AC_VI	2		/* video */
#define	WME_AC_VO	3		/* voice */

/*
 * AUTH management packets
 *
 *	octet algo[2]
 *	octet seq[2]
 *	octet status[2]
 *	octet chal.id
 *	octet chal.length
 *	octet chal.text[253]		NB: 1-253 bytes
 */

/* challenge length for shared key auth */
#define IEEE80211_CHALLENGE_LEN		128

#define	IEEE80211_AUTH_ALG_OPEN		0x0000
#define	IEEE80211_AUTH_ALG_SHARED	0x0001
#define	IEEE80211_AUTH_ALG_LEAP		0x0080

enum {
	IEEE80211_AUTH_OPEN_REQUEST		= 1,
	IEEE80211_AUTH_OPEN_RESPONSE		= 2,
};

enum {
	IEEE80211_AUTH_SHARED_REQUEST		= 1,
	IEEE80211_AUTH_SHARED_CHALLENGE		= 2,
	IEEE80211_AUTH_SHARED_RESPONSE		= 3,
	IEEE80211_AUTH_SHARED_PASS		= 4,
};

/*
 * Reason and status codes.
 *
 * Reason codes are used in management frames to indicate why an
 * action took place (e.g. on disassociation).  Status codes are
 * used in management frames to indicate the result of an operation.
 *
 * Unlisted codes are reserved
 */

enum {
	IEEE80211_REASON_UNSPECIFIED		= 1,
	IEEE80211_REASON_AUTH_EXPIRE		= 2,
	IEEE80211_REASON_AUTH_LEAVE		= 3,
	IEEE80211_REASON_ASSOC_EXPIRE		= 4,
	IEEE80211_REASON_ASSOC_TOOMANY		= 5,
	IEEE80211_REASON_NOT_AUTHED		= 6,
	IEEE80211_REASON_NOT_ASSOCED		= 7,
	IEEE80211_REASON_ASSOC_LEAVE		= 8,
	IEEE80211_REASON_ASSOC_NOT_AUTHED	= 9,
	IEEE80211_REASON_DISASSOC_PWRCAP_BAD	= 10,	/* 11h */
	IEEE80211_REASON_DISASSOC_SUPCHAN_BAD	= 11,	/* 11h */
	IEEE80211_REASON_IE_INVALID		= 13,	/* 11i */
	IEEE80211_REASON_MIC_FAILURE		= 14,	/* 11i */
	IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT	= 15,	/* 11i */
	IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16,	/* 11i */
	IEEE80211_REASON_IE_IN_4WAY_DIFFERS	= 17,	/* 11i */
	IEEE80211_REASON_GROUP_CIPHER_INVALID	= 18,	/* 11i */
	IEEE80211_REASON_PAIRWISE_CIPHER_INVALID= 19,	/* 11i */
	IEEE80211_REASON_AKMP_INVALID		= 20,	/* 11i */
	IEEE80211_REASON_UNSUPP_RSN_IE_VERSION	= 21,	/* 11i */
	IEEE80211_REASON_INVALID_RSN_IE_CAP	= 22,	/* 11i */
	IEEE80211_REASON_802_1X_AUTH_FAILED	= 23,	/* 11i */
	IEEE80211_REASON_CIPHER_SUITE_REJECTED	= 24,	/* 11i */
	IEEE80211_REASON_UNSPECIFIED_QOS	= 32,	/* 11e */
	IEEE80211_REASON_INSUFFICIENT_BW	= 33,	/* 11e */
	IEEE80211_REASON_TOOMANY_FRAMES		= 34,	/* 11e */
	IEEE80211_REASON_OUTSIDE_TXOP		= 35,	/* 11e */
	IEEE80211_REASON_LEAVING_QBSS		= 36,	/* 11e */
	IEEE80211_REASON_BAD_MECHANISM		= 37,	/* 11e */
	IEEE80211_REASON_SETUP_NEEDED		= 38,	/* 11e */
	IEEE80211_REASON_TIMEOUT		= 39,	/* 11e */

	/* values not yet allocated by ANA */
	IEEE80211_REASON_PEER_LINK_CANCELED	= 2,	/* 11s */
	IEEE80211_REASON_MESH_MAX_PEERS		= 3,	/* 11s */
	IEEE80211_REASON_MESH_CPVIOLATION	= 4,	/* 11s */
	IEEE80211_REASON_MESH_CLOSE_RCVD	= 5,	/* 11s */
	IEEE80211_REASON_MESH_MAX_RETRIES	= 6,	/* 11s */
	IEEE80211_REASON_MESH_CONFIRM_TIMEOUT	= 7,	/* 11s */
	IEEE80211_REASON_MESH_INVALID_GTK	= 8,	/* 11s */
	IEEE80211_REASON_MESH_INCONS_PARAMS	= 9,	/* 11s */
	IEEE80211_REASON_MESH_INVALID_SECURITY	= 10,	/* 11s */
	IEEE80211_REASON_MESH_PERR_UNSPEC	= 11,	/* 11s */
	IEEE80211_REASON_MESH_PERR_NO_FI	= 12,	/* 11s */
	IEEE80211_REASON_MESH_PERR_DEST_UNREACH	= 13,	/* 11s */

	IEEE80211_STATUS_SUCCESS		= 0,
	IEEE80211_STATUS_UNSPECIFIED		= 1,
	IEEE80211_STATUS_CAPINFO		= 10,
	IEEE80211_STATUS_NOT_ASSOCED		= 11,
	IEEE80211_STATUS_OTHER			= 12,
	IEEE80211_STATUS_ALG			= 13,
	IEEE80211_STATUS_SEQUENCE		= 14,
	IEEE80211_STATUS_CHALLENGE		= 15,
	IEEE80211_STATUS_TIMEOUT		= 16,
	IEEE80211_STATUS_TOOMANY		= 17,
	IEEE80211_STATUS_BASIC_RATE		= 18,
	IEEE80211_STATUS_SP_REQUIRED		= 19,	/* 11b */
	IEEE80211_STATUS_PBCC_REQUIRED		= 20,	/* 11b */
	IEEE80211_STATUS_CA_REQUIRED		= 21,	/* 11b */
	IEEE80211_STATUS_SPECMGMT_REQUIRED	= 22,	/* 11h */
	IEEE80211_STATUS_PWRCAP_REQUIRED	= 23,	/* 11h */
	IEEE80211_STATUS_SUPCHAN_REQUIRED	= 24,	/* 11h */
	IEEE80211_STATUS_SHORTSLOT_REQUIRED	= 25,	/* 11g */
	IEEE80211_STATUS_DSSSOFDM_REQUIRED	= 26,	/* 11g */
	IEEE80211_STATUS_MISSING_HT_CAPS	= 27,	/* 11n D3.0 */
	IEEE80211_STATUS_INVALID_IE		= 40,	/* 11i */
	IEEE80211_STATUS_GROUP_CIPHER_INVALID	= 41,	/* 11i */
	IEEE80211_STATUS_PAIRWISE_CIPHER_INVALID = 42,	/* 11i */
	IEEE80211_STATUS_AKMP_INVALID		= 43,	/* 11i */
	IEEE80211_STATUS_UNSUPP_RSN_IE_VERSION	= 44,	/* 11i */
	IEEE80211_STATUS_INVALID_RSN_IE_CAP	= 45,	/* 11i */
	IEEE80211_STATUS_CIPHER_SUITE_REJECTED	= 46,	/* 11i */
};

#define	IEEE80211_WEP_KEYLEN		5	/* 40bit */
#define	IEEE80211_WEP_IVLEN		3	/* 24bit */
#define	IEEE80211_WEP_KIDLEN		1	/* 1 octet */
#define	IEEE80211_WEP_CRCLEN		4	/* CRC-32 */
#define	IEEE80211_WEP_TOTLEN		(IEEE80211_WEP_IVLEN + \
					 IEEE80211_WEP_KIDLEN + \
					 IEEE80211_WEP_CRCLEN)
#define	IEEE80211_WEP_NKID		4	/* number of key ids */

/*
 * 802.11i defines an extended IV for use with non-WEP ciphers.
 * When the EXTIV bit is set in the key id byte an additional
 * 4 bytes immediately follow the IV for TKIP.  For CCMP the
 * EXTIV bit is likewise set but the 8 bytes represent the
 * CCMP header rather than IV+extended-IV.
 */
#define	IEEE80211_WEP_EXTIV		0x20
#define	IEEE80211_WEP_EXTIVLEN		4	/* extended IV length */
#define	IEEE80211_WEP_MICLEN		8	/* trailing MIC */

#define	IEEE80211_CRC_LEN		4

/*
 * Maximum acceptable MTU is:
 *	IEEE80211_MAX_LEN - WEP overhead - CRC -
 *		QoS overhead - RSN/WPA overhead
 * Min is arbitrarily chosen > IEEE80211_MIN_LEN.  The default
 * mtu is Ethernet-compatible; it's set by ether_ifattach.
 */
#define	IEEE80211_MTU_MAX		2290
#define	IEEE80211_MTU_MIN		32

#define	IEEE80211_MAX_LEN		(2300 + IEEE80211_CRC_LEN + \
    (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN))
#define	IEEE80211_ACK_LEN \
	(sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN)
#define	IEEE80211_MIN_LEN \
	(sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN)

/*
 * The 802.11 spec says at most 2007 stations may be
 * associated at once.  For most AP's this is way more
 * than is feasible so we use a default of IEEE80211_AID_DEF.
 * This number may be overridden by the driver and/or by
 * user configuration but may not be less than IEEE80211_AID_MIN
 * (see _ieee80211.h for implementation-specific settings).
 */
#define	IEEE80211_AID_MAX		2007

#define	IEEE80211_AID(b)	((b) &~ 0xc000)

/*
 * RTS frame length parameters.  The default is specified in
 * the 802.11 spec as 512; we treat it as implementation-dependent
 * so it's defined in ieee80211_var.h.  The max may be wrong
 * for jumbo frames.
 */
#define	IEEE80211_RTS_MIN		1
#define	IEEE80211_RTS_MAX		2346

/*
 * TX fragmentation parameters.  As above for RTS, we treat
 * default as implementation-dependent so define it elsewhere.
 */
#define	IEEE80211_FRAG_MIN		256
#define	IEEE80211_FRAG_MAX		2346

/*
 * Beacon interval (TU's).  Min+max come from WiFi requirements.
 * As above, we treat default as implementation-dependent so
 * define it elsewhere.
 */
#define	IEEE80211_BINTVAL_MAX	1000	/* max beacon interval (TU's) */
#define	IEEE80211_BINTVAL_MIN	25	/* min beacon interval (TU's) */

/*
 * DTIM period (beacons).  Min+max are not really defined
 * by the protocol but we want them publicly visible so
 * define them here.
 */
#define	IEEE80211_DTIM_MAX	15	/* max DTIM period */
#define	IEEE80211_DTIM_MIN	1	/* min DTIM period */

/*
 * Beacon miss threshold (beacons).  As for DTIM, we define
 * them here to be publicly visible.  Note the max may be
 * clamped depending on device capabilities.
 */
#define	IEEE80211_HWBMISS_MIN 	1
#define	IEEE80211_HWBMISS_MAX 	255

/*
 * 802.11 frame duration definitions.
 */

struct ieee80211_duration {
	uint16_t	d_rts_dur;
	uint16_t	d_data_dur;
	uint16_t	d_plcp_len;
	uint8_t		d_residue;	/* unused octets in time slot */
};

/* One Time Unit (TU) is 1Kus = 1024 microseconds. */
#define IEEE80211_DUR_TU		1024

/* IEEE 802.11b durations for DSSS PHY in microseconds */
#define IEEE80211_DUR_DS_LONG_PREAMBLE	144
#define IEEE80211_DUR_DS_SHORT_PREAMBLE	72

#define IEEE80211_DUR_DS_SLOW_PLCPHDR	48
#define IEEE80211_DUR_DS_FAST_PLCPHDR	24
#define IEEE80211_DUR_DS_SLOW_ACK	112
#define IEEE80211_DUR_DS_FAST_ACK	56
#define IEEE80211_DUR_DS_SLOW_CTS	112
#define IEEE80211_DUR_DS_FAST_CTS	56

#define IEEE80211_DUR_DS_SLOT		20
#define IEEE80211_DUR_DS_SIFS		10
#define IEEE80211_DUR_DS_PIFS	(IEEE80211_DUR_DS_SIFS + IEEE80211_DUR_DS_SLOT)
#define IEEE80211_DUR_DS_DIFS	(IEEE80211_DUR_DS_SIFS + \
				 2 * IEEE80211_DUR_DS_SLOT)
#define IEEE80211_DUR_DS_EIFS	(IEEE80211_DUR_DS_SIFS + \
				 IEEE80211_DUR_DS_SLOW_ACK + \
				 IEEE80211_DUR_DS_LONG_PREAMBLE + \
				 IEEE80211_DUR_DS_SLOW_PLCPHDR + \
				 IEEE80211_DUR_DIFS)

#endif /* _NET80211_IEEE80211_H_ */


code:
/*-
 * Copyright (c) 2009 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_action.h 195377 2009-07-05 17:59:19Z sam $
 */
#ifndef _NET80211_IEEE80211_ACTION_H_
#define _NET80211_IEEE80211_ACTION_H_

/*
 * 802.11 send/recv action frame support.
 */

struct ieee80211_node;
struct ieee80211_frame;

typedef int ieee80211_send_action_func(struct ieee80211_node *,
    int, int, void *);
int	ieee80211_send_action_register(int cat, int act,
		ieee80211_send_action_func *f);
void	ieee80211_send_action_unregister(int cat, int act);
int	ieee80211_send_action(struct ieee80211_node *, int, int, void *);

typedef int ieee80211_recv_action_func(struct ieee80211_node *,
    const struct ieee80211_frame *, const uint8_t *, const uint8_t *);
int	ieee80211_recv_action_register(int cat, int act,
		ieee80211_recv_action_func *);
void	ieee80211_recv_action_unregister(int cat, int act);
int	ieee80211_recv_action(struct ieee80211_node *,
		const struct ieee80211_frame *,
		const uint8_t *, const uint8_t *);
#endif /* _NET80211_IEEE80211_ACTION_H_ */

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_adhoc.h 178354 2008-04-20 20:35:46Z sam $
 */
#ifndef _NET80211_IEEE80211_ADHOC_H_
#define _NET80211_IEEE80211_ADHOC_H_

/*
 * Adhoc-mode (ibss+ahdemo) implementation definitions.
 */
void	ieee80211_adhoc_attach(struct ieee80211com *);
void	ieee80211_adhoc_detach(struct ieee80211com *);
#endif /* !_NET80211_IEEE80211_STA_H_ */


code:
/*-
 * Copyright (c) 2009 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_ageq.h 195379 2009-07-05 18:17:37Z sam $
 */
#ifndef _NET80211_IEEE80211_STAGEQ_H_
#define _NET80211_IEEE80211_STAGEQ_H_

struct ieee80211_node;
struct mbuf;

struct ieee80211_ageq {
	ieee80211_ageq_lock_t	aq_lock;
	int			aq_len;		/* # items on queue */
	int			aq_maxlen;	/* max queue length */
	int			aq_drops;	/* frames dropped */
	struct mbuf		*aq_head;	/* frames linked w/ m_nextpkt */
	struct mbuf		*aq_tail;	/* last frame in queue */
};

void	ieee80211_ageq_init(struct ieee80211_ageq *, int maxlen,
	    const char *name);
void	ieee80211_ageq_cleanup(struct ieee80211_ageq *);
void	ieee80211_ageq_mfree(struct mbuf *);
int	ieee80211_ageq_append(struct ieee80211_ageq *, struct mbuf *,
	    int age);
void	ieee80211_ageq_drain(struct ieee80211_ageq *);
void	ieee80211_ageq_drain_node(struct ieee80211_ageq *,
	    struct ieee80211_node *);
struct mbuf *ieee80211_ageq_age(struct ieee80211_ageq *, int quanta);
struct mbuf *ieee80211_ageq_remove(struct ieee80211_ageq *,
	    struct ieee80211_node *match);
#endif /* _NET80211_IEEE80211_STAGEQ_H_ */


code:
/*-
 * Copyright (c) 2011 Adrian Chadd, Xenion Lty Ltd
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_alq.h 220908 2011-04-21 03:59:37Z adrian $
 */
#ifndef	__IEEE80211_ALQ_H__
#define	__IEEE80211_ALQ_H__

#define	IEEE80211_ALQ_PAYLOAD_SIZE	24

/*
 * timestamp
 * wlan interface
 * operation
 * sub-operation
 * rest of structure - operation specific
 */
struct ieee80211_alq_rec {
	uint32_t	r_timestamp;	/* XXX may wrap! */
	uint16_t	r_wlan;		/* wlan interface number */
	uint8_t		r_version;	/* version */
	uint8_t		r_op;		/* top-level operation id */
	u_char		r_payload[IEEE80211_ALQ_PAYLOAD_SIZE];
					/* operation-specific payload */
};

/* General logging function */
extern void ieee80211_alq_log(struct ieee80211vap *vap, uint8_t op, u_char *p, int l);

#endif	/* __IEEE80211_ALQ_H__ */


code:
/* $FreeBSD: release/9.0.0/sys/net80211/ieee80211_amrr.h 206358 2010-04-07 15:29:13Z rpaulo $ */
/*	$OpenBSD: ieee80211_amrr.h,v 1.3 2006/06/17 19:34:31 damien Exp $	*/

/*-
 * Copyright (c) 2006
 *	Damien Bergamini <damien.bergamini@free.fr>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#ifndef _NET80211_IEEE80211_AMRR_H_
#define _NET80211_IEEE80211_AMRR_H_

/*-
 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
 *
 * "IEEE 802.11 Rate Adaptation: A Practical Approach"
 *  Mathieu Lacage, Hossein Manshaei, Thierry Turletti
 *  INRIA Sophia - Projet Planete
 *  http://www-sop.inria.fr/rapports/sophia/RR-5208.html
 */

/*
 * Rate control settings.
 */
struct ieee80211vap;

struct ieee80211_amrr {
	u_int	amrr_min_success_threshold;
	u_int	amrr_max_success_threshold;
	int	amrr_interval;		/* update interval (ticks) */
};

#define IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD	 1
#define IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD	15

/*
 * Rate control state for a given node.
 */
struct ieee80211_amrr_node {
	struct ieee80211_amrr *amn_amrr;/* backpointer */
	int	amn_rix;		/* current rate index */
	int	amn_ticks;		/* time of last update */
	/* statistics */
	u_int	amn_txcnt;
	u_int	amn_success;
	u_int	amn_success_threshold;
	u_int	amn_recovery;
	u_int	amn_retrycnt;
};

#endif /* _NET80211_IEEE80211_AMRR_H_ */


code:
/*-
 * Copyright (c) 2001 Atsushi Onoe
 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_crypto.h 209636 2010-07-01 20:50:12Z bschmidt $
 */
#ifndef _NET80211_IEEE80211_CRYPTO_H_
#define _NET80211_IEEE80211_CRYPTO_H_

/*
 * 802.11 protocol crypto-related definitions.
 */
#define	IEEE80211_KEYBUF_SIZE	16
#define	IEEE80211_MICBUF_SIZE	(8+8)	/* space for both tx+rx keys */

/*
 * Old WEP-style key.  Deprecated.
 */
struct ieee80211_wepkey {
	u_int		wk_len;		/* key length in bytes */
	uint8_t		wk_key[IEEE80211_KEYBUF_SIZE];
};

struct ieee80211_rsnparms {
	uint8_t		rsn_mcastcipher;	/* mcast/group cipher */
	uint8_t		rsn_mcastkeylen;	/* mcast key length */
	uint8_t		rsn_ucastcipher;	/* selected unicast cipher */
	uint8_t		rsn_ucastkeylen;	/* unicast key length */
	uint8_t		rsn_keymgmt;		/* selected key mgmt algo */
	uint16_t	rsn_caps;		/* capabilities */
};

struct ieee80211_cipher;

/*
 * Crypto key state.  There is sufficient room for all supported
 * ciphers (see below).  The underlying ciphers are handled
 * separately through loadable cipher modules that register with
 * the generic crypto support.  A key has a reference to an instance
 * of the cipher; any per-key state is hung off wk_private by the
 * cipher when it is attached.  Ciphers are automatically called
 * to detach and cleanup any such state when the key is deleted.
 *
 * The generic crypto support handles encap/decap of cipher-related
 * frame contents for both hardware- and software-based implementations.
 * A key requiring software crypto support is automatically flagged and
 * the cipher is expected to honor this and do the necessary work.
 * Ciphers such as TKIP may also support mixed hardware/software
 * encrypt/decrypt and MIC processing.
 */
typedef uint16_t ieee80211_keyix;	/* h/w key index */

struct ieee80211_key {
	uint8_t		wk_keylen;	/* key length in bytes */
	uint8_t		wk_pad;
	uint16_t	wk_flags;
#define	IEEE80211_KEY_XMIT	0x0001	/* key used for xmit */
#define	IEEE80211_KEY_RECV	0x0002	/* key used for recv */
#define	IEEE80211_KEY_GROUP	0x0004	/* key used for WPA group operation */
#define	IEEE80211_KEY_NOREPLAY	0x0008	/* ignore replay failures */
#define	IEEE80211_KEY_SWENCRYPT	0x0010	/* host-based encrypt */
#define	IEEE80211_KEY_SWDECRYPT	0x0020	/* host-based decrypt */
#define	IEEE80211_KEY_SWENMIC	0x0040	/* host-based enmic */
#define	IEEE80211_KEY_SWDEMIC	0x0080	/* host-based demic */
#define	IEEE80211_KEY_DEVKEY	0x0100	/* device key request completed */
#define	IEEE80211_KEY_CIPHER0	0x1000	/* cipher-specific action 0 */
#define	IEEE80211_KEY_CIPHER1	0x2000	/* cipher-specific action 1 */
	ieee80211_keyix	wk_keyix;	/* h/w key index */
	ieee80211_keyix	wk_rxkeyix;	/* optional h/w rx key index */
	uint8_t		wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
#define	wk_txmic	wk_key+IEEE80211_KEYBUF_SIZE+0	/* XXX can't () right */
#define	wk_rxmic	wk_key+IEEE80211_KEYBUF_SIZE+8	/* XXX can't () right */
					/* key receive sequence counter */
	uint64_t	wk_keyrsc[IEEE80211_TID_SIZE];
	uint64_t	wk_keytsc;	/* key transmit sequence counter */
	const struct ieee80211_cipher *wk_cipher;
	void		*wk_private;	/* private cipher state */
	uint8_t		wk_macaddr[IEEE80211_ADDR_LEN];
};
#define	IEEE80211_KEY_COMMON 		/* common flags passed in by apps */\
	(IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP | \
	 IEEE80211_KEY_NOREPLAY)
#define	IEEE80211_KEY_DEVICE		/* flags owned by device driver */\
	(IEEE80211_KEY_DEVKEY|IEEE80211_KEY_CIPHER0|IEEE80211_KEY_CIPHER1)

#define	IEEE80211_KEY_SWCRYPT \
	(IEEE80211_KEY_SWENCRYPT | IEEE80211_KEY_SWDECRYPT)
#define	IEEE80211_KEY_SWMIC	(IEEE80211_KEY_SWENMIC | IEEE80211_KEY_SWDEMIC)

#define	IEEE80211_KEY_BITS \
	"\20\1XMIT\2RECV\3GROUP\4SWENCRYPT\5SWDECRYPT\6SWENMIC\7SWDEMIC" \
	"\10DEVKEY\11CIPHER0\12CIPHER1"

#define	IEEE80211_KEYIX_NONE	((ieee80211_keyix) -1)

/*
 * NB: these values are ordered carefully; there are lots of
 * of implications in any reordering.  Beware that 4 is used
 * only to indicate h/w TKIP MIC support in driver capabilities;
 * there is no separate cipher support (it's rolled into the
 * TKIP cipher support).
 */
#define	IEEE80211_CIPHER_WEP		0
#define	IEEE80211_CIPHER_TKIP		1
#define	IEEE80211_CIPHER_AES_OCB	2
#define	IEEE80211_CIPHER_AES_CCM	3
#define	IEEE80211_CIPHER_TKIPMIC	4	/* TKIP MIC capability */
#define	IEEE80211_CIPHER_CKIP		5
#define	IEEE80211_CIPHER_NONE		6	/* pseudo value */

#define	IEEE80211_CIPHER_MAX		(IEEE80211_CIPHER_NONE+1)

/* capability bits in ic_cryptocaps/iv_cryptocaps */
#define	IEEE80211_CRYPTO_WEP		(1<<IEEE80211_CIPHER_WEP)
#define	IEEE80211_CRYPTO_TKIP		(1<<IEEE80211_CIPHER_TKIP)
#define	IEEE80211_CRYPTO_AES_OCB	(1<<IEEE80211_CIPHER_AES_OCB)
#define	IEEE80211_CRYPTO_AES_CCM	(1<<IEEE80211_CIPHER_AES_CCM)
#define	IEEE80211_CRYPTO_TKIPMIC	(1<<IEEE80211_CIPHER_TKIPMIC)
#define	IEEE80211_CRYPTO_CKIP		(1<<IEEE80211_CIPHER_CKIP)

#define	IEEE80211_CRYPTO_BITS \
	"\20\1WEP\2TKIP\3AES\4AES_CCM\5TKIPMIC\6CKIP"

#if defined(__KERNEL__) || defined(_KERNEL)

struct ieee80211com;
struct ieee80211vap;
struct ieee80211_node;
struct mbuf;

MALLOC_DECLARE(M_80211_CRYPTO);

void	ieee80211_crypto_attach(struct ieee80211com *);
void	ieee80211_crypto_detach(struct ieee80211com *);
void	ieee80211_crypto_vattach(struct ieee80211vap *);
void	ieee80211_crypto_vdetach(struct ieee80211vap *);
int	ieee80211_crypto_newkey(struct ieee80211vap *,
		int cipher, int flags, struct ieee80211_key *);
int	ieee80211_crypto_delkey(struct ieee80211vap *,
		struct ieee80211_key *);
int	ieee80211_crypto_setkey(struct ieee80211vap *, struct ieee80211_key *);
void	ieee80211_crypto_delglobalkeys(struct ieee80211vap *);
void	ieee80211_crypto_reload_keys(struct ieee80211com *);

/*
 * Template for a supported cipher.  Ciphers register with the
 * crypto code and are typically loaded as separate modules
 * (the null cipher is always present).
 * XXX may need refcnts
 */
struct ieee80211_cipher {
	const char *ic_name;		/* printable name */
	u_int	ic_cipher;		/* IEEE80211_CIPHER_* */
	u_int	ic_header;		/* size of privacy header (bytes) */
	u_int	ic_trailer;		/* size of privacy trailer (bytes) */
	u_int	ic_miclen;		/* size of mic trailer (bytes) */
	void*	(*ic_attach)(struct ieee80211vap *, struct ieee80211_key *);
	void	(*ic_detach)(struct ieee80211_key *);
	int	(*ic_setkey)(struct ieee80211_key *);
	int	(*ic_encap)(struct ieee80211_key *, struct mbuf *,
			uint8_t keyid);
	int	(*ic_decap)(struct ieee80211_key *, struct mbuf *, int);
	int	(*ic_enmic)(struct ieee80211_key *, struct mbuf *, int);
	int	(*ic_demic)(struct ieee80211_key *, struct mbuf *, int);
};
extern	const struct ieee80211_cipher ieee80211_cipher_none;

#define	IEEE80211_KEY_UNDEFINED(k) \
	((k)->wk_cipher == &ieee80211_cipher_none)

void	ieee80211_crypto_register(const struct ieee80211_cipher *);
void	ieee80211_crypto_unregister(const struct ieee80211_cipher *);
int	ieee80211_crypto_available(u_int cipher);

struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
		struct mbuf *);
struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
		struct mbuf *, int);

/*
 * Check and remove any MIC.
 */
static __inline int
ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
	struct mbuf *m, int force)
{
	const struct ieee80211_cipher *cip = k->wk_cipher;
	return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1);
}

/*
 * Add any MIC.
 */
static __inline int
ieee80211_crypto_enmic(struct ieee80211vap *vap,
	struct ieee80211_key *k, struct mbuf *m, int force)
{
	const struct ieee80211_cipher *cip = k->wk_cipher;
	return (cip->ic_miclen > 0 ? cip->ic_enmic(k, m, force) : 1);
}

/*
 * Reset key state to an unused state.  The crypto
 * key allocation mechanism insures other state (e.g.
 * key data) is properly setup before a key is used.
 */
static __inline void
ieee80211_crypto_resetkey(struct ieee80211vap *vap,
	struct ieee80211_key *k, ieee80211_keyix ix)
{
	k->wk_cipher = &ieee80211_cipher_none;
	k->wk_private = k->wk_cipher->ic_attach(vap, k);
	k->wk_keyix = k->wk_rxkeyix = ix;
	k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
}

/*
 * Crypt-related notification methods.
 */
void	ieee80211_notify_replay_failure(struct ieee80211vap *,
		const struct ieee80211_frame *, const struct ieee80211_key *,
		uint64_t rsc, int tid);
void	ieee80211_notify_michael_failure(struct ieee80211vap *,
		const struct ieee80211_frame *, u_int keyix);
#endif /* defined(__KERNEL__) || defined(_KERNEL) */
#endif /* _NET80211_IEEE80211_CRYPTO_H_ */


code:
/*-
 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_dfs.h 186107 2008-12-15 01:26:33Z sam $
 */
#ifndef _NET80211_IEEE80211_DFS_H_
#define _NET80211_IEEE80211_DFS_H_

/*
 * 802.11h/DFS definitions.
 */

struct ieee80211_dfs_state {
	int		nol_event[IEEE80211_CHAN_MAX];
	struct callout	nol_timer;		/* NOL list processing */
	struct callout	cac_timer;		/* CAC timer */
	struct timeval	lastevent;		/* time of last radar event */
	int		cureps;			/* current events/second */
	const struct ieee80211_channel *lastchan;/* chan w/ last radar event */
	struct ieee80211_channel *newchan;	/* chan selected next */
};

void	ieee80211_dfs_attach(struct ieee80211com *);
void	ieee80211_dfs_detach(struct ieee80211com *);

void	ieee80211_dfs_reset(struct ieee80211com *);

void	ieee80211_dfs_cac_start(struct ieee80211vap *);
void	ieee80211_dfs_cac_stop(struct ieee80211vap *);
void	ieee80211_dfs_cac_clear(struct ieee80211com *,
		const struct ieee80211_channel *);

void	ieee80211_dfs_notify_radar(struct ieee80211com *,
		struct ieee80211_channel *);
struct ieee80211_channel *ieee80211_dfs_pickchannel(struct ieee80211com *);
#endif /* _NET80211_IEEE80211_DFS_H_ */


code:
/*-
 * Copyright (c) 2003-2008 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_freebsd.h 206617 2010-04-14 18:29:40Z rpaulo $
 */
#ifndef _NET80211_IEEE80211_FREEBSD_H_
#define _NET80211_IEEE80211_FREEBSD_H_

#ifdef _KERNEL
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>

/*
 * Common state locking definitions.
 */
typedef struct {
	char		name[16];		/* e.g. "ath0_com_lock" */
	struct mtx	mtx;
} ieee80211_com_lock_t;
#define	IEEE80211_LOCK_INIT(_ic, _name) do {				\
	ieee80211_com_lock_t *cl = &(_ic)->ic_comlock;			\
	snprintf(cl->name, sizeof(cl->name), "%s_com_lock", _name);	\
	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF | MTX_RECURSE);	\
} while (0)
#define	IEEE80211_LOCK_OBJ(_ic)	(&(_ic)->ic_comlock.mtx)
#define	IEEE80211_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_LOCK_OBJ(_ic))
#define	IEEE80211_LOCK(_ic)	   mtx_lock(IEEE80211_LOCK_OBJ(_ic))
#define	IEEE80211_UNLOCK(_ic)	   mtx_unlock(IEEE80211_LOCK_OBJ(_ic))
#define	IEEE80211_LOCK_ASSERT(_ic) \
	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_OWNED)

/*
 * Node locking definitions.
 */
typedef struct {
	char		name[16];		/* e.g. "ath0_node_lock" */
	struct mtx	mtx;
} ieee80211_node_lock_t;
#define	IEEE80211_NODE_LOCK_INIT(_nt, _name) do {			\
	ieee80211_node_lock_t *nl = &(_nt)->nt_nodelock;		\
	snprintf(nl->name, sizeof(nl->name), "%s_node_lock", _name);	\
	mtx_init(&nl->mtx, nl->name, NULL, MTX_DEF | MTX_RECURSE);	\
} while (0)
#define	IEEE80211_NODE_LOCK_OBJ(_nt)	(&(_nt)->nt_nodelock.mtx)
#define	IEEE80211_NODE_LOCK_DESTROY(_nt) \
	mtx_destroy(IEEE80211_NODE_LOCK_OBJ(_nt))
#define	IEEE80211_NODE_LOCK(_nt) \
	mtx_lock(IEEE80211_NODE_LOCK_OBJ(_nt))
#define	IEEE80211_NODE_IS_LOCKED(_nt) \
	mtx_owned(IEEE80211_NODE_LOCK_OBJ(_nt))
#define	IEEE80211_NODE_UNLOCK(_nt) \
	mtx_unlock(IEEE80211_NODE_LOCK_OBJ(_nt))
#define	IEEE80211_NODE_LOCK_ASSERT(_nt)	\
	mtx_assert(IEEE80211_NODE_LOCK_OBJ(_nt), MA_OWNED)

/*
 * Node table iteration locking definitions; this protects the
 * scan generation # used to iterate over the station table
 * while grabbing+releasing the node lock.
 */
typedef struct {
	char		name[16];		/* e.g. "ath0_scan_lock" */
	struct mtx	mtx;
} ieee80211_scan_lock_t;
#define	IEEE80211_NODE_ITERATE_LOCK_INIT(_nt, _name) do {		\
	ieee80211_scan_lock_t *sl = &(_nt)->nt_scanlock;		\
	snprintf(sl->name, sizeof(sl->name), "%s_scan_lock", _name);	\
	mtx_init(&sl->mtx, sl->name, NULL, MTX_DEF);			\
} while (0)
#define	IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt)	(&(_nt)->nt_scanlock.mtx)
#define	IEEE80211_NODE_ITERATE_LOCK_DESTROY(_nt) \
	mtx_destroy(IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt))
#define	IEEE80211_NODE_ITERATE_LOCK(_nt) \
	mtx_lock(IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt))
#define	IEEE80211_NODE_ITERATE_UNLOCK(_nt) \
	mtx_unlock(IEEE80211_NODE_ITERATE_LOCK_OBJ(_nt))

/*
 * Power-save queue definitions.
 */
typedef struct mtx ieee80211_psq_lock_t;
#define	IEEE80211_PSQ_INIT(_psq, _name) \
	mtx_init(&(_psq)->psq_lock, _name, "802.11 ps q", MTX_DEF)
#define	IEEE80211_PSQ_DESTROY(_psq)	mtx_destroy(&(_psq)->psq_lock)
#define	IEEE80211_PSQ_LOCK(_psq)	mtx_lock(&(_psq)->psq_lock)
#define	IEEE80211_PSQ_UNLOCK(_psq)	mtx_unlock(&(_psq)->psq_lock)

#ifndef IF_PREPEND_LIST
#define _IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do {	\
	(mtail)->m_nextpkt = (ifq)->ifq_head;			\
	if ((ifq)->ifq_tail == NULL)				\
		(ifq)->ifq_tail = (mtail);			\
	(ifq)->ifq_head = (mhead);				\
	(ifq)->ifq_len += (mcount);				\
} while (0)
#define IF_PREPEND_LIST(ifq, mhead, mtail, mcount) do {		\
	IF_LOCK(ifq);						\
	_IF_PREPEND_LIST(ifq, mhead, mtail, mcount);		\
	IF_UNLOCK(ifq);						\
} while (0)
#endif /* IF_PREPEND_LIST */

/*
 * Age queue definitions.
 */
typedef struct mtx ieee80211_ageq_lock_t;
#define	IEEE80211_AGEQ_INIT(_aq, _name) \
	mtx_init(&(_aq)->aq_lock, _name, "802.11 age q", MTX_DEF)
#define	IEEE80211_AGEQ_DESTROY(_aq)	mtx_destroy(&(_aq)->aq_lock)
#define	IEEE80211_AGEQ_LOCK(_aq)	mtx_lock(&(_aq)->aq_lock)
#define	IEEE80211_AGEQ_UNLOCK(_aq)	mtx_unlock(&(_aq)->aq_lock)

/*
 * 802.1x MAC ACL database locking definitions.
 */
typedef struct mtx acl_lock_t;
#define	ACL_LOCK_INIT(_as, _name) \
	mtx_init(&(_as)->as_lock, _name, "802.11 ACL", MTX_DEF)
#define	ACL_LOCK_DESTROY(_as)		mtx_destroy(&(_as)->as_lock)
#define	ACL_LOCK(_as)			mtx_lock(&(_as)->as_lock)
#define	ACL_UNLOCK(_as)			mtx_unlock(&(_as)->as_lock)
#define	ACL_LOCK_ASSERT(_as) \
	mtx_assert((&(_as)->as_lock), MA_OWNED)

/*
 * Scan table definitions.
 */
typedef struct mtx ieee80211_scan_table_lock_t;
#define	IEEE80211_SCAN_TABLE_LOCK_INIT(_st, _name) \
	mtx_init(&(_st)->st_lock, _name, "802.11 scan table", MTX_DEF)
#define	IEEE80211_SCAN_TABLE_LOCK_DESTROY(_st)	mtx_destroy(&(_st)->st_lock)
#define	IEEE80211_SCAN_TABLE_LOCK(_st)		mtx_lock(&(_st)->st_lock)
#define	IEEE80211_SCAN_TABLE_UNLOCK(_st)	mtx_unlock(&(_st)->st_lock)

/*
 * Node reference counting definitions.
 *
 * ieee80211_node_initref	initialize the reference count to 1
 * ieee80211_node_incref	add a reference
 * ieee80211_node_decref	remove a reference
 * ieee80211_node_dectestref	remove a reference and return 1 if this
 *				is the last reference, otherwise 0
 * ieee80211_node_refcnt	reference count for printing (only)
 */
#include <machine/atomic.h>

#define ieee80211_node_initref(_ni) \
	do { ((_ni)->ni_refcnt = 1); } while (0)
#define ieee80211_node_incref(_ni) \
	atomic_add_int(&(_ni)->ni_refcnt, 1)
#define	ieee80211_node_decref(_ni) \
	atomic_subtract_int(&(_ni)->ni_refcnt, 1)
struct ieee80211_node;
int	ieee80211_node_dectestref(struct ieee80211_node *ni);
#define	ieee80211_node_refcnt(_ni)	(_ni)->ni_refcnt

struct ifqueue;
struct ieee80211vap;
void	ieee80211_drain_ifq(struct ifqueue *);
void	ieee80211_flush_ifq(struct ifqueue *, struct ieee80211vap *);

void	ieee80211_vap_destroy(struct ieee80211vap *);

#define	IFNET_IS_UP_RUNNING(_ifp) \
	(((_ifp)->if_flags & IFF_UP) && \
	 ((_ifp)->if_drv_flags & IFF_DRV_RUNNING))

#define	msecs_to_ticks(ms)	(((ms)*hz)/1000)
#define	ticks_to_msecs(t)	(1000*(t) / hz)
#define	ticks_to_secs(t)	((t) / hz)
#define time_after(a,b) 	((long)(b) - (long)(a) < 0)
#define time_before(a,b)	time_after(b,a)
#define time_after_eq(a,b)	((long)(a) - (long)(b) >= 0)
#define time_before_eq(a,b)	time_after_eq(b,a)

struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);

/* tx path usage */
#define	M_ENCAP		M_PROTO1		/* 802.11 encap done */
#define	M_EAPOL		M_PROTO3		/* PAE/EAPOL frame */
#define	M_PWR_SAV	M_PROTO4		/* bypass PS handling */
#define	M_MORE_DATA	M_PROTO5		/* more data frames to follow */
#define	M_FF		M_PROTO6		/* fast frame */
#define	M_TXCB		M_PROTO7		/* do tx complete callback */
#define	M_AMPDU_MPDU	M_PROTO8		/* ok for A-MPDU aggregation */
#define	M_80211_TX \
	(M_FRAG|M_FIRSTFRAG|M_LASTFRAG|M_ENCAP|M_EAPOL|M_PWR_SAV|\
	 M_MORE_DATA|M_FF|M_TXCB|M_AMPDU_MPDU)

/* rx path usage */
#define	M_AMPDU		M_PROTO1		/* A-MPDU subframe */
#define	M_WEP		M_PROTO2		/* WEP done by hardware */
#if 0
#define	M_AMPDU_MPDU	M_PROTO8		/* A-MPDU re-order done */
#endif
#define	M_80211_RX	(M_AMPDU|M_WEP|M_AMPDU_MPDU)

#define	IEEE80211_MBUF_TX_FLAG_BITS \
	"\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_RDONLY\5M_ENCAP\6M_WEP\7M_EAPOL" \
	"\10M_PWR_SAV\11M_MORE_DATA\12M_BCAST\13M_MCAST\14M_FRAG\15M_FIRSTFRAG" \
	"\16M_LASTFRAG\17M_SKIP_FIREWALL\20M_FREELIST\21M_VLANTAG\22M_PROMISC" \
	"\23M_NOFREE\24M_FF\25M_TXCB\26M_AMPDU_MPDU\27M_FLOWID"

#define	IEEE80211_MBUF_RX_FLAG_BITS \
	"\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_RDONLY\5M_AMPDU\6M_WEP\7M_PROTO3" \
	"\10M_PROTO4\11M_PROTO5\12M_BCAST\13M_MCAST\14M_FRAG\15M_FIRSTFRAG" \
	"\16M_LASTFRAG\17M_SKIP_FIREWALL\20M_FREELIST\21M_VLANTAG\22M_PROMISC" \
	"\23M_NOFREE\24M_PROTO6\25M_PROTO7\26M_AMPDU_MPDU\27M_FLOWID"

/*
 * Store WME access control bits in the vlan tag.
 * This is safe since it's done after the packet is classified
 * (where we use any previous tag) and because it's passed
 * directly in to the driver and there's no chance someone
 * else will clobber them on us.
 */
#define	M_WME_SETAC(m, ac) \
	((m)->m_pkthdr.ether_vtag = (ac))
#define	M_WME_GETAC(m)	((m)->m_pkthdr.ether_vtag)

/*
 * Mbufs on the power save queue are tagged with an age and
 * timed out.  We reuse the hardware checksum field in the
 * mbuf packet header to store this data.
 */
#define	M_AGE_SET(m,v)		(m->m_pkthdr.csum_data = v)
#define	M_AGE_GET(m)		(m->m_pkthdr.csum_data)
#define	M_AGE_SUB(m,adj)	(m->m_pkthdr.csum_data -= adj)

/*
 * Store the sequence number.
 */
#define	M_SEQNO_SET(m, seqno) \
	((m)->m_pkthdr.tso_segsz = (seqno))
#define	M_SEQNO_GET(m)	((m)->m_pkthdr.tso_segsz)

#define	MTAG_ABI_NET80211	1132948340	/* net80211 ABI */

struct ieee80211_cb {
	void	(*func)(struct ieee80211_node *, void *, int status);
	void	*arg;
};
#define	NET80211_TAG_CALLBACK	0	/* xmit complete callback */
int	ieee80211_add_callback(struct mbuf *m,
		void (*func)(struct ieee80211_node *, void *, int), void *arg);
void	ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int);

void	get_random_bytes(void *, size_t);

struct ieee80211com;

void	ieee80211_sysctl_attach(struct ieee80211com *);
void	ieee80211_sysctl_detach(struct ieee80211com *);
void	ieee80211_sysctl_vattach(struct ieee80211vap *);
void	ieee80211_sysctl_vdetach(struct ieee80211vap *);

SYSCTL_DECL(_net_wlan);
int	ieee80211_sysctl_msecs_ticks(SYSCTL_HANDLER_ARGS);

void	ieee80211_load_module(const char *);

/*
 * A "policy module" is an adjunct module to net80211 that provides
 * functionality that typically includes policy decisions.  This
 * modularity enables extensibility and vendor-supplied functionality.
 */
#define	_IEEE80211_POLICY_MODULE(policy, name, version)			\
typedef void (*policy##_setup)(int);					\
SET_DECLARE(policy##_set, policy##_setup);				\
static int								\
wlan_##name##_modevent(module_t mod, int type, void *unused)		\
{									\
	policy##_setup * const *iter, f;				\
	switch (type) {							\
	case MOD_LOAD:							\
		SET_FOREACH(iter, policy##_set) {			\
			f = (void*) *iter;				\
			f(type);					\
		}							\
		return 0;						\
	case MOD_UNLOAD:						\
	case MOD_QUIESCE:						\
		if (nrefs) {						\
			printf("wlan_##name: still in use (%u dynamic refs)\n",\
				nrefs);					\
			return EBUSY;					\
		}							\
		if (type == MOD_UNLOAD) {				\
			SET_FOREACH(iter, policy##_set) {		\
				f = (void*) *iter;			\
				f(type);				\
			}						\
		}							\
		return 0;						\
	}								\
	return EINVAL;							\
}									\
static moduledata_t name##_mod = {					\
	"wlan_" #name,							\
	wlan_##name##_modevent,						\
	0								\
};									\
DECLARE_MODULE(wlan_##name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);\
MODULE_VERSION(wlan_##name, version);					\
MODULE_DEPEND(wlan_##name, wlan, 1, 1, 1)

/*
 * Crypto modules implement cipher support.
 */
#define	IEEE80211_CRYPTO_MODULE(name, version)				\
_IEEE80211_POLICY_MODULE(crypto, name, version);			\
static void								\
name##_modevent(int type)						\
{									\
	if (type == MOD_LOAD)						\
		ieee80211_crypto_register(&name);			\
	else								\
		ieee80211_crypto_unregister(&name);			\
}									\
TEXT_SET(crypto##_set, name##_modevent)

/*
 * Scanner modules provide scanning policy.
 */
#define	IEEE80211_SCANNER_MODULE(name, version)				\
	_IEEE80211_POLICY_MODULE(scanner, name, version)

#define	IEEE80211_SCANNER_ALG(name, alg, v)				\
static void								\
name##_modevent(int type)						\
{									\
	if (type == MOD_LOAD)						\
		ieee80211_scanner_register(alg, &v);			\
	else								\
		ieee80211_scanner_unregister(alg, &v);			\
}									\
TEXT_SET(scanner_set, name##_modevent);					\

/*
 * ACL modules implement acl policy.
 */
#define	IEEE80211_ACL_MODULE(name, alg, version)			\
_IEEE80211_POLICY_MODULE(acl, name, version);				\
static void								\
alg##_modevent(int type)						\
{									\
	if (type == MOD_LOAD)						\
		ieee80211_aclator_register(&alg);			\
	else								\
		ieee80211_aclator_unregister(&alg);			\
}									\
TEXT_SET(acl_set, alg##_modevent);					\

/*
 * Authenticator modules handle 802.1x/WPA authentication.
 */
#define	IEEE80211_AUTH_MODULE(name, version)				\
	_IEEE80211_POLICY_MODULE(auth, name, version)

#define	IEEE80211_AUTH_ALG(name, alg, v)				\
static void								\
name##_modevent(int type)						\
{									\
	if (type == MOD_LOAD)						\
		ieee80211_authenticator_register(alg, &v);		\
	else								\
		ieee80211_authenticator_unregister(alg);		\
}									\
TEXT_SET(auth_set, name##_modevent)

/*
 * Rate control modules provide tx rate control support.
 */
#define	IEEE80211_RATECTL_MODULE(alg, version)				\
	_IEEE80211_POLICY_MODULE(ratectl, alg, version);		\

#define	IEEE80211_RATECTL_ALG(name, alg, v)				\
static void								\
alg##_modevent(int type)						\
{									\
	if (type == MOD_LOAD)						\
		ieee80211_ratectl_register(alg, &v);			\
	else								\
		ieee80211_ratectl_unregister(alg);			\
}									\
TEXT_SET(ratectl##_set, alg##_modevent)

struct ieee80211req;
typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *,
    struct ieee80211req *);
SET_DECLARE(ieee80211_ioctl_getset, ieee80211_ioctl_getfunc);
#define	IEEE80211_IOCTL_GET(_name, _get) TEXT_SET(ieee80211_ioctl_getset, _get)

typedef int ieee80211_ioctl_setfunc(struct ieee80211vap *,
    struct ieee80211req *);
SET_DECLARE(ieee80211_ioctl_setset, ieee80211_ioctl_setfunc);
#define	IEEE80211_IOCTL_SET(_name, _set) TEXT_SET(ieee80211_ioctl_setset, _set)
#endif /* _KERNEL */

/* XXX this stuff belongs elsewhere */
/*
 * Message formats for messages from the net80211 layer to user
 * applications via the routing socket.  These messages are appended
 * to an if_announcemsghdr structure.
 */
struct ieee80211_join_event {
	uint8_t		iev_addr[6];
};

struct ieee80211_leave_event {
	uint8_t		iev_addr[6];
};

struct ieee80211_replay_event {
	uint8_t		iev_src[6];	/* src MAC */
	uint8_t		iev_dst[6];	/* dst MAC */
	uint8_t		iev_cipher;	/* cipher type */
	uint8_t		iev_keyix;	/* key id/index */
	uint64_t	iev_keyrsc;	/* RSC from key */
	uint64_t	iev_rsc;	/* RSC from frame */
};

struct ieee80211_michael_event {
	uint8_t		iev_src[6];	/* src MAC */
	uint8_t		iev_dst[6];	/* dst MAC */
	uint8_t		iev_cipher;	/* cipher type */
	uint8_t		iev_keyix;	/* key id/index */
};

struct ieee80211_wds_event {
	uint8_t		iev_addr[6];
};

struct ieee80211_csa_event {
	uint32_t	iev_flags;	/* channel flags */
	uint16_t	iev_freq;	/* setting in Mhz */
	uint8_t		iev_ieee;	/* IEEE channel number */
	uint8_t		iev_mode;	/* CSA mode */
	uint8_t		iev_count;	/* CSA count */
};

struct ieee80211_cac_event {
	uint32_t	iev_flags;	/* channel flags */
	uint16_t	iev_freq;	/* setting in Mhz */
	uint8_t		iev_ieee;	/* IEEE channel number */
	/* XXX timestamp? */
	uint8_t		iev_type;	/* IEEE80211_NOTIFY_CAC_* */
};

struct ieee80211_radar_event {
	uint32_t	iev_flags;	/* channel flags */
	uint16_t	iev_freq;	/* setting in Mhz */
	uint8_t		iev_ieee;	/* IEEE channel number */
	/* XXX timestamp? */
};

struct ieee80211_auth_event {
	uint8_t		iev_addr[6];
};

struct ieee80211_deauth_event {
	uint8_t		iev_addr[6];
};

struct ieee80211_country_event {
	uint8_t		iev_addr[6];
	uint8_t		iev_cc[2];	/* ISO country code */
};

struct ieee80211_radio_event {
	uint8_t		iev_state;	/* 1 on, 0 off */
};

#define	RTM_IEEE80211_ASSOC	100	/* station associate (bss mode) */
#define	RTM_IEEE80211_REASSOC	101	/* station re-associate (bss mode) */
#define	RTM_IEEE80211_DISASSOC	102	/* station disassociate (bss mode) */
#define	RTM_IEEE80211_JOIN	103	/* station join (ap mode) */
#define	RTM_IEEE80211_LEAVE	104	/* station leave (ap mode) */
#define	RTM_IEEE80211_SCAN	105	/* scan complete, results available */
#define	RTM_IEEE80211_REPLAY	106	/* sequence counter replay detected */
#define	RTM_IEEE80211_MICHAEL	107	/* Michael MIC failure detected */
#define	RTM_IEEE80211_REJOIN	108	/* station re-associate (ap mode) */
#define	RTM_IEEE80211_WDS	109	/* WDS discovery (ap mode) */
#define	RTM_IEEE80211_CSA	110	/* Channel Switch Announcement event */
#define	RTM_IEEE80211_RADAR	111	/* radar event */
#define	RTM_IEEE80211_CAC	112	/* Channel Availability Check event */
#define	RTM_IEEE80211_DEAUTH	113	/* station deauthenticate */
#define	RTM_IEEE80211_AUTH	114	/* station authenticate (ap mode) */
#define	RTM_IEEE80211_COUNTRY	115	/* discovered country code (sta mode) */
#define	RTM_IEEE80211_RADIO	116	/* RF kill switch state change */

/*
 * Structure prepended to raw packets sent through the bpf
 * interface when set to DLT_IEEE802_11_RADIO.  This allows
 * user applications to specify pretty much everything in
 * an Atheros tx descriptor.  XXX need to generalize.
 *
 * XXX cannot be more than 14 bytes as it is copied to a sockaddr's
 * XXX sa_data area.
 */
struct ieee80211_bpf_params {
	uint8_t		ibp_vers;	/* version */
#define	IEEE80211_BPF_VERSION	0
	uint8_t		ibp_len;	/* header length in bytes */
	uint8_t		ibp_flags;
#define	IEEE80211_BPF_SHORTPRE	0x01	/* tx with short preamble */
#define	IEEE80211_BPF_NOACK	0x02	/* tx with no ack */
#define	IEEE80211_BPF_CRYPTO	0x04	/* tx with h/w encryption */
#define	IEEE80211_BPF_FCS	0x10	/* frame incldues FCS */
#define	IEEE80211_BPF_DATAPAD	0x20	/* frame includes data padding */
#define	IEEE80211_BPF_RTS	0x40	/* tx with RTS/CTS */
#define	IEEE80211_BPF_CTS	0x80	/* tx with CTS only */
	uint8_t		ibp_pri;	/* WME/WMM AC+tx antenna */
	uint8_t		ibp_try0;	/* series 1 try count */
	uint8_t		ibp_rate0;	/* series 1 IEEE tx rate */
	uint8_t		ibp_power;	/* tx power (device units) */
	uint8_t		ibp_ctsrate;	/* IEEE tx rate for CTS */
	uint8_t		ibp_try1;	/* series 2 try count */
	uint8_t		ibp_rate1;	/* series 2 IEEE tx rate */
	uint8_t		ibp_try2;	/* series 3 try count */
	uint8_t		ibp_rate2;	/* series 3 IEEE tx rate */
	uint8_t		ibp_try3;	/* series 4 try count */
	uint8_t		ibp_rate3;	/* series 4 IEEE tx rate */
};
#endif /* _NET80211_IEEE80211_FREEBSD_H_ */


code:
/*-
 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_hostap.h 178354 2008-04-20 20:35:46Z sam $
 */
#ifndef _NET80211_IEEE80211_HOSTAP_H_
#define _NET80211_IEEE80211_HOSTAP_H_

/*
 * Hostap implementation definitions.
 */
void	ieee80211_hostap_attach(struct ieee80211com *);
void	ieee80211_hostap_detach(struct ieee80211com *);
#endif /* !_NET80211_IEEE80211_HOSTAP_H_ */


code:
/*-
 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_ht.h 219456 2011-03-10 18:17:24Z bschmidt $
 */
#ifndef _NET80211_IEEE80211_HT_H_
#define _NET80211_IEEE80211_HT_H_

/*
 * 802.11n protocol implementation definitions.
 */

#define	IEEE80211_AGGR_BAWMAX	64	/* max block ack window size */
/* threshold for aging overlapping non-HT bss */
#define	IEEE80211_NONHT_PRESENT_AGE	msecs_to_ticks(60*1000)

struct ieee80211_tx_ampdu {
	struct ieee80211_node *txa_ni;	/* back pointer */
	u_short		txa_flags;
#define	IEEE80211_AGGR_IMMEDIATE	0x0001	/* BA policy */
#define	IEEE80211_AGGR_XCHGPEND		0x0002	/* ADDBA response pending */
#define	IEEE80211_AGGR_RUNNING		0x0004	/* ADDBA response received */
#define	IEEE80211_AGGR_SETUP		0x0008	/* deferred state setup */
#define	IEEE80211_AGGR_NAK		0x0010	/* peer NAK'd ADDBA request */
#define	IEEE80211_AGGR_BARPEND		0x0020	/* BAR response pending */
	uint8_t		txa_ac;
	uint8_t		txa_token;	/* dialog token */
	int		txa_lastsample;	/* ticks @ last traffic sample */
	int		txa_pkts;	/* packets over last sample interval */
	int		txa_avgpps;	/* filtered traffic over window */
	int		txa_qbytes;	/* data queued (bytes) */
	short		txa_qframes;	/* data queued (frames) */
	ieee80211_seq	txa_start;	/* BA window left edge */
	ieee80211_seq	txa_seqpending;	/* new txa_start pending BAR response */
	uint16_t	txa_wnd;	/* BA window size */
	uint8_t		txa_attempts;	/* # ADDBA/BAR requests w/o a response*/
	int		txa_nextrequest;/* soonest to make next request */
	struct callout	txa_timer;
	void		*txa_private;	/* driver-private storage */
	uint64_t	txa_pad[4];
};

/* return non-zero if AMPDU tx for the TID is running */
#define	IEEE80211_AMPDU_RUNNING(tap) \
	(((tap)->txa_flags & IEEE80211_AGGR_RUNNING) != 0)

/* return non-zero if AMPDU tx for the TID is running or started */
#define	IEEE80211_AMPDU_REQUESTED(tap) \
	(((tap)->txa_flags & \
	 (IEEE80211_AGGR_RUNNING|IEEE80211_AGGR_XCHGPEND|IEEE80211_AGGR_NAK)) != 0)

#define	IEEE80211_AGGR_BITS \
	"\20\1IMMEDIATE\2XCHGPEND\3RUNNING\4SETUP\5NAK"

/*
 * Traffic estimator support.  We estimate packets/sec for
 * each AC that is setup for AMPDU or will potentially be
 * setup for AMPDU.  The traffic rate can be used to decide
 * when AMPDU should be setup (according to a threshold)
 * and is available for drivers to do things like cache
 * eviction when only a limited number of BA streams are
 * available and more streams are requested than available.
 */

static __inline void
ieee80211_txampdu_update_pps(struct ieee80211_tx_ampdu *tap)
{
	/* NB: scale factor of 2 was picked heuristically */
	tap->txa_avgpps = ((tap->txa_avgpps << 2) -
	     tap->txa_avgpps + tap->txa_pkts) >> 2;
}

/*
 * Count a packet towards the pps estimate.
 */
static __inline void
ieee80211_txampdu_count_packet(struct ieee80211_tx_ampdu *tap)
{
	/* XXX bound loop/do more crude estimate? */
	while (ticks - tap->txa_lastsample >= hz) {
		ieee80211_txampdu_update_pps(tap);
		/* reset to start new sample interval */
		tap->txa_pkts = 0;
		if (tap->txa_avgpps == 0) {
			tap->txa_lastsample = ticks;
			break;
		}
		tap->txa_lastsample += hz;
	}
	tap->txa_pkts++;
}

/*
 * Get the current pps estimate.  If the average is out of
 * date due to lack of traffic then we decay the estimate
 * to account for the idle time.
 */
static __inline int
ieee80211_txampdu_getpps(struct ieee80211_tx_ampdu *tap)
{
	/* XXX bound loop/do more crude estimate? */
	while (ticks - tap->txa_lastsample >= hz) {
		ieee80211_txampdu_update_pps(tap);
		tap->txa_pkts = 0;
		if (tap->txa_avgpps == 0) {
			tap->txa_lastsample = ticks;
			break;
		}
		tap->txa_lastsample += hz;
	}
	return tap->txa_avgpps;
}

struct ieee80211_rx_ampdu {
	int		rxa_flags;
	int		rxa_qbytes;	/* data queued (bytes) */
	short		rxa_qframes;	/* data queued (frames) */
	ieee80211_seq	rxa_seqstart;
	ieee80211_seq	rxa_start;	/* start of current BA window */
	uint16_t	rxa_wnd;	/* BA window size */
	int		rxa_age;	/* age of oldest frame in window */
	int		rxa_nframes;	/* frames since ADDBA */
	struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX];
	void		*rxa_private;
	uint64_t	rxa_pad[3];
};

void	ieee80211_ht_attach(struct ieee80211com *);
void	ieee80211_ht_detach(struct ieee80211com *);
void	ieee80211_ht_vattach(struct ieee80211vap *);
void	ieee80211_ht_vdetach(struct ieee80211vap *);

void	ieee80211_ht_announce(struct ieee80211com *);

struct ieee80211_mcs_rates {
	uint16_t	ht20_rate_800ns;
	uint16_t	ht20_rate_400ns;
	uint16_t	ht40_rate_800ns;
	uint16_t	ht40_rate_400ns;
};
extern const struct ieee80211_mcs_rates ieee80211_htrates[];
const struct ieee80211_htrateset *ieee80211_get_suphtrates(
		struct ieee80211com *, const struct ieee80211_channel *);

struct ieee80211_node;
int	ieee80211_setup_htrates(struct ieee80211_node *,
		const uint8_t *htcap, int flags);
void	ieee80211_setup_basic_htrates(struct ieee80211_node *,
		const uint8_t *htinfo);
struct mbuf *ieee80211_decap_amsdu(struct ieee80211_node *, struct mbuf *);
int	ieee80211_ampdu_reorder(struct ieee80211_node *, struct mbuf *);
void	ieee80211_recv_bar(struct ieee80211_node *, struct mbuf *);
void	ieee80211_ht_node_init(struct ieee80211_node *);
void	ieee80211_ht_node_cleanup(struct ieee80211_node *);
void	ieee80211_ht_node_age(struct ieee80211_node *);

struct ieee80211_channel *ieee80211_ht_adjust_channel(struct ieee80211com *,
		struct ieee80211_channel *, int);
void	ieee80211_ht_wds_init(struct ieee80211_node *);
void	ieee80211_ht_node_join(struct ieee80211_node *);
void	ieee80211_ht_node_leave(struct ieee80211_node *);
void	ieee80211_htprot_update(struct ieee80211com *, int protmode);
void	ieee80211_ht_timeout(struct ieee80211com *);
void	ieee80211_parse_htcap(struct ieee80211_node *, const uint8_t *);
void	ieee80211_parse_htinfo(struct ieee80211_node *, const uint8_t *);
void	ieee80211_ht_updateparams(struct ieee80211_node *, const uint8_t *,
		const uint8_t *);
void	ieee80211_ht_updatehtcap(struct ieee80211_node *, const uint8_t *);
int	ieee80211_ampdu_request(struct ieee80211_node *,
		struct ieee80211_tx_ampdu *);
void	ieee80211_ampdu_stop(struct ieee80211_node *,
		struct ieee80211_tx_ampdu *, int);
int	ieee80211_send_bar(struct ieee80211_node *, struct ieee80211_tx_ampdu *,
		ieee80211_seq);
uint8_t	*ieee80211_add_htcap(uint8_t *, struct ieee80211_node *);
uint8_t	*ieee80211_add_htcap_vendor(uint8_t *, struct ieee80211_node *);
uint8_t	*ieee80211_add_htinfo(uint8_t *, struct ieee80211_node *);
uint8_t	*ieee80211_add_htinfo_vendor(uint8_t *, struct ieee80211_node *);
struct ieee80211_beacon_offsets;
void	ieee80211_ht_update_beacon(struct ieee80211vap *,
		struct ieee80211_beacon_offsets *);
#endif /* _NET80211_IEEE80211_HT_H_ */


code:
/*-
 * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/net80211/ieee80211_input.h 221418 2011-05-04 02:23:59Z adrian $
 */
#ifndef _NET80211_IEEE80211_INPUT_H_
#define _NET80211_IEEE80211_INPUT_H_

/* Verify the existence and length of __elem or get out. */
#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen, _action) do {	\
	if ((__elem) == NULL) {						\
		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\
		    wh, NULL, "%s", "no " #__elem );			\
		vap->iv_stats.is_rx_elem_missing++;			\
		_action;						\
	} else if ((__elem)[1] > (__maxlen)) {				\
		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\
		    wh, NULL, "bad " #__elem " len %d", (__elem)[1]);	\
		vap->iv_stats.is_rx_elem_toobig++;			\
		_action;						\
	}								\
} while (0)

#define	IEEE80211_VERIFY_LENGTH(_len, _minlen, _action) do {		\
	if ((_len) < (_minlen)) {					\
		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\
		    wh, NULL, "ie too short, got %d, expected %d",	\
		    (_len), (_minlen));					\
		vap->iv_stats.is_rx_elem_toosmall++;			\
		_action;						\
	}								\
} while (0)

#ifdef IEEE80211_DEBUG
void	ieee80211_ssid_mismatch(struct ieee80211vap *, const char *tag,
	uint8_t mac[IEEE80211_ADDR_LEN], uint8_t *ssid);

#define	IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do {			\
	if ((_ssid)[1] != 0 &&						\
	    ((_ssid)[1] != (_ni)->ni_esslen ||				\
	    memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {	\
		if (ieee80211_msg_input(vap))				\
			ieee80211_ssid_mismatch(vap, 			\
			    ieee80211_mgt_subtype_name[subtype >>	\
				IEEE80211_FC0_SUBTYPE_SHIFT],		\
				wh->i_addr2, _ssid);			\
		vap->iv_stats.is_rx_ssidmismatch++;			\
		_action;						\
	}								\
} while (0)
#else /* !IEEE80211_DEBUG */
#define	IEEE80211_VERIFY_SSID(_ni, _ssid, _action) do {			\
	if ((_ssid)[1] != 0 &&						\
	    ((_ssid)[1] != (_ni)->ni_esslen ||				\
	    memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {	\
		vap->iv_stats.is_rx_ssidmismatch++;			\
		_action;						\
	}								\
} while (0)
#endif /* !IEEE80211_DEBUG */

/* unalligned little endian access */
#define LE_READ_2(p)					\
	((uint16_t)					\
	 ((((const uint8_t *)(p))[0]      ) |		\
	  (((const uint8_t *)(p))[1] <<  8)))
#define LE_READ_4(p)					\
	((uint32_t)					\
	 ((((const uint8_t *)(p))[0]      ) |		\
	  (((const uint8_t *)(p))[1] <<  8) |		\
	  (((const uint8_t *)(p))[2] << 16) |		\
	  (((const uint8_t *)(p))[3] << 24)))

static __inline int
iswpaoui(const uint8_t *frm)
{
	return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
}

static __inline int
iswmeoui(const uint8_t *frm)
{
	return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);
}

static __inline int
iswmeparam(const uint8_t *frm)
{
	return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
		frm[6] == WME_PARAM_OUI_SUBTYPE;
}

static __inline int
iswmeinfo(const uint8_t *frm)
{
	return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
		frm[6] == WME_INFO_OUI_SUBTYPE;
}

static __inline int
isatherosoui(const uint8_t *frm)
{
	return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
}

static __inline int
istdmaoui(const uint8_t *frm)
{
	return frm[1] > 3 && LE_READ_4(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI);
}

static __inline int
ishtcapoui(const uint8_t *frm)
{
	return frm[1] > 3 && LE_READ_4(frm+2) == ((BCM_OUI_HTCAP<<24)|BCM_OUI);
}

static __inline int
ishtinfooui(const uint8_t *frm)
{
	return frm[1] > 3 && LE_READ_4(frm+2) == ((BCM_OUI_HTINFO<<24)|BCM_OUI);
}

#include <sys/endian.h>		/* For le16toh() */

/*
 * Check the current frame sequence number against the current TID
 * state and return whether it's in sequence or should be dropped.
 *
 * Since out of order packet and duplicate packet eliminations should
 * be done by the AMPDU RX code, this routine blindly accepts all
 * frames from a HT station w/ a TID that is currently doing AMPDU-RX.
 * HT stations without WME or where the TID is not doing AMPDU-RX
 * are checked like non-HT stations.
 *
 * The routine only eliminates packets whose sequence/fragment
 * match or are less than the last seen sequence/fragment number
 * AND are retransmits It doesn't try to eliminate out of order packets.
 *
 * Since all frames after sequence number 4095 will be less than 4095
 * (as the seqnum wraps), handle that special case so packets aren't
 * incorrectly dropped - ie, if the next packet is sequence number 0
 * but a retransmit since the initial packet didn't make it.
 */
static __inline int
ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh)
{
#define	SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
#define	SEQ_EQ(a,b)	((int)((a)-(b)) == 0)
#define	HAS_SEQ(type)	((type & 0x4) == 0)
#define	SEQNO(a)	((a) >> IEEE80211_SEQ_SEQ_SHIFT)
#define	FRAGNO(a)	((a) & IEEE80211_SEQ_FRAG_MASK)
	uint16_t rxseq;
	uint8_t type;
	uint8_t tid;
	struct ieee80211_rx_ampdu *rap;

	rxseq = le16toh(*(uint16_t *)wh->i_seq);
	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;

	/* Types with no sequence number are always treated valid */
	if (! HAS_SEQ(type))
		return 1;

	tid = ieee80211_gettid(wh);

	/*
	 * Only do the HT AMPDU check for WME stations; non-WME HT stations
	 * shouldn't exist outside of debugging. We should at least
	 * handle that.
	 */
	if (tid < WME_NUM_TID) {
		rap = &ni->ni_rx_ampdu[tid];
		/* HT nodes currently doing RX AMPDU are always valid */
		if ((ni->ni_flags & IEEE80211_NODE_HT) &&
		    (rap->rxa_flags & IEEE80211_AGGR_RUNNING))
			return 1;
	}

	/*
	 * Otherwise, retries for packets below or equal to the last
	 * seen sequence number should be dropped.
	 */

	/*
	 * Treat frame seqnum 4095 as special due to boundary
	 * wrapping conditions.
	 */
	if (SEQNO(ni->ni_rxseqs[tid]) == 4095) {
		/*
		 * Drop retransmits on seqnum 4095/current fragment for itself.
		 */
		if (SEQ_EQ(rxseq, ni->ni_rxseqs[tid]) &&
		    (wh->i_fc[1] & IEEE80211_FC1_RETRY))
			return 0;
		/*
		 * Treat any subsequent frame as fine if the last seen frame
		 * is 4095 and it's not a retransmit for the same sequence
		 * number. However, this doesn't capture incorrectly ordered
	 	 * fragments w/ sequence number 4095. It shouldn't be seen
		 * in practice, but see the comment above for further info.
		 */
		return 1;
	}

	/*
	 * At this point we assume that retransmitted seq/frag numbers below
	 * the current can simply be eliminated.
	 */
	if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
	    SEQ_LEQ(rxseq, ni->ni_rxseqs[tid]))
		return 0;

	return 1;
#undef	SEQ_LEQ
#undef	SEQ_EQ
#undef	HAS_SEQ
#undef	SEQNO
#undef	FRAGNO
}

void	ieee80211_deliver_data(struct ieee80211vap *,
		struct ieee80211_node *, struct mbuf *);
struct mbuf *ieee80211_defrag(struct ieee80211_node *,
		struct mbuf *, int);
struct mbuf *ieee80211_realign(struct ieee80211vap *, struct mbuf *, size_t);
struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int);
struct mbuf *ieee80211_decap1(struct mbuf *, int *);
int	ieee80211_setup_rates(struct ieee80211_node *ni,
		const uint8_t *rates, const uint8_t *xrates, int flags);
void ieee80211_send_error(struct ieee80211_node *,
		const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg);
int	ieee80211_alloc_challenge(struct ieee80211_node *);
int	ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *,
		struct ieee80211_scanparams *);
int	ieee80211_parse_action(struct ieee80211_node *, struct mbuf *);
#endif /* _NET80211_IEEE80211_INPUT_H_ */