mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Merge branch 'develop'
This commit is contained in:
@@ -40,13 +40,30 @@ using std::vector;
|
||||
using namespace Tins;
|
||||
|
||||
int main() {
|
||||
vector<Utils::RouteEntry> entries = Utils::route_entries();
|
||||
for (size_t i = 0; i < entries.size(); ++i) {
|
||||
vector<Utils::RouteEntry> v4_entries = Utils::route_entries();
|
||||
cout << "IPv4 route table entries: " << endl
|
||||
<< "========================= " << endl;
|
||||
for (size_t i = 0; i < v4_entries.size(); ++i) {
|
||||
cout << "Entry " << setw(2) << i << ": " << endl
|
||||
<< "Interface: " << entries[i].interface << endl
|
||||
<< "Destination: " << entries[i].destination << endl
|
||||
<< "Gateway: " << entries[i].gateway << endl
|
||||
<< "Genmask: " << entries[i].mask << endl
|
||||
<< "Metric: " << entries[i].metric << endl << endl;
|
||||
<< "Interface: " << v4_entries[i].interface << endl
|
||||
<< "Destination: " << v4_entries[i].destination << endl
|
||||
<< "Gateway: " << v4_entries[i].gateway << endl
|
||||
<< "Genmask: " << v4_entries[i].mask << endl
|
||||
<< "Metric: " << v4_entries[i].metric << endl << endl;
|
||||
}
|
||||
|
||||
vector<Utils::Route6Entry> v6_entries = Utils::route6_entries();
|
||||
if (!v6_entries.empty()) {
|
||||
cout << endl
|
||||
<< "IPv6 route table entries: " << endl
|
||||
<< "========================= " << endl;
|
||||
for (size_t i = 0; i < v6_entries.size(); ++i) {
|
||||
cout << "Entry " << setw(2) << i << ": " << endl
|
||||
<< "Interface: " << v6_entries[i].interface << endl
|
||||
<< "Destination: " << v6_entries[i].destination << endl
|
||||
<< "Gateway: " << v6_entries[i].gateway << endl
|
||||
<< "Genmask: " << v6_entries[i].mask << endl
|
||||
<< "Metric: " << v6_entries[i].metric << endl << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,14 @@
|
||||
* 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
|
||||
@@ -125,10 +125,10 @@ private:
|
||||
* \brief Represents a range of addresses.
|
||||
*
|
||||
* This class provides a begin()/end() interface which allows
|
||||
* iterating through every address stored in it.
|
||||
* iterating through every address stored in it.
|
||||
*
|
||||
* Note that when iterating a range that was created using
|
||||
* operator/(IPv4Address, int) and the analog for IPv6, the
|
||||
* operator/(IPv4Address, int) and the analog for IPv6, the
|
||||
* network and broadcast addresses are discarded:
|
||||
*
|
||||
* \code
|
||||
@@ -139,12 +139,12 @@ private:
|
||||
* }
|
||||
*
|
||||
* // That's only valid for iteration, not for AddressRange<>::contains
|
||||
*
|
||||
*
|
||||
* assert(range.contains("192.168.5.0")); // works
|
||||
* assert(range.contains("192.168.5.255")); // works
|
||||
* \endcode
|
||||
*
|
||||
* Ranges created using AddressRange(address_type, address_type)
|
||||
* Ranges created using AddressRange(address_type, address_type)
|
||||
* will allow the iteration over the entire range:
|
||||
*
|
||||
* \code
|
||||
@@ -153,11 +153,11 @@ private:
|
||||
* // process 192.168.5.0-255, no addresses are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
*
|
||||
*
|
||||
* assert(range.contains("192.168.5.0")); // still valid
|
||||
* assert(range.contains("192.168.5.255")); // still valid
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
*/
|
||||
template<typename Address>
|
||||
class AddressRange {
|
||||
@@ -186,10 +186,10 @@ public:
|
||||
* The range will consist of the addresses [first, last].
|
||||
*
|
||||
* If only_hosts is true, then the network and broadcast addresses
|
||||
* will not be available when iterating the range.
|
||||
* will not be available when iterating the range.
|
||||
*
|
||||
* If last < first, an std::runtime_error exception is thrown.
|
||||
*
|
||||
*
|
||||
* \param first The first address in the range.
|
||||
* \param last The last address(inclusive) in the range.
|
||||
* \param only_hosts Indicates whether only host addresses
|
||||
@@ -211,8 +211,8 @@ public:
|
||||
*/
|
||||
static AddressRange from_mask(const address_type& first, const address_type& mask) {
|
||||
return AddressRange<address_type>(
|
||||
first,
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
Internals::first_address_from_mask(first, mask),
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
true
|
||||
);
|
||||
}
|
||||
@@ -253,15 +253,15 @@ public:
|
||||
/**
|
||||
* \brief Indicates whether this range is iterable.
|
||||
*
|
||||
* Iterable ranges are those for which there is at least one
|
||||
* Iterable ranges are those for which there is at least one
|
||||
* address that could represent a host. For IPv4 ranges, a /31 or
|
||||
* /32 ranges does not contain any, therefore it's not iterable.
|
||||
* The same is true for /127 and /128 IPv6 ranges.
|
||||
*
|
||||
* If is_iterable returns false for a range, then iterating it
|
||||
* through the iterators returned by begin() and end() is
|
||||
* undefined.
|
||||
*
|
||||
* through the iterators returned by begin() and end() is
|
||||
* undefined.
|
||||
*
|
||||
* \return bool indicating whether this range is iterable.
|
||||
*/
|
||||
bool is_iterable() const {
|
||||
|
||||
@@ -463,7 +463,8 @@ public:
|
||||
uint16_t dwell_time;
|
||||
uint8_t hop_set, hop_pattern, hop_index;
|
||||
|
||||
fh_params_set() {}
|
||||
fh_params_set()
|
||||
: dwell_time(0), hop_set(0), hop_pattern(0), hop_index(0) {}
|
||||
|
||||
fh_params_set(uint16_t dwell_time,
|
||||
uint8_t hop_set,
|
||||
@@ -482,7 +483,8 @@ public:
|
||||
uint8_t cfp_count, cfp_period;
|
||||
uint16_t cfp_max_duration, cfp_dur_remaining;
|
||||
|
||||
cf_params_set() {}
|
||||
cf_params_set()
|
||||
: cfp_count(0), cfp_period(0), cfp_max_duration(0), cfp_dur_remaining(0) {}
|
||||
|
||||
cf_params_set(uint8_t cfp_count,
|
||||
uint8_t cfp_period,
|
||||
@@ -505,7 +507,7 @@ public:
|
||||
uint8_t recovery_interval;
|
||||
channel_map_type channel_map;
|
||||
|
||||
ibss_dfs_params() {}
|
||||
ibss_dfs_params() : recovery_interval(0) {}
|
||||
|
||||
ibss_dfs_params(const address_type& addr,
|
||||
uint8_t recovery_interval,
|
||||
@@ -547,7 +549,8 @@ public:
|
||||
uint8_t flag, number_of_sets, modulus, offset;
|
||||
byte_array random_table;
|
||||
|
||||
fh_pattern_type() {}
|
||||
fh_pattern_type()
|
||||
: flag(0), number_of_sets(0), modulus(0), offset(0) {}
|
||||
|
||||
fh_pattern_type(uint8_t flag,
|
||||
uint8_t sets,
|
||||
@@ -566,7 +569,8 @@ public:
|
||||
struct channel_switch_type {
|
||||
uint8_t switch_mode, new_channel, switch_count;
|
||||
|
||||
channel_switch_type() {}
|
||||
channel_switch_type()
|
||||
: switch_mode(0), new_channel(0), switch_count(0) {}
|
||||
|
||||
channel_switch_type(uint8_t mode,
|
||||
uint8_t channel,
|
||||
@@ -583,7 +587,8 @@ public:
|
||||
uint8_t quiet_count, quiet_period;
|
||||
uint16_t quiet_duration, quiet_offset;
|
||||
|
||||
quiet_type() {}
|
||||
quiet_type()
|
||||
: quiet_count(0), quiet_period(0), quiet_duration(0), quiet_offset(0) {}
|
||||
|
||||
quiet_type(uint8_t count,
|
||||
uint8_t period,
|
||||
@@ -603,7 +608,8 @@ public:
|
||||
uint16_t available_capacity;
|
||||
uint8_t channel_utilization;
|
||||
|
||||
bss_load_type() {}
|
||||
bss_load_type()
|
||||
: station_count(0), available_capacity(0), channel_utilization(0) {}
|
||||
|
||||
bss_load_type(uint16_t count, uint8_t utilization, uint16_t capacity)
|
||||
: station_count(count), available_capacity(capacity),
|
||||
@@ -619,7 +625,8 @@ public:
|
||||
uint8_t dtim_count, dtim_period, bitmap_control;
|
||||
byte_array partial_virtual_bitmap;
|
||||
|
||||
tim_type() {}
|
||||
tim_type()
|
||||
: dtim_count(0), dtim_period(0), bitmap_control(0) {}
|
||||
|
||||
tim_type(uint8_t count,
|
||||
uint8_t period,
|
||||
|
||||
@@ -507,7 +507,9 @@ private:
|
||||
bool are_extensions_allowed() const;
|
||||
|
||||
icmp_header header_;
|
||||
uint32_t orig_timestamp_or_address_mask_, recv_timestamp_, trans_timestamp_;
|
||||
uint32_t orig_timestamp_or_address_mask_;
|
||||
uint32_t recv_timestamp_;
|
||||
uint32_t trans_timestamp_;
|
||||
ICMPExtensionsStructure extensions_;
|
||||
};
|
||||
|
||||
|
||||
@@ -251,8 +251,8 @@ public:
|
||||
uint8_t prefix_len;
|
||||
small_uint<1> A, L;
|
||||
uint32_t valid_lifetime,
|
||||
preferred_lifetime,
|
||||
reserved2;
|
||||
preferred_lifetime,
|
||||
reserved2;
|
||||
ipaddress_type prefix;
|
||||
|
||||
prefix_info_type(uint8_t prefix_len = 0,
|
||||
@@ -262,7 +262,7 @@ public:
|
||||
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), prefix(prefix) { }
|
||||
preferred_lifetime(preferred_lifetime), reserved2(0), prefix(prefix) { }
|
||||
|
||||
static prefix_info_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
@@ -108,6 +108,7 @@ private:
|
||||
|
||||
void skip_line(std::istream& input);
|
||||
bool from_hex(const std::string& str, uint32_t& result);
|
||||
bool from_hex(const std::string& str, std::string& result);
|
||||
|
||||
template<bool, typename T = void>
|
||||
struct enable_if {
|
||||
@@ -133,7 +134,7 @@ Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
|
||||
PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag);
|
||||
|
||||
uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment);
|
||||
void try_parse_icmp_extensions(Memory::InputMemoryStream& stream,
|
||||
void try_parse_icmp_extensions(Memory::InputMemoryStream& stream,
|
||||
uint32_t payload_length, ICMPExtensionsStructure& extensions);
|
||||
|
||||
template<typename T>
|
||||
@@ -182,6 +183,18 @@ bool decrement(HWAddress<n>& addr) {
|
||||
// Compares sequence numbers as defined by RFC 1982.
|
||||
int seq_compare(uint32_t seq1, uint32_t seq2);
|
||||
|
||||
|
||||
IPv4Address first_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address first_address_from_mask(IPv6Address addr, const IPv6Address& mask);
|
||||
template<size_t n>
|
||||
HWAddress<n> first_address_from_mask(HWAddress<n> addr, const HWAddress<n>& mask) {
|
||||
typename HWAddress<n>::iterator addr_iter = addr.begin();
|
||||
for (typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter & *it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
|
||||
template<size_t n>
|
||||
@@ -229,10 +242,10 @@ template <typename T, typename P, typename=void>
|
||||
struct accepts_type : std::false_type { };
|
||||
|
||||
template <typename T, typename P>
|
||||
struct accepts_type<T, P,
|
||||
struct accepts_type<T, P,
|
||||
typename std::enable_if<
|
||||
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
|
||||
>::type
|
||||
>::type
|
||||
> : std::true_type { };
|
||||
|
||||
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
|
||||
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
* \param addr The IPv4Address to be written.
|
||||
* \return std::stream& pointing to output.
|
||||
*/
|
||||
friend std::ostream& operator<<(std::ostream& output, const IPv4Address& addr);
|
||||
TINS_API friend std::ostream& operator<<(std::ostream& output, const IPv4Address& addr);
|
||||
private:
|
||||
uint32_t ip_to_int(const char* ip);
|
||||
|
||||
|
||||
@@ -55,6 +55,13 @@ public:
|
||||
*/
|
||||
typedef const uint8_t* const_iterator;
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv6 address from a prefix length
|
||||
*
|
||||
* \param prefix_length The length of the prefix
|
||||
*/
|
||||
static IPv6Address from_prefix_length(uint32_t prefix_length);
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
* Initializes this IPv6 address to "::"
|
||||
|
||||
@@ -333,8 +333,10 @@ public:
|
||||
PDUOption(option_type opt = option_type(),
|
||||
size_t length = 0,
|
||||
const data_type* data = 0)
|
||||
: option_(opt), size_(static_cast<uint16_t>(length)) {
|
||||
set_payload_contents(data, data + (data ? length : 0));
|
||||
: option_(opt), size_(static_cast<uint16_t>(length)), real_size_(0) {
|
||||
if (data != 0) {
|
||||
set_payload_contents(data, data + length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -506,10 +506,21 @@ private:
|
||||
radiotap_hdr radio_;
|
||||
// present fields...
|
||||
uint64_t tsft_;
|
||||
uint16_t channel_type_, channel_freq_, rx_flags_, signal_quality_, tx_flags_;
|
||||
uint16_t channel_type_;
|
||||
uint16_t channel_freq_;
|
||||
uint16_t rx_flags_;
|
||||
uint16_t signal_quality_;
|
||||
uint16_t tx_flags_;
|
||||
mcs_type mcs_;
|
||||
uint8_t antenna_, flags_, rate_, channel_, max_power_, db_signal_, data_retries_;
|
||||
int8_t dbm_signal_, dbm_noise_;
|
||||
uint8_t antenna_;
|
||||
uint8_t flags_;
|
||||
uint8_t rate_;
|
||||
uint8_t channel_;
|
||||
uint8_t max_power_;
|
||||
uint8_t db_signal_;
|
||||
uint8_t data_retries_;
|
||||
int8_t dbm_signal_;
|
||||
int8_t dbm_noise_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ public:
|
||||
private:
|
||||
// Compress all flags into just one struct using bitfields
|
||||
struct flags {
|
||||
flags() : ignore_data_packets(0), sack_permitted(0), ack_tracking(0) {
|
||||
flags() : is_v6(0), ignore_data_packets(0), sack_permitted(0), ack_tracking(0) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ public:
|
||||
IPv4Address client_addr, server_addr;
|
||||
uint16_t client_port, server_port;
|
||||
|
||||
StreamInfo() {}
|
||||
StreamInfo() : client_port(0), server_port(0) {}
|
||||
|
||||
StreamInfo(IPv4Address client, IPv4Address server,
|
||||
uint16_t cport, uint16_t sport);
|
||||
uint16_t cport, uint16_t sport);
|
||||
|
||||
bool operator<(const StreamInfo& rhs) const;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "internals.h"
|
||||
|
||||
// Fix for Windows interface define on combaseapi.h
|
||||
@@ -89,6 +90,36 @@ struct RouteEntry {
|
||||
int metric;
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct that represents an entry the IPv6 routing table
|
||||
*/
|
||||
struct Route6Entry {
|
||||
/**
|
||||
* This interface's name.
|
||||
*/
|
||||
std::string interface;
|
||||
|
||||
/**
|
||||
* This route entry's destination.
|
||||
*/
|
||||
IPv6Address destination;
|
||||
|
||||
/**
|
||||
* This route entry's subnet mask.
|
||||
*/
|
||||
IPv6Address mask;
|
||||
|
||||
/**
|
||||
* This route entry's next hop.
|
||||
*/
|
||||
IPv6Address gateway;
|
||||
|
||||
/**
|
||||
* This route entry's metric.
|
||||
*/
|
||||
int metric;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
@@ -176,6 +207,13 @@ void route_entries(ForwardIterator output);
|
||||
*/
|
||||
TINS_API std::vector<RouteEntry> route_entries();
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \return a vector which contains all of the route entries.
|
||||
*/
|
||||
TINS_API std::vector<Route6Entry> route6_entries();
|
||||
|
||||
/** \brief Returns the 32 bit crc of the given buffer.
|
||||
*
|
||||
* \param data The input buffer.
|
||||
|
||||
@@ -49,15 +49,7 @@ IPv6Range operator/(const IPv6Address& addr, int mask) {
|
||||
if (mask > 128) {
|
||||
throw std::logic_error("Prefix length cannot exceed 128");
|
||||
}
|
||||
IPv6Address last_addr;
|
||||
IPv6Address::iterator it = last_addr.begin();
|
||||
while (mask > 8) {
|
||||
*it = 0xff;
|
||||
++it;
|
||||
mask -= 8;
|
||||
}
|
||||
*it = 0xff << (8 - mask);
|
||||
return IPv6Range::from_mask(addr, last_addr);
|
||||
return IPv6Range::from_mask(addr, IPv6Address::from_prefix_length(mask));
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
@@ -270,7 +270,7 @@ SessionKeys::SessionKeys(const ptk_type& ptk, bool is_ccmp)
|
||||
}
|
||||
|
||||
SessionKeys::SessionKeys(const RSNHandshake& hs, const pmk_type& pmk)
|
||||
: ptk_(PTK_SIZE) {
|
||||
: ptk_(PTK_SIZE), is_ccmp_(false) {
|
||||
if (pmk.size() != PMK_SIZE) {
|
||||
throw invalid_handshake();
|
||||
}
|
||||
|
||||
@@ -605,7 +605,7 @@ bool DNS::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
||||
// SOA record
|
||||
|
||||
DNS::soa_record::soa_record()
|
||||
: serial_(0), refresh_(0), retry_(0), expire_(0) {
|
||||
: serial_(0), refresh_(0), retry_(0), expire_(0), minimum_ttl_(0) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ uint32_t Dot11BlockAckRequest::header_size() const {
|
||||
|
||||
Dot11BlockAck::Dot11BlockAck(const address_type& dst_addr,
|
||||
const address_type& target_addr)
|
||||
: Dot11ControlTA(dst_addr, target_addr), bitmap_() {
|
||||
: Dot11ControlTA(dst_addr, target_addr), bar_control_(0), start_sequence_(0), bitmap_() {
|
||||
subtype(BLOCK_ACK);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@ ICMP::ICMP(Flags flag)
|
||||
type(flag);
|
||||
}
|
||||
|
||||
ICMP::ICMP(const uint8_t* buffer, uint32_t total_sz) {
|
||||
ICMP::ICMP(const uint8_t* buffer, uint32_t total_sz)
|
||||
: orig_timestamp_or_address_mask_(), recv_timestamp_(), trans_timestamp_() {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.read(header_);
|
||||
if (type() == TIMESTAMP_REQUEST || type() == TIMESTAMP_REPLY) {
|
||||
|
||||
@@ -47,13 +47,13 @@ using Tins::Memory::OutputMemoryStream;
|
||||
namespace Tins {
|
||||
|
||||
ICMPv6::ICMPv6(Types tp)
|
||||
: options_size_(), reach_time_(0), retrans_timer_(0) {
|
||||
: options_size_(), reach_time_(0), retrans_timer_(0), mlqm_() {
|
||||
memset(&header_, 0, sizeof(header_));
|
||||
type(tp);
|
||||
}
|
||||
|
||||
ICMPv6::ICMPv6(const uint8_t* buffer, uint32_t total_sz)
|
||||
: options_size_(), reach_time_(0), retrans_timer_(0) {
|
||||
: options_size_(), reach_time_(0), retrans_timer_(0), mlqm_() {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.read(header_);
|
||||
if (has_target_addr()) {
|
||||
@@ -850,7 +850,7 @@ ICMPv6::prefix_info_type ICMPv6::prefix_info_type::from_option(const option& opt
|
||||
output.A = (stream.read<uint8_t>() >> 6) & 0x1;
|
||||
output.valid_lifetime = stream.read_be<uint32_t>();
|
||||
output.preferred_lifetime = stream.read_be<uint32_t>();
|
||||
stream.skip(sizeof(uint32_t));
|
||||
output.reserved2 = stream.read_be<uint32_t>();
|
||||
output.prefix = stream.read<ICMPv6::ipaddress_type>();
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
* 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
|
||||
@@ -63,7 +63,7 @@ namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
bool from_hex(const string& str, uint32_t& result) {
|
||||
unsigned i(0);
|
||||
size_t i = 0;
|
||||
result = 0;
|
||||
while (i < str.size()) {
|
||||
uint8_t tmp;
|
||||
@@ -82,6 +82,29 @@ bool from_hex(const string& str, uint32_t& result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool from_hex(const string& str, string& result) {
|
||||
result = "";
|
||||
for (size_t i = 0; i < str.size(); i+= 2) {
|
||||
uint8_t value = 0;
|
||||
for (size_t j = i; j < i + 2 && j < str.size(); ++j) {
|
||||
if (str[j] >= 'A' && str[j] <= 'F') {
|
||||
value = (value << 4) | (str[j] - 'A' + 10);
|
||||
}
|
||||
else if (str[j] >= 'a' && str[j] <= 'f') {
|
||||
value = (value << 4) | (str[j] - 'a' + 10);
|
||||
}
|
||||
else if (str[j] >= '0' && str[j] <= '9') {
|
||||
value = (value << 4) | (str[j] - '0');
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
result.push_back(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void skip_line(std::istream& input) {
|
||||
int c = 0;
|
||||
while (c != '\n' && input) {
|
||||
@@ -115,7 +138,7 @@ Tins::PDU* pdu_from_flag(Constants::Ethernet::e flag,
|
||||
{
|
||||
PDU* pdu = Internals::allocate<EthernetII>(
|
||||
static_cast<uint16_t>(flag),
|
||||
buffer,
|
||||
buffer,
|
||||
size
|
||||
);
|
||||
if (pdu) {
|
||||
@@ -126,8 +149,8 @@ Tins::PDU* pdu_from_flag(Constants::Ethernet::e flag,
|
||||
};
|
||||
}
|
||||
|
||||
Tins::PDU* pdu_from_flag(Constants::IP::e flag,
|
||||
const uint8_t* buffer,
|
||||
Tins::PDU* pdu_from_flag(Constants::IP::e flag,
|
||||
const uint8_t* buffer,
|
||||
uint32_t size,
|
||||
bool rawpdu_on_no_match) {
|
||||
switch (flag) {
|
||||
@@ -156,8 +179,8 @@ Tins::PDU* pdu_from_flag(Constants::IP::e flag,
|
||||
return 0;
|
||||
}
|
||||
|
||||
PDU* pdu_from_dlt_flag(int flag,
|
||||
const uint8_t* buffer,
|
||||
PDU* pdu_from_dlt_flag(int flag,
|
||||
const uint8_t* buffer,
|
||||
uint32_t size,
|
||||
bool rawpdu_on_no_match) {
|
||||
switch (flag) {
|
||||
@@ -315,8 +338,8 @@ uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_align
|
||||
}
|
||||
}
|
||||
|
||||
void try_parse_icmp_extensions(InputMemoryStream& stream,
|
||||
uint32_t payload_length,
|
||||
void try_parse_icmp_extensions(InputMemoryStream& stream,
|
||||
uint32_t payload_length,
|
||||
ICMPExtensionsStructure& extensions) {
|
||||
if (!stream) {
|
||||
return;
|
||||
@@ -332,7 +355,7 @@ void try_parse_icmp_extensions(InputMemoryStream& stream,
|
||||
extensions_size = stream.size() - payload_length;
|
||||
}
|
||||
else if (stream.can_read(minimum_payload)) {
|
||||
// This packet might be non-rfc compliant. In that case the length
|
||||
// This packet might be non-rfc compliant. In that case the length
|
||||
// field can contain garbage.
|
||||
extensions_ptr = stream.pointer() + minimum_payload;
|
||||
extensions_size = stream.size() - minimum_payload;
|
||||
@@ -420,5 +443,19 @@ IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
IPv4Address first_address_from_mask(IPv4Address addr, IPv4Address mask) {
|
||||
uint32_t addr_int = Endian::be_to_host<uint32_t>(addr),
|
||||
mask_int = Endian::be_to_host<uint32_t>(mask);
|
||||
return IPv4Address(Endian::host_to_be(addr_int & mask_int));
|
||||
}
|
||||
|
||||
IPv6Address first_address_from_mask(IPv6Address addr, const IPv6Address& mask) {
|
||||
IPv6Address::iterator addr_iter = addr.begin();
|
||||
for (IPv6Address::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter & *it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace Tins
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
IPv4Stream::IPv4Stream()
|
||||
: received_end_(false), received_size_(), total_size_() {
|
||||
: received_end_(false), transport_proto_(0xff), received_size_(), total_size_() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,18 @@ namespace Tins {
|
||||
const IPv6Address loopback_address = "::1";
|
||||
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
|
||||
|
||||
IPv6Address IPv6Address::from_prefix_length(uint32_t prefix_length) {
|
||||
IPv6Address address;
|
||||
IPv6Address::iterator it = address.begin();
|
||||
while (prefix_length > 8) {
|
||||
*it = 0xff;
|
||||
++it;
|
||||
prefix_length -= 8;
|
||||
}
|
||||
*it = 0xff << (8 - prefix_length);
|
||||
return address;
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address() {
|
||||
fill(address_, address_ + address_size, 0);
|
||||
}
|
||||
|
||||
@@ -263,7 +263,9 @@ void PacketSender::open_l3_socket(SocketType type) {
|
||||
#else
|
||||
typedef const char* option_ptr;
|
||||
#endif
|
||||
setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,(option_ptr)&on,sizeof(on));
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, (option_ptr)&on, sizeof(on)) != 0) {
|
||||
throw socket_open_error(make_error_string());
|
||||
}
|
||||
|
||||
sockets_[type] = static_cast<int>(sockfd);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ using Tins::Memory::OutputMemoryStream;
|
||||
namespace Tins {
|
||||
|
||||
RSNInformation::RSNInformation()
|
||||
: version_(1), capabilities_(0) {
|
||||
: version_(1), capabilities_(0), group_suite_(static_cast<CypherSuites>(0)) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ struct sniff_data {
|
||||
PDU* pdu;
|
||||
bool packet_processed;
|
||||
|
||||
sniff_data() : pdu(0), packet_processed(true) { }
|
||||
sniff_data() : tv(), pdu(0), packet_processed(true) { }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -408,7 +408,7 @@ const unsigned SnifferConfiguration::DEFAULT_TIMEOUT = 1000;
|
||||
|
||||
SnifferConfiguration::SnifferConfiguration()
|
||||
: flags_(0), snap_len_(DEFAULT_SNAP_LEN), buffer_size_(0), timeout_(DEFAULT_TIMEOUT),
|
||||
promisc_(false), rfmon_(false), immediate_mode_(false) {
|
||||
promisc_(false), rfmon_(false), immediate_mode_(false), direction_(PCAP_D_INOUT) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
186
src/utils.cpp
186
src/utils.cpp
@@ -54,8 +54,8 @@
|
||||
#endif
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#undef interface
|
||||
#endif
|
||||
#include "utils.h"
|
||||
@@ -110,7 +110,7 @@ addrinfo* resolve_domain(const string& to_resolve, int family) {
|
||||
}
|
||||
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
vector<char> query_route_table() {
|
||||
vector<char> query_route_table(int family) {
|
||||
int mib[6];
|
||||
vector<char> buf;
|
||||
size_t len;
|
||||
@@ -118,7 +118,7 @@ vector<char> query_route_table() {
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = AF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = AF_INET;
|
||||
mib[3] = family;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
|
||||
@@ -133,20 +133,19 @@ vector<char> query_route_table() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
template<typename ForwardIterator>
|
||||
void parse_header(struct rt_msghdr* rtm, ForwardIterator iter) {
|
||||
void parse_header(struct rt_msghdr* rtm, vector<sockaddr*>& addrs) {
|
||||
char* ptr = (char *)(rtm + 1);
|
||||
sockaddr* sa = 0;
|
||||
|
||||
for (int i = 0; i < RTAX_MAX; i++) {
|
||||
if (rtm->rtm_addrs & (1 << i)) {
|
||||
// Iterate from RTA_DST (0) to RTA_NETMASK (2)
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
sockaddr* sa = 0;
|
||||
if ((rtm->rtm_addrs & (1 << i)) != 0) {
|
||||
sa = (struct sockaddr *)ptr;
|
||||
ptr += sa->sa_len;
|
||||
if (sa->sa_family == 0) {
|
||||
sa = 0;
|
||||
}
|
||||
}
|
||||
*iter++ = sa;
|
||||
addrs[i] = sa;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -191,35 +190,105 @@ HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender) {
|
||||
}
|
||||
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
|
||||
vector<RouteEntry> route_entries() {
|
||||
vector<RouteEntry> output;
|
||||
vector<char> buffer = query_route_table();
|
||||
vector<char> buffer = query_route_table(AF_INET);
|
||||
char* next = &buffer[0], *end = &buffer[buffer.size()];
|
||||
rt_msghdr* rtm;
|
||||
vector<sockaddr*> sa(RTAX_MAX);
|
||||
vector<sockaddr*> sa(32);
|
||||
char iface_name[IF_NAMESIZE];
|
||||
while (next < end) {
|
||||
rtm = (rt_msghdr*)next;
|
||||
parse_header(rtm, sa.begin());
|
||||
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
|
||||
RouteEntry entry;
|
||||
entry.destination = IPv4Address(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr.s_addr);
|
||||
entry.gateway = IPv4Address(((struct sockaddr_in *)sa[RTAX_GATEWAY])->sin_addr.s_addr);
|
||||
if (sa[RTAX_GENMASK]) {
|
||||
entry.mask = IPv4Address(((struct sockaddr_in *)sa[RTAX_GENMASK])->sin_addr.s_addr);
|
||||
// Filter:
|
||||
// * RTF_STATIC (only manually added routes)
|
||||
if ((rtm->rtm_flags & (RTF_STATIC)) != 0) {
|
||||
parse_header(rtm, sa);
|
||||
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
|
||||
RouteEntry entry;
|
||||
entry.destination = IPv4Address(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr.s_addr);
|
||||
entry.gateway = IPv4Address(((struct sockaddr_in *)sa[RTAX_GATEWAY])->sin_addr.s_addr);
|
||||
if (sa[RTAX_NETMASK]) {
|
||||
entry.mask = IPv4Address(((struct sockaddr_in *)sa[RTAX_NETMASK])->sin_addr.s_addr);
|
||||
}
|
||||
entry.interface = iface_name;
|
||||
entry.metric = 0;
|
||||
output.push_back(entry);
|
||||
}
|
||||
else {
|
||||
entry.mask = IPv4Address(uint32_t());
|
||||
}
|
||||
entry.interface = iface_name;
|
||||
entry.metric = 0;
|
||||
output.push_back(entry);
|
||||
}
|
||||
next += rtm->rtm_msglen;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
vector<Route6Entry> route6_entries() {
|
||||
vector<Route6Entry> output;
|
||||
vector<char> buffer = query_route_table(AF_INET6);
|
||||
char* next = &buffer[0], *end = &buffer[buffer.size()];
|
||||
rt_msghdr* rtm;
|
||||
vector<sockaddr*> sa(9);
|
||||
char iface_name[IF_NAMESIZE];
|
||||
while (next < end) {
|
||||
rtm = (rt_msghdr*)next;
|
||||
// Filter protocol-cloned entries
|
||||
if ((rtm->rtm_flags & RTF_WASCLONED) == 0 || (rtm->rtm_flags & RTF_PRCLONING) == 0) {
|
||||
parse_header(rtm, sa);
|
||||
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
|
||||
Route6Entry entry;
|
||||
entry.destination = IPv6Address(((struct sockaddr_in6 *)sa[RTAX_DST])->sin6_addr.s6_addr);
|
||||
entry.gateway = IPv6Address(((struct sockaddr_in6 *)sa[RTAX_GATEWAY])->sin6_addr.s6_addr);
|
||||
int prefix_length = 0;
|
||||
if (sa[RTAX_NETMASK]) {
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa[RTAX_NETMASK];
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
uint8_t this_byte = sin->sin6_addr.s6_addr[i];
|
||||
// Stop when we find a zero byte
|
||||
if (this_byte == 0) {
|
||||
break;
|
||||
}
|
||||
switch (this_byte) {
|
||||
case 0xff:
|
||||
prefix_length += 8;
|
||||
break;
|
||||
case 0xfe:
|
||||
prefix_length += 7;
|
||||
break;
|
||||
case 0xfc:
|
||||
prefix_length += 6;
|
||||
break;
|
||||
case 0xf8:
|
||||
prefix_length += 5;
|
||||
break;
|
||||
case 0xf0:
|
||||
prefix_length += 4;
|
||||
break;
|
||||
case 0xe0:
|
||||
prefix_length += 3;
|
||||
break;
|
||||
case 0xc0:
|
||||
prefix_length += 2;
|
||||
break;
|
||||
case 0x80:
|
||||
prefix_length += 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.mask = IPv6Address::from_prefix_length(prefix_length);
|
||||
entry.interface = iface_name;
|
||||
entry.metric = 0;
|
||||
output.push_back(entry);
|
||||
}
|
||||
}
|
||||
next += rtm->rtm_msglen;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
vector<RouteEntry> route_entries() {
|
||||
vector<RouteEntry> output;
|
||||
MIB_IPFORWARDTABLE* table;
|
||||
@@ -244,7 +313,34 @@ vector<RouteEntry> route_entries() {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
#else
|
||||
|
||||
vector<Route6Entry> route6_entries() {
|
||||
vector<Route6Entry> output;
|
||||
MIB_IPFORWARD_TABLE2* table;
|
||||
GetIpForwardTable2(AF_INET6, &table);
|
||||
for (ULONG i = 0; i < table->NumEntries; i++) {
|
||||
MIB_IPFORWARD_ROW2* row = &table->Table[i];
|
||||
if (true) {
|
||||
try {
|
||||
Route6Entry entry;
|
||||
entry.interface = NetworkInterface::from_index(row->InterfaceIndex).name();
|
||||
entry.destination = IPv6Address(row->DestinationPrefix.Prefix.Ipv6.sin6_addr.s6_addr);
|
||||
entry.mask = IPv6Address::from_prefix_length(row->DestinationPrefix.PrefixLength);
|
||||
entry.gateway = IPv6Address(row->NextHop.Ipv6.sin6_addr.s6_addr);
|
||||
entry.metric = row->Metric;
|
||||
output.push_back(entry);
|
||||
}
|
||||
catch (invalid_interface&) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeMibTable(table);
|
||||
return output;
|
||||
}
|
||||
|
||||
#else // GNU/LINUX
|
||||
|
||||
vector<RouteEntry> route_entries() {
|
||||
using namespace Tins::Internals;
|
||||
vector<RouteEntry> output;
|
||||
@@ -271,6 +367,44 @@ vector<RouteEntry> route_entries() {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
vector<Route6Entry> route6_entries() {
|
||||
using namespace Tins::Internals;
|
||||
vector<Route6Entry> output;
|
||||
ifstream input("/proc/net/ipv6_route");
|
||||
string destination, mask_length, metric, next_hop, dummy, flags;
|
||||
Route6Entry entry;
|
||||
while (input >> destination >> mask_length) {
|
||||
string temporary;
|
||||
uint32_t temporary_int;
|
||||
for (unsigned i(0); i < 2; ++i) {
|
||||
input >> dummy;
|
||||
}
|
||||
input >> next_hop;
|
||||
input >> metric;
|
||||
for (unsigned i(0); i < 2; ++i) {
|
||||
input >> dummy;
|
||||
}
|
||||
input >> flags >> entry.interface;
|
||||
from_hex(destination, temporary);
|
||||
entry.destination = IPv6Address((const uint8_t*)&temporary[0]);
|
||||
from_hex(mask_length, temporary_int);
|
||||
entry.mask = IPv6Address::from_prefix_length(temporary_int);
|
||||
from_hex(next_hop, temporary);
|
||||
entry.gateway = IPv6Address((const uint8_t*)&temporary[0]);
|
||||
from_hex(metric, temporary_int);
|
||||
entry.metric = temporary_int;
|
||||
// Process flags
|
||||
from_hex(flags, temporary_int);
|
||||
// Skip:
|
||||
// * 0x01000000 -> cache entries
|
||||
if ((temporary_int & 0x01000000) == 0) {
|
||||
output.push_back(entry);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
|
||||
|
||||
@@ -100,3 +100,9 @@ TEST(IPv6AddressTest, IsMulticast) {
|
||||
EXPECT_FALSE(IPv6Address("feaa::dead").is_multicast());
|
||||
}
|
||||
|
||||
TEST(IPv6AddressTest, FromPrefixLength) {
|
||||
EXPECT_EQ(IPv6Address("ffff:fe00::"), IPv6Address::from_prefix_length(23));
|
||||
EXPECT_EQ(IPv6Address("ffff::"), IPv6Address::from_prefix_length(16));
|
||||
EXPECT_EQ(IPv6Address("ffff:ffff::"), IPv6Address::from_prefix_length(32));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user