1612 lines
46 KiB
C++
1612 lines
46 KiB
C++
/*
|
|
* Copyright (c) 2017, Matias Fontanini
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following disclaimer
|
|
* in the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#ifndef TINS_ICMPV6_H
|
|
#define TINS_ICMPV6_H
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <tins/macros.h>
|
|
#include <tins/pdu.h>
|
|
#include <tins/ipv6_address.h>
|
|
#include <tins/pdu_option.h>
|
|
#include <tins/endianness.h>
|
|
#include <tins/small_uint.h>
|
|
#include <tins/hw_address.h>
|
|
#include <tins/small_uint.h>
|
|
#include <tins/icmp_extension.h>
|
|
#include <tins/cxxstd.h>
|
|
|
|
namespace Tins {
|
|
namespace Memory {
|
|
|
|
class InputMemoryStream;
|
|
class OutputMemoryStream;
|
|
|
|
} // memory
|
|
|
|
/**
|
|
* \class ICMPv6
|
|
* \brief Represents an ICMPv6 PDU.
|
|
*/
|
|
class TINS_API ICMPv6 : public PDU {
|
|
public:
|
|
/**
|
|
* \brief This PDU's flag.
|
|
*/
|
|
static const PDU::PDUType pdu_flag = PDU::ICMPv6;
|
|
|
|
/**
|
|
* The types of ICMPv6 messages
|
|
*/
|
|
enum Types {
|
|
DEST_UNREACHABLE = 1,
|
|
PACKET_TOOBIG = 2,
|
|
TIME_EXCEEDED = 3,
|
|
PARAM_PROBLEM = 4,
|
|
ECHO_REQUEST = 128,
|
|
ECHO_REPLY = 129,
|
|
MGM_QUERY = 130,
|
|
MGM_REPORT = 131,
|
|
MGM_REDUCTION = 132,
|
|
ROUTER_SOLICIT = 133,
|
|
ROUTER_ADVERT = 134,
|
|
NEIGHBOUR_SOLICIT = 135,
|
|
NEIGHBOUR_ADVERT = 136,
|
|
REDIRECT = 137,
|
|
ROUTER_RENUMBER = 138,
|
|
NI_QUERY = 139,
|
|
NI_REPLY = 140,
|
|
MLD2_REPORT = 143,
|
|
DHAAD_REQUEST = 144,
|
|
DHAAD_REPLY = 145,
|
|
MOBILE_PREFIX_SOLICIT = 146,
|
|
MOBILE_PREFIX_ADVERT = 147,
|
|
CERT_PATH_SOLICIT = 148,
|
|
CERT_PATH_ADVERT = 149,
|
|
MULTICAST_ROUTER_ADVERT = 151,
|
|
MULTICAST_ROUTER_SOLICIT = 152,
|
|
MULTICAST_ROUTER_TERMINATE = 153,
|
|
RPL_CONTROL_MSG = 155,
|
|
EXTENDED_ECHO_REQUEST = 160,
|
|
EXTENDED_ECHO_REPLY = 161
|
|
};
|
|
|
|
/**
|
|
* The types of ICMPv6 options.
|
|
*/
|
|
enum OptionTypes {
|
|
SOURCE_ADDRESS = 1,
|
|
TARGET_ADDRESS,
|
|
PREFIX_INFO,
|
|
REDIRECT_HEADER,
|
|
MTU,
|
|
NBMA_SHORT_LIMIT,
|
|
ADVERT_INTERVAL,
|
|
HOME_AGENT_INFO,
|
|
S_ADDRESS_LIST,
|
|
T_ADDRESS_LIST,
|
|
CGA,
|
|
RSA_SIGN,
|
|
TIMESTAMP,
|
|
NONCE,
|
|
TRUST_ANCHOR,
|
|
CERTIFICATE,
|
|
IP_PREFIX,
|
|
NEW_ROUTER_PREFIX,
|
|
LINK_ADDRESS,
|
|
NAACK,
|
|
MAP = 23,
|
|
ROUTE_INFO,
|
|
RECURSIVE_DNS_SERV,
|
|
RA_FLAGS_EXT,
|
|
HANDOVER_KEY_REQ,
|
|
HANDOVER_KEY_REPLY,
|
|
HANDOVER_ASSIST_INFO,
|
|
MOBILE_NODE_ID,
|
|
DNS_SEARCH_LIST,
|
|
PROXY_SIGNATURE,
|
|
ADDRESS_REG,
|
|
SIXLOWPAN_CONTEXT,
|
|
AUTHORITATIVE_BORDER_ROUTER,
|
|
CARD_REQUEST = 138,
|
|
CARD_REPLY
|
|
};
|
|
|
|
/**
|
|
* The type used to store addresses.
|
|
*/
|
|
typedef IPv6Address ipaddress_type;
|
|
|
|
/**
|
|
* The type used to store addresses.
|
|
*/
|
|
typedef HWAddress<6> hwaddress_type;
|
|
|
|
/**
|
|
* The type used to represent ICMPv6 options.
|
|
*/
|
|
typedef PDUOption<uint8_t, ICMPv6> option;
|
|
|
|
/**
|
|
* The type used to store options.
|
|
*/
|
|
typedef std::vector<option> options_type;
|
|
|
|
/**
|
|
* \brief The type used to store the new home agent information
|
|
* option data.
|
|
*/
|
|
typedef std::vector<uint16_t> new_ha_info_type;
|
|
|
|
/**
|
|
* The type used to store the source/target address list options.
|
|
*/
|
|
struct addr_list_type {
|
|
typedef std::vector<ipaddress_type> addresses_type;
|
|
|
|
uint8_t reserved[6];
|
|
addresses_type addresses;
|
|
|
|
addr_list_type(const addresses_type& addresses = addresses_type())
|
|
: addresses(addresses) {
|
|
std::fill(reserved, reserved + sizeof(reserved), static_cast<uint8_t>(0));
|
|
}
|
|
|
|
static addr_list_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the nonce option data.
|
|
*/
|
|
typedef std::vector<uint8_t> nonce_type;
|
|
|
|
/**
|
|
* The type used to store the MTU option.
|
|
*/
|
|
typedef std::pair<uint16_t, uint32_t> mtu_type;
|
|
|
|
/**
|
|
* \brief The type used to store the neighbour advertisement
|
|
* acknowledgement option data.
|
|
*/
|
|
struct naack_type {
|
|
uint8_t code, status;
|
|
uint8_t reserved[4];
|
|
|
|
naack_type(uint8_t code = 0, uint8_t status = 0)
|
|
: code(code), status(status) {
|
|
std::fill(reserved, reserved + 4, static_cast<uint8_t>(0));
|
|
}
|
|
|
|
static naack_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* \brief The type used to store the link layer address option data.
|
|
*/
|
|
struct lladdr_type {
|
|
typedef std::vector<uint8_t> address_type;
|
|
|
|
uint8_t option_code;
|
|
address_type address;
|
|
|
|
/**
|
|
* Constructor taking an option code and an address.
|
|
*
|
|
* \param option_code The option code.
|
|
* \param address The address to be stored.
|
|
*/
|
|
lladdr_type(uint8_t option_code = 0,
|
|
const address_type& address = address_type())
|
|
: option_code(option_code), address(address) {
|
|
|
|
}
|
|
|
|
/**
|
|
* \brief Constructor taking an option code and hwaddress_type.
|
|
*
|
|
* This is a helper constructor, since it'll be common to use
|
|
* hwaddress_type as the link layer address.
|
|
*
|
|
* \param option_code The option code.
|
|
* \param address The address to be stored.
|
|
*/
|
|
lladdr_type(uint8_t option_code, const hwaddress_type& address)
|
|
: option_code(option_code), address(address.begin(), address.end()) {
|
|
|
|
}
|
|
|
|
static lladdr_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* Type type used to store the prefix information option data.
|
|
*/
|
|
struct prefix_info_type {
|
|
uint8_t prefix_len;
|
|
small_uint<1> A, L;
|
|
uint32_t valid_lifetime,
|
|
preferred_lifetime,
|
|
reserved2;
|
|
ipaddress_type prefix;
|
|
|
|
prefix_info_type(uint8_t prefix_len = 0,
|
|
small_uint<1> A = 0,
|
|
small_uint<1> L = 0,
|
|
uint32_t valid_lifetime = 0,
|
|
uint32_t preferred_lifetime = 0,
|
|
const ipaddress_type& prefix = ipaddress_type())
|
|
: prefix_len(prefix_len), A(A), L(L), valid_lifetime(valid_lifetime),
|
|
preferred_lifetime(preferred_lifetime), reserved2(0), prefix(prefix) { }
|
|
|
|
static prefix_info_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the RSA signature option.
|
|
*/
|
|
struct rsa_sign_type {
|
|
typedef std::vector<uint8_t> signature_type;
|
|
|
|
uint8_t key_hash[16];
|
|
signature_type signature;
|
|
|
|
/**
|
|
* \brief Constructs a rsa_sign_type object.
|
|
*
|
|
* The first parameter must be a random access iterator
|
|
* which will be used to initialize the key_hash member.
|
|
* It is assumed that std::distance(hash, end_of_hash) >= 16.
|
|
*
|
|
* The second and third arguments indicate the start and end of
|
|
* the sequence which will be used to initialize the signature
|
|
* member.
|
|
*
|
|
* \param hash A random access iterator used to initialize the
|
|
* key_hash member.
|
|
* \param start A forward iterator pointing to the start of the
|
|
* sequence which will be used to initialize the signature member.
|
|
* \param end A forward iterator pointing to the end of the
|
|
* sequence used to initialize signature.
|
|
*/
|
|
template <typename RAIterator, typename ForwardIterator>
|
|
rsa_sign_type(RAIterator hash, ForwardIterator start, ForwardIterator end)
|
|
: signature(start, end) {
|
|
std::copy(hash, hash + sizeof(key_hash), key_hash);
|
|
}
|
|
|
|
/**
|
|
* \brief Constructs a rsa_sign_type object.
|
|
*
|
|
* The first parameter must be a random access iterator
|
|
* which will be used to initialize the key_hash member.
|
|
* It is assumed that std::distance(hash, end_of_hash) >= 16.
|
|
*
|
|
*
|
|
* \param hash A random access iterator used to initialize the
|
|
* key_hash member.
|
|
* \param sign The signature to be set.
|
|
*/
|
|
template <typename RAIterator>
|
|
rsa_sign_type(RAIterator hash, const signature_type& sign)
|
|
: signature(sign) {
|
|
std::copy(hash, hash + sizeof(key_hash), key_hash);
|
|
}
|
|
|
|
/**
|
|
* \brief Default constructs a rsa_sign_type.
|
|
*
|
|
* The key_hash member will be 0-initialized.
|
|
*/
|
|
rsa_sign_type() {
|
|
std::fill(key_hash, key_hash + sizeof(key_hash), static_cast<uint8_t>(0));
|
|
}
|
|
|
|
static rsa_sign_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store IP address/preffix option.
|
|
*/
|
|
struct ip_prefix_type {
|
|
uint8_t option_code, prefix_len;
|
|
ipaddress_type address;
|
|
|
|
ip_prefix_type(uint8_t option_code = 0,
|
|
uint8_t prefix_len = 0,
|
|
const ipaddress_type& address = ipaddress_type())
|
|
: option_code(option_code), prefix_len(prefix_len), address(address)
|
|
{}
|
|
|
|
static ip_prefix_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the map option.
|
|
*/
|
|
struct map_type {
|
|
small_uint<4> dist, pref;
|
|
small_uint<1> r;
|
|
uint32_t valid_lifetime;
|
|
ipaddress_type address;
|
|
|
|
map_type(small_uint<4> dist = 0,
|
|
small_uint<4> pref = 0,
|
|
small_uint<1> r = 0,
|
|
uint32_t valid_lifetime = 0,
|
|
const ipaddress_type& address = ipaddress_type())
|
|
: dist(dist), pref(pref), r(r), valid_lifetime(valid_lifetime),
|
|
address(address) { }
|
|
|
|
static map_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the route information option.
|
|
*/
|
|
struct route_info_type {
|
|
typedef std::vector<uint8_t> prefix_type;
|
|
|
|
uint8_t prefix_len;
|
|
small_uint<2> pref;
|
|
uint32_t route_lifetime;
|
|
prefix_type prefix;
|
|
|
|
route_info_type(uint8_t prefix_len = 0,
|
|
small_uint<2> pref = 0,
|
|
uint32_t route_lifetime = 0,
|
|
const prefix_type& prefix = prefix_type())
|
|
: prefix_len(prefix_len), pref(pref), route_lifetime(route_lifetime),
|
|
prefix(prefix) { }
|
|
|
|
static route_info_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the recursive DNS servers option.
|
|
*/
|
|
struct recursive_dns_type {
|
|
typedef std::vector<ipaddress_type> servers_type;
|
|
|
|
uint32_t lifetime;
|
|
servers_type servers;
|
|
|
|
recursive_dns_type(uint32_t lifetime = 0,
|
|
const servers_type& servers = servers_type())
|
|
: lifetime(lifetime), servers(servers) {}
|
|
|
|
static recursive_dns_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the handover key request option.
|
|
*/
|
|
struct handover_key_req_type {
|
|
typedef std::vector<uint8_t> key_type;
|
|
|
|
small_uint<4> AT;
|
|
key_type key;
|
|
|
|
handover_key_req_type(small_uint<4> AT = 0,
|
|
const key_type& key = key_type())
|
|
: AT(AT), key(key) { }
|
|
|
|
static handover_key_req_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the handover key reply option.
|
|
*/
|
|
struct handover_key_reply_type : handover_key_req_type {
|
|
uint16_t lifetime;
|
|
|
|
handover_key_reply_type(uint16_t lifetime = 0,
|
|
small_uint<4> AT = 0,
|
|
const key_type& key = key_type())
|
|
: handover_key_req_type(AT, key), lifetime(lifetime) { }
|
|
|
|
static handover_key_reply_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the handover assist information option.
|
|
*/
|
|
struct handover_assist_info_type {
|
|
typedef std::vector<uint8_t> hai_type;
|
|
|
|
uint8_t option_code;
|
|
hai_type hai;
|
|
|
|
handover_assist_info_type(uint8_t option_code=0,
|
|
const hai_type& hai = hai_type())
|
|
: option_code(option_code), hai(hai) { }
|
|
|
|
static handover_assist_info_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the mobile node identifier option.
|
|
*/
|
|
struct mobile_node_id_type {
|
|
typedef std::vector<uint8_t> mn_type;
|
|
|
|
uint8_t option_code;
|
|
mn_type mn;
|
|
|
|
mobile_node_id_type(uint8_t option_code=0,
|
|
const mn_type& mn = mn_type())
|
|
: option_code(option_code), mn(mn) { }
|
|
|
|
static mobile_node_id_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the DNS search list option.
|
|
*/
|
|
struct dns_search_list_type {
|
|
typedef std::vector<std::string> domains_type;
|
|
|
|
uint32_t lifetime;
|
|
domains_type domains;
|
|
|
|
dns_search_list_type(uint32_t lifetime = 0,
|
|
const domains_type& domains = domains_type())
|
|
: lifetime(lifetime), domains(domains) { }
|
|
|
|
static dns_search_list_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the timestamp option.
|
|
*/
|
|
struct timestamp_type {
|
|
uint8_t reserved[6];
|
|
uint64_t timestamp;
|
|
|
|
timestamp_type(uint64_t timestamp = 0)
|
|
: timestamp(timestamp) {
|
|
std::fill(reserved, reserved + sizeof(reserved), static_cast<uint8_t>(0));
|
|
}
|
|
|
|
static timestamp_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store the shortcut limit option.
|
|
*/
|
|
struct shortcut_limit_type {
|
|
uint8_t limit, reserved1;
|
|
uint32_t reserved2;
|
|
|
|
shortcut_limit_type(uint8_t limit = 0)
|
|
: limit(limit), reserved1(), reserved2() {
|
|
|
|
}
|
|
|
|
static shortcut_limit_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to store new advertisement interval option.
|
|
*/
|
|
struct new_advert_interval_type {
|
|
uint16_t reserved;
|
|
uint32_t interval;
|
|
|
|
new_advert_interval_type(uint32_t interval = 0)
|
|
: reserved(), interval(interval) {
|
|
|
|
}
|
|
|
|
static new_advert_interval_type from_option(const option& opt);
|
|
};
|
|
|
|
/**
|
|
* The type used to represent a multicast address record
|
|
*/
|
|
struct multicast_address_record {
|
|
typedef std::vector<ipaddress_type> sources_type;
|
|
typedef std::vector<uint8_t> aux_data_type;
|
|
|
|
multicast_address_record(uint8_t type = 0) : type(type) { }
|
|
|
|
multicast_address_record(const uint8_t* buffer, uint32_t total_sz);
|
|
void serialize(uint8_t* buffer, uint32_t total_sz) const;
|
|
uint32_t size() const;
|
|
|
|
uint8_t type;
|
|
ipaddress_type multicast_address;
|
|
sources_type sources;
|
|
aux_data_type aux_data;
|
|
};
|
|
|
|
/*
|
|
* The type used to store all multicast address records in a packet
|
|
*/
|
|
typedef std::vector<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::vector<ipaddress_type> sources_list;
|
|
|
|
/**
|
|
* \brief Constructs an ICMPv6 object.
|
|
*
|
|
* The type of the constructed object will be an echo request, unless
|
|
* you provide another one in the tp parameter.
|
|
*
|
|
* \param tp The message type of this ICMPv6 object.
|
|
*/
|
|
ICMPv6(Types tp = ECHO_REQUEST);
|
|
|
|
/**
|
|
* \brief Constructs an ICMPv6 object from a buffer.
|
|
*
|
|
* If there is not enough size for an ICMPv6 header, a
|
|
* malformed_packet exception is thrown.
|
|
*
|
|
* Any extra data is stored in a RawPDU.
|
|
*
|
|
* \param buffer The buffer from which this PDU will be constructed.
|
|
* \param total_sz The total size of the buffer.
|
|
*/
|
|
ICMPv6(const uint8_t* buffer, uint32_t total_sz);
|
|
|
|
// Getters
|
|
|
|
/**
|
|
* \brief Getter for the type field.
|
|
* \return The stored type field value.
|
|
*/
|
|
Types type() const {
|
|
return static_cast<Types>(header_.type);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the code field.
|
|
* \return The stored code field value.
|
|
*/
|
|
uint8_t code() const {
|
|
return header_.code;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the cksum field.
|
|
* \return The stored cksum field value.
|
|
*/
|
|
uint16_t checksum() const {
|
|
return Endian::be_to_host(header_.cksum);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the identifier field.
|
|
* \return The stored identifier field value.
|
|
*/
|
|
uint16_t identifier() const {
|
|
return Endian::be_to_host(header_.u_echo.identifier);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the sequence field.
|
|
* \return The stored sequence field value.
|
|
*/
|
|
uint16_t sequence() const {
|
|
return Endian::be_to_host(header_.u_echo.sequence);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the override field.
|
|
* \return The stored override field value.
|
|
*/
|
|
small_uint<1> override() const {
|
|
return header_.u_nd_advt.override;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the solicited field.
|
|
* \return The stored solicited field value.
|
|
*/
|
|
small_uint<1> solicited() const {
|
|
return header_.u_nd_advt.solicited;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the router field.
|
|
* \return The stored router field value.
|
|
*/
|
|
small_uint<1> router() const {
|
|
return header_.u_nd_advt.router;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the hop limit field.
|
|
* \return The stored hop limit field value.
|
|
*/
|
|
uint8_t hop_limit() const {
|
|
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.
|
|
* \return The stored router_pref field value.
|
|
*/
|
|
small_uint<2> router_pref() const {
|
|
return header_.u_nd_ra.router_pref;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the home_agent field.
|
|
* \return The stored home_agent field value.
|
|
*/
|
|
small_uint<1> home_agent() const {
|
|
return header_.u_nd_ra.home_agent;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the other field.
|
|
* \return The stored other field value.
|
|
*/
|
|
small_uint<1> other() const {
|
|
return header_.u_nd_ra.other;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the managed field.
|
|
* \return The stored managed field value.
|
|
*/
|
|
small_uint<1> managed() const {
|
|
return header_.u_nd_ra.managed;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the router_lifetime field.
|
|
* \return The stored router_lifetime field value.
|
|
*/
|
|
uint16_t router_lifetime() const {
|
|
return Endian::be_to_host(header_.u_nd_ra.router_lifetime);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the reachable_time field.
|
|
* \return The stored reachable_time field value.
|
|
*/
|
|
uint32_t reachable_time() const {
|
|
return Endian::be_to_host(reach_time_);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the retransmit_timer field.
|
|
* \return The stored retransmit_timer field value.
|
|
*/
|
|
uint32_t retransmit_timer() const {
|
|
return Endian::be_to_host(retrans_timer_);
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the target address field.
|
|
* \return The stored target address field value.
|
|
*/
|
|
const ipaddress_type& target_addr() const {
|
|
return target_address_;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the destination address field.
|
|
* \return The stored destination address field value.
|
|
*/
|
|
const ipaddress_type& dest_addr() const {
|
|
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.
|
|
* \return The stored options.
|
|
*/
|
|
const options_type& options() const {
|
|
return options_;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the length field.
|
|
*
|
|
* \return Returns the length field value.
|
|
*/
|
|
uint8_t length() const {
|
|
return header_.rfc4884.length;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the multicast address records field
|
|
*/
|
|
const multicast_address_records_list& multicast_address_records() const {
|
|
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
|
|
|
|
/**
|
|
* \brief Setter for the type field.
|
|
* \param new_type The new type field value.
|
|
*/
|
|
void type(Types new_type);
|
|
|
|
/**
|
|
* \brief Setter for the code field.
|
|
* \param new_code The new code field value.
|
|
*/
|
|
void code(uint8_t new_code);
|
|
|
|
/**
|
|
* \brief Setter for the cksum field.
|
|
* \param new_cksum The new cksum field value.
|
|
*/
|
|
void checksum(uint16_t new_cksum);
|
|
|
|
/**
|
|
* \brief Setter for the identifier field.
|
|
* \param new_identifier The new identifier field value.
|
|
*/
|
|
void identifier(uint16_t new_identifier);
|
|
|
|
/**
|
|
* \brief Setter for the sequence field.
|
|
* \param new_sequence The new sequence field value.
|
|
*/
|
|
void sequence(uint16_t new_sequence);
|
|
|
|
/**
|
|
* \brief Setter for the override field.
|
|
* \param new_override The new override field value.
|
|
*/
|
|
void override(small_uint<1> new_override);
|
|
|
|
/**
|
|
* \brief Setter for the solicited field.
|
|
* \param new_solicited The new solicited field value.
|
|
*/
|
|
void solicited(small_uint<1> new_solicited);
|
|
|
|
/**
|
|
* \brief Setter for the router field.
|
|
* \param new_router The new router field value.
|
|
*/
|
|
void router(small_uint<1> new_router);
|
|
|
|
/**
|
|
* \brief Setter for the hop_limit field.
|
|
* \param new_hop_limit The new hop_limit field value.
|
|
*/
|
|
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.
|
|
* \param new_router_pref The new router_pref field value.
|
|
*/
|
|
void router_pref(small_uint<2> new_router_pref);
|
|
|
|
/**
|
|
* \brief Setter for the home_agent field.
|
|
* \param new_home_agent The new home_agent field value.
|
|
*/
|
|
void home_agent(small_uint<1> new_home_agent);
|
|
|
|
/**
|
|
* \brief Setter for the other field.
|
|
* \param new_other The new other field value.
|
|
*/
|
|
void other(small_uint<1> new_other);
|
|
|
|
/**
|
|
* \brief Setter for the managed field.
|
|
* \param new_managed The new managed field value.
|
|
*/
|
|
void managed(small_uint<1> new_managed);
|
|
|
|
/**
|
|
* \brief Setter for the router_lifetime field.
|
|
* \param new_router_lifetime The new router_lifetime field value.
|
|
*/
|
|
void router_lifetime(uint16_t new_router_lifetime);
|
|
|
|
/**
|
|
* \brief Setter for the target address field.
|
|
* \param new_target_addr The new target address field value.
|
|
*/
|
|
void target_addr(const ipaddress_type& new_target_addr);
|
|
|
|
/**
|
|
* \brief Setter for the destination address field.
|
|
* \param new_dest_addr The new destination address field value.
|
|
*/
|
|
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.
|
|
* \param new_reachable_time The new reachable_time field value.
|
|
*/
|
|
void reachable_time(uint32_t new_reachable_time);
|
|
|
|
/**
|
|
* \brief Setter for the retransmit_timer field.
|
|
* \param new_retrans_timer The new retrans_timer field value.
|
|
*/
|
|
void retransmit_timer(uint32_t new_retrans_timer);
|
|
|
|
/**
|
|
* \brief Setter for the multicast address records field.
|
|
*
|
|
* This field is only valid if the type of this PDU is MLD2_REPORT
|
|
*/
|
|
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.
|
|
*
|
|
* \sa PDU::pdu_type
|
|
*/
|
|
PDUType pdu_type() const { return pdu_flag; }
|
|
|
|
/**
|
|
* \brief Checks whether this ICMPv6 object has a target_addr field.
|
|
*
|
|
* This depends on the type field.
|
|
*/
|
|
bool has_target_addr() const {
|
|
return type() == NEIGHBOUR_SOLICIT ||
|
|
type() == NEIGHBOUR_ADVERT ||
|
|
type() == REDIRECT;
|
|
}
|
|
|
|
/**
|
|
* \brief Checks whether this ICMPv6 object has a target_addr field.
|
|
*
|
|
* This depends on the type field.
|
|
*/
|
|
bool has_dest_addr() const {
|
|
return type() == REDIRECT;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds an ICMPv6 option.
|
|
*
|
|
* The option is added after the last option in the option
|
|
* fields.
|
|
*
|
|
* \param option The option to be added
|
|
*/
|
|
void add_option(const option& option);
|
|
|
|
#if TINS_IS_CXX11
|
|
/**
|
|
* \brief Adds an ICMPv6 option.
|
|
*
|
|
* The option is move-constructed.
|
|
*
|
|
* \param option The option to be added.
|
|
*/
|
|
void add_option(option &&option) {
|
|
internal_add_option(option);
|
|
options_.push_back(std::move(option));
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* \brief Removes an ICMPv6 option.
|
|
*
|
|
* If there are multiple options of the given type, only the first one
|
|
* will be removed.
|
|
*
|
|
* \param type The type of the option to be removed.
|
|
* \return true if the option was removed, false otherwise.
|
|
*/
|
|
bool remove_option(OptionTypes type);
|
|
|
|
/**
|
|
* \brief Returns the header size.
|
|
*
|
|
* This method overrides PDU::header_size. This size includes the
|
|
* payload and options size. \sa PDU::header_size
|
|
*/
|
|
uint32_t header_size() const;
|
|
|
|
/**
|
|
* \brief Returns the trailer size.
|
|
*
|
|
* This method overrides PDU::trailer_size. This size will hold the extensions size
|
|
*
|
|
* \sa PDU::header_size
|
|
*/
|
|
uint32_t trailer_size() const;
|
|
|
|
/**
|
|
* \brief Getter for the extensions field.
|
|
*
|
|
* \return The extensions field
|
|
*/
|
|
const ICMPExtensionsStructure& extensions() const {
|
|
return extensions_;
|
|
}
|
|
|
|
/**
|
|
* \brief Getter for the extensions field.
|
|
*
|
|
* \return The extensions field
|
|
*/
|
|
ICMPExtensionsStructure& extensions() {
|
|
return extensions_;
|
|
}
|
|
|
|
/**
|
|
* \brief Indicates whether this object contains ICMP extensions
|
|
*/
|
|
bool has_extensions() const {
|
|
return !extensions_.extensions().empty();
|
|
}
|
|
|
|
/**
|
|
* \brief Sets whether the length field will be set for packets that use it
|
|
*
|
|
* As defined in RFC 4884, some ICMP packet types can have a length field. This
|
|
* method controlers whether the length field is set or not.
|
|
*
|
|
* Note that this only indicates that the packet should use this field. The
|
|
* actual value will be set during the packet's serialization.
|
|
*
|
|
* Note that, in order to br RFC compliant, if the size of the encapsulated
|
|
* PDU is greater than 128, the length field will always be set, regardless
|
|
* of whether this method was called or not.
|
|
*
|
|
* /param value true iff the length field should be set appropriately
|
|
*/
|
|
void use_length_field(bool value);
|
|
|
|
/**
|
|
* \brief Check whether ptr points to a valid response for this PDU.
|
|
*
|
|
* \sa PDU::matches_response
|
|
* \param ptr The pointer to the buffer.
|
|
* \param total_sz The size of the buffer.
|
|
*/
|
|
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
|
|
|
/**
|
|
* \brief Searchs for an option that matchs the given flag.
|
|
*
|
|
* If the header is not found, a null pointer is returned.
|
|
* Deleting the returned pointer will result in <b>undefined
|
|
* behaviour</b>.
|
|
*
|
|
* \param type The option identifier to be searched.
|
|
*/
|
|
const option* search_option(OptionTypes type) const;
|
|
|
|
/**
|
|
* \sa PDU::clone
|
|
*/
|
|
ICMPv6* clone() const {
|
|
return new ICMPv6(*this);
|
|
}
|
|
|
|
/**
|
|
* \brief Indicates whether to use MLDv2
|
|
*
|
|
* If this is set to true, then MLDv2 will be used rather than MLDv1 when
|
|
* serializing Multicast Listener Discovery messages. By default,
|
|
* MLDv2 will be used.
|
|
*
|
|
* \param value The value to set
|
|
*/
|
|
void use_mldv2(bool value);
|
|
|
|
// ****************************************************************
|
|
// Option setters
|
|
// ****************************************************************
|
|
|
|
/**
|
|
* \brief Setter for the source link layer address option.
|
|
*
|
|
* \param addr The source link layer address.
|
|
*/
|
|
void source_link_layer_addr(const hwaddress_type& addr);
|
|
|
|
/**
|
|
* \brief Setter for the target link layer address option.
|
|
*
|
|
* \param addr The target link layer address.
|
|
*/
|
|
void target_link_layer_addr(const hwaddress_type& addr);
|
|
|
|
/**
|
|
* \brief Setter for the prefix information option.
|
|
*
|
|
* \param info The prefix information.
|
|
*/
|
|
void prefix_info(prefix_info_type info);
|
|
|
|
/**
|
|
* \brief Setter for the redirect header option.
|
|
*
|
|
* \param data The redirect header option data.
|
|
*/
|
|
void redirect_header(const byte_array& data);
|
|
|
|
/**
|
|
* \brief Setter for the MTU option.
|
|
*
|
|
* \param value The MTU option data.
|
|
*/
|
|
void mtu(const mtu_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the shortcut limit option.
|
|
*
|
|
* \param value The shortcut limit option data.
|
|
*/
|
|
void shortcut_limit(const shortcut_limit_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new advertisement interval option.
|
|
*
|
|
* \param value The new advertisement interval option data.
|
|
*/
|
|
void new_advert_interval(const new_advert_interval_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new home agent information option.
|
|
*
|
|
* \param value The new home agent information option data.
|
|
*/
|
|
void new_home_agent_info(const new_ha_info_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new source address list option.
|
|
*
|
|
* \param value The new source address list option data.
|
|
*/
|
|
void source_addr_list(const addr_list_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new target address list option.
|
|
*
|
|
* \param value The new target address list option data.
|
|
*/
|
|
void target_addr_list(const addr_list_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new RSA signature option.
|
|
*
|
|
* \param value The new RSA signature option data.
|
|
*/
|
|
void rsa_signature(const rsa_sign_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new timestamp option.
|
|
*
|
|
* \param value The new timestamp option data.
|
|
*/
|
|
void timestamp(const timestamp_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new nonce option.
|
|
*
|
|
* \param value The new nonce option data.
|
|
*/
|
|
void nonce(const nonce_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new IP address/prefix option.
|
|
*
|
|
* \param value The new IP address/prefix option data.
|
|
*/
|
|
void ip_prefix(const ip_prefix_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the new link layer address option.
|
|
*
|
|
* \param value The new link layer address option data.
|
|
*/
|
|
void link_layer_addr(lladdr_type value);
|
|
|
|
/**
|
|
* \brief Setter for the neighbour advertisement acknowledgement option.
|
|
*
|
|
* \param value The new naack option data.
|
|
*/
|
|
void naack(const naack_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the map option.
|
|
*
|
|
* \param value The new map option data.
|
|
*/
|
|
void map(const map_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the route information option.
|
|
*
|
|
* \param value The new route information option data.
|
|
*/
|
|
void route_info(const route_info_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the recursive DNS servers option.
|
|
*
|
|
* \param value The new recursive DNS servers option data.
|
|
*/
|
|
void recursive_dns_servers(const recursive_dns_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the handover key request option.
|
|
*
|
|
* \param value The new handover key request option data.
|
|
*/
|
|
void handover_key_request(const handover_key_req_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the handover key reply option.
|
|
*
|
|
* \param value The new handover key reply option data.
|
|
*/
|
|
void handover_key_reply(const handover_key_reply_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the handover assist info option.
|
|
*
|
|
* \param value The new handover assist info option data.
|
|
*/
|
|
void handover_assist_info(const handover_assist_info_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the mobile node identifier option.
|
|
*
|
|
* \param value The new mobile node identifier option data.
|
|
*/
|
|
void mobile_node_identifier(const mobile_node_id_type& value);
|
|
|
|
/**
|
|
* \brief Setter for the DNS search list option.
|
|
*
|
|
* \param value The new DNS search list option data.
|
|
*/
|
|
void dns_search_list(const dns_search_list_type& value);
|
|
|
|
// ****************************************************************
|
|
// Option getters
|
|
// ****************************************************************
|
|
|
|
/**
|
|
* \brief Getter for the source link layer address option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
hwaddress_type source_link_layer_addr() const;
|
|
|
|
/**
|
|
* \brief Getter for the target link layer address option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
hwaddress_type target_link_layer_addr() const;
|
|
|
|
/**
|
|
* \brief Getter for the prefix information option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
prefix_info_type prefix_info() const;
|
|
|
|
/**
|
|
* \brief Getter for the redirect header option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
byte_array redirect_header() const;
|
|
|
|
/**
|
|
* \brief Getter for the MTU option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
mtu_type mtu() const;
|
|
|
|
/**
|
|
* \brief Getter for the shortcut limit option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
shortcut_limit_type shortcut_limit() const;
|
|
|
|
/**
|
|
* \brief Getter for the new advertisement interval option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
new_advert_interval_type new_advert_interval() const;
|
|
|
|
/**
|
|
* \brief Getter for the new home agent information option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
new_ha_info_type new_home_agent_info() const;
|
|
|
|
/**
|
|
* \brief Getter for the source address list option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
addr_list_type source_addr_list() const;
|
|
|
|
/**
|
|
* \brief Getter for the target address list option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
addr_list_type target_addr_list() const;
|
|
|
|
/**
|
|
* \brief Getter for the RSA signature option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
rsa_sign_type rsa_signature() const;
|
|
|
|
/**
|
|
* \brief Getter for the timestamp option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
timestamp_type timestamp() const;
|
|
|
|
/**
|
|
* \brief Getter for the nonce option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
nonce_type nonce() const;
|
|
|
|
/**
|
|
* \brief Getter for the IP address/prefix option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
ip_prefix_type ip_prefix() const;
|
|
|
|
/**
|
|
* \brief Getter for the link layer address option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
lladdr_type link_layer_addr() const;
|
|
|
|
/**
|
|
* \brief Getter for the neighbour advertisement acknowledgement
|
|
* option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
naack_type naack() const;
|
|
|
|
/**
|
|
* \brief Getter for the map option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
map_type map() const;
|
|
|
|
/**
|
|
* \brief Getter for the route information option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
route_info_type route_info() const;
|
|
|
|
/**
|
|
* \brief Getter for the recursive dns servers option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
recursive_dns_type recursive_dns_servers() const;
|
|
|
|
/**
|
|
* \brief Getter for the handover key request option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
handover_key_req_type handover_key_request() const;
|
|
|
|
/**
|
|
* \brief Getter for the handover key reply option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
handover_key_reply_type handover_key_reply() const;
|
|
|
|
/**
|
|
* \brief Getter for the handover key reply option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
handover_assist_info_type handover_assist_info() const;
|
|
|
|
/**
|
|
* \brief Getter for the mobile node identifier option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
mobile_node_id_type mobile_node_identifier() const;
|
|
|
|
/**
|
|
* \brief Getter for the mobile node identifier option.
|
|
*
|
|
* This method will throw an option_not_found exception if the
|
|
* option is not found.
|
|
*/
|
|
dns_search_list_type dns_search_list() const;
|
|
private:
|
|
TINS_BEGIN_PACK
|
|
struct icmp6_header {
|
|
uint8_t type;
|
|
uint8_t code;
|
|
uint16_t cksum;
|
|
union {
|
|
struct {
|
|
uint16_t identifier;
|
|
uint16_t sequence;
|
|
} u_echo;
|
|
|
|
struct {
|
|
#if TINS_IS_LITTLE_ENDIAN
|
|
uint32_t reserved:5,
|
|
override:1,
|
|
solicited:1,
|
|
router:1,
|
|
reserved2:24;
|
|
#else
|
|
uint32_t router:1,
|
|
solicited:1,
|
|
override:1,
|
|
reserved:29;
|
|
#endif
|
|
} u_nd_advt;
|
|
struct {
|
|
uint8_t hop_limit;
|
|
#if TINS_IS_LITTLE_ENDIAN
|
|
uint8_t reserved:3,
|
|
router_pref:2,
|
|
home_agent:1,
|
|
other:1,
|
|
managed:1;
|
|
#else
|
|
uint8_t managed:1,
|
|
other:1,
|
|
home_agent:1,
|
|
router_pref:2,
|
|
reserved:3;
|
|
#endif
|
|
uint16_t router_lifetime;
|
|
} u_nd_ra;
|
|
struct {
|
|
uint8_t length;
|
|
uint8_t unused[3];
|
|
} rfc4884;
|
|
// Multicast Listener Report Message (mld2)
|
|
struct {
|
|
uint16_t reserved;
|
|
uint16_t record_count;
|
|
} mlrm2;
|
|
};
|
|
} 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 write_serialization(uint8_t* buffer, uint32_t total_sz);
|
|
bool has_options() const;
|
|
void write_option(const option& opt, Memory::OutputMemoryStream& stream);
|
|
void parse_options(Memory::InputMemoryStream& stream);
|
|
void add_addr_list(uint8_t type, const addr_list_type& value);
|
|
addr_list_type search_addr_list(OptionTypes type) const;
|
|
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
|
options_type::iterator search_option_iterator(OptionTypes type);
|
|
void try_parse_extensions(Memory::InputMemoryStream& stream);
|
|
bool are_extensions_allowed() const;
|
|
uint32_t get_adjusted_inner_pdu_size() const;
|
|
uint8_t get_option_padding(uint32_t data_size);
|
|
|
|
template <template <typename> class Functor>
|
|
const option* safe_search_option(OptionTypes opt, uint32_t size) const {
|
|
const option* option = search_option(opt);
|
|
if (!option || Functor<uint32_t>()(option->data_size(), size)) {
|
|
throw option_not_found();
|
|
}
|
|
return option;
|
|
}
|
|
|
|
template <typename T>
|
|
T search_and_convert(OptionTypes type) const {
|
|
const option* opt = search_option(type);
|
|
if (!opt) {
|
|
throw option_not_found();
|
|
}
|
|
return opt->to<T>();
|
|
}
|
|
|
|
icmp6_header header_;
|
|
ipaddress_type target_address_;
|
|
ipaddress_type dest_address_;
|
|
ipaddress_type multicast_address_;
|
|
options_type options_;
|
|
uint32_t options_size_;
|
|
uint32_t reach_time_, retrans_timer_;
|
|
multicast_address_records_list multicast_records_;
|
|
multicast_listener_query_message_fields mlqm_;
|
|
sources_list sources_;
|
|
ICMPExtensionsStructure extensions_;
|
|
bool use_mldv2_;
|
|
};
|
|
|
|
} // Tins
|
|
|
|
#endif // TINS_ICMPV6_H
|