wifi: move nm_wifi_utils_parse_ies() to "src/nm-core-utils.h"

We will need it in "src/supplicant".
This commit is contained in:
Thomas Haller 2020-01-27 20:16:22 +01:00
parent 05ff735ec0
commit cc002ed3c1
3 changed files with 338 additions and 324 deletions

View file

@ -452,329 +452,6 @@ security_from_vardict (GVariant *security)
/*****************************************************************************/
static guint32
get_max_rate_ht_20 (int mcs)
{
switch (mcs) {
case 0: return 6500000;
case 1:
case 8: return 13000000;
case 2:
case 16: return 19500000;
case 3:
case 9:
case 24: return 26000000;
case 4:
case 10:
case 17: return 39000000;
case 5:
case 11:
case 25: return 52000000;
case 6:
case 18: return 58500000;
case 7: return 65000000;
case 12:
case 19:
case 26: return 78000000;
case 13:
case 27: return 104000000;
case 14:
case 20: return 117000000;
case 15: return 130000000;
case 21:
case 28: return 156000000;
case 22: return 175500000;
case 23: return 195000000;
case 29: return 208000000;
case 30: return 234000000;
case 31: return 260000000;
}
return 0;
}
static guint32
get_max_rate_ht_40 (int mcs)
{
switch (mcs) {
case 0: return 13500000;
case 1:
case 8: return 27000000;
case 2: return 40500000;
case 3:
case 9:
case 24: return 54000000;
case 4:
case 10:
case 17: return 81000000;
case 5:
case 11:
case 25: return 108000000;
case 6:
case 18: return 121500000;
case 7: return 135000000;
case 12:
case 19:
case 26: return 162000000;
case 13:
case 27: return 216000000;
case 14:
case 20: return 243000000;
case 15: return 270000000;
case 16: return 40500000;
case 21:
case 28: return 324000000;
case 22: return 364500000;
case 23: return 405000000;
case 29: return 432000000;
case 30: return 486000000;
case 31: return 540000000;
}
return 0;
}
static guint32
get_max_rate_vht_80_ss1 (int mcs)
{
switch (mcs) {
case 0: return 29300000;
case 1: return 58500000;
case 2: return 87800000;
case 3: return 117000000;
case 4: return 175500000;
case 5: return 234000000;
case 6: return 263300000;
case 7: return 292500000;
case 8: return 351000000;
case 9: return 390000000;
}
return 0;
}
static guint32
get_max_rate_vht_80_ss2 (int mcs)
{
switch (mcs) {
case 0: return 58500000;
case 1: return 117000000;
case 2: return 175500000;
case 3: return 234000000;
case 4: return 351000000;
case 5: return 468000000;
case 6: return 526500000;
case 7: return 585000000;
case 8: return 702000000;
case 9: return 780000000;
}
return 0;
}
static guint32
get_max_rate_vht_80_ss3 (int mcs)
{
switch (mcs) {
case 0: return 87800000;
case 1: return 175500000;
case 2: return 263300000;
case 3: return 351000000;
case 4: return 526500000;
case 5: return 702000000;
case 6: return 0;
case 7: return 877500000;
case 8: return 105300000;
case 9: return 117000000;
}
return 0;
}
static guint32
get_max_rate_vht_160_ss1 (int mcs)
{
switch (mcs) {
case 0: return 58500000;
case 1: return 117000000;
case 2: return 175500000;
case 3: return 234000000;
case 4: return 351000000;
case 5: return 468000000;
case 6: return 526500000;
case 7: return 585000000;
case 8: return 702000000;
case 9: return 780000000;
}
return 0;
}
static guint32
get_max_rate_vht_160_ss2 (int mcs)
{
switch (mcs) {
case 0: return 117000000;
case 1: return 234000000;
case 2: return 351000000;
case 3: return 468000000;
case 4: return 702000000;
case 5: return 936000000;
case 6: return 1053000000;
case 7: return 1170000000;
case 8: return 1404000000;
case 9: return 1560000000;
}
return 0;
}
static guint32
get_max_rate_vht_160_ss3 (int mcs)
{
switch (mcs) {
case 0: return 175500000;
case 1: return 351000000;
case 2: return 526500000;
case 3: return 702000000;
case 4: return 1053000000;
case 5: return 1404000000;
case 6: return 1579500000;
case 7: return 1755000000;
case 8: return 2106000000;
case 9: return 0;
}
return 0;
}
static gboolean
get_max_rate_ht (const guint8 *bytes, guint len, guint32 *out_maxrate)
{
guint32 i;
guint8 ht_cap_info;
const guint8 *supported_mcs_set;
guint32 rate;
/* http://standards.ieee.org/getieee802/download/802.11-2012.pdf
* https://mrncciew.com/2014/10/19/cwap-ht-capabilities-ie/
*/
if (len != 26)
return FALSE;
ht_cap_info = bytes[0];
supported_mcs_set = &bytes[3];
*out_maxrate = 0;
/* Find the maximum supported mcs rate */
for (i = 0; i <= 76; i++) {
unsigned int mcs_octet = i / 8;
unsigned int MCS_RATE_BIT = 1 << i % 8;
if (supported_mcs_set[mcs_octet] & MCS_RATE_BIT) {
/* Check for 40Mhz wide channel support */
if (ht_cap_info & (1 << 1))
rate = get_max_rate_ht_40 (i);
else
rate = get_max_rate_ht_20 (i);
if (rate > *out_maxrate)
*out_maxrate = rate;
}
}
return TRUE;
}
static gboolean
get_max_rate_vht (const guint8 *bytes, guint len, guint32 *out_maxrate)
{
guint32 mcs, m;
guint8 vht_cap, tx_map;
/* https://tda802dot11.blogspot.it/2014/10/vht-capabilities-element-vht.html
* http://chimera.labs.oreilly.com/books/1234000001739/ch03.html#management_frames */
if (len != 12)
return FALSE;
vht_cap = bytes[0];
tx_map = bytes[8];
/* Check for mcs rates 8 and 9 support */
if (tx_map & 0x2a)
mcs = 9;
else if (tx_map & 0x15)
mcs = 8;
else
mcs = 7;
/* Check for 160Mhz wide channel support and
* spatial stream support */
if (vht_cap & (1 << 2)) {
if (tx_map & 0x30)
m = get_max_rate_vht_160_ss3 (mcs);
else if (tx_map & 0x0C)
m = get_max_rate_vht_160_ss2 (mcs);
else
m = get_max_rate_vht_160_ss1 (mcs);
} else {
if (tx_map & 0x30)
m = get_max_rate_vht_80_ss3 (mcs);
else if (tx_map & 0x0C)
m = get_max_rate_vht_80_ss2 (mcs);
else
m = get_max_rate_vht_80_ss1 (mcs);
}
*out_maxrate = m;
return TRUE;
}
/* Management Frame Information Element IDs, ieee80211_eid */
#define WLAN_EID_HT_CAPABILITY 45
#define WLAN_EID_VHT_CAPABILITY 191
#define WLAN_EID_VENDOR_SPECIFIC 221
static void
parse_ies (const guint8 *bytes, gsize len, guint32 *out_max_rate, gboolean *out_metered)
{
guint8 id, elem_len;
guint32 m;
*out_max_rate = 0;
*out_metered = FALSE;
while (len) {
if (len < 2)
break;
id = *bytes++;
elem_len = *bytes++;
len -= 2;
if (elem_len > len)
break;
switch (id) {
case WLAN_EID_HT_CAPABILITY:
if (get_max_rate_ht (bytes, elem_len, &m))
*out_max_rate = NM_MAX (*out_max_rate, m);
break;
case WLAN_EID_VHT_CAPABILITY:
if (get_max_rate_vht (bytes, elem_len, &m))
*out_max_rate = NM_MAX (*out_max_rate, m);
break;
case WLAN_EID_VENDOR_SPECIFIC:
if ( len == 8
&& bytes[0] == 0x00 /* OUI: Microsoft */
&& bytes[1] == 0x50
&& bytes[2] == 0xf2
&& bytes[3] == 0x11) /* OUI type: Network cost */
*out_metered = (bytes[7] > 1); /* Cost level > 1 */
break;
}
len -= elem_len;
bytes += elem_len;
}
}
/*****************************************************************************/
gboolean
nm_wifi_ap_update_from_properties (NMWifiAP *ap,
const char *supplicant_path,
@ -872,7 +549,7 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING);
if (v) {
bytes = g_variant_get_fixed_array (v, &len, 1);
parse_ies (bytes, len, &rate, &metered);
nm_wifi_utils_parse_ies (bytes, len, &rate, &metered);
max_rate = NM_MAX (max_rate, rate);
g_variant_unref (v);
priv->metered = metered;

View file

@ -4073,6 +4073,338 @@ nm_utils_strdict_to_variant (GHashTable *options)
/*****************************************************************************/
static guint32
get_max_rate_ht_20 (int mcs)
{
switch (mcs) {
case 0: return 6500000;
case 1:
case 8: return 13000000;
case 2:
case 16: return 19500000;
case 3:
case 9:
case 24: return 26000000;
case 4:
case 10:
case 17: return 39000000;
case 5:
case 11:
case 25: return 52000000;
case 6:
case 18: return 58500000;
case 7: return 65000000;
case 12:
case 19:
case 26: return 78000000;
case 13:
case 27: return 104000000;
case 14:
case 20: return 117000000;
case 15: return 130000000;
case 21:
case 28: return 156000000;
case 22: return 175500000;
case 23: return 195000000;
case 29: return 208000000;
case 30: return 234000000;
case 31: return 260000000;
}
return 0;
}
static guint32
get_max_rate_ht_40 (int mcs)
{
switch (mcs) {
case 0: return 13500000;
case 1:
case 8: return 27000000;
case 2: return 40500000;
case 3:
case 9:
case 24: return 54000000;
case 4:
case 10:
case 17: return 81000000;
case 5:
case 11:
case 25: return 108000000;
case 6:
case 18: return 121500000;
case 7: return 135000000;
case 12:
case 19:
case 26: return 162000000;
case 13:
case 27: return 216000000;
case 14:
case 20: return 243000000;
case 15: return 270000000;
case 16: return 40500000;
case 21:
case 28: return 324000000;
case 22: return 364500000;
case 23: return 405000000;
case 29: return 432000000;
case 30: return 486000000;
case 31: return 540000000;
}
return 0;
}
static guint32
get_max_rate_vht_80_ss1 (int mcs)
{
switch (mcs) {
case 0: return 29300000;
case 1: return 58500000;
case 2: return 87800000;
case 3: return 117000000;
case 4: return 175500000;
case 5: return 234000000;
case 6: return 263300000;
case 7: return 292500000;
case 8: return 351000000;
case 9: return 390000000;
}
return 0;
}
static guint32
get_max_rate_vht_80_ss2 (int mcs)
{
switch (mcs) {
case 0: return 58500000;
case 1: return 117000000;
case 2: return 175500000;
case 3: return 234000000;
case 4: return 351000000;
case 5: return 468000000;
case 6: return 526500000;
case 7: return 585000000;
case 8: return 702000000;
case 9: return 780000000;
}
return 0;
}
static guint32
get_max_rate_vht_80_ss3 (int mcs)
{
switch (mcs) {
case 0: return 87800000;
case 1: return 175500000;
case 2: return 263300000;
case 3: return 351000000;
case 4: return 526500000;
case 5: return 702000000;
case 6: return 0;
case 7: return 877500000;
case 8: return 105300000;
case 9: return 117000000;
}
return 0;
}
static guint32
get_max_rate_vht_160_ss1 (int mcs)
{
switch (mcs) {
case 0: return 58500000;
case 1: return 117000000;
case 2: return 175500000;
case 3: return 234000000;
case 4: return 351000000;
case 5: return 468000000;
case 6: return 526500000;
case 7: return 585000000;
case 8: return 702000000;
case 9: return 780000000;
}
return 0;
}
static guint32
get_max_rate_vht_160_ss2 (int mcs)
{
switch (mcs) {
case 0: return 117000000;
case 1: return 234000000;
case 2: return 351000000;
case 3: return 468000000;
case 4: return 702000000;
case 5: return 936000000;
case 6: return 1053000000;
case 7: return 1170000000;
case 8: return 1404000000;
case 9: return 1560000000;
}
return 0;
}
static guint32
get_max_rate_vht_160_ss3 (int mcs)
{
switch (mcs) {
case 0: return 175500000;
case 1: return 351000000;
case 2: return 526500000;
case 3: return 702000000;
case 4: return 1053000000;
case 5: return 1404000000;
case 6: return 1579500000;
case 7: return 1755000000;
case 8: return 2106000000;
case 9: return 0;
}
return 0;
}
static gboolean
get_max_rate_ht (const guint8 *bytes, guint len, guint32 *out_maxrate)
{
guint32 i;
guint8 ht_cap_info;
const guint8 *supported_mcs_set;
guint32 rate;
/* http://standards.ieee.org/getieee802/download/802.11-2012.pdf
* https://mrncciew.com/2014/10/19/cwap-ht-capabilities-ie/
*/
if (len != 26)
return FALSE;
ht_cap_info = bytes[0];
supported_mcs_set = &bytes[3];
*out_maxrate = 0;
/* Find the maximum supported mcs rate */
for (i = 0; i <= 76; i++) {
const unsigned mcs_octet = i / 8;
const unsigned MCS_RATE_BIT = 1 << i % 8;
if (supported_mcs_set[mcs_octet] & MCS_RATE_BIT) {
/* Check for 40Mhz wide channel support */
if (ht_cap_info & (1 << 1))
rate = get_max_rate_ht_40 (i);
else
rate = get_max_rate_ht_20 (i);
if (rate > *out_maxrate)
*out_maxrate = rate;
}
}
return TRUE;
}
static gboolean
get_max_rate_vht (const guint8 *bytes, guint len, guint32 *out_maxrate)
{
guint32 mcs, m;
guint8 vht_cap, tx_map;
/* https://tda802dot11.blogspot.it/2014/10/vht-capabilities-element-vht.html
* http://chimera.labs.oreilly.com/books/1234000001739/ch03.html#management_frames */
if (len != 12)
return FALSE;
vht_cap = bytes[0];
tx_map = bytes[8];
/* Check for mcs rates 8 and 9 support */
if (tx_map & 0x2a)
mcs = 9;
else if (tx_map & 0x15)
mcs = 8;
else
mcs = 7;
/* Check for 160Mhz wide channel support and
* spatial stream support */
if (vht_cap & (1 << 2)) {
if (tx_map & 0x30)
m = get_max_rate_vht_160_ss3 (mcs);
else if (tx_map & 0x0C)
m = get_max_rate_vht_160_ss2 (mcs);
else
m = get_max_rate_vht_160_ss1 (mcs);
} else {
if (tx_map & 0x30)
m = get_max_rate_vht_80_ss3 (mcs);
else if (tx_map & 0x0C)
m = get_max_rate_vht_80_ss2 (mcs);
else
m = get_max_rate_vht_80_ss1 (mcs);
}
*out_maxrate = m;
return TRUE;
}
/* Management Frame Information Element IDs, ieee80211_eid */
#define WLAN_EID_HT_CAPABILITY 45
#define WLAN_EID_VHT_CAPABILITY 191
#define WLAN_EID_VENDOR_SPECIFIC 221
void
nm_wifi_utils_parse_ies (const guint8 *bytes,
gsize len,
guint32 *out_max_rate,
gboolean *out_metered)
{
guint8 id, elem_len;
guint32 m;
NM_SET_OUT (out_max_rate, 0);
NM_SET_OUT (out_metered, FALSE);
while (len) {
if (len < 2)
break;
id = *bytes++;
elem_len = *bytes++;
len -= 2;
if (elem_len > len)
break;
switch (id) {
case WLAN_EID_HT_CAPABILITY:
if (out_max_rate) {
if (get_max_rate_ht (bytes, elem_len, &m))
*out_max_rate = NM_MAX (*out_max_rate, m);
}
break;
case WLAN_EID_VHT_CAPABILITY:
if (out_max_rate) {
if (get_max_rate_vht (bytes, elem_len, &m))
*out_max_rate = NM_MAX (*out_max_rate, m);
}
break;
case WLAN_EID_VENDOR_SPECIFIC:
if (out_metered) {
if ( len == 8
&& bytes[0] == 0x00 /* OUI: Microsoft */
&& bytes[1] == 0x50
&& bytes[2] == 0xf2
&& bytes[3] == 0x11) /* OUI type: Network cost */
*out_metered = (bytes[7] > 1); /* Cost level > 1 */
}
break;
}
len -= elem_len;
bytes += elem_len;
}
}
/*****************************************************************************/
guint8
nm_wifi_utils_level_to_quality (int val)
{

View file

@ -473,6 +473,11 @@ const char *nm_utils_parse_dns_domain (const char *domain, gboolean *is_routing)
/*****************************************************************************/
void nm_wifi_utils_parse_ies (const guint8 *bytes,
gsize len,
guint32 *out_max_rate,
gboolean *out_metered);
guint8 nm_wifi_utils_level_to_quality (int val);
/*****************************************************************************/