Added logic to lookup IPv6 prefix for incoming packet (#873)
This commit is contained in:
parent
cc63c04334
commit
f2dc853247
@ -737,39 +737,50 @@ std::string print_ipv6_address(struct in6_addr& ipv6_address) {
|
||||
return result;
|
||||
}
|
||||
|
||||
direction_t get_packet_direction_ipv6(patricia_tree_t* lookup_tree, struct in6_addr src_ipv6, struct in6_addr dst_ipv6) {
|
||||
direction_t get_packet_direction_ipv6(patricia_tree_t* lookup_tree, struct in6_addr src_ipv6, struct in6_addr dst_ipv6, subnet_ipv6_cidr_mask_t& subnet) {
|
||||
direction_t packet_direction;
|
||||
|
||||
bool our_ip_is_destination = false;
|
||||
bool our_ip_is_source = false;
|
||||
bool our_ip_is_source = false;
|
||||
|
||||
prefix_t prefix_for_check_address;
|
||||
prefix_for_check_address.family = AF_INET6;
|
||||
prefix_for_check_address.bitlen = 128;
|
||||
prefix_for_check_address.bitlen = 128;
|
||||
|
||||
patricia_node_t* found_patrica_node = NULL;
|
||||
prefix_for_check_address.add.sin6 = dst_ipv6;
|
||||
prefix_for_check_address.add.sin6 = dst_ipv6;
|
||||
|
||||
found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_address, 1);
|
||||
|
||||
subnet_ipv6_cidr_mask_t destination_subnet;
|
||||
if (found_patrica_node) {
|
||||
our_ip_is_destination = true;
|
||||
}
|
||||
|
||||
found_patrica_node = NULL;
|
||||
destination_subnet.subnet_address = found_patrica_node->prefix->add.sin6;
|
||||
destination_subnet.cidr_prefix_length = found_patrica_node->prefix->bitlen;
|
||||
}
|
||||
|
||||
found_patrica_node = NULL;
|
||||
prefix_for_check_address.add.sin6 = src_ipv6;
|
||||
|
||||
subnet_ipv6_cidr_mask_t source_subnet;
|
||||
|
||||
found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_address, 1);
|
||||
|
||||
if (found_patrica_node) {
|
||||
our_ip_is_source = true;
|
||||
}
|
||||
|
||||
source_subnet.subnet_address = found_patrica_node->prefix->add.sin6;
|
||||
source_subnet.cidr_prefix_length = found_patrica_node->prefix->bitlen;
|
||||
}
|
||||
|
||||
if (our_ip_is_source && our_ip_is_destination) {
|
||||
packet_direction = INTERNAL;
|
||||
} else if (our_ip_is_source) {
|
||||
subnet = source_subnet;
|
||||
packet_direction = OUTGOING;
|
||||
} else if (our_ip_is_destination) {
|
||||
subnet = destination_subnet;
|
||||
packet_direction = INCOMING;
|
||||
} else {
|
||||
packet_direction = OTHER;
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include "fast_endianless.hpp"
|
||||
|
||||
#include "fastnetmon_networks.hpp"
|
||||
|
||||
#define TCP_FIN_FLAG_SHIFT 1
|
||||
#define TCP_SYN_FLAG_SHIFT 2
|
||||
#define TCP_RST_FLAG_SHIFT 3
|
||||
@ -92,7 +94,7 @@ direction_t get_packet_direction(patricia_tree_t* lookup_tree,
|
||||
unsigned long& source_subnet,
|
||||
unsigned int& source_subnet_cidr_mas);
|
||||
|
||||
direction_t get_packet_direction_ipv6(patricia_tree_t* lookup_tree, struct in6_addr src_ipv6, struct in6_addr dst_ipv6);
|
||||
direction_t get_packet_direction_ipv6(patricia_tree_t* lookup_tree, struct in6_addr src_ipv6, struct in6_addr dst_ipv6, subnet_ipv6_cidr_mask_t& subnet);
|
||||
|
||||
std::string convert_prefix_to_string_representation(prefix_t* prefix);
|
||||
std::string find_subnet_by_ip_in_string_format(patricia_tree_t* patricia_tree, std::string ip);
|
||||
|
@ -2643,8 +2643,10 @@ void process_packet(simple_packet_t& current_packet) {
|
||||
}
|
||||
|
||||
if (current_packet.ip_protocol_version == 6) {
|
||||
subnet_ipv6_cidr_mask_t ipv6_cidr_subnet;
|
||||
|
||||
current_packet.packet_direction =
|
||||
get_packet_direction_ipv6(lookup_tree_ipv6, current_packet.src_ipv6, current_packet.dst_ipv6);
|
||||
get_packet_direction_ipv6(lookup_tree_ipv6, current_packet.src_ipv6, current_packet.dst_ipv6, ipv6_cidr_subnet);
|
||||
|
||||
#ifdef USE_NEW_ATOMIC_BUILTINS
|
||||
__atomic_add_fetch(&total_ipv6_packets, 1, __ATOMIC_RELAXED);
|
||||
|
198
src/fastnetmon_networks.hpp
Normal file
198
src/fastnetmon_networks.hpp
Normal file
@ -0,0 +1,198 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
// IPv6 subnet with mask in cidr form
|
||||
class subnet_ipv6_cidr_mask_t {
|
||||
public:
|
||||
subnet_ipv6_cidr_mask_t() {
|
||||
// Fill subnet by zeros
|
||||
memset(&this->subnet_address, 0, sizeof(in6_addr));
|
||||
}
|
||||
|
||||
void set_cidr_prefix_length(uint32_t cidr_prefix_length) {
|
||||
this->cidr_prefix_length = cidr_prefix_length;
|
||||
}
|
||||
|
||||
// Just copy this data by pointer
|
||||
void set_subnet_address(in6_addr* ipv6_host_address_param) {
|
||||
memcpy(&subnet_address, ipv6_host_address_param, sizeof(in6_addr));
|
||||
}
|
||||
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
|
||||
// Boost does not know how to serialize in6_addr but nested s6_addr is a just array with 16 elements of char and we do serialzie it instead
|
||||
ar& BOOST_SERIALIZATION_NVP(subnet_address.s6_addr);
|
||||
ar& BOOST_SERIALIZATION_NVP(cidr_prefix_length);
|
||||
}
|
||||
|
||||
in6_addr subnet_address;
|
||||
uint32_t cidr_prefix_length = 128;
|
||||
};
|
||||
|
||||
// We need this operator because we are using this class in std::map which
|
||||
// requires ordering
|
||||
// We use inline to suppress angry compiler
|
||||
inline bool operator<(const subnet_ipv6_cidr_mask_t& lhs, const subnet_ipv6_cidr_mask_t& rhs) {
|
||||
if (lhs.cidr_prefix_length < rhs.cidr_prefix_length) {
|
||||
return true;
|
||||
} else if (lhs.cidr_prefix_length == rhs.cidr_prefix_length) {
|
||||
// Compare addresses as memory blocks
|
||||
// Order may be incorrect (desc vs asc)
|
||||
return memcmp(&lhs.subnet_address, &rhs.subnet_address, sizeof(in6_addr)) < 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Inject custom specialization of std::hash in namespace std
|
||||
// We need it for std::unordered_map
|
||||
namespace std {
|
||||
template <> struct hash<subnet_ipv6_cidr_mask_t> {
|
||||
typedef std::size_t result_type;
|
||||
std::size_t operator()(subnet_ipv6_cidr_mask_t const& s) const {
|
||||
std::size_t seed = 0;
|
||||
|
||||
const uint8_t* b = s.subnet_address.s6_addr;
|
||||
|
||||
boost::hash_combine(seed, s.cidr_prefix_length);
|
||||
|
||||
// Add all elements from IPv6 into hash
|
||||
for (int i = 0; i < 16; i++) {
|
||||
boost::hash_combine(seed, b[i]);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
inline bool operator==(const subnet_ipv6_cidr_mask_t& lhs, const subnet_ipv6_cidr_mask_t& rhs) {
|
||||
// Prefixes has different lengths
|
||||
if (lhs.cidr_prefix_length != rhs.cidr_prefix_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return memcmp(&lhs.subnet_address, &rhs.subnet_address, sizeof(in6_addr)) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const subnet_ipv6_cidr_mask_t& lhs, const subnet_ipv6_cidr_mask_t& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// Subnet with cidr mask
|
||||
class subnet_cidr_mask_t {
|
||||
public:
|
||||
subnet_cidr_mask_t() {
|
||||
this->subnet_address = 0;
|
||||
this->cidr_prefix_length = 0;
|
||||
}
|
||||
subnet_cidr_mask_t(uint32_t subnet_address, uint32_t cidr_prefix_length) {
|
||||
this->subnet_address = subnet_address;
|
||||
this->cidr_prefix_length = cidr_prefix_length;
|
||||
}
|
||||
|
||||
// We need this operator because we are using this class in std::map which
|
||||
// requires order
|
||||
bool operator<(const subnet_cidr_mask_t& rhs) {
|
||||
if (this->cidr_prefix_length < rhs.cidr_prefix_length) {
|
||||
return true;
|
||||
} else if (this->cidr_prefix_length == rhs.cidr_prefix_length) {
|
||||
return this->subnet_address < rhs.subnet_address;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_zero_subnet() {
|
||||
if (subnet_address == 0 && cidr_prefix_length == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void set_subnet_address(uint32_t subnet_address) {
|
||||
this->subnet_address = subnet_address;
|
||||
}
|
||||
|
||||
void set_cidr_prefix_length(uint32_t cidr_prefix_length) {
|
||||
this->cidr_prefix_length = cidr_prefix_length;
|
||||
}
|
||||
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
|
||||
ar& BOOST_SERIALIZATION_NVP(subnet_address);
|
||||
ar& BOOST_SERIALIZATION_NVP(cidr_prefix_length);
|
||||
}
|
||||
|
||||
// Big endian (network byte order)
|
||||
uint32_t subnet_address = 0;
|
||||
|
||||
// Little endian
|
||||
uint32_t cidr_prefix_length = 0;
|
||||
};
|
||||
|
||||
// TODO: move to .cpp file!!!
|
||||
inline bool operator==(const subnet_cidr_mask_t& lhs, const subnet_cidr_mask_t& rhs) {
|
||||
// Prefixes has different lengths
|
||||
if (lhs.cidr_prefix_length != rhs.cidr_prefix_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return lhs.subnet_address == rhs.subnet_address;
|
||||
}
|
||||
|
||||
inline bool operator!=(const subnet_cidr_mask_t& lhs, const subnet_cidr_mask_t& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// TODO: move to .cpp file!!!
|
||||
// We need free function for comparision code
|
||||
inline bool operator<(const subnet_cidr_mask_t& lhs, const subnet_cidr_mask_t& rhs) {
|
||||
if (lhs.cidr_prefix_length < rhs.cidr_prefix_length) {
|
||||
return true;
|
||||
} else if (lhs.cidr_prefix_length == rhs.cidr_prefix_length) {
|
||||
return lhs.subnet_address < rhs.subnet_address;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Subnet with binary mask
|
||||
class subnet_binary_netmask_t {
|
||||
public:
|
||||
subnet_binary_netmask_t() {
|
||||
this->subnet_address = 0;
|
||||
this->subnet_binary_mask = 0;
|
||||
}
|
||||
subnet_binary_netmask_t(uint32_t subnet_address, uint32_t subnet_binary_mask) {
|
||||
this->subnet_address = subnet_address;
|
||||
this->subnet_binary_mask = subnet_binary_mask;
|
||||
}
|
||||
uint32_t subnet_address = 0;
|
||||
uint32_t subnet_binary_mask = 0;
|
||||
};
|
||||
|
||||
namespace std {
|
||||
|
||||
// Inject custom specialization of std::hash in namespace std
|
||||
// We need it for std::unordered_map
|
||||
template <> struct hash<subnet_cidr_mask_t> {
|
||||
typedef std::size_t result_type;
|
||||
std::size_t operator()(subnet_cidr_mask_t const& s) const {
|
||||
std::size_t seed = 0;
|
||||
|
||||
boost::hash_combine(seed, s.cidr_prefix_length);
|
||||
boost::hash_combine(seed, s.subnet_address);
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
Loading…
Reference in New Issue
Block a user