2022-03-24 02:29:11 +01:00
# pragma once
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
# include <algorithm>
# include <cstdint>
# include <cstring>
# include <iostream>
# include <sstream>
2015-07-08 17:45:33 +02:00
# include <string>
2015-07-10 14:43:46 +02:00
# include <vector>
2023-07-18 18:52:45 +02:00
# include "dynamic_binary_buffer.hpp"
2022-06-26 16:10:12 +02:00
# include "fast_library.hpp"
2023-07-18 18:52:45 +02:00
# include "fastnetmon_networks.hpp"
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
# include <boost/serialization/nvp.hpp>
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
# include "iana_ip_protocols.hpp"
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
# include "all_logcpp_libraries.hpp"
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
// Get log4cpp logger from main programme
extern log4cpp : : Category & logger ;
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
class bgp_attribute_origin ;
class bgp_attribute_next_hop_ipv4 ;
class IPv4UnicastAnnounce ;
class IPv6UnicastAnnounce ;
bool decode_bgp_subnet_encoding_ipv4_raw ( uint8_t * value , subnet_cidr_mask_t & extracted_prefix ) ;
bool decode_bgp_subnet_encoding_ipv4 ( int len , uint8_t * value , subnet_cidr_mask_t & extracted_prefix , uint32_t & parsed_nlri_length ) ;
uint32_t how_much_bytes_we_need_for_storing_certain_subnet_mask ( uint8_t prefix_bit_length ) ;
std : : string get_bgp_attribute_name_by_number ( uint8_t bgp_attribute_type ) ;
enum BGP_PROTOCOL_MESSAGE_TYPES_UNTYPED : uint8_t {
BGP_PROTOCOL_MESSAGE_OPEN = 1 ,
BGP_PROTOCOL_MESSAGE_UPDATE = 2 ,
BGP_PROTOCOL_MESSAGE_NOTIFICATION = 3 ,
BGP_PROTOCOL_MESSAGE_KEEPALIVE = 4 ,
} ;
// More details here https://tools.ietf.org/html/rfc4271#page-12
class __attribute__ ( ( __packed__ ) ) bgp_message_header_t {
public :
uint8_t marker [ 16 ] = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff } ;
uint16_t length = 0 ;
uint8_t type = 0 ;
void host_byte_order_to_network_byte_order ( ) {
length = htons ( length ) ;
}
} ;
static_assert ( sizeof ( bgp_message_header_t ) = = 19 , " Broken size for bgp_message_header_t " ) ;
// TODO: move to
//
// https://www.ietf.org/rfc/rfc4271.txt pages 15 and 16
// https://github.com/osrg/gobgp/blob/d6148c75a30d87c3f8c1d0f68725127e4c5f3a65/packet/bgp.go#L3012
struct __attribute__ ( ( __packed__ ) ) bgp_attribute_flags {
uint8_t : 4 , extended_length_bit : 1 = 0 , partial_bit : 1 = 0 , transitive_bit : 1 = 0 , optional_bit : 1 = 0 ;
bgp_attribute_flags ( uint8_t flag_as_integer ) {
memcpy ( this , & flag_as_integer , sizeof ( flag_as_integer ) ) ;
}
bgp_attribute_flags ( ) {
memset ( this , 0 , sizeof ( * this ) ) ;
}
void set_optional_bit ( bool bit_value ) {
optional_bit = ( int ) bit_value ;
}
void set_transitive_bit ( bool bit_value ) {
transitive_bit = ( int ) bit_value ;
}
void set_partial_bit ( bool bit_value ) {
partial_bit = ( int ) bit_value ;
}
void set_extended_length_bit ( bool bit_value ) {
extended_length_bit = ( int ) bit_value ;
}
bool get_optional_bit ( ) {
return optional_bit = = 1 ? true : false ;
}
bool get_transitive_bit ( ) {
return transitive_bit = = 1 ? true : false ;
}
bool get_partial_bit ( ) {
return partial_bit = = 1 ? true : false ;
}
bool get_extended_length_bit ( ) {
return extended_length_bit = = 1 ? true : false ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
std : : string print ( ) const {
std : : stringstream buf ;
buf < < " optional: " < < int ( optional_bit ) < < " transitive: " < < int ( transitive_bit )
< < " partial_bit: " < < int ( partial_bit ) < < " extended_length_bit: " < < int ( extended_length_bit ) ;
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
return buf . str ( ) ;
}
2015-07-08 17:45:33 +02:00
} ;
2023-07-18 18:52:45 +02:00
class bgp_attibute_common_header_t {
public :
uint8_t attribute_flags = 0 ;
uint8_t attribute_type = 0 ;
uint32_t length_of_length_field = 0 ;
uint32_t attribute_value_length = 0 ;
uint32_t attribute_body_shift = 0 ;
// Just const value
uint32_t attribute_flag_and_type_length = 2 ;
std : : string print ( ) const {
std : : stringstream buffer ;
buffer < < " attribute_flags: " < < uint32_t ( attribute_flags )
< < " "
// << "attribute_pretty_flags: " <<
// bgp_attribute_flags(attribute_flags).print() << " "
< < " attribute_type: " < < uint32_t ( attribute_type ) < < " "
< < " attribute_name: " < < get_bgp_attribute_name_by_number ( attribute_type ) < < " "
< < " length_of_length_field: " < < length_of_length_field < < " "
< < " attribute_value_length: " < < attribute_value_length ;
return buffer . str ( ) ;
}
// More user friendly form
bool parse_raw_bgp_attribute_binary_buffer ( dynamic_binary_buffer_t dynamic_binary_buffer ) {
return parse_raw_bgp_attribute ( ( uint8_t * ) dynamic_binary_buffer . get_pointer ( ) , dynamic_binary_buffer . get_used_size ( ) ) ;
}
bool parse_raw_bgp_attribute ( uint8_t * value , size_t len ) {
if ( len < attribute_flag_and_type_length or value = = NULL ) {
logger < < log4cpp : : Priority : : WARN < < " Too short attribute. We need least two bytes here but get " < < len < < " bytes " ;
return false ;
}
// https://www.ietf.org/rfc/rfc4271.txt page 15
attribute_flags = value [ 0 ] ;
attribute_type = value [ 1 ] ;
bgp_attribute_flags attr_flags ( attribute_flags ) ;
// attr_flags.print();
length_of_length_field = 1 ;
if ( attr_flags . extended_length_bit = = 1 ) {
// When we have extended_length_bit we have two bytes for length
// information
// TODO: add support for this type of attributes
// logger << log4cpp::Priority::WARN << "We haven't support for extended
// length attributes.
// Sorry!" <<
// std::endl;
length_of_length_field = 2 ;
}
if ( len < attribute_flag_and_type_length + length_of_length_field ) {
logger < < log4cpp : : Priority : : WARN < < " Too short attribute because we need least "
< < attribute_flag_and_type_length + length_of_length_field < < " bytes " ;
return false ;
}
attribute_value_length = value [ 2 ] ;
// logger << log4cpp::Priority::WARN << "Attribute type: " <<
// int(attribute_type) ;
// logger << log4cpp::Priority::WARN << "Raw attribute length: " << len ;
// logger << log4cpp::Priority::WARN << "Attribute internal length: " <<
// int(attribute_value_length)
// ;
uint32_t total_attribute_length = attribute_flag_and_type_length + length_of_length_field + attribute_value_length ;
// logger << log4cpp::Priority::WARN << "attribute_flag_and_type_length: "
// <<
// attribute_flag_and_type_length <<
// std::endl
// << "length_of_length_field: " << length_of_length_field
// << "attribute_value_length: " << attribute_value_length ;
if ( len < total_attribute_length ) {
logger < < log4cpp : : Priority : : WARN < < " Atrribute value length: " < < total_attribute_length
< < " length exceed whole packet length " < < len ;
return false ;
}
// Store shift to attribute payload
attribute_body_shift = attribute_flag_and_type_length + length_of_length_field ;
return true ;
}
2015-07-13 12:27:09 +02:00
} ;
2023-07-18 18:52:45 +02:00
bool decode_nlri_ipv4 ( int len , uint8_t * value , subnet_cidr_mask_t & extracted_prefix ) ;
bool decode_attribute ( int len , char * value , IPv4UnicastAnnounce & unicast_ipv4_announce ) ;
bool encode_bgp_subnet_encoding ( const subnet_cidr_mask_t & prefix , dynamic_binary_buffer_t & buffer_result ) ;
std : : string get_origin_name_by_value ( uint8_t origin_value ) ;
const unsigned int AFI_IP = 1 ;
const unsigned int AFI_IP6 = 2 ;
const unsigned int SAFI_UNICAST = 1 ;
const unsigned int SAFI_FLOW_SPEC_UNICAST = 133 ;
const unsigned int ipv4_unicast_route_family = AFI_IP < < 16 | SAFI_UNICAST ;
const unsigned int ipv4_flow_spec_route_family = AFI_IP < < 16 | SAFI_FLOW_SPEC_UNICAST ;
const unsigned int ipv6_unicast_route_family = AFI_IP6 < < 16 | SAFI_UNICAST ;
const unsigned int ipv6_flow_spec_route_family = AFI_IP6 < < 16 | SAFI_FLOW_SPEC_UNICAST ;
// http://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml
// https://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml#transitive
enum EXTENDED_COMMUNITY_TYPES_HIGHT_UNTYPED : uint8_t {
// Transitive IPv4-Address-Specific Extended Community (Sub-Types are defined in the "Transitive IPv4-Address-Specific Extended Community Sub-Types" registry)
EXTENDED_COMMUNITY_TRANSITIVE_IPV4_ADDRESS_SPECIFIC = 1 , // 0x01
// We are encoding attributes for BGP flow spec this way
// Generic Transitive Experimental Use Extended Community
EXTENDED_COMMUNITY_TRANSITIVE_EXPEREMENTAL = 128 , // 0x80
2015-07-08 17:45:33 +02:00
} ;
2023-07-18 18:52:45 +02:00
// Subtypes for EXTENDED_COMMUNITY_TRANSITIVE_EXPEREMENTAL
// http://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml
// https://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml#transitive
enum EXTENDED_COMMUNITY_TYPES_LOW_FOR_COMMUNITY_TRANSITIVE_EXPEREMENTAL : uint8_t {
FLOW_SPEC_EXTENDED_COMMUNITY_SUBTYPE_TRAFFIC_RATE = 6 ,
FLOW_SPEC_EXTENDED_COMMUNITY_SUBTYPE_TRAFFIC_ACTION = 7 ,
FLOW_SPEC_EXTENDED_COMMUNITY_SUBTYPE_REDIRECT_AS_TWO_BYTE = 8 ,
FLOW_SPEC_EXTENDED_COMMUNITY_SUBTYPE_TRAFFIC_REMARKING = 9 ,
} ;
enum BGP_ATTRIBUTES_TYPES : uint8_t {
// https://www.ietf.org/rfc/rfc4271.txt from page 17
BGP_ATTRIBUTE_ORIGIN = 1 ,
BGP_ATTRIBUTE_AS_PATH = 2 ,
BGP_ATTRIBUTE_NEXT_HOP = 3 ,
BGP_ATTRIBUTE_MULTI_EXIT_DISC = 4 ,
BGP_ATTRIBUTE_LOCAL_PREF = 5 ,
BGP_ATTRIBUTE_ATOMIC_AGGREGATE = 6 ,
BGP_ATTRIBUTE_AGGREGATOR = 7 ,
// https://tools.ietf.org/html/rfc1997 from page 1
BGP_ATTRIBUTE_COMMUNITY = 8 ,
// https://tools.ietf.org/html/rfc4760 from page 2
BGP_ATTRIBUTE_MP_REACH_NLRI = 14 ,
// https://tools.ietf.org/html/rfc4360 from page 1
BGP_ATTRIBUTE_EXTENDED_COMMUNITY = 16 ,
} ;
// https://www.ietf.org/rfc/rfc4271.txt from page 17
enum BGP_ORIGIN_TYPES : uint8_t { BGP_ORIGIN_IGP = 0 , BGP_ORIGIN_EGP = 1 , BGP_ORIGIN_INCOMPLETE = 2 } ;
// https://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml#trans-ipv4
enum BGP_IPV4_EXTENDED_COMMUNITY_SUBTYPES_TRANSITIVE : uint8_t {
BGP_IPV4_EXTENDED_COMMUNITY_SUBTYPE_FLOW_SPEC_REDIRECT_IPv4 = 0x0c ,
2015-07-10 14:43:46 +02:00
} ;
2023-07-18 18:52:45 +02:00
// It's short MP reach NLRI header. We use it in case when we have non zero length for length_of_next_hop
// I use it only to decode/encode IPv6 annnounces
class __attribute__ ( ( __packed__ ) ) bgp_mp_reach_short_header_t {
public :
uint16_t afi_identifier = AFI_IP6 ;
uint8_t safi_identifier = SAFI_UNICAST ;
// According to https://www.ietf.org/rfc/rfc2545.txt we should set it to 16 for global IP addresses
uint8_t length_of_next_hop = 16 ;
void network_to_host_byte_order ( ) {
afi_identifier = ntohs ( afi_identifier ) ;
}
void host_byte_order_to_network_byte_order ( ) {
afi_identifier = htons ( afi_identifier ) ;
}
std : : string print ( ) const {
std : : stringstream buffer ;
buffer < < " afi_identifier: " < < uint32_t ( afi_identifier ) < < " "
< < " safi_identifier: " < < uint32_t ( safi_identifier ) < < " "
< < " length_of_next_hop: " < < uint32_t ( length_of_next_hop ) ;
return buffer . str ( ) ;
}
} ;
class __attribute__ ( ( __packed__ ) ) bgp_attribute_community_t {
public :
bgp_attribute_community_t ( ) {
attribute_type = BGP_ATTRIBUTE_COMMUNITY ;
// Set attribute flags
attribute_flags . set_transitive_bit ( true ) ;
attribute_flags . set_partial_bit ( false ) ;
attribute_flags . set_optional_bit ( true ) ;
attribute_flags . set_extended_length_bit ( false ) ;
}
bgp_attribute_flags attribute_flags ;
uint8_t attribute_type = 0 ;
// This variable store total size in bytes of all community elements (each
// element should has
// size 4 bytes)
uint8_t attribute_length = 0 ;
// Here we have multiple elements of type: bgp_community_attribute_element_t
} ;
// This is new extended communities:
// More details: https://tools.ietf.org/html/rfc4360
class __attribute__ ( ( __packed__ ) ) bgp_extended_community_attribute_t {
public :
bgp_extended_community_attribute_t ( ) {
// Set attribute flags
attribute_flags . set_transitive_bit ( true ) ;
attribute_flags . set_partial_bit ( false ) ;
attribute_flags . set_optional_bit ( true ) ;
attribute_flags . set_extended_length_bit ( false ) ;
}
bgp_attribute_flags attribute_flags ;
uint8_t attribute_type = BGP_ATTRIBUTE_EXTENDED_COMMUNITY ;
// This variable store total size in bytes of all community elements. Each
// community element has
// size 8 bytes
uint8_t attribute_length = 0 ;
// Here we have multiple elements of type: bgp_extended_community_element_t
} ;
// BGP extended community attribute
class __attribute__ ( ( __packed__ ) ) bgp_extended_community_element_t {
public :
uint8_t type_hight = 0 ;
uint8_t type_low = 0 ;
// This data depends on implementation and values in type_* variables
uint8_t value [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
std : : string print ( ) const {
std : : stringstream buffer ;
buffer < < " type hight: " < < uint32_t ( type_hight ) < < " "
< < " type low: " < < uint32_t ( type_low ) < < " "
< < " value raw: " < < print_binary_string_as_hex_with_leading_0x ( value , sizeof ( value ) ) ;
return buffer . str ( ) ;
}
} ;
static_assert ( sizeof ( bgp_extended_community_element_t ) = = 8 , " Bad size for bgp_extended_community_element_t " ) ;
// This is class for storing old style BGP communities which support only 16
// bit AS numbers
2022-03-24 02:29:11 +01:00
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 " ) ;
2023-07-18 18:52:45 +02:00
// With this attribute we are encoding different things (flow spec for example)
class __attribute__ ( ( __packed__ ) ) bgp_attribute_multiprotocol_extensions_t {
public :
bgp_attribute_multiprotocol_extensions_t ( ) {
attribute_flags . set_transitive_bit ( false ) ;
attribute_flags . set_optional_bit ( true ) ;
attribute_flags . set_partial_bit ( false ) ;
attribute_flags . set_extended_length_bit ( false ) ;
}
2022-03-24 02:29:11 +01:00
2023-07-18 18:52:45 +02:00
std : : string print ( ) const {
std : : stringstream buf ;
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
buf < < attribute_flags . print ( ) < < " attribute type: " < < int ( attribute_type )
< < " attribute_length: " < < int ( attribute_length ) ;
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
return buf . str ( ) ;
}
bgp_attribute_flags attribute_flags ;
uint8_t attribute_type = BGP_ATTRIBUTE_MP_REACH_NLRI ;
uint8_t attribute_length = 0 ;
// value has very complex format and we are encoding it with external code
} ;
2015-07-13 12:27:09 +02:00
2023-07-18 18:52:45 +02:00
class __attribute__ ( ( __packed__ ) ) bgp_attribute_origin {
2015-07-08 17:45:33 +02:00
public :
2023-07-18 18:52:45 +02:00
bgp_attribute_origin ( ) {
// Set attribute flags
attribute_flags . set_transitive_bit ( true ) ;
2015-07-13 17:00:20 +02:00
2023-07-18 18:52:45 +02:00
attribute_flags . set_partial_bit ( false ) ;
attribute_flags . set_optional_bit ( false ) ;
attribute_flags . set_extended_length_bit ( false ) ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
std : : string print ( ) const {
std : : stringstream buf ;
buf < < attribute_flags . print ( ) < < " attribute type: " < < int ( attribute_type )
< < " attribute_length: " < < int ( attribute_length ) < < " attribute_value: " < < attribute_value ;
2022-02-09 15:27:32 +01:00
2023-07-18 18:52:45 +02:00
return buf . str ( ) ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
bgp_attribute_flags attribute_flags ;
uint8_t attribute_type = BGP_ATTRIBUTE_ORIGIN ;
uint8_t attribute_length = 1 ;
uint8_t attribute_value = ( uint8_t ) BGP_ORIGIN_INCOMPLETE ;
} ;
class __attribute__ ( ( __packed__ ) ) bgp_attribute_next_hop_ipv4 {
public :
bgp_attribute_next_hop_ipv4 ( ) {
// Set attribute flags
attribute_flags . set_transitive_bit ( true ) ;
attribute_flags . set_partial_bit ( false ) ;
attribute_flags . set_optional_bit ( false ) ;
attribute_flags . set_extended_length_bit ( false ) ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
bgp_attribute_next_hop_ipv4 ( uint32_t next_hop ) : bgp_attribute_next_hop_ipv4 ( ) {
attribute_value = next_hop ;
2022-02-09 15:27:32 +01:00
}
2015-07-13 17:00:20 +02:00
2023-07-18 18:52:45 +02:00
bgp_attribute_flags attribute_flags ;
uint8_t attribute_type = BGP_ATTRIBUTE_NEXT_HOP ;
uint8_t attribute_length = 4 ;
uint32_t attribute_value = 0 ;
std : : string print ( ) const {
std : : stringstream buf ;
buf < < attribute_flags . print ( ) < < " attribute type: " < < int ( attribute_type )
< < " attribute_length: " < < int ( attribute_length ) < < " attribute_value: " < < attribute_value ;
2022-02-09 15:27:32 +01:00
2023-07-18 18:52:45 +02:00
return buf . str ( ) ;
}
2015-07-08 17:45:33 +02:00
} ;
2023-07-18 18:52:45 +02:00
class IPv4UnicastAnnounce {
2015-07-08 17:45:33 +02:00
public :
2023-07-18 18:52:45 +02:00
void set_withdraw ( bool withdraw ) {
this - > is_withdraw = withdraw ;
}
bool get_withdraw ( ) {
return this - > is_withdraw ;
}
void set_next_hop ( uint32_t next_hop ) {
this - > next_hop = next_hop ;
}
void set_prefix ( subnet_cidr_mask_t prefix ) {
this - > prefix = prefix ;
}
void set_origin ( BGP_ORIGIN_TYPES origin ) {
this - > origin = origin ;
}
uint32_t get_next_hop ( ) {
return next_hop ;
}
subnet_cidr_mask_t get_prefix ( ) {
return this - > prefix ;
}
BGP_ORIGIN_TYPES get_origin ( ) {
return this - > origin ;
}
// Returns prefix in text form
std : : string get_prefix_in_cidr_form ( ) {
return convert_ip_as_uint_to_string ( prefix . subnet_address ) + " / " + std : : to_string ( prefix . cidr_prefix_length ) ;
}
bool generate_nlri ( dynamic_binary_buffer_t & buffer_result ) const {
return encode_bgp_subnet_encoding ( this - > prefix , buffer_result ) ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
std : : vector < dynamic_binary_buffer_t > get_attributes ( ) const {
/*
* The sender of an UPDATE message SHOULD order path attributes within
* the UPDATE message in ascending order of attribute type . The
* receiver of an UPDATE message MUST be prepared to handle path
* attributes within UPDATE messages that are out of order .
*/
bgp_attribute_origin origin_attr ;
// logger << log4cpp::Priority::WARN << "origin_attr: " <<
// origin_attr.print() <<
// std::endl;
bgp_attribute_next_hop_ipv4 next_hop_attr ( next_hop ) ;
// logger << log4cpp::Priority::WARN << "next_hop_attr: " <<
// next_hop_attr.print() <<
// std::endl;
dynamic_binary_buffer_t origin_as_binary_array ;
origin_as_binary_array . set_maximum_buffer_size_in_bytes ( sizeof ( origin_attr ) ) ;
origin_as_binary_array . append_data_as_object_ptr ( & origin_attr ) ;
dynamic_binary_buffer_t next_hop_as_binary_array ;
next_hop_as_binary_array . set_maximum_buffer_size_in_bytes ( sizeof ( next_hop_attr ) ) ;
next_hop_as_binary_array . append_data_as_object_ptr ( & next_hop_attr ) ;
// TODO: remove ugly code with custom build of each vector
if ( community_list . empty ( ) ) {
// Vector should be ordered in ascending order of attribute types
return std : : vector < dynamic_binary_buffer_t > { origin_as_binary_array , next_hop_as_binary_array } ;
2022-02-09 15:27:32 +01:00
} else {
2023-07-18 18:52:45 +02:00
// We have communities
bgp_attribute_community_t bgp_attribute_community ;
// Each record has this of 4 bytes
bgp_attribute_community . attribute_length = community_list . size ( ) * sizeof ( bgp_community_attribute_element_t ) ;
uint32_t community_attribute_full_length = sizeof ( bgp_attribute_community_t ) + bgp_attribute_community . attribute_length ;
dynamic_binary_buffer_t communities_list_as_binary_array ;
communities_list_as_binary_array . set_maximum_buffer_size_in_bytes ( community_attribute_full_length ) ;
communities_list_as_binary_array . append_data_as_object_ptr ( & bgp_attribute_community ) ;
for ( auto bgp_community_element : community_list ) {
// Encode they in network byte order
bgp_community_element . host_byte_order_to_network_byte_order ( ) ;
communities_list_as_binary_array . append_data_as_object_ptr ( & bgp_community_element ) ;
}
return std : : vector < dynamic_binary_buffer_t > { origin_as_binary_array , next_hop_as_binary_array ,
communities_list_as_binary_array } ;
2015-07-10 18:08:06 +02:00
}
2022-02-09 15:27:32 +01:00
}
2015-07-10 18:08:06 +02:00
2023-07-18 18:52:45 +02:00
std : : string print ( ) const {
std : : stringstream buf ;
buf < < " Prefix: " < < convert_ip_as_uint_to_string ( prefix . subnet_address ) < < " / " < < prefix . cidr_prefix_length < < " "
< < " Origin: " < < get_origin_name_by_value ( origin ) < < " "
< < " Next hop: " < < convert_ip_as_uint_to_string ( next_hop ) + " /32 " ;
// TODO: print pretty communities!!!
return buf . str ( ) ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
// Add multiple communities in single step
bool add_multiple_communities ( std : : vector < bgp_community_attribute_element_t > bgp_communities ) {
for ( auto bgp_community : bgp_communities ) {
community_list . push_back ( bgp_community ) ;
}
return true ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
bool add_community ( bgp_community_attribute_element_t bgp_community ) {
community_list . push_back ( bgp_community ) ;
return true ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
private :
uint32_t next_hop = 0 ;
subnet_cidr_mask_t prefix ;
BGP_ORIGIN_TYPES origin = BGP_ORIGIN_INCOMPLETE ;
bool is_withdraw = false ;
std : : vector < bgp_community_attribute_element_t > community_list ;
} ;
class IPv6UnicastAnnounce {
public :
void set_withdraw ( bool withdraw ) {
this - > is_withdraw = withdraw ;
}
bool get_withdraw ( ) {
return this - > is_withdraw ;
}
void set_next_hop ( subnet_ipv6_cidr_mask_t next_hop ) {
this - > next_hop = next_hop ;
}
void set_prefix ( subnet_ipv6_cidr_mask_t prefix ) {
this - > prefix = prefix ;
}
void set_origin ( BGP_ORIGIN_TYPES origin ) {
this - > origin = origin ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
subnet_ipv6_cidr_mask_t get_next_hop ( ) const {
return next_hop ;
2022-02-09 15:27:32 +01:00
}
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
subnet_ipv6_cidr_mask_t get_prefix ( ) const {
return this - > prefix ;
2022-02-09 15:27:32 +01:00
}
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
BGP_ORIGIN_TYPES get_origin ( ) const {
return this - > origin ;
}
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
std : : string print ( ) const {
std : : stringstream buf ;
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
buf < < " Prefix: " < < convert_ipv6_subnet_to_string ( prefix ) < < " "
< < " Origin: " < < get_origin_name_by_value ( origin ) < < " "
< < " Next hop: " < < convert_ipv6_subnet_to_string ( next_hop ) ;
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
return buf . str ( ) ;
2022-02-09 15:27:32 +01:00
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
// Returns prefix in text form
std : : string get_prefix_in_cidr_form ( ) const {
return convert_ipv6_subnet_to_string ( prefix ) ;
2022-02-09 15:27:32 +01:00
}
2023-07-18 18:52:45 +02:00
// Add multiple communities in single step
bool add_multiple_communities ( std : : vector < bgp_community_attribute_element_t > bgp_communities ) {
for ( auto bgp_community : bgp_communities ) {
community_list . push_back ( bgp_community ) ;
}
return true ;
2022-02-09 15:27:32 +01:00
}
2015-07-13 12:27:09 +02:00
2023-07-18 18:52:45 +02:00
bool add_community ( bgp_community_attribute_element_t bgp_community ) {
community_list . push_back ( bgp_community ) ;
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
return true ;
}
2015-07-10 14:43:46 +02:00
2023-07-18 18:52:45 +02:00
std : : vector < bgp_community_attribute_element_t > get_communities ( ) const {
return community_list ;
}
2015-07-08 17:45:33 +02:00
2023-07-18 18:52:45 +02:00
private :
subnet_ipv6_cidr_mask_t next_hop { } ;
subnet_ipv6_cidr_mask_t prefix { } ;
BGP_ORIGIN_TYPES origin = BGP_ORIGIN_INCOMPLETE ;
bool is_withdraw = false ;
std : : vector < bgp_community_attribute_element_t > community_list ;
2015-07-10 14:43:46 +02:00
} ;
2023-07-18 18:52:45 +02:00
static_assert ( sizeof ( bgp_attribute_flags ) = = 1 , " broken size for bgp_attribute_flags " ) ;
static_assert ( sizeof ( bgp_attribute_origin ) = = 4 , " Bad size for bgp_attribute_origin " ) ;
static_assert ( sizeof ( bgp_attribute_next_hop_ipv4 ) = = 7 , " Bad size for bgp_attribute_next_hop_ipv4 " ) ;
2022-03-24 02:29:11 +01:00
bool is_bgp_community_valid ( std : : string community_as_string ) ;
2023-07-18 18:52:45 +02:00
bool decode_ipv6_announce_from_binary_encoded_atributes ( std : : vector < dynamic_binary_buffer_t > binary_attributes ,
IPv6UnicastAnnounce & ipv6_announce ) ;
bool decode_mp_reach_ipv6 ( int len , uint8_t * value , bgp_attibute_common_header_t bgp_attibute_common_header , IPv6UnicastAnnounce & ipv6_announce ) ;
bool encode_ipv6_announces_into_bgp_mp_reach_attribute_internal ( const IPv6UnicastAnnounce & ipv6_announce ,
dynamic_binary_buffer_t & bgp_mp_reach_ipv6_attribute ) ;
bool encode_ipv6_announces_into_bgp_mp_reach_attribute ( const IPv6UnicastAnnounce & ipv6_announce ,
dynamic_binary_buffer_t & bgp_mp_reach_ipv6_attribute ) ;
bool encode_ipv6_prefix ( const subnet_ipv6_cidr_mask_t & prefix , dynamic_binary_buffer_t & dynamic_buffer ) ;