From 30cc86a45862ffdd298460a8143d0d809d570307 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Thu, 29 Aug 2013 15:30:01 -0400 Subject: [PATCH] separate supported channels into their respective bands --- ieee80211.h | 294 ++++++++++++++++++++++++++++++++++++++++++++++ iptest/iptest.cpp | 60 +++++++--- libip.pro | 2 +- wireless.cpp | 211 ++++++++++++++------------------- wireless.h | 44 +++++-- 5 files changed, 462 insertions(+), 149 deletions(-) create mode 100644 ieee80211.h diff --git a/ieee80211.h b/ieee80211.h new file mode 100644 index 0000000..5ab7937 --- /dev/null +++ b/ieee80211.h @@ -0,0 +1,294 @@ +#define FCS_LEN 4 +#define IEEE80211_FCTL_VERS 0x0003 +#define IEEE80211_FCTL_FTYPE 0x000c +#define IEEE80211_FCTL_STYPE 0x00f0 +#define IEEE80211_FCTL_TODS 0x0100 +#define IEEE80211_FCTL_FROMDS 0x0200 +#define IEEE80211_FCTL_MOREFRAGS 0x0400 +#define IEEE80211_FCTL_RETRY 0x0800 +#define IEEE80211_FCTL_PM 0x1000 +#define IEEE80211_FCTL_MOREDATA 0x2000 +#define IEEE80211_FCTL_PROTECTED 0x4000 +#define IEEE80211_FCTL_ORDER 0x8000 +#define IEEE80211_FCTL_CTL_EXT 0x0f00 +#define IEEE80211_SCTL_FRAG 0x000F +#define IEEE80211_SCTL_SEQ 0xFFF0 +#define IEEE80211_FTYPE_MGMT 0x0000 +#define IEEE80211_FTYPE_CTL 0x0004 +#define IEEE80211_FTYPE_DATA 0x0008 +#define IEEE80211_FTYPE_EXT 0x000c +#define IEEE80211_STYPE_ASSOC_REQ 0x0000 +#define IEEE80211_STYPE_ASSOC_RESP 0x0010 +#define IEEE80211_STYPE_REASSOC_REQ 0x0020 +#define IEEE80211_STYPE_REASSOC_RESP 0x0030 +#define IEEE80211_STYPE_PROBE_REQ 0x0040 +#define IEEE80211_STYPE_PROBE_RESP 0x0050 +#define IEEE80211_STYPE_BEACON 0x0080 +#define IEEE80211_STYPE_ATIM 0x0090 +#define IEEE80211_STYPE_DISASSOC 0x00A0 +#define IEEE80211_STYPE_AUTH 0x00B0 +#define IEEE80211_STYPE_DEAUTH 0x00C0 +#define IEEE80211_STYPE_ACTION 0x00D0 +#define IEEE80211_STYPE_CTL_EXT 0x0060 +#define IEEE80211_STYPE_BACK_REQ 0x0080 +#define IEEE80211_STYPE_BACK 0x0090 +#define IEEE80211_STYPE_PSPOLL 0x00A0 +#define IEEE80211_STYPE_RTS 0x00B0 +#define IEEE80211_STYPE_CTS 0x00C0 +#define IEEE80211_STYPE_ACK 0x00D0 +#define IEEE80211_STYPE_CFEND 0x00E0 +#define IEEE80211_STYPE_CFENDACK 0x00F0 +#define IEEE80211_STYPE_DATA 0x0000 +#define IEEE80211_STYPE_DATA_CFACK 0x0010 +#define IEEE80211_STYPE_DATA_CFPOLL 0x0020 +#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 +#define IEEE80211_STYPE_NULLFUNC 0x0040 +#define IEEE80211_STYPE_CFACK 0x0050 +#define IEEE80211_STYPE_CFPOLL 0x0060 +#define IEEE80211_STYPE_CFACKPOLL 0x0070 +#define IEEE80211_STYPE_QOS_DATA 0x0080 +#define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 +#define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 +#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 +#define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 +#define IEEE80211_STYPE_QOS_CFACK 0x00D0 +#define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 +#define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 +#define IEEE80211_STYPE_DMG_BEACON 0x0000 +#define IEEE80211_CTL_EXT_POLL 0x2000 +#define IEEE80211_CTL_EXT_SPR 0x3000 +#define IEEE80211_CTL_EXT_GRANT 0x4000 +#define IEEE80211_CTL_EXT_DMG_CTS 0x5000 +#define IEEE80211_CTL_EXT_DMG_DTS 0x6000 +#define IEEE80211_CTL_EXT_SSW 0x8000 +#define IEEE80211_CTL_EXT_SSW_FBACK 0x9000 +#define IEEE80211_CTL_EXT_SSW_ACK 0xa000 +#define IEEE80211_SN_MASK ((IEEE80211_SCTL_SEQ) >> 4) +#define IEEE80211_MAX_SN IEEE80211_SN_MASK +#define IEEE80211_SN_MODULO (IEEE80211_MAX_SN + 1) +#define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) +#define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) +#define IEEE80211_MAX_FRAG_THRESHOLD 2352 +#define IEEE80211_MAX_RTS_THRESHOLD 2353 +#define IEEE80211_MAX_AID 2007 +#define IEEE80211_MAX_TIM_LEN 251 +#define IEEE80211_MAX_DATA_LEN 2304 +#define IEEE80211_MAX_FRAME_LEN 2352 +#define IEEE80211_MAX_SSID_LEN 32 +#define IEEE80211_MAX_MESH_ID_LEN 32 +#define IEEE80211_NUM_TIDS 16 +#define IEEE80211_QOS_CTL_LEN 2 +#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 +#define IEEE80211_QOS_CTL_TID_MASK 0x000f +#define IEEE80211_QOS_CTL_EOSP 0x0010 +#define IEEE80211_QOS_CTL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020 +#define IEEE80211_QOS_CTL_ACK_POLICY_NO_EXPL 0x0040 +#define IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK 0x0060 +#define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060 +#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080 +#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 +#define IEEE80211_QOS_CTL_MESH_PS_LEVEL 0x0200 +#define IEEE80211_QOS_CTL_RSPI 0x0400 +#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) +#define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 +#define IEEE80211_HT_CTL_LEN 4 +#define MESH_FLAGS_AE_A4 0x1 +#define MESH_FLAGS_AE_A5_A6 0x2 +#define MESH_FLAGS_AE 0x3 +#define MESH_FLAGS_PS_DEEP 0x4 +#define WLAN_SA_QUERY_TR_ID_LEN 2 +#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 +#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) +#define IEEE80211_P2P_NOA_DESC_MAX 4 +#define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7) +#define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_BAR_CTRL_MULTI_TID 0x0002 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 +#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000 +#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12 +#define IEEE80211_HT_MCS_MASK_LEN 10 +#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff +#define IEEE80211_HT_MCS_TX_DEFINED 0x01 +#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 +#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ +#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 +#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 +#define IEEE80211_HT_CAP_SM_PS 0x000C +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 +#define IEEE80211_HT_CAP_GRN_FLD 0x0010 +#define IEEE80211_HT_CAP_SGI_20 0x0020 +#define IEEE80211_HT_CAP_SGI_40 0x0040 +#define IEEE80211_HT_CAP_TX_STBC 0x0080 +#define IEEE80211_HT_CAP_RX_STBC 0x0300 +#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 +#define IEEE80211_HT_CAP_DELAY_BA 0x0400 +#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 +#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 +#define IEEE80211_HT_CAP_RESERVED 0x2000 +#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 +#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 +#define IEEE80211_HT_EXT_CAP_PCO 0x0001 +#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 +#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 +#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 +#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 +#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 +#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 +#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 +#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C +#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 +#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 +#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 +#define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 +#define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 +#define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 +#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 +#define IEEE80211_HT_PARAM_RIFS_MODE 0x08 +#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 +#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 +#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 +#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 +#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 +#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 +#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 +#define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 +#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 +#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 +#define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 +#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 +#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0 +#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 +#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 +#define IEEE80211_MIN_AMPDU_BUF 0x8 +#define IEEE80211_MAX_AMPDU_BUF 0x40 +#define WLAN_HT_CAP_SM_PS_STATIC 0 +#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 +#define WLAN_HT_CAP_SM_PS_INVALID 2 +#define WLAN_HT_CAP_SM_PS_DISABLED 3 +#define WLAN_HT_SMPS_CONTROL_DISABLED 0 +#define WLAN_HT_SMPS_CONTROL_STATIC 1 +#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK 0x0000000C +#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 +#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 +#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 +#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 +#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 +#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 +#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 +#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 +#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 +#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 +#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 +#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 +#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 +#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 +#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 +#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 +#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_FT 2 +#define WLAN_AUTH_SAE 3 +#define WLAN_AUTH_LEAP 128 +#define WLAN_AUTH_CHALLENGE_LEN 128 +#define WLAN_CAPABILITY_ESS (1<<0) +#define WLAN_CAPABILITY_IBSS (1<<1) +#define WLAN_CAPABILITY_IS_STA_BSS(cap) (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS))) +#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) +#define WLAN_CAPABILITY_PRIVACY (1<<4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) +#define WLAN_CAPABILITY_PBCC (1<<6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) +#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_QOS (1<<9) +#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) +#define WLAN_CAPABILITY_APSD (1<<11) +#define WLAN_CAPABILITY_RADIO_MEASURE (1<<12) +#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) +#define WLAN_CAPABILITY_DEL_BACK (1<<14) +#define WLAN_CAPABILITY_IMM_BACK (1<<15) +#define WLAN_CAPABILITY_DMG_TYPE_MASK (3<<0) +#define WLAN_CAPABILITY_DMG_TYPE_IBSS (1<<0) /* Tx by: STA */ +#define WLAN_CAPABILITY_DMG_TYPE_PBSS (2<<0) /* Tx by: PCP */ +#define WLAN_CAPABILITY_DMG_TYPE_AP (3<<0) /* Tx by: AP */ +#define WLAN_CAPABILITY_DMG_CBAP_ONLY (1<<2) +#define WLAN_CAPABILITY_DMG_CBAP_SOURCE (1<<3) +#define WLAN_CAPABILITY_DMG_PRIVACY (1<<4) +#define WLAN_CAPABILITY_DMG_ECPAC (1<<5) +#define WLAN_CAPABILITY_DMG_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_DMG_RADIO_MEASURE (1<<12) +#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) +#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) +#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) +#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) +#define WLAN_EXT_CAPA5_TDLS_ENABLED BIT(5) +#define WLAN_EXT_CAPA5_TDLS_PROHIBITED BIT(6) +#define WLAN_EXT_CAPA8_OPMODE_NOTIF BIT(6) +#define WLAN_TDLS_SNAP_RFTYPE 0x2 +#define IEEE80211_COUNTRY_IE_MIN_LEN 6 +#define IEEE80211_COUNTRY_STRING_LEN 3 +#define IEEE80211_COUNTRY_EXTENSION_ID 201 +#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 +#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 +#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 +#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 +#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 +#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 +#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 +#define WLAN_CIPHER_SUITE_SMS4 0x00147201 +#define WLAN_AKM_SUITE_8021X 0x000FAC01 +#define WLAN_AKM_SUITE_PSK 0x000FAC02 +#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 +#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 +#define WLAN_AKM_SUITE_TDLS 0x000FAC07 +#define WLAN_AKM_SUITE_SAE 0x000FAC08 +#define WLAN_AKM_SUITE_FT_OVER_SAE 0x000FAC09 +#define WLAN_MAX_KEY_LEN 32 +#define WLAN_PMKID_LEN 16 +#define WLAN_OUI_WFA 0x506f9a +#define WLAN_OUI_TYPE_WFA_P2P 9 +#define WLAN_OUI_MICROSOFT 0x0050f2 +#define WLAN_OUI_TYPE_MICROSOFT_WPA 1 +#define WLAN_OUI_TYPE_MICROSOFT_WMM 2 +#define WLAN_OUI_TYPE_MICROSOFT_WPS 4 +#define IEEE80211_WMM_IE_TSPEC_TID_MASK 0x0F +#define IEEE80211_WMM_IE_TSPEC_TID_SHIFT 1 diff --git a/iptest/iptest.cpp b/iptest/iptest.cpp index 5eef904..26cf45c 100644 --- a/iptest/iptest.cpp +++ b/iptest/iptest.cpp @@ -44,27 +44,49 @@ int main(int argc, char *argv[]) { Wireless wi("wlp0s11u1"); - QList channels = wi.channelMap(); - - foreach(ChannelInfo info, channels) { - std::cout << "found channel " << info.chan << " (" << info.freq << "): " << - "Disabled?: " << (info.disabled ? "yes" : "no") << " " << - "Passive?: " << (info.passive ? "yes" : "no") << " " << - "Radar?: " << (info.radar ? "yes" : "no") << " " << - "Max TX Power: " << info.max_txpower << - std::endl; + QList bands = wi.bandMap(); + + foreach(BandInfo band, bands) { + std::cout << "found band" << + (((band.band & Wireless::BAND_2GHZ) == Wireless::BAND_2GHZ) ? " 2GHz" : "") << + (((band.band & Wireless::BAND_5GHZ) == Wireless::BAND_5GHZ) ? " 5GHz" : "") << + (((band.protocols & Wireless::PROTOCOL_80211_A) == Wireless::PROTOCOL_80211_A) ? " (802.11a)" : "") << + (((band.protocols & Wireless::PROTOCOL_80211_B) == Wireless::PROTOCOL_80211_B) ? " (802.11b)" : "") << + (((band.protocols & Wireless::PROTOCOL_80211_G) == Wireless::PROTOCOL_80211_G) ? " (802.11g)" : "") << + (((band.protocols & Wireless::PROTOCOL_80211_N) == Wireless::PROTOCOL_80211_N) ? " (802.11n)" : ""); + + if((band.width & Wireless::WIDTH_20MHZ) == Wireless::WIDTH_20MHZ) { + std::cout << " (20MHz)"; + } + + if((band.width & Wireless::WIDTH_40MHZ) == Wireless::WIDTH_40MHZ) { + std::cout << " (40MHz)"; + } + + std::cout << std::endl; + + if(band.channels.count() > 0) { + foreach(ChannelInfo info, band.channels) { + std::cout << " found channel " << info.chan << " (" << info.freq << "): " << + "Disabled?: " << (info.disabled ? "yes" : "no") << " " << + "Passive?: " << (info.passive ? "yes" : "no") << " " << + "Radar?: " << (info.radar ? "yes" : "no") << " " << + "Max TX Power: " << info.max_txpower << " " << + std::endl; + } + + std::cout << "converting channel 1 to freq: " << qPrintable(Wireless::ChanToFreq("Channel: 1")) << std::endl; + std::cout << "converting freq 5200 to channel: " << qPrintable(Wireless::FreqToChan("Frequency: 5.2GHz")) << std::endl; + std::cout << "is channel 11 supported? " << (wi.channelSupported(11) ? "yes" : "no") << std::endl; + std::cout << "is channel 165 supported? " << (wi.channelSupported(165) ? "yes" : "no") << std::endl; + std::cout << "is frequency 2.437GHz supported? " << (wi.frequencySupported(2437) ? "yes" : "no") << std::endl; + std::cout << "is frequency 5.825GHz supported? " << (wi.frequencySupported(5825) ? "yes" : "no") << std::endl; + std::cout << "all channels:"; + }else{ + std::cout << "no channels supported" << std::endl; + } } - std::cout << "converting channel 1 to freq: " << qPrintable(Wireless::ChanToFreq("Channel: 1")) << std::endl; - std::cout << "converting freq 5200 to channel: " << qPrintable(Wireless::FreqToChan("Frequency: 5.2GHz")) << std::endl; - std::cout << "is channel 11 supported? " << (wi.channelSupported(11) ? "yes" : "no") << std::endl; - std::cout << "is channel 165 supported? " << (wi.channelSupported(165) ? "yes" : "no") << std::endl; - std::cout << "is frequency 2.437GHz supported? " << (wi.frequencySupported(2437) ? "yes" : "no") << std::endl; - std::cout << "is frequency 5.825GHz supported? " << (wi.frequencySupported(5825) ? "yes" : "no") << std::endl; - std::cout << "is 802.11a supported? " << (((wi.supportedBands() & Wireless::BAND_80211_A) == Wireless::BAND_80211_A) ? "yes" : "no") << std::endl; - std::cout << "is 802.11b supported? " << (((wi.supportedBands() & Wireless::BAND_80211_B) == Wireless::BAND_80211_B) ? "yes" : "no") << std::endl; - std::cout << "all channels:"; - foreach(int chan, wi.allChannels()) { std::cout << " " << chan; } diff --git a/libip.pro b/libip.pro index 160b916..541cfc8 100644 --- a/libip.pro +++ b/libip.pro @@ -14,5 +14,5 @@ QMAKE_CFLAGS += -Wall -Wextra -Werror -fsanitize=address -fPIE LIBS += -lnl-route-3 -lnl-3 -lnl-genl-3 -lasan -HEADERS += interface.h neighbor.h wireless.h utils.h +HEADERS += interface.h neighbor.h wireless.h utils.h ieee80211.h SOURCES += interface.cpp neighbor.cpp wireless.cpp utils.cpp diff --git a/wireless.cpp b/wireless.cpp index fe655e2..85d4551 100644 --- a/wireless.cpp +++ b/wireless.cpp @@ -5,6 +5,7 @@ extern "C" { #include #include #include +#include "ieee80211.h" } #include "wireless.h" @@ -13,17 +14,7 @@ extern "C" { #include #include -struct nl80211_channel_block { - char *phyname; - int nfreqs; - int *channel_list; - int *disabled_list; - int *passive_list; - int *radar_list; - int *txpower_list; -}; - -typedef struct nl80211_channel_block nl80211_channel_block_t; +#define BIT(x) (1ULL<<(x)) int IEEE80211Freq[][2] = { {1, 2412}, @@ -87,10 +78,15 @@ int IEEE80211Freq[][2] = { {0, 0} }; +struct nl_callback { + char *phyname; + void *bands; +}; + Wireless::Wireless(QString interface) : QObject(0), m_interface(interface), -m_channels(), +m_bands(), m_isValid(false), m_isNL80211(false) { @@ -99,14 +95,13 @@ m_isNL80211(false) struct nl_cache *cache = NULL; struct nl_msg *msg = nlmsg_alloc(); struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); - nl80211_channel_block_t cblock; QByteArray interfaceArray = m_interface.toLatin1(); const char *interfaceStr = interfaceArray.constData(); int err = 1; - cblock.phyname = nl80211_find_parent(interfaceStr); + char *phyname = nl80211_find_parent(interfaceStr); - if(cblock.phyname == NULL) { + if(phyname == NULL) { if(!(Utils::interfaceIndex(interfaceStr))) { fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr); }else{ @@ -123,7 +118,9 @@ m_isNL80211(false) return; } - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_freqlist_cb, &cblock); + struct nl_callback callback = { .phyname = phyname, .bands = &m_bands }; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_freqlist_cb, &callback); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_finish_cb, &err); nl_cb_err(cb, NL_CB_CUSTOM, nl80211_error_cb, &err); @@ -141,57 +138,22 @@ m_isNL80211(false) nl80211_disconnect(handle, cache, family); - for(int i = 0; i < cblock.nfreqs; ++i) { - ChannelInfo info; - info.chan = cblock.channel_list[i]; - info.freq = ChanToFreq(cblock.channel_list[i]); - info.disabled = cblock.disabled_list[i]; - info.passive = cblock.passive_list[i]; - info.radar = cblock.radar_list[i]; - info.max_txpower = cblock.txpower_list[i]; - - m_channels.append(info); - - - // check supported channels to see what bands we support (only makes sense for A and B) - // is there a better way to do this? - if(!((m_supportedBands & BAND_80211_A) == BAND_80211_A)) { - if(cblock.channel_list[i] >= 36) { // first US 5GHz channel - m_supportedBands = static_cast(m_supportedBands | BAND_80211_A); - } - } - - if(!((m_supportedBands & BAND_80211_B) == BAND_80211_B)) { - if(cblock.channel_list[i] >= 1) { // first 2.4GHz channel - m_supportedBands = static_cast(m_supportedBands | BAND_80211_B); - } - } - } - - free(cblock.channel_list); - free(cblock.disabled_list); - free(cblock.passive_list); - free(cblock.radar_list); - free(cblock.txpower_list); - free(cblock.phyname); m_isValid = true; } Wireless::~Wireless() { std::cerr << "del wireless" << std::endl; - m_channels.clear(); -} - -Wireless::Bands Wireless::supportedBands() { - return m_supportedBands; + m_bands.clear(); } QList Wireless::allChannels() const { QList channels; - foreach(ChannelInfo info, m_channels) { - channels.append(info.chan); + foreach(BandInfo info, m_bands) { + foreach(ChannelInfo chan, info.channels) { + channels.append(chan.chan); + } } return channels; @@ -200,12 +162,14 @@ QList Wireless::allChannels() const { QList Wireless::allowedChannels(Direction dir) const { QList channels; - foreach(ChannelInfo info, m_channels) { - if(!info.disabled) { - if(((dir & Direction_Both) == Direction_Both) && (!info.passive)) { - channels.append(info.chan); - }else if(((dir & Direction_RX) == Direction_RX)) { - channels.append(info.chan); + foreach(BandInfo info, m_bands) { + foreach(ChannelInfo chan, info.channels) { + if(!chan.disabled) { + if(((dir & Direction_Both) == Direction_Both) && (!chan.passive)) { + channels.append(chan.chan); + }else if(((dir & Direction_RX) == Direction_RX)) { + channels.append(chan.chan); + } } } } @@ -216,8 +180,10 @@ QList Wireless::allowedChannels(Direction dir) const { QList Wireless::allFrequencies() const { QList freqs; - foreach(ChannelInfo info, m_channels) { - freqs.append(info.freq); + foreach(BandInfo band, m_bands) { + foreach(ChannelInfo info, band.channels) { + freqs.append(info.freq); + } } return freqs; @@ -226,12 +192,14 @@ QList Wireless::allFrequencies() const { QList Wireless::allowedFrequencies(Direction dir) const { QList freqs; - foreach(ChannelInfo info, m_channels) { - if(!info.disabled) { - if(((dir & Direction_Both) == Direction_Both) && (!info.passive)) { - freqs.append(info.freq); - }else if(((dir & Direction_RX) == Direction_RX)) { - freqs.append(info.freq); + foreach(BandInfo band, m_bands) { + foreach(ChannelInfo info, band.channels) { + if(!info.disabled) { + if(((dir & Direction_Both) == Direction_Both) && (!info.passive)) { + freqs.append(info.freq); + }else if(((dir & Direction_RX) == Direction_RX)) { + freqs.append(info.freq); + } } } } @@ -242,10 +210,12 @@ QList Wireless::allowedFrequencies(Direction dir) const { bool Wireless::channelSupported(int chan) const { bool found = false; - foreach(ChannelInfo info, m_channels) { - if(info.chan == chan) { - found = true; - break; + foreach(BandInfo band, m_bands) { + foreach(ChannelInfo info, band.channels) { + if(info.chan == chan) { + found = true; + break; + } } } @@ -255,10 +225,12 @@ bool Wireless::channelSupported(int chan) const { bool Wireless::frequencySupported(int freq) const { bool found = false; - foreach(ChannelInfo info, m_channels) { - if(info.freq == freq) { - found = true; - break; + foreach(BandInfo band, m_bands) { + foreach(ChannelInfo info, band.channels) { + if(info.freq == freq) { + found = true; + break; + } } } @@ -396,9 +368,8 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; struct nlattr *nl_band, *nl_freq; - int rem_band, rem_freq, num_freq = 0; - uint32_t freq; - struct nl80211_channel_block *chanb = (struct nl80211_channel_block *) arg; + int rem_band, rem_freq = 0; + struct nl_callback *callback = (struct nl_callback*)arg; nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -409,7 +380,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { if (tb_msg[NL80211_ATTR_WIPHY_NAME]) { if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]), - chanb->phyname) != 0) { + callback->phyname) != 0) { return NL_SKIP; } } @@ -423,38 +394,18 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), nla_len(nl_band), NULL); - for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]), - rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]); - nla_ok(nl_freq, rem_freq); - nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) { - - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, - (struct nlattr *) nla_data(nl_freq), - nla_len(nl_freq), NULL); + QList *bands = static_cast*>(callback->bands); + BandInfo band; - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; + if(tb_band[NL80211_BAND_ATTR_HT_CAPA]) { + __u16 cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]); + band.protocols = static_cast(band.protocols | PROTOCOL_80211_N); + band.width |= WIDTH_20MHZ; - num_freq++; + if((cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) { // 40-mhz 802.11n + band.width |= WIDTH_40MHZ; + } } - } - - chanb->nfreqs = num_freq; - chanb->channel_list = (int*)malloc(sizeof(int) * num_freq); - chanb->disabled_list = (int*)malloc(sizeof(int) * num_freq); - chanb->passive_list = (int*)malloc(sizeof(int) * num_freq); - chanb->radar_list = (int*)malloc(sizeof(int) * num_freq); - chanb->txpower_list = (int*)malloc(sizeof(int) * num_freq); - num_freq = 0; - - // Assemble a return - for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), - rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]); - nla_ok(nl_band, rem_band); - nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) { - - nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), - nla_len(nl_band), NULL); for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]), rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]); @@ -468,16 +419,36 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) continue; - freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); + uint32_t freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); + + ChannelInfo info; + info.chan = FreqToChan(freq); + info.freq = freq; + info.disabled = (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) ? 1 : 0; + info.passive = (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) ? 1 : 0; + info.radar = (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) ? 1 : 0; + info.max_txpower = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]); + + // check supported channels to see what bands we support (only makes sense for A and B) + // is there a better way to do this? + if(!((band.protocols & PROTOCOL_80211_A) == PROTOCOL_80211_A)) { + if(info.chan >= 36) { // first US 5GHz channel + band.protocols = static_cast(band.protocols | PROTOCOL_80211_A); + band.band = static_cast(band.band | BAND_5GHZ); + } + } - int index = num_freq++; + if(!((band.protocols & PROTOCOL_80211_B) == PROTOCOL_80211_B)) { + if(info.chan >= 1) { // first 2.4GHz channel + band.protocols = static_cast(band.protocols | PROTOCOL_80211_B); + band.band = static_cast(band.band | BAND_2GHZ); + } + } - chanb->channel_list[index] = FreqToChan(freq); - chanb->disabled_list[index] = (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) ? 1 : 0; - chanb->passive_list[index] = (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) ? 1 : 0; - chanb->radar_list[index] = (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) ? 1 : 0; - chanb->txpower_list[index] = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]); + band.channels.append(info); } + + bands->append(band); } return NL_SKIP; @@ -519,6 +490,6 @@ char* Wireless::nl80211_find_parent(const char *interface) const { return NULL; } -const QList& Wireless::channelMap() const { - return m_channels; +const QList& Wireless::bandMap() const { + return m_bands; } diff --git a/wireless.h b/wireless.h index cec1efa..076499a 100644 --- a/wireless.h +++ b/wireless.h @@ -24,6 +24,21 @@ struct ChannelInfo { } }; +struct BandInfo { + int band; + int width; + int protocols; + QList channels; + + BandInfo() : + band(0), + width(0), + protocols(0), + channels() + { + } +}; + class LIBIP_EXPORT Wireless : public QObject { Q_OBJECT @@ -32,19 +47,32 @@ public: ~Wireless(); enum Bands { - BAND_80211_A = (1 << 0), - BAND_80211_B = (1 << 1), - BAND_80211_G = (1 << 2), - BAND_80211_N = (1 << 3) + BAND_2GHZ = (1 << 0), + BAND_5GHZ = (1 << 1), + BAND_60GHZ = (1 << 2) + }; + + enum Protocols { + PROTOCOL_80211_A = (1 << 0), + PROTOCOL_80211_B = (1 << 1), + PROTOCOL_80211_G = (1 << 2), + PROTOCOL_80211_N = (1 << 3) }; enum Direction { - Direction_RX = (1 << 0), + Direction_RX = (1 << 0), Direction_Both = (1 << 1) }; + enum ChannelWidth { + WIDTH_20MHZ = (1 << 0), + WIDTH_40MHZ = (1 << 1), + WIDTH_80MHZ = (1 << 2), + WIDTH_160MHZ = (1 << 3) + }; + const QString& name() const; - const QList& channelMap() const; + const QList& bandMap() const; QList allChannels() const; QList allowedChannels(Direction dir) const; QList allFrequencies() const; @@ -57,14 +85,12 @@ public: bool isNL80211() const; bool channelSupported(int chan) const; bool frequencySupported(int freq) const; - enum Bands supportedBands(); private: QString m_interface; - QList m_channels; + QList m_bands; bool m_isValid; bool m_isNL80211; - enum Bands m_supportedBands; static int nl80211_freqlist_cb(struct nl_msg *msg, void *arg); static int nl80211_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);