mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 06:29:23 +01:00
monitor: parse/print HS2.0/WFA IEs
This is just a few of the WiFi Alliance IEs used for Hotspot 2.0
This commit is contained in:
parent
f3ad319e59
commit
e0c9b68467
328
monitor/nlmon.c
328
monitor/nlmon.c
@ -578,6 +578,7 @@ static const struct cipher_suites rsn_akm_selectors[] = {
|
||||
{ 0x000fac10, "FILS FT SHA256" },
|
||||
{ 0x000fac11, "FILS FT SHA3854" },
|
||||
{ 0x000fac12, "OWE" },
|
||||
{ 0x506f9a01, "WFA OSEN" },
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -700,6 +701,60 @@ static void print_ie_bitfield(unsigned int level, const char *label,
|
||||
}
|
||||
}
|
||||
|
||||
static size_t print_ie_rsn_suites(unsigned int level, const char *label,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
uint16_t count;
|
||||
uint16_t orig_size = size;
|
||||
|
||||
print_ie_cipher_suites(level + 1, "Group Data Cipher Suite", data, 4,
|
||||
rsn_cipher_selectors);
|
||||
|
||||
data += 4;
|
||||
size -= 4;
|
||||
|
||||
if (size < 2)
|
||||
goto end;
|
||||
|
||||
count = l_get_le16(data) * 4;
|
||||
data += 2;
|
||||
size -= 2;
|
||||
|
||||
if (size < count)
|
||||
goto end;
|
||||
|
||||
print_ie_cipher_suites(level + 1, "Pairwise Cipher Suite", data,
|
||||
count, rsn_cipher_selectors);
|
||||
data += count;
|
||||
size -= count;
|
||||
|
||||
if (size < 2)
|
||||
goto end;
|
||||
|
||||
count = l_get_le16(data) * 4;
|
||||
data += 2;
|
||||
size -= 2;
|
||||
|
||||
if (size < count)
|
||||
goto end;
|
||||
|
||||
print_ie_cipher_suites(level + 1, "AKM Suite", data, count,
|
||||
rsn_akm_selectors);
|
||||
data += count;
|
||||
size -= count;
|
||||
|
||||
if (size < 2)
|
||||
goto end;
|
||||
|
||||
return orig_size - size;
|
||||
|
||||
end:
|
||||
if (size)
|
||||
print_ie_error(level, label, size, -EINVAL);
|
||||
|
||||
return orig_size - size;
|
||||
}
|
||||
|
||||
static void print_ie_rsn(unsigned int level, const char *label,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
@ -733,39 +788,7 @@ static void print_ie_rsn(unsigned int level, const char *label,
|
||||
if (end - data < 4)
|
||||
goto end;
|
||||
|
||||
print_ie_cipher_suites(level + 1, "Group Data Cipher Suite", data, 4,
|
||||
rsn_cipher_selectors);
|
||||
|
||||
data += 4;
|
||||
|
||||
if (end - data < 2)
|
||||
goto end;
|
||||
|
||||
count = l_get_le16(data) * 4;
|
||||
data += 2;
|
||||
|
||||
if (end - data < count)
|
||||
goto end;
|
||||
|
||||
print_ie_cipher_suites(level + 1, "Pairwise Cipher Suite", data,
|
||||
count, rsn_cipher_selectors);
|
||||
data += count;
|
||||
|
||||
if (end - data < 2)
|
||||
goto end;
|
||||
|
||||
count = l_get_le16(data) * 4;
|
||||
data += 2;
|
||||
|
||||
if (end - data < count)
|
||||
goto end;
|
||||
|
||||
print_ie_cipher_suites(level + 1, "AKM Suite", data, count,
|
||||
rsn_akm_selectors);
|
||||
data += count;
|
||||
|
||||
if (end - data < 2)
|
||||
goto end;
|
||||
data += print_ie_rsn_suites(level, label, data, size);
|
||||
|
||||
bytemask[0] = 0x03;
|
||||
bytemask[1] = 0x00;
|
||||
@ -881,10 +904,63 @@ end:
|
||||
print_ie_error(level, label, size, -EINVAL);
|
||||
}
|
||||
|
||||
static void print_ie_wfa_hs20(unsigned int level, const char *label,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
const uint8_t *ptr = data;
|
||||
bool pps_mo_id_present;
|
||||
bool anpq_domain_id_present;
|
||||
|
||||
if (size < 1)
|
||||
return;
|
||||
|
||||
pps_mo_id_present = util_is_bit_set(ptr[0], 1);
|
||||
anpq_domain_id_present = util_is_bit_set(ptr[0], 2);
|
||||
|
||||
print_attr(level + 1, "HS2.0 Indication Element:");
|
||||
print_attr(level + 2, "DGAF Disabled: %u", util_is_bit_set(ptr[0], 0));
|
||||
print_attr(level + 2, "PPS MO ID Present: %u", pps_mo_id_present);
|
||||
print_attr(level + 2, "ANQP Domain ID Present: %u",
|
||||
anpq_domain_id_present);
|
||||
|
||||
switch (util_bit_field(ptr[0], 4, 7)) {
|
||||
case 0:
|
||||
print_attr(level + 2, "Version Number: 1.x");
|
||||
break;
|
||||
case 1:
|
||||
print_attr(level + 2, "Version Number: 2.x");
|
||||
break;
|
||||
case 2:
|
||||
print_attr(level + 2, "Version Number: 3.x");
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += 1;
|
||||
size -= 1;
|
||||
|
||||
if (pps_mo_id_present) {
|
||||
if (size < 2)
|
||||
return;
|
||||
|
||||
print_attr(level + 2, "PPS MO ID: %02x %02x", ptr[0], ptr[1]);
|
||||
ptr += 2;
|
||||
size -= 2;
|
||||
}
|
||||
|
||||
if (anpq_domain_id_present) {
|
||||
if (size < 2)
|
||||
return;
|
||||
|
||||
print_attr(level + 2, "ANQP Domain ID: %02x %02x",
|
||||
ptr[0], ptr[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_ie_vendor(unsigned int level, const char *label,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
static const unsigned char msoft_oui[3] = { 0x00, 0x50, 0xf2 };
|
||||
static const unsigned char wfa_oui[3] = { 0x50, 0x6f, 0x9a };
|
||||
const uint8_t *oui = data;
|
||||
const char *str = NULL;
|
||||
unsigned int i;
|
||||
@ -923,6 +999,17 @@ static void print_ie_vendor(unsigned int level, const char *label,
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else if (!memcmp(oui, wfa_oui, 3)) {
|
||||
switch (oui[3]) {
|
||||
case 0x10:
|
||||
print_ie_wfa_hs20(level + 1, label, data, size);
|
||||
return;
|
||||
case 0x12:
|
||||
print_ie_rsn_suites(level + 1, label, data, size);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1410,6 +1497,177 @@ static void print_ie_rm_enabled_caps(unsigned int level,
|
||||
bytemask2, sizeof(bytemask2), capabilities);
|
||||
}
|
||||
|
||||
static void print_ie_interworking(unsigned int level,
|
||||
const char *label,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
const uint8_t *ptr = data;
|
||||
const char *msg;
|
||||
uint8_t type;
|
||||
bool venue = false;
|
||||
bool hessid = false;
|
||||
|
||||
print_attr(level, "%s: len %u", label, size);
|
||||
|
||||
type = util_bit_field(ptr[0], 0, 3);
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
msg = "Private network";
|
||||
break;
|
||||
case 1:
|
||||
msg = "Private network w/ guest access";
|
||||
break;
|
||||
case 2:
|
||||
msg = "Chargeable public network";
|
||||
break;
|
||||
case 3:
|
||||
msg = "Free public network";
|
||||
break;
|
||||
case 4:
|
||||
msg = "Personal device network";
|
||||
break;
|
||||
case 5:
|
||||
msg = "Emergency services only network";
|
||||
break;
|
||||
case 14:
|
||||
msg = "Test/Experimental";
|
||||
break;
|
||||
case 15:
|
||||
msg = "Wildcard";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
print_attr(level + 1, "Network Type: %s", msg);
|
||||
print_attr(level + 1, "Internet: %u", util_is_bit_set(ptr[0], 4));
|
||||
print_attr(level + 1, "ASRA: %u", util_is_bit_set(ptr[0], 5));
|
||||
print_attr(level + 1, "ESR: %u", util_is_bit_set(ptr[0], 6));
|
||||
print_attr(level + 1, "UESA: %u", util_is_bit_set(ptr[0], 7));
|
||||
|
||||
size--;
|
||||
ptr++;
|
||||
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
/*
|
||||
* There is venue/hessid info optionally, and no way of determining if
|
||||
* they exist except looking at the length.
|
||||
*/
|
||||
if (size == 2)
|
||||
venue = true;
|
||||
else if (size == 6)
|
||||
hessid = true;
|
||||
else if (size == 8) {
|
||||
venue = true;
|
||||
hessid = true;
|
||||
}
|
||||
|
||||
if (venue) {
|
||||
switch (ptr[0]) {
|
||||
case 0:
|
||||
msg = "Unspecified";
|
||||
break;
|
||||
case 1:
|
||||
msg = "Assembly";
|
||||
break;
|
||||
case 2:
|
||||
msg = "Business";
|
||||
break;
|
||||
case 3:
|
||||
msg = "Educational";
|
||||
break;
|
||||
case 5:
|
||||
msg = "Factory and Industrial";
|
||||
break;
|
||||
case 6:
|
||||
msg = "Institutional";
|
||||
break;
|
||||
case 7:
|
||||
msg = "Mercantile";
|
||||
break;
|
||||
case 8:
|
||||
msg = "Residential";
|
||||
break;
|
||||
case 9:
|
||||
msg = "Utility and Miscellaneous";
|
||||
break;
|
||||
case 10:
|
||||
msg = "Vehicular";
|
||||
break;
|
||||
case 11:
|
||||
msg = "Outdoor";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each of the above groups have many group types, but if
|
||||
* anyone really cares they can cross reference the integer
|
||||
* type with IEEE 802.11-2016 Table 9-62
|
||||
*/
|
||||
print_attr(level + 1, "Venue: %s, type: %u", msg, ptr[1]);
|
||||
|
||||
ptr += 2;
|
||||
size -= 2;
|
||||
}
|
||||
|
||||
if (hessid)
|
||||
print_attr(level + 1, "HESSID: "MAC, MAC_STR(ptr));
|
||||
}
|
||||
|
||||
static void print_ie_advertisement(unsigned int level,
|
||||
const char *label,
|
||||
const void *data, uint16_t size)
|
||||
{
|
||||
const uint8_t *ptr = data;
|
||||
const char *msg = NULL;
|
||||
|
||||
print_attr(level, "%s: len %u", label, size);
|
||||
|
||||
while (size) {
|
||||
uint8_t qr_len = util_bit_field(ptr[0], 0, 7);
|
||||
uint8_t id = ptr[1];
|
||||
|
||||
switch (id) {
|
||||
case IE_ADVERTISEMENT_ANQP:
|
||||
msg = "ANQP";
|
||||
break;
|
||||
case IE_ADVERTISEMENT_MIH_SERVICE:
|
||||
msg = "MIH Information Service";
|
||||
break;
|
||||
case IE_ADVERTISEMENT_MIH_DISCOVERY:
|
||||
msg = "MIH Command and Event Services";
|
||||
break;
|
||||
case IE_ADVERTISEMENT_EAS:
|
||||
msg = "EAS";
|
||||
break;
|
||||
case IE_ADVERTISEMENT_RLQP:
|
||||
msg = "RLQP";
|
||||
break;
|
||||
case IE_ADVERTISEMENT_VENDOR_SPECIFIC:
|
||||
msg = "Vendor Specific";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == IE_ADVERTISEMENT_VENDOR_SPECIFIC) {
|
||||
size -= ptr[3];
|
||||
ptr += ptr[3];
|
||||
} else {
|
||||
size -= 2;
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
print_attr(level + 1, "Protocol: %s, Query Resp Limit: %u",
|
||||
msg, qr_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_ie_owe(unsigned int level,
|
||||
const char *label,
|
||||
const void *data, uint16_t size)
|
||||
@ -1500,6 +1758,10 @@ static struct attr_entry ie_entry[] = {
|
||||
ATTR_CUSTOM, { .function = print_ie_ht_capabilities } },
|
||||
{ IE_TYPE_RM_ENABLED_CAPABILITIES, "RM Enabled Capabilities",
|
||||
ATTR_CUSTOM, { .function = print_ie_rm_enabled_caps } },
|
||||
{ IE_TYPE_INTERWORKING, "Interworking",
|
||||
ATTR_CUSTOM, { .function = print_ie_interworking } },
|
||||
{ IE_TYPE_ADVERTISEMENT_PROTOCOL, "Advertisement Protocol",
|
||||
ATTR_CUSTOM, { .function = print_ie_advertisement } },
|
||||
{ IE_TYPE_OWE_DH_PARAM, "OWE Diffie-Hellman Parameter",
|
||||
ATTR_CUSTOM, { .function = print_ie_owe } },
|
||||
{ IE_TYPE_FILS_INDICATION, "FILS Indication",
|
||||
|
Loading…
Reference in New Issue
Block a user