mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Add ICMPv6 Multicast Listener Query Messages support
This commit is contained in:
@@ -527,7 +527,7 @@ public:
|
|||||||
typedef std::vector<ipaddress_type> sources_type;
|
typedef std::vector<ipaddress_type> sources_type;
|
||||||
typedef std::vector<uint8_t> aux_data_type;
|
typedef std::vector<uint8_t> aux_data_type;
|
||||||
|
|
||||||
multicast_address_record(uint8_t type) : type(type) { }
|
multicast_address_record(uint8_t type = 0) : type(type) { }
|
||||||
|
|
||||||
multicast_address_record(const uint8_t* buffer, uint32_t total_sz);
|
multicast_address_record(const uint8_t* buffer, uint32_t total_sz);
|
||||||
void serialize(uint8_t* buffer, uint32_t total_sz) const;
|
void serialize(uint8_t* buffer, uint32_t total_sz) const;
|
||||||
@@ -544,6 +544,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
typedef std::list<multicast_address_record> multicast_address_records_list;
|
typedef std::list<multicast_address_record> multicast_address_records_list;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The type used to store all source address (from Multicast
|
||||||
|
* Listener Query messages) in a packet
|
||||||
|
*/
|
||||||
|
typedef std::list<ipaddress_type> sources_list;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Constructs an ICMPv6 object.
|
* \brief Constructs an ICMPv6 object.
|
||||||
*
|
*
|
||||||
@@ -634,13 +640,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the hop_limit field.
|
* \brief Getter for the hop limit field.
|
||||||
* \return The stored hop_limit field value.
|
* \return The stored hop limit field value.
|
||||||
*/
|
*/
|
||||||
uint8_t hop_limit() const {
|
uint8_t hop_limit() const {
|
||||||
return header_.u_nd_ra.hop_limit;
|
return header_.u_nd_ra.hop_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the maximum response code field.
|
||||||
|
* \return The stored maximum response code field value.
|
||||||
|
*/
|
||||||
|
uint16_t maximum_response_code() const {
|
||||||
|
return Endian::be_to_host(header_.u_echo.identifier);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the router_pref field.
|
* \brief Getter for the router_pref field.
|
||||||
* \return The stored router_pref field value.
|
* \return The stored router_pref field value.
|
||||||
@@ -713,6 +727,17 @@ public:
|
|||||||
return dest_address_;
|
return dest_address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the multicast address field.
|
||||||
|
*
|
||||||
|
* Note that this field is only valid for Multicast Listener Query
|
||||||
|
* Message packets
|
||||||
|
* \return The stored multicast address field value.
|
||||||
|
*/
|
||||||
|
const ipaddress_type& multicast_addr() const {
|
||||||
|
return multicast_address_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the ICMPv6 options.
|
* \brief Getter for the ICMPv6 options.
|
||||||
* \return The stored options.
|
* \return The stored options.
|
||||||
@@ -737,6 +762,46 @@ public:
|
|||||||
return multicast_records_;
|
return multicast_records_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the multicast address records field.
|
||||||
|
*
|
||||||
|
* Note that this field is only valid for Multicast Listener Query Message
|
||||||
|
* packets
|
||||||
|
*/
|
||||||
|
const sources_list& sources() const {
|
||||||
|
return sources_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the Suppress Router-Side Processing field.
|
||||||
|
*
|
||||||
|
* Note that this field is only valid for Multicast Listener Query Message
|
||||||
|
* packets
|
||||||
|
*/
|
||||||
|
small_uint<1> supress() const {
|
||||||
|
return mlqm_.supress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the Querier's Robustnes Variable field.
|
||||||
|
*
|
||||||
|
* Note that this field is only valid for Multicast Listener Query Message
|
||||||
|
* packets
|
||||||
|
*/
|
||||||
|
small_uint<3> qrv() const {
|
||||||
|
return mlqm_.qrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the Querier's Query Interval Code field.
|
||||||
|
*
|
||||||
|
* Note that this field is only valid for Multicast Listener Query Message
|
||||||
|
* packets
|
||||||
|
*/
|
||||||
|
uint8_t qqic() const {
|
||||||
|
return mlqm_.qqic;
|
||||||
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -793,6 +858,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
void hop_limit(uint8_t new_hop_limit);
|
void hop_limit(uint8_t new_hop_limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the maximum response code field.
|
||||||
|
* \param new_hop_limit The new maximum response code field value.
|
||||||
|
*/
|
||||||
|
void maximum_response_code(uint16_t maximum_response_code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the router_pref field.
|
* \brief Setter for the router_pref field.
|
||||||
* \param new_router_pref The new router_pref field value.
|
* \param new_router_pref The new router_pref field value.
|
||||||
@@ -835,6 +906,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
void dest_addr(const ipaddress_type& new_dest_addr);
|
void dest_addr(const ipaddress_type& new_dest_addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the multicast address field.
|
||||||
|
*
|
||||||
|
* Note that this field is only valid if the type is MGM_QUERY
|
||||||
|
*
|
||||||
|
* \param new_multicast_addr The new multicast address field value.
|
||||||
|
*/
|
||||||
|
void multicast_addr(const ipaddress_type& new_multicast_addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the reachable_time field.
|
* \brief Setter for the reachable_time field.
|
||||||
* \param new_reachable_time The new reachable_time field value.
|
* \param new_reachable_time The new reachable_time field value.
|
||||||
@@ -854,6 +934,34 @@ public:
|
|||||||
*/
|
*/
|
||||||
void multicast_address_records(const multicast_address_records_list& records);
|
void multicast_address_records(const multicast_address_records_list& records);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the sources field.
|
||||||
|
*
|
||||||
|
* This field is only valid if the type of this PDU is MGM_QUERY
|
||||||
|
*/
|
||||||
|
void sources(const sources_list& new_sources);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the supress field.
|
||||||
|
*
|
||||||
|
* This field is only valid if the type of this PDU is MGM_QUERY
|
||||||
|
*/
|
||||||
|
void supress(small_uint<1> value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the Querier's Robustness Variable field.
|
||||||
|
*
|
||||||
|
* This field is only valid if the type of this PDU is MGM_QUERY
|
||||||
|
*/
|
||||||
|
void qrv(small_uint<3> value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the Querier's Query Interval Code field.
|
||||||
|
*
|
||||||
|
* This field is only valid if the type of this PDU is MGM_QUERY
|
||||||
|
*/
|
||||||
|
void qqic(uint8_t value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the PDU's type.
|
* \brief Getter for the PDU's type.
|
||||||
*
|
*
|
||||||
@@ -1421,9 +1529,17 @@ private:
|
|||||||
struct {
|
struct {
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
uint16_t record_count;
|
uint16_t record_count;
|
||||||
} mlrm2 ;
|
} mlrm2;
|
||||||
};
|
};
|
||||||
} TINS_END_PACK;
|
} TINS_END_PACK;
|
||||||
|
|
||||||
|
TINS_BEGIN_PACK
|
||||||
|
struct multicast_listener_query_message_fields {
|
||||||
|
uint8_t reserved:4,
|
||||||
|
supress:1,
|
||||||
|
qrv:3;
|
||||||
|
uint8_t qqic;
|
||||||
|
} TINS_END_PACK;
|
||||||
|
|
||||||
void internal_add_option(const option& option);
|
void internal_add_option(const option& option);
|
||||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||||
@@ -1458,14 +1574,18 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
icmp6_header header_;
|
icmp6_header header_;
|
||||||
ipaddress_type target_address_, dest_address_;
|
ipaddress_type target_address_;
|
||||||
|
ipaddress_type dest_address_;
|
||||||
|
ipaddress_type multicast_address_;
|
||||||
options_type options_;
|
options_type options_;
|
||||||
uint32_t options_size_;
|
uint32_t options_size_;
|
||||||
uint32_t reach_time_, retrans_timer_;
|
uint32_t reach_time_, retrans_timer_;
|
||||||
multicast_address_records_list multicast_records_;
|
multicast_address_records_list multicast_records_;
|
||||||
|
multicast_listener_query_message_fields mlqm_;
|
||||||
|
sources_list sources_;
|
||||||
ICMPExtensionsStructure extensions_;
|
ICMPExtensionsStructure extensions_;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
} // Tins
|
||||||
|
|
||||||
#endif // TINS_ICMPV6_H
|
#endif // TINS_ICMPV6_H
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ ICMPv6::ICMPv6(const uint8_t* buffer, uint32_t total_sz)
|
|||||||
stream.skip(multicast_records_.back().size());
|
stream.skip(multicast_records_.back().size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type() == MGM_QUERY) {
|
||||||
|
stream.read(multicast_address_);
|
||||||
|
stream.read(mlqm_);
|
||||||
|
int sources_count = stream.read_be<uint16_t>();
|
||||||
|
while (sources_count--) {
|
||||||
|
ipaddress_type address;
|
||||||
|
stream.read(address);
|
||||||
|
sources_.push_back(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Retrieve options
|
// Retrieve options
|
||||||
if (has_options()) {
|
if (has_options()) {
|
||||||
parse_options(stream);
|
parse_options(stream);
|
||||||
@@ -145,6 +155,10 @@ void ICMPv6::hop_limit(uint8_t new_hop_limit) {
|
|||||||
header_.u_nd_ra.hop_limit = new_hop_limit;
|
header_.u_nd_ra.hop_limit = new_hop_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICMPv6::maximum_response_code(uint16_t maximum_response_code) {
|
||||||
|
header_.u_echo.identifier = Endian::host_to_be(maximum_response_code);
|
||||||
|
}
|
||||||
|
|
||||||
void ICMPv6::router_pref(small_uint<2> new_router_pref) {
|
void ICMPv6::router_pref(small_uint<2> new_router_pref) {
|
||||||
header_.u_nd_ra.router_pref = new_router_pref;
|
header_.u_nd_ra.router_pref = new_router_pref;
|
||||||
}
|
}
|
||||||
@@ -177,6 +191,22 @@ void ICMPv6::multicast_address_records(const multicast_address_records_list& rec
|
|||||||
multicast_records_ = records;
|
multicast_records_ = records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICMPv6::sources(const sources_list& new_sources) {
|
||||||
|
sources_ = new_sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICMPv6::supress(small_uint<1> value) {
|
||||||
|
mlqm_.supress = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICMPv6::qrv(small_uint<3> value) {
|
||||||
|
mlqm_.qrv = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICMPv6::qqic(uint8_t value) {
|
||||||
|
mlqm_.qqic = value;
|
||||||
|
}
|
||||||
|
|
||||||
void ICMPv6::target_addr(const ipaddress_type& new_target_addr) {
|
void ICMPv6::target_addr(const ipaddress_type& new_target_addr) {
|
||||||
target_address_ = new_target_addr;
|
target_address_ = new_target_addr;
|
||||||
}
|
}
|
||||||
@@ -185,6 +215,10 @@ void ICMPv6::dest_addr(const ipaddress_type& new_dest_addr) {
|
|||||||
dest_address_ = new_dest_addr;
|
dest_address_ = new_dest_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICMPv6::multicast_addr(const ipaddress_type& new_multicast_addr) {
|
||||||
|
multicast_address_ = new_multicast_addr;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t ICMPv6::header_size() const {
|
uint32_t ICMPv6::header_size() const {
|
||||||
uint32_t extra = 0;
|
uint32_t extra = 0;
|
||||||
if (type() == ROUTER_ADVERT) {
|
if (type() == ROUTER_ADVERT) {
|
||||||
@@ -197,6 +231,10 @@ uint32_t ICMPv6::header_size() const {
|
|||||||
extra += iter->size();
|
extra += iter->size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type() == MGM_QUERY) {
|
||||||
|
extra += ipaddress_type::address_size + sizeof(mlqm_) + sizeof(uint16_t) +
|
||||||
|
ipaddress_type::address_size * sources_.size();
|
||||||
|
}
|
||||||
return sizeof(header_) + options_size_ + extra +
|
return sizeof(header_) + options_size_ + extra +
|
||||||
(has_target_addr() ? ipaddress_type::address_size : 0) +
|
(has_target_addr() ? ipaddress_type::address_size : 0) +
|
||||||
(has_dest_addr() ? ipaddress_type::address_size : 0);
|
(has_dest_addr() ? ipaddress_type::address_size : 0);
|
||||||
@@ -275,6 +313,15 @@ void ICMPv6::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU*
|
|||||||
stream.skip(iter->size());
|
stream.skip(iter->size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type() == MGM_QUERY) {
|
||||||
|
stream.write(multicast_address_);
|
||||||
|
stream.write(mlqm_);
|
||||||
|
stream.write_be<uint16_t>(sources_.size());
|
||||||
|
typedef sources_list::const_iterator iterator;
|
||||||
|
for (iterator iter = sources_.begin(); iter != sources_.end(); ++iter) {
|
||||||
|
stream.write(*iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
for (options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
||||||
write_option(*it, stream);
|
write_option(*it, stream);
|
||||||
}
|
}
|
||||||
@@ -286,8 +333,7 @@ void ICMPv6::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU*
|
|||||||
uint32_t inner_pdu_size = get_adjusted_inner_pdu_size();
|
uint32_t inner_pdu_size = get_adjusted_inner_pdu_size();
|
||||||
// If it's lower than 128, we need to padd enough zeroes to make it 128 bytes long
|
// If it's lower than 128, we need to padd enough zeroes to make it 128 bytes long
|
||||||
if (inner_pdu_size < 128) {
|
if (inner_pdu_size < 128) {
|
||||||
memset(extensions_ptr + inner_pdu_size, 0,
|
memset(extensions_ptr + inner_pdu_size, 0, 128 - inner_pdu_size);
|
||||||
128 - inner_pdu_size);
|
|
||||||
inner_pdu_size = 128;
|
inner_pdu_size = 128;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public:
|
|||||||
static const uint8_t packet_with_extensions[];
|
static const uint8_t packet_with_extensions[];
|
||||||
static const uint8_t packet_with_extensions_and_length[];
|
static const uint8_t packet_with_extensions_and_length[];
|
||||||
static const uint8_t mld2_icmpv6_layer[];
|
static const uint8_t mld2_icmpv6_layer[];
|
||||||
|
static const uint8_t mlqm_icmpv6_layer[];
|
||||||
|
|
||||||
void test_equals(const ICMPv6& icmp1, const ICMPv6& icmp2);
|
void test_equals(const ICMPv6& icmp1, const ICMPv6& icmp2);
|
||||||
};
|
};
|
||||||
@@ -73,6 +74,16 @@ const uint8_t ICMPv6Test::mld2_icmpv6_layer[] = {
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 9, 222, 173, 190, 239, 190, 173, 254, 237
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 9, 222, 173, 190, 239, 190, 173, 254, 237
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Multicast Listener Query Message
|
||||||
|
const uint8_t ICMPv6Test::mlqm_icmpv6_layer[] = {
|
||||||
|
130, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 2, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 2,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 9
|
||||||
|
};
|
||||||
|
|
||||||
TEST_F(ICMPv6Test, Constructor) {
|
TEST_F(ICMPv6Test, Constructor) {
|
||||||
ICMPv6 icmp;
|
ICMPv6 icmp;
|
||||||
EXPECT_EQ(icmp.type(), ICMPv6::ECHO_REQUEST);
|
EXPECT_EQ(icmp.type(), ICMPv6::ECHO_REQUEST);
|
||||||
@@ -166,6 +177,34 @@ TEST_F(ICMPv6Test, ConstructorFromBuffer_MLD2_Layer) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ICMPv6Test, ConstructorFromBuffer_MLQM_Layer) {
|
||||||
|
ICMPv6 icmp(mlqm_icmpv6_layer, sizeof(mlqm_icmpv6_layer));
|
||||||
|
ICMPv6::sources_list sources;
|
||||||
|
sources.push_back("::");
|
||||||
|
sources.push_back("ff02::1");
|
||||||
|
sources.push_back("::");
|
||||||
|
sources.push_back("ff02::1");
|
||||||
|
sources.push_back("ff02::1");
|
||||||
|
sources.push_back("ff02::2");
|
||||||
|
sources.push_back("::1");
|
||||||
|
sources.push_back("ff02::1:ff00:9");
|
||||||
|
EXPECT_EQ(sources, icmp.sources());
|
||||||
|
EXPECT_EQ(0, icmp.supress());
|
||||||
|
EXPECT_EQ(0, icmp.qrv());
|
||||||
|
EXPECT_EQ(0, icmp.qqic());
|
||||||
|
EXPECT_EQ(0, icmp.maximum_response_code());
|
||||||
|
EXPECT_EQ(IPv6Address("ff02::1"), icmp.multicast_addr());
|
||||||
|
|
||||||
|
PDU::serialization_type buffer = icmp.serialize();
|
||||||
|
EXPECT_EQ(
|
||||||
|
PDU::serialization_type(
|
||||||
|
mlqm_icmpv6_layer,
|
||||||
|
mlqm_icmpv6_layer + sizeof(mlqm_icmpv6_layer)
|
||||||
|
),
|
||||||
|
buffer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ICMPv6Test, Type) {
|
TEST_F(ICMPv6Test, Type) {
|
||||||
ICMPv6 icmp;
|
ICMPv6 icmp;
|
||||||
icmp.type(ICMPv6::MLD2_REPORT);
|
icmp.type(ICMPv6::MLD2_REPORT);
|
||||||
@@ -516,6 +555,59 @@ TEST_F(ICMPv6Test, DNSSearchList) {
|
|||||||
EXPECT_EQ(data.domains, output.domains);
|
EXPECT_EQ(data.domains, output.domains);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ICMPv6Test, MLD2Fields) {
|
||||||
|
ICMPv6 icmp;
|
||||||
|
ICMPv6::multicast_address_records_list records;
|
||||||
|
ICMPv6::multicast_address_record r;
|
||||||
|
r.type = 1;
|
||||||
|
r.aux_data.push_back(0xde);
|
||||||
|
r.aux_data.push_back(0xad);
|
||||||
|
r.aux_data.push_back(0xbe);
|
||||||
|
r.aux_data.push_back(0xef);
|
||||||
|
r.aux_data.push_back(0xbe);
|
||||||
|
r.aux_data.push_back(0xad);
|
||||||
|
r.aux_data.push_back(0xfe);
|
||||||
|
r.aux_data.push_back(0xed);
|
||||||
|
r.sources.push_back("::");
|
||||||
|
r.sources.push_back("ff02::1");
|
||||||
|
r.sources.push_back("::");
|
||||||
|
r.sources.push_back("ff02::1");
|
||||||
|
r.sources.push_back("ff02::1");
|
||||||
|
r.sources.push_back("ff02::2");
|
||||||
|
r.sources.push_back("::1");
|
||||||
|
r.sources.push_back("ff02::1:ff00:9");
|
||||||
|
|
||||||
|
records.push_back(r);
|
||||||
|
icmp.multicast_address_records(records);
|
||||||
|
ICMPv6::multicast_address_records_list stored_records;
|
||||||
|
stored_records = icmp.multicast_address_records();
|
||||||
|
ASSERT_EQ(1, stored_records.size());
|
||||||
|
|
||||||
|
ICMPv6::multicast_address_record r2 = *stored_records.begin();
|
||||||
|
EXPECT_EQ(r.type, r2.type);
|
||||||
|
EXPECT_EQ(r.sources, r2.sources);
|
||||||
|
EXPECT_EQ(r.aux_data, r2.aux_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ICMPv6Test, MLQMFields) {
|
||||||
|
ICMPv6 icmp;
|
||||||
|
ICMPv6::sources_list sources;
|
||||||
|
sources.push_back("::");
|
||||||
|
sources.push_back("ff02::1");
|
||||||
|
icmp.sources(sources);
|
||||||
|
icmp.qrv(3);
|
||||||
|
icmp.maximum_response_code(0x928a);
|
||||||
|
icmp.supress(1);
|
||||||
|
icmp.qqic(0xa8);
|
||||||
|
icmp.multicast_addr("feed::beef");
|
||||||
|
EXPECT_EQ(sources, icmp.sources());
|
||||||
|
EXPECT_EQ(1, icmp.supress());
|
||||||
|
EXPECT_EQ(3, icmp.qrv());
|
||||||
|
EXPECT_EQ(0xa8, icmp.qqic());
|
||||||
|
EXPECT_EQ(0x928a, icmp.maximum_response_code());
|
||||||
|
EXPECT_EQ(IPv6Address("feed::beef"), icmp.multicast_addr());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ICMPv6Test, SpoofedOptions) {
|
TEST_F(ICMPv6Test, SpoofedOptions) {
|
||||||
ICMPv6 pdu;
|
ICMPv6 pdu;
|
||||||
uint8_t a[] = { 1,2,3,4,5,6 };
|
uint8_t a[] = { 1,2,3,4,5,6 };
|
||||||
|
|||||||
Reference in New Issue
Block a user