diff --git a/examples/route_table.cpp b/examples/route_table.cpp index 49f22be..f6c58ce 100644 --- a/examples/route_table.cpp +++ b/examples/route_table.cpp @@ -40,13 +40,30 @@ using std::vector; using namespace Tins; int main() { - vector entries = Utils::route_entries(); - for (size_t i = 0; i < entries.size(); ++i) { + vector 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 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; + } } } \ No newline at end of file diff --git a/include/tins/address_range.h b/include/tins/address_range.h index 5d9f9e7..9880151 100644 --- a/include/tins/address_range.h +++ b/include/tins/address_range.h @@ -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 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( - 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 { diff --git a/include/tins/dot11/dot11_mgmt.h b/include/tins/dot11/dot11_mgmt.h index e1ae39a..09ad501 100644 --- a/include/tins/dot11/dot11_mgmt.h +++ b/include/tins/dot11/dot11_mgmt.h @@ -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, diff --git a/include/tins/icmp.h b/include/tins/icmp.h index 890bd85..c357a37 100644 --- a/include/tins/icmp.h +++ b/include/tins/icmp.h @@ -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_; }; diff --git a/include/tins/icmpv6.h b/include/tins/icmpv6.h index ec70eef..7a34523 100644 --- a/include/tins/icmpv6.h +++ b/include/tins/icmpv6.h @@ -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); }; diff --git a/include/tins/internals.h b/include/tins/internals.h index db51de9..47df50d 100644 --- a/include/tins/internals.h +++ b/include/tins/internals.h @@ -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 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 @@ -182,6 +183,18 @@ bool decrement(HWAddress& 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 +HWAddress first_address_from_mask(HWAddress addr, const HWAddress& mask) { + typename HWAddress::iterator addr_iter = addr.begin(); + for (typename HWAddress::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 @@ -229,10 +242,10 @@ template struct accepts_type : std::false_type { }; template -struct accepts_type()(std::declval

()) ), 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 diff --git a/include/tins/ip_address.h b/include/tins/ip_address.h index 2776e79..ddcce30 100644 --- a/include/tins/ip_address.h +++ b/include/tins/ip_address.h @@ -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); diff --git a/include/tins/ipv6_address.h b/include/tins/ipv6_address.h index fd677f3..fb11600 100644 --- a/include/tins/ipv6_address.h +++ b/include/tins/ipv6_address.h @@ -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 "::" diff --git a/include/tins/pdu_option.h b/include/tins/pdu_option.h index ab63796..63be671 100644 --- a/include/tins/pdu_option.h +++ b/include/tins/pdu_option.h @@ -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(length)) { - set_payload_contents(data, data + (data ? length : 0)); + : option_(opt), size_(static_cast(length)), real_size_(0) { + if (data != 0) { + set_payload_contents(data, data + length); + } } /** diff --git a/include/tins/radiotap.h b/include/tins/radiotap.h index a613512..61bf599 100644 --- a/include/tins/radiotap.h +++ b/include/tins/radiotap.h @@ -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_; }; } diff --git a/include/tins/tcp_ip/flow.h b/include/tins/tcp_ip/flow.h index 977247e..9c48cd1 100644 --- a/include/tins/tcp_ip/flow.h +++ b/include/tins/tcp_ip/flow.h @@ -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) { } diff --git a/include/tins/tcp_stream.h b/include/tins/tcp_stream.h index ddeb0c3..d2bdbbd 100644 --- a/include/tins/tcp_stream.h +++ b/include/tins/tcp_stream.h @@ -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; }; diff --git a/include/tins/utils.h b/include/tins/utils.h index c647e19..2d5b709 100644 --- a/include/tins/utils.h +++ b/include/tins/utils.h @@ -36,6 +36,7 @@ #include #include #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 route_entries(); +/** + * \brief Retrieves entries in the routing table. + * + * \return a vector which contains all of the route entries. + */ +TINS_API std::vector route6_entries(); + /** \brief Returns the 32 bit crc of the given buffer. * * \param data The input buffer. diff --git a/src/address_range.cpp b/src/address_range.cpp index bcbfb05..00291a9 100644 --- a/src/address_range.cpp +++ b/src/address_range.cpp @@ -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 diff --git a/src/crypto.cpp b/src/crypto.cpp index c5b44b4..117dc7d 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -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(); } diff --git a/src/dns.cpp b/src/dns.cpp index dd8bb73..0b76139 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -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) { } diff --git a/src/dot11/dot11_control.cpp b/src/dot11/dot11_control.cpp index 39e51e4..83ab999 100644 --- a/src/dot11/dot11_control.cpp +++ b/src/dot11/dot11_control.cpp @@ -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); } diff --git a/src/icmp.cpp b/src/icmp.cpp index 1c2a670..cc59a84 100644 --- a/src/icmp.cpp +++ b/src/icmp.cpp @@ -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) { diff --git a/src/icmpv6.cpp b/src/icmpv6.cpp index 0ba43c7..585bcd6 100644 --- a/src/icmpv6.cpp +++ b/src/icmpv6.cpp @@ -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() >> 6) & 0x1; output.valid_lifetime = stream.read_be(); output.preferred_lifetime = stream.read_be(); - stream.skip(sizeof(uint32_t)); + output.reserved2 = stream.read_be(); output.prefix = stream.read(); return output; } diff --git a/src/internals.cpp b/src/internals.cpp index b15f017..2449db6 100644 --- a/src/internals.cpp +++ b/src/internals.cpp @@ -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( static_cast(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(addr), + mask_int = Endian::be_to_host(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 diff --git a/src/ip_reassembler.cpp b/src/ip_reassembler.cpp index df784c2..6bb735f 100644 --- a/src/ip_reassembler.cpp +++ b/src/ip_reassembler.cpp @@ -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_() { } diff --git a/src/ipv6_address.cpp b/src/ipv6_address.cpp index 2a94706..f6a90e7 100644 --- a/src/ipv6_address.cpp +++ b/src/ipv6_address.cpp @@ -52,6 +52,18 @@ namespace Tins { const IPv6Address loopback_address = "::1"; const AddressRange 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); } diff --git a/src/packet_sender.cpp b/src/packet_sender.cpp index ecab256..ebc1744 100644 --- a/src/packet_sender.cpp +++ b/src/packet_sender.cpp @@ -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(sockfd); } diff --git a/src/rsn_information.cpp b/src/rsn_information.cpp index df641dc..cc58616 100644 --- a/src/rsn_information.cpp +++ b/src/rsn_information.cpp @@ -43,7 +43,7 @@ using Tins::Memory::OutputMemoryStream; namespace Tins { RSNInformation::RSNInformation() -: version_(1), capabilities_(0) { +: version_(1), capabilities_(0), group_suite_(static_cast(0)) { } diff --git a/src/sniffer.cpp b/src/sniffer.cpp index e22bb6a..9ea2741 100644 --- a/src/sniffer.cpp +++ b/src/sniffer.cpp @@ -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 @@ -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) { } diff --git a/src/utils.cpp b/src/utils.cpp index 14a05e3..3be76ed 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -54,8 +54,8 @@ #endif #else #include - #include #include + #include #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 query_route_table() { +vector query_route_table(int family) { int mib[6]; vector buf; size_t len; @@ -118,7 +118,7 @@ vector 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 query_route_table() { return buf; } -template -void parse_header(struct rt_msghdr* rtm, ForwardIterator iter) { +void parse_header(struct rt_msghdr* rtm, vector& 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 route_entries() { vector output; - vector buffer = query_route_table(); + vector buffer = query_route_table(AF_INET); char* next = &buffer[0], *end = &buffer[buffer.size()]; rt_msghdr* rtm; - vector sa(RTAX_MAX); + vector 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 route6_entries() { + vector output; + vector buffer = query_route_table(AF_INET6); + char* next = &buffer[0], *end = &buffer[buffer.size()]; + rt_msghdr* rtm; + vector 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 route_entries() { vector output; MIB_IPFORWARDTABLE* table; @@ -244,7 +313,34 @@ vector route_entries() { } return output; } -#else + +vector route6_entries() { + vector 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 route_entries() { using namespace Tins::Internals; vector output; @@ -271,6 +367,44 @@ vector route_entries() { } return output; } + +vector route6_entries() { + using namespace Tins::Internals; + vector 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) { diff --git a/tests/src/ipv6address.cpp b/tests/src/ipv6address.cpp index fad5019..a4919e2 100644 --- a/tests/src/ipv6address.cpp +++ b/tests/src/ipv6address.cpp @@ -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)); +} +