mirror of
https://github.com/mfontanini/libtins
synced 2026-01-26 12:01:34 +01:00
Added unit tests for Dot11ManagementFrame.
This commit is contained in:
@@ -965,7 +965,7 @@ namespace Tins {
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct ibss_dfs_params {
|
||||
static const bool minimum_size = address_type::address_size + sizeof(uint8_t) + 2 * sizeof(uint8_t);
|
||||
static const size_t minimum_size = address_type::address_size + sizeof(uint8_t) + 2 * sizeof(uint8_t);
|
||||
|
||||
address_type dfs_owner;
|
||||
uint8_t recovery_interval;
|
||||
@@ -979,6 +979,36 @@ namespace Tins {
|
||||
channel_map(channels) {}
|
||||
};
|
||||
|
||||
struct country_params {
|
||||
typedef std::vector<uint8_t> container_type;
|
||||
// String identifier: 3 bytes
|
||||
static const size_t minimum_size = 3 + sizeof(uint8_t) * 3;
|
||||
|
||||
std::string country;
|
||||
container_type first_channel, number_channels, max_transmit_power;
|
||||
|
||||
country_params() {}
|
||||
|
||||
country_params(const std::string &country, const container_type &first,
|
||||
const container_type &number, const container_type &max)
|
||||
: country(country), first_channel(first), number_channels(number),
|
||||
max_transmit_power(max) {}
|
||||
};
|
||||
|
||||
struct fh_pattern_type {
|
||||
typedef std::vector<uint8_t> container_type;
|
||||
static const size_t minimum_size = sizeof(uint8_t) * 4;
|
||||
|
||||
uint8_t flag, number_of_sets, modulus, offset;
|
||||
container_type random_table;
|
||||
|
||||
fh_pattern_type() {}
|
||||
|
||||
fh_pattern_type(uint8_t flag, uint8_t sets, uint8_t modulus,
|
||||
uint8_t offset, const container_type& table) : flag(flag),
|
||||
number_of_sets(sets), modulus(modulus), offset(offset),
|
||||
random_table(table) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Getter for the second address.
|
||||
@@ -1006,7 +1036,7 @@ namespace Tins {
|
||||
*
|
||||
* \return The sequence number as an uint16_t.
|
||||
*/
|
||||
uint16_t seq_num() const { return this->_ext_header.seq_control.seq_number; }
|
||||
uint16_t seq_num() const { return Utils::le_to_host(_ext_header.seq_control.seq_number); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the fourth address.
|
||||
@@ -1157,12 +1187,9 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Helper method to set the country tagged option.
|
||||
*
|
||||
* \param countries Reference to a vector of uint8_t arrays of 3 bytes. Containing the list of countries.
|
||||
* \param first_channels Reference to a vector of uint8_t. Containing the first channels for each country.
|
||||
* \param num_channels Reference to a vector of uint8_t. Containing the number of channels for each country.
|
||||
* \param max_power Reference to a vector of uint8_t. Containing the max power for each country.
|
||||
* \param params The data to be used for this country option.
|
||||
*/
|
||||
void country(const std::vector<uint8_t*>& countries, const std::vector<uint8_t>& first_channels, const std::vector<uint8_t>& number_channels, const std::vector<uint8_t>& max_power);
|
||||
void country(const country_params ¶ms);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the FH parameters.
|
||||
@@ -1175,13 +1202,9 @@ namespace Tins {
|
||||
/**
|
||||
* \brief Helper method to set the FH pattern table.
|
||||
*
|
||||
* \param flag uint8_t with the value of the flag field.
|
||||
* \param number_of_sets uint8_t with the value of the number of sets field.
|
||||
* \param modulus uint8_t with the value of the modulus field.
|
||||
* \param offset uint8_t with the value of the offset field.
|
||||
* \param random_table reference to vector of uint8_t witht the elements of the table.
|
||||
* \param params The data to be used for this fh_pattern_table option.
|
||||
*/
|
||||
void fh_pattern_table(uint8_t flag, uint8_t number_of_sets, uint8_t modulus, uint8_t offset, const std::vector<uint8_t>& random_table);
|
||||
void fh_pattern_table(const fh_pattern_type ¶ms);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Power Constraint tagged option.
|
||||
@@ -1362,6 +1385,33 @@ namespace Tins {
|
||||
*/
|
||||
ibss_dfs_params ibss_dfs() const;
|
||||
|
||||
/**
|
||||
* \brief Helper method to get the country option.
|
||||
*
|
||||
* Throws a std::runtime_error if the option has not been set.
|
||||
*
|
||||
* \return country_params containing the country attributes.
|
||||
*/
|
||||
country_params country() const;
|
||||
|
||||
/**
|
||||
* \brief Helper method to get the fh parameters option.
|
||||
*
|
||||
* Throws a std::runtime_error if the option has not been set.
|
||||
*
|
||||
* \return ibss_dfs_params containing the fh parameters.
|
||||
*/
|
||||
std::pair<uint8_t, uint8_t> fh_parameters() const;
|
||||
|
||||
/**
|
||||
* \brief Helper method to get the fh patterns option.
|
||||
*
|
||||
* Throws a std::runtime_error if the option has not been set.
|
||||
*
|
||||
* \return ibss_dfs_params containing the fh patterns.
|
||||
*/
|
||||
fh_pattern_type fh_pattern_table() const;
|
||||
|
||||
// ************************
|
||||
|
||||
/**
|
||||
|
||||
114
src/dot11.cpp
114
src/dot11.cpp
@@ -308,7 +308,7 @@ void Dot11ManagementFrame::frag_num(uint8_t new_frag_num) {
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::seq_num(uint16_t new_seq_num) {
|
||||
this->_ext_header.seq_control.seq_number = new_seq_num;
|
||||
this->_ext_header.seq_control.seq_number = Utils::host_to_le(new_seq_num);
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::addr4(const address_type &new_addr4) {
|
||||
@@ -455,35 +455,24 @@ void Dot11ManagementFrame::ibss_dfs(const ibss_dfs_params ¶ms) {
|
||||
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::country(const std::vector<uint8_t*>& countries,
|
||||
const std::vector<uint8_t>& first_channels,
|
||||
const std::vector<uint8_t>& number_channels,
|
||||
const std::vector<uint8_t>& max_power) {
|
||||
|
||||
/* Check that the lists have the same number of elements */
|
||||
if ((countries.size() != first_channels.size()) ||
|
||||
(countries.size() != number_channels.size()) ||
|
||||
(countries.size() != max_power.size()))
|
||||
throw runtime_error("Lists should be of equal length!");
|
||||
|
||||
uint8_t sz = 6 * countries.size();
|
||||
if (sz & 1) // If size is odd, pad it
|
||||
void Dot11ManagementFrame::country(const country_params ¶ms) {
|
||||
if ((params.first_channel.size() != params.number_channels.size()) ||
|
||||
(params.number_channels.size() != params.max_transmit_power.size()))
|
||||
throw runtime_error("The length of the lists are distinct");
|
||||
if(params.country.size() != 3)
|
||||
throw runtime_error("Invalid country identifier length");
|
||||
size_t sz = sizeof(uint8_t) * 3 * params.first_channel.size() + params.country.size();
|
||||
// Use 1 byte padding at the end if the length is odd.
|
||||
if((sz & 1) == 1)
|
||||
sz++;
|
||||
uint8_t* buffer = new uint8_t[sz];
|
||||
uint8_t* ptr_buffer = buffer;
|
||||
for (uint8_t i = 0; i < countries.size(); i++) {
|
||||
memcpy(ptr_buffer, countries[i], 3);
|
||||
ptr_buffer += 3;
|
||||
*ptr_buffer = first_channels[i];
|
||||
ptr_buffer++;
|
||||
*ptr_buffer = number_channels[i];
|
||||
ptr_buffer++;
|
||||
*ptr_buffer = max_power[i];
|
||||
ptr_buffer++;
|
||||
std::vector<uint8_t> buffer(sz);
|
||||
uint8_t *ptr = std::copy(params.country.begin(), params.country.end(), &buffer[0]);
|
||||
for(size_t i(0); i < params.first_channel.size(); ++i) {
|
||||
*(ptr++) = params.first_channel[i];
|
||||
*(ptr++) = params.number_channels[i];
|
||||
*(ptr++) = params.max_transmit_power[i];
|
||||
}
|
||||
add_tagged_option(COUNTRY, sz, buffer);
|
||||
delete[] buffer;
|
||||
|
||||
add_tagged_option(COUNTRY, sz, &buffer[0]);
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::fh_parameters(uint8_t prime_radix, uint8_t number_channels) {
|
||||
@@ -493,13 +482,8 @@ void Dot11ManagementFrame::fh_parameters(uint8_t prime_radix, uint8_t number_cha
|
||||
add_tagged_option(HOPPING_PATTERN_PARAMS, 2, buffer);
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::fh_pattern_table(uint8_t flag,
|
||||
uint8_t number_of_sets,
|
||||
uint8_t modulus,
|
||||
uint8_t offset,
|
||||
const vector<uint8_t>& random_table) {
|
||||
|
||||
uint8_t sz = 4 + random_table.size();
|
||||
void Dot11ManagementFrame::fh_pattern_table(const fh_pattern_type ¶ms) {
|
||||
/*uint8_t sz = 4 + random_table.size();
|
||||
uint8_t* buffer = new uint8_t[sz];
|
||||
buffer[0] = flag;
|
||||
buffer[1] = number_of_sets;
|
||||
@@ -509,7 +493,17 @@ void Dot11ManagementFrame::fh_pattern_table(uint8_t flag,
|
||||
for (vector<uint8_t>::const_iterator it = random_table.begin(); it != random_table.end(); it++)
|
||||
*(ptr_buffer++) = *it;
|
||||
add_tagged_option(HOPPING_PATTERN_TABLE, sz, buffer);
|
||||
delete[] buffer;
|
||||
delete[] buffer;*/
|
||||
std::vector<uint8_t> data(sizeof(uint8_t) * 4 + params.random_table.size());
|
||||
uint8_t *ptr = &data[0];
|
||||
*(ptr++) = params.flag;
|
||||
*(ptr++) = params.number_of_sets;
|
||||
*(ptr++) = params.modulus;
|
||||
*(ptr++) = params.offset;
|
||||
fh_pattern_type::container_type::const_iterator it(params.random_table.begin());
|
||||
for(; it != params.random_table.end(); ++it)
|
||||
*(ptr++) = *it;
|
||||
add_tagged_option(HOPPING_PATTERN_TABLE, data.size(), &data[0]);
|
||||
}
|
||||
|
||||
void Dot11ManagementFrame::power_constraint(uint8_t local_power_constraint) {
|
||||
@@ -675,8 +669,9 @@ Dot11ManagementFrame::request_info_type Dot11ManagementFrame::request_informatio
|
||||
throw std::runtime_error("Request information not set");
|
||||
request_info_type output;
|
||||
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
|
||||
while(ptr != end)
|
||||
output.push_back(*(ptr++));
|
||||
//while(ptr != end)
|
||||
// output.push_back(*(ptr++));
|
||||
output.assign(ptr, end);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -724,6 +719,49 @@ Dot11ManagementFrame::ibss_dfs_params Dot11ManagementFrame::ibss_dfs() const {
|
||||
return output;
|
||||
}
|
||||
|
||||
Dot11ManagementFrame::country_params Dot11ManagementFrame::country() const {
|
||||
const Dot11::Dot11Option *option = search_option(COUNTRY);
|
||||
if(!option || option->data_size() < country_params::minimum_size)
|
||||
throw std::runtime_error("Country option not set");
|
||||
country_params output;
|
||||
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
|
||||
std::copy(ptr, ptr + 3, std::back_inserter(output.country));
|
||||
ptr += output.country.size();
|
||||
while(end - ptr >= 3) {
|
||||
output.first_channel.push_back(*(ptr++));
|
||||
output.number_channels.push_back(*(ptr++));
|
||||
output.max_transmit_power.push_back(*(ptr++));
|
||||
}
|
||||
if(ptr != end)
|
||||
throw std::runtime_error("Malformed option");
|
||||
return output;
|
||||
}
|
||||
|
||||
std::pair<uint8_t, uint8_t> Dot11ManagementFrame::fh_parameters() const {
|
||||
const Dot11::Dot11Option *option = search_option(HOPPING_PATTERN_PARAMS);
|
||||
if(!option || option->data_size() != sizeof(uint8_t) * 2)
|
||||
throw std::runtime_error("FH parameters option not set");
|
||||
const uint8_t *ptr = option->data_ptr();
|
||||
uint8_t first = *(ptr++);
|
||||
return std::make_pair(first, *ptr);
|
||||
}
|
||||
|
||||
Dot11ManagementFrame::fh_pattern_type Dot11ManagementFrame::fh_pattern_table() const {
|
||||
const Dot11::Dot11Option *option = search_option(HOPPING_PATTERN_TABLE);
|
||||
if(!option || option->data_size() < fh_pattern_type::minimum_size)
|
||||
throw std::runtime_error("FH pattern option not set");
|
||||
fh_pattern_type output;
|
||||
const uint8_t *ptr = option->data_ptr(), *end = ptr + option->data_size();
|
||||
|
||||
output.flag = *(ptr++);
|
||||
output.number_of_sets = *(ptr++);
|
||||
output.modulus = *(ptr++);
|
||||
output.offset = *(ptr++);
|
||||
|
||||
output.random_table.assign(ptr, end);
|
||||
return output;
|
||||
}
|
||||
|
||||
/* Dot11Beacon */
|
||||
|
||||
Dot11Beacon::Dot11Beacon(const NetworkInterface& iface,
|
||||
|
||||
@@ -183,8 +183,7 @@ TEST_F(Dot11BeaconTest, SupportedRates) {
|
||||
rates.push_back(7.5f);
|
||||
dot11.supported_rates(rates);
|
||||
found_rates = dot11.supported_rates();
|
||||
ASSERT_EQ(rates.size(), found_rates.size());
|
||||
EXPECT_TRUE(std::equal(rates.begin(), rates.end(), found_rates.begin()));
|
||||
EXPECT_EQ(rates, found_rates);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, ExtendedSupportedRates) {
|
||||
@@ -196,8 +195,7 @@ TEST_F(Dot11BeaconTest, ExtendedSupportedRates) {
|
||||
rates.push_back(7.5f);
|
||||
dot11.extended_supported_rates(rates);
|
||||
found_rates = dot11.extended_supported_rates();
|
||||
ASSERT_EQ(rates.size(), found_rates.size());
|
||||
EXPECT_TRUE(std::equal(rates.begin(), rates.end(), found_rates.begin()));
|
||||
EXPECT_EQ(rates, found_rates);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, QOSCapability) {
|
||||
@@ -223,8 +221,7 @@ TEST_F(Dot11BeaconTest, SupportedChannels) {
|
||||
channels.push_back(std::make_pair(67, 159));
|
||||
dot11.supported_channels(channels);
|
||||
output = dot11.supported_channels();
|
||||
ASSERT_EQ(output.size(), channels.size());
|
||||
EXPECT_TRUE(std::equal(channels.begin(), channels.end(), output.begin()));
|
||||
EXPECT_EQ(output, channels);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, RequestInformation) {
|
||||
@@ -236,8 +233,7 @@ TEST_F(Dot11BeaconTest, RequestInformation) {
|
||||
info.push_back(42);
|
||||
dot11.request_information(info);
|
||||
found_info = dot11.request_information();
|
||||
ASSERT_EQ(info.size(), found_info.size());
|
||||
EXPECT_TRUE(std::equal(info.begin(), info.end(), found_info.begin()));
|
||||
EXPECT_EQ(info, found_info);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, FHParameterSet) {
|
||||
@@ -275,7 +271,58 @@ TEST_F(Dot11BeaconTest, IBSS_DFS) {
|
||||
output = dot11.ibss_dfs();
|
||||
EXPECT_EQ(params.dfs_owner, output.dfs_owner);
|
||||
EXPECT_EQ(params.recovery_interval, output.recovery_interval);
|
||||
ASSERT_EQ(params.channel_map.size(), output.channel_map.size());
|
||||
EXPECT_TRUE(std::equal(params.channel_map.begin(), params.channel_map.end(), output.channel_map.begin()));
|
||||
EXPECT_EQ(params.channel_map, output.channel_map);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, Country) {
|
||||
Dot11Beacon dot11;
|
||||
Dot11Beacon::country_params params, output;
|
||||
params.country = "ARO";
|
||||
params.first_channel.push_back(65);
|
||||
params.first_channel.push_back(11);
|
||||
params.first_channel.push_back(97);
|
||||
|
||||
params.number_channels.push_back(123);
|
||||
params.number_channels.push_back(56);
|
||||
params.number_channels.push_back(42);
|
||||
|
||||
params.max_transmit_power.push_back(4);
|
||||
params.max_transmit_power.push_back(213);
|
||||
params.max_transmit_power.push_back(165);
|
||||
|
||||
dot11.country(params);
|
||||
output = dot11.country();
|
||||
|
||||
EXPECT_EQ(params.country, output.country);
|
||||
EXPECT_EQ(params.first_channel, output.first_channel);
|
||||
EXPECT_EQ(params.number_channels, output.number_channels);
|
||||
EXPECT_EQ(params.max_transmit_power, output.max_transmit_power);
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, FHParameters) {
|
||||
Dot11Beacon dot11;
|
||||
std::pair<uint8_t, uint8_t> data(0x42, 0x1f);
|
||||
dot11.fh_parameters(data.first, data.second);
|
||||
EXPECT_EQ(data, dot11.fh_parameters());
|
||||
}
|
||||
|
||||
TEST_F(Dot11BeaconTest, FHPattern) {
|
||||
Dot11Beacon dot11;
|
||||
Dot11Beacon::fh_pattern_type data, output;
|
||||
data.flag = 0x67;
|
||||
data.number_of_sets = 0x42;
|
||||
data.modulus = 0x1f;
|
||||
data.offset = 0x3a;
|
||||
data.random_table.push_back(23);
|
||||
data.random_table.push_back(15);
|
||||
data.random_table.push_back(129);
|
||||
|
||||
dot11.fh_pattern_table(data);
|
||||
output = dot11.fh_pattern_table();
|
||||
|
||||
EXPECT_EQ(data.flag, data.flag);
|
||||
EXPECT_EQ(data.number_of_sets, data.number_of_sets);
|
||||
EXPECT_EQ(data.modulus, data.modulus);
|
||||
EXPECT_EQ(data.offset, data.offset);
|
||||
EXPECT_EQ(data.random_table, data.random_table);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user