diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 33edf5ac..34621de6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -212,7 +212,7 @@ target_link_libraries(unified_parser fastnetmon_packet_parser) # Our ipfix database library add_library(ipfix_rfc STATIC ipfix_rfc.cpp) -add_library(bgp_protocol bgp_flow_spec.cpp) +add_library(bgp_protocol bgp_protocol.cpp) # Our packet parser add_library(fastnetmon_packet_parser STATIC fastnetmon_packet_parser.c) diff --git a/src/bgp_flow_spec.cpp b/src/bgp_protocol.cpp similarity index 50% rename from src/bgp_flow_spec.cpp rename to src/bgp_protocol.cpp index 520640a9..a027fc84 100644 --- a/src/bgp_flow_spec.cpp +++ b/src/bgp_protocol.cpp @@ -1,4 +1,4 @@ -#include "bgp_flow_spec.h" +#include "bgp_protocol.hpp" #include "log4cpp/Appender.hh" #include "log4cpp/BasicLayout.hh" @@ -9,6 +9,11 @@ #include "log4cpp/PatternLayout.hh" #include "log4cpp/Priority.hh" +#include "all_logcpp_libraries.h" + +// Get log4cpp logger from main programm +extern log4cpp::Category& logger; + // Enable custom casts from our own types std::ostream& operator<<(std::ostream& os, bgp_flow_spec_protocol_t const& protocol) { if (protocol == FLOW_SPEC_PROTOCOL_UDP) { @@ -63,3 +68,55 @@ std::ostream& operator<<(std::ostream& os, flow_spec_fragmentation_types_t const } } +bool read_bgp_community_from_string(std::string community_as_string, bgp_community_attribute_element_t& bgp_community_attribute_element) { + std::vector community_as_vector; + + split(community_as_vector, community_as_string, boost::is_any_of(":"), boost::token_compress_on); + + if (community_as_vector.size() != 2) { + logger << log4cpp::Priority::WARN << "Could not parse community: " << community_as_string; + return false; + } + + int asn_as_integer = 0; + + if (!convert_string_to_positive_integer_safe(community_as_vector[0], asn_as_integer)) { + logger << log4cpp::Priority::WARN << "Could not parse ASN from raw format: " << community_as_vector[0]; + return false; + } + + int community_number_as_integer = 0; + + if (!convert_string_to_positive_integer_safe(community_as_vector[1], community_number_as_integer)) { + logger << log4cpp::Priority::WARN << "Could not parse community from raw format: " << community_as_vector[0]; + return false; + } + + if (asn_as_integer < 0 or community_number_as_integer < 0) { + logger << log4cpp::Priority::WARN << "For some strange reasons we've got negative ASN or community numbers"; + return false; + } + + if (asn_as_integer > UINT16_MAX) { + logger << log4cpp::Priority::ERROR << "Your ASN value exceeds maximum allowed value " << UINT16_MAX; + return false; + } + + if (community_number_as_integer > UINT16_MAX) { + logger << log4cpp::Priority::ERROR << "Your community value exceeds maximum allowed value " << UINT16_MAX; + return false; + } + + bgp_community_attribute_element.asn_number = asn_as_integer; + bgp_community_attribute_element.community_number = community_number_as_integer; + + return true; +} + +// Wrapper function which just checks correctness of bgp community +bool is_bgp_community_valid(std::string community_as_string) { + bgp_community_attribute_element_t bgp_community_attribute_element; + + return read_bgp_community_from_string(community_as_string, bgp_community_attribute_element); +} + diff --git a/src/bgp_flow_spec.h b/src/bgp_protocol.hpp similarity index 94% rename from src/bgp_flow_spec.h rename to src/bgp_protocol.hpp index 0d2616dd..20299c15 100644 --- a/src/bgp_flow_spec.h +++ b/src/bgp_protocol.hpp @@ -1,5 +1,4 @@ -#ifndef BGP_FLOW_SPEC_H -#define BGP_FLOW_SPEC_H +#pragma once #include #include @@ -64,6 +63,23 @@ enum bgp_flow_spec_protocol_t { FLOW_SPEC_PROTOCOL_ICMP, }; +// Class for storing old style BGP communities which support only 16 bit ASN numbers +class __attribute__((__packed__)) bgp_community_attribute_element_t { + public: + uint16_t asn_number = 0; + uint16_t community_number = 0; + + void host_byte_order_to_network_byte_order() { + asn_number = htons(asn_number); + community_number = htons(community_number); + } +}; + +bool read_bgp_community_from_string(std::string community_as_string, bgp_community_attribute_element_t& bgp_community_attribute_element); + +static_assert(sizeof(bgp_community_attribute_element_t) == 4, "Broken size of bgp_community_attribute_element_t"); + + // Enable custom casts from our own types std::ostream& operator<<(std::ostream& os, bgp_flow_spec_protocol_t const& protocol); @@ -524,4 +540,5 @@ class exabgp_flow_spec_rule_t : public flow_spec_rule_t { void exabgp_flow_spec_rule_ban_manage(std::string action, flow_spec_rule_t flow_spec_rule); -#endif +bool read_bgp_community_from_string(std::string community_as_string, bgp_community_attribute_element_t& bgp_community_attribute_element); +bool is_bgp_community_valid(std::string community_as_string); diff --git a/src/fast_library.cpp b/src/fast_library.cpp index 3c2d277d..f5635a6c 100644 --- a/src/fast_library.cpp +++ b/src/fast_library.cpp @@ -1439,3 +1439,26 @@ bool ip_belongs_to_patricia_tree_ipv6(patricia_tree_t* patricia_tree, struct in6 return patricia_search_best2(patricia_tree, &prefix_for_check_address, 1) != NULL; } +// Safe way to convert string to positive integer. +// We accept only positive numbers here +bool convert_string_to_positive_integer_safe(std::string line, int& value) { + int temp_value = 0; + + try { + temp_value = std::stoi(line); + } catch (...) { + // Could not parse number correctly + return false; + } + + if (temp_value >= 0) { + value = temp_value; + return true; + } else { + // We do not expect negative values here + return false; + } + + return true; +} + diff --git a/src/fast_library.h b/src/fast_library.h index 06357a84..a13bfa06 100644 --- a/src/fast_library.h +++ b/src/fast_library.h @@ -1,5 +1,4 @@ -#ifndef FAST_LIBRARY_H -#define FAST_LIBRARY_H +#pragma once #include "fastnetmon_types.h" @@ -121,4 +120,4 @@ bool set_boost_process_name(boost::thread* thread, std::string process_name); std::string print_ipv6_cidr_subnet(subnet_ipv6_cidr_mask_t subnet); std::string convert_any_ip_to_string(subnet_ipv6_cidr_mask_t subnet); -#endif +bool convert_string_to_positive_integer_safe(std::string line, int& value); diff --git a/src/fastnetmon.conf b/src/fastnetmon.conf index cbd173eb..8f7c0fc1 100644 --- a/src/fastnetmon.conf +++ b/src/fastnetmon.conf @@ -229,6 +229,7 @@ gobgp = off gobgp_next_hop = 0.0.0.0 gobgp_announce_host = on gobgp_announce_whole_subnet = off +gobgp_community = 65001:666 # Graphite monitoring # InfluxDB is also supported, please check our reference: diff --git a/src/fastnetmon.cpp b/src/fastnetmon.cpp index 1f09b4ab..5101b043 100644 --- a/src/fastnetmon.cpp +++ b/src/fastnetmon.cpp @@ -23,7 +23,7 @@ #include #include -#include "bgp_flow_spec.h" +#include "bgp_protocol.hpp" #include "fast_library.h" #include "fastnetmon_packet_parser.h" #include "fastnetmon_types.h" diff --git a/src/fastnetmon_logic.cpp b/src/fastnetmon_logic.cpp index 5deccf12..01031ab8 100644 --- a/src/fastnetmon_logic.cpp +++ b/src/fastnetmon_logic.cpp @@ -6,7 +6,7 @@ #include #include "all_logcpp_libraries.h" -#include "bgp_flow_spec.h" +#include "bgp_protocol.hpp" #include "fast_library.h" #include "fast_platform.h" #include "fastnetmon_packet_parser.h" diff --git a/src/fastnetmon_logic.hpp b/src/fastnetmon_logic.hpp index 208b4082..040d4c49 100644 --- a/src/fastnetmon_logic.hpp +++ b/src/fastnetmon_logic.hpp @@ -1,5 +1,5 @@ #include "fastnetmon_types.h" -#include "bgp_flow_spec.h" +#include "bgp_protocol.hpp" #ifdef ENABLE_DPI #include "fast_dpi.h"