15 #include <arpa/inet.h> 27 this->use_4b_asn = use_4b_asn;
38 for (std::shared_ptr<BgpPathAttrib> attrib : path_attribute) {
39 if (attrib->type_code == type)
return *attrib;
42 throw "no such attribute";
53 for (
const std::shared_ptr<BgpPathAttrib> &attrib : path_attribute) {
54 if (attrib->type_code == type)
return *attrib;
57 throw "no such attribute";
68 for (
const std::shared_ptr<BgpPathAttrib> &attrib : path_attribute) {
69 if (attrib->type_code == type)
return true;
86 path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(attrib.
clone(logger)));
98 path_attribute.clear();
99 for (
const std::shared_ptr<BgpPathAttrib> &attrib : attrs) {
100 path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(attrib->clone(logger)));
114 for (
auto attr = path_attribute.begin(); attr != path_attribute.end(); attr++) {
115 if ((*attr)->type_code == type) {
116 path_attribute.erase(attr);
131 bool removed =
false;
133 for (
auto attr = path_attribute.begin(); attr != path_attribute.end();) {
134 if (!(*attr)->transitive) {
136 path_attribute.erase(attr);
186 logger->
log(ERROR,
"BgpUpdateMessage::prepend: we have AS4_PATH attribute but we are running in 4b mode. " 187 "consider restoreAsPath().\n");
194 path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(path));
200 logger->
log(ERROR,
"BgpUpdateMessage::prepend: existing AS_PATH is 2b but we are running in 4b mode. " 201 "consider restoreAsPath().\n");
211 uint16_t prep_asn = asn >= 0xffff ? 23456 : asn;
216 path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(path));
220 logger->
log(ERROR,
"BgpUpdateMessage::prepend: existing AS_PATH is 4b but we are running in 2b mode. " 221 "consider downgradeAsPath().\n");
224 if(!path.
prepend(prep_asn))
return false;
229 if(!path4.
prepend(prep_asn))
return false;
249 if (path.
is_4b)
return true;
253 std::vector<BgpAsPathSegment> new_segs;
257 logger->
log(ERROR,
"BgpUpdateMessage::restoreAsPath: 4b seg found in 2b attrib.\n");
262 for (uint16_t asn : seg2.
value) {
264 logger->
log(ERROR,
"BgpUpdateMessage::restoreAsPath: warning: AS_TRANS found but no AS4_PATH.\n");
266 new_seg.
value.push_back(asn);
269 new_segs.push_back(new_seg);
278 std::vector<uint32_t> full_as_path;
282 logger->
log(ERROR,
"BgpUpdateMessage::restoreAsPath: bad as4_path: found 2b seg.\n");
286 if (seg4.
type == AS_SEQUENCE) {
287 const std::vector<uint32_t> &part = seg4.
value;
288 full_as_path.insert(full_as_path.end(), part.begin(), part.end());
298 std::vector<uint32_t>::const_iterator iter_4b = full_as_path.begin();
300 for(; iter_4b != full_as_path.end(); iter_4b++) {
302 if (*iter_4b > 0xffff)
break;
305 std::vector<BgpAsPathSegment> new_segs;
308 std::vector<uint32_t>::const_iterator local_iter = iter_4b;
310 logger->
log(ERROR,
"BgpUpdateMessage::restoreAsPath: 4b seg found in 2b attrib.\n");
317 bool incr_iter =
false;
318 for (uint16_t asn : seg2.
value) {
319 uint32_t new_asn = asn;
322 if (has_4b && local_iter != full_as_path.end()) {
325 if (new_asn == 23456) {
330 new_asn = *local_iter;
331 }
else if (new_asn != *local_iter) {
332 logger->
log(ERROR,
"BgpUpdateMessage::restoreAsPath: warning: AS_PATH and AS4_PATH does not match.\n");
335 if (incr_iter) local_iter++;
338 new_seg.
value.push_back(new_asn);
341 new_segs.push_back(new_seg);
363 if (!path.
is_4b)
return true;
365 std::vector<BgpAsPathSegment> new_segs;
370 logger->
log(ERROR,
"BgpUpdateMessage::downgradeAsPath: 2b seg found in 4b attrib.\n");
375 for (uint32_t asn : seg4.
value) {
376 uint16_t new_as = asn >= 0xffff ? 23456 : asn;
377 new_seg.
value.push_back(new_as);
381 new_segs.push_back(new_seg);
402 if (!
hasAttrib(AS4_AGGREGATOR))
return true;
441 withdrawn_routes = routes;
454 Prefix4 route (prefix, length);
455 withdrawn_routes.push_back(route);
467 withdrawn_routes.push_back(route);
493 nlri.push_back(route);
505 nlri.push_back(route);
509 bool BgpUpdateMessage::validateAttribs() {
510 bool has_origin =
false;
511 bool has_nexthop =
false;
512 bool has_as_path =
false;
514 uint32_t typecode_bitsmap = 0;
516 for (std::vector<std::shared_ptr<BgpPathAttrib>>::const_iterator attr_iter = path_attribute.begin();
517 attr_iter != path_attribute.end(); attr_iter++) {
518 uint8_t type_code = (*attr_iter)->type_code;
520 if (type_code == AS_PATH) has_as_path =
true;
521 else if (type_code == NEXT_HOP) has_nexthop =
true;
522 else if (type_code == ORIGIN) has_origin =
true;
524 if ((typecode_bitsmap >> type_code) & 1U) {
525 logger->
log(ERROR,
"BgpUpdateMessage::validateAttribs:: duplicated attribute type in list: %d\n", type_code);
526 setError(E_UPDATE, E_ATTR_LIST, NULL, 0);
530 typecode_bitsmap &= ~(1UL << type_code);
533 if (!(has_as_path && has_nexthop && has_origin)) {
534 logger->
log(ERROR,
"BgpUpdateMessage::validateAttribs: mandatory attribute(s) missing.\n");
535 setError(E_UPDATE, E_MISS_WELL_KNOWN, NULL, 0);
542 bool BgpUpdateMessage::setWithdrawn6(
const std::vector<Prefix6> &routes) {
545 unr6.withdrawn_routes = routes;
551 bool BgpUpdateMessage::setNlri6(
const std::vector<Prefix6> &routes,
const uint8_t nexthop_global[16],
const uint8_t nexthop_linklocal[16]) {
555 memcpy(r6.nexthop_global, nexthop_global, 16);
556 if (nexthop_linklocal != NULL) {
557 memcpy(r6.nexthop_linklocal, nexthop_linklocal, 16);
558 }
else memset(r6.nexthop_linklocal, 0, 16);
566 uint8_t _err_data = msg_sz;
567 setError(E_HEADER, E_LENGTH, &_err_data,
sizeof(uint8_t));
568 logger->
log(ERROR,
"BgpUpdateMessage::parse: invalid update message size: %d.\n", msg_sz);
572 const uint8_t *buffer = from;
574 uint16_t withdrawn_len = ntohs(getValue<uint16_t>(&buffer));
576 if (withdrawn_len > msg_sz - 4) {
577 logger->
log(ERROR,
"BgpUpdateMessage::parse: withdrawn routes length overflows message.\n");
578 setError(E_UPDATE, E_UNSPEC, NULL, 0);
582 uint16_t parsed_withdrawn_len = 0;
584 while (parsed_withdrawn_len < withdrawn_len) {
585 if (withdrawn_len - parsed_withdrawn_len < 1) {
586 logger->
log(ERROR,
"BgpUpdateMessage::parse: unexpected end of withdrawn routes list.\n");
587 setError(E_UPDATE, E_UNSPEC, NULL, 0);
592 ssize_t route_read_ret = route.
parse(buffer, withdrawn_len - parsed_withdrawn_len);
593 if (route_read_ret < 0) {
594 logger->
log(ERROR,
"BgpUpdateMessage::parse: error parsing route len in withdrawn routes.\n");
595 setError(E_UPDATE, E_UNSPEC, NULL, 0);
598 parsed_withdrawn_len += route_read_ret;
599 buffer += route_read_ret;
601 withdrawn_routes.push_back(route);
604 if (parsed_withdrawn_len != withdrawn_len)
throw "bad_parse";
606 uint16_t attribute_len = ntohs(getValue<uint16_t>(&buffer));
607 if ((
size_t) (attribute_len + withdrawn_len + 4) > msg_sz) {
608 logger->
log(ERROR,
"BgpUpdateMessage::parse: attribute list length overflows message buffer.\n");
609 setError(E_UPDATE, E_ATTR_LIST, NULL, 0);
613 uint16_t parsed_attribute_len = 0;
615 while (parsed_attribute_len < attribute_len) {
616 if (attribute_len - parsed_attribute_len < 3) {
617 logger->
log(ERROR,
"BgpUpdateMessage::parse: unexpected end of attribute list.\n");
618 setError(E_UPDATE, E_UNSPEC, NULL, 0);
624 if (attr_type == 0) {
625 logger->
log(ERROR,
"BgpUpdateMessage::parse: failed to parse attribute type.\n");
626 setError(E_UPDATE, E_UNSPEC, NULL, 0);
644 case MP_UNREACH_NLRI: {
645 int16_t afi = BgpPathAttribMpNlriBase::GetAfiFromBuffer(buffer, attribute_len - parsed_attribute_len);
647 logger->
log(ERROR,
"BgpUpdateMessage::parse: failed to parse mp-bgp afi.\n");
648 setError(E_UPDATE, E_UNSPEC, NULL, 0);
652 if (afi == IPV6 && attr_type == MP_REACH_NLRI) {
657 if (afi == IPV6 && attr_type == MP_UNREACH_NLRI) {
670 if (attrib == NULL)
throw "bad_parse";
672 ssize_t attrib_parsed = attrib->
parse(buffer, attribute_len - parsed_attribute_len);
674 if (attrib_parsed < 0) {
680 buffer += attrib_parsed;
681 parsed_attribute_len += attrib_parsed;
682 path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(attrib));
685 if (parsed_attribute_len != attribute_len)
throw "bad_parse";
688 size_t nlri_len = msg_sz - 4 - parsed_attribute_len - parsed_withdrawn_len;
689 size_t parsed_nlri_len = 0;
691 while (parsed_nlri_len < nlri_len) {
692 if (nlri_len - parsed_nlri_len < 1) {
693 logger->
log(ERROR,
"BgpOpenMessage::parse: unexpected end of nlri.\n");
694 setError(E_UPDATE, E_UNSPEC, NULL, 0);
699 ssize_t route_read_ret = route.
parse(buffer, nlri_len - parsed_nlri_len);
700 if (route_read_ret < 0) {
701 logger->
log(ERROR,
"BgpUpdateMessage::parse: error parsing route len in nlri routes.\n");
702 setError(E_UPDATE, E_UNSPEC, NULL, 0);
705 parsed_nlri_len += route_read_ret;
706 buffer += route_read_ret;
708 nlri.push_back(route);
711 if (parsed_nlri_len + parsed_attribute_len + parsed_withdrawn_len + 4 != msg_sz) {
715 if (nlri.size() > 0 && !validateAttribs())
return -1;
722 logger->
log(ERROR,
"BgpUpdateMessage::write: destination buffer too small.\n");
726 size_t tot_written = 0;
727 uint8_t *buffer = to;
730 uint8_t *withdrawn_routes_len_ptr = buffer;
733 size_t written_withdrawn_length = 0;
735 for (
const Prefix4 &route : withdrawn_routes) {
736 size_t buf_avali = buf_sz - (written_withdrawn_length + tot_written);
737 ssize_t route_write_ret = route.write(buffer, buf_avali);
739 if (route_write_ret < 0) {
740 logger->
log(ERROR,
"BgpUpdateMessage::write: failed to write withdraw entry.\n");
744 buffer += route_write_ret;
745 written_withdrawn_length += route_write_ret;
749 putValue<uint16_t>(&withdrawn_routes_len_ptr, htons(written_withdrawn_length));
751 tot_written += written_withdrawn_length + 2;
754 uint8_t *route_attrib_len_ptr = buffer;
757 size_t written_attrib_length = 0;
759 for (
const std::shared_ptr<BgpPathAttrib> &attr : path_attribute) {
760 ssize_t buf_left = buf_sz - written_attrib_length - tot_written;
762 logger->
log(ERROR,
"BgpUpdateMessage::write: unexpected end of buffer.\n");
766 ssize_t write_ret = attr->write(buffer, buf_left);
768 if (write_ret < 0)
return -1;
770 written_attrib_length += write_ret;
774 putValue<uint16_t>(&route_attrib_len_ptr, htons(written_attrib_length));
776 tot_written += written_attrib_length + 2;
778 size_t written_nlri_len = 0;
780 for (
const Prefix4 &route : nlri) {
781 size_t buf_avali = buf_sz - (written_nlri_len + tot_written);
782 ssize_t route_write_ret = route.write(buffer, buf_avali);
784 if (route_write_ret < 0) {
785 logger->
log(ERROR,
"BgpUpdateMessage::write: failed to write nlri entry.\n");
789 buffer += route_write_ret;
790 written_nlri_len += route_write_ret;
793 tot_written += written_nlri_len;
800 written +=
_print(indent, to, buf_sz,
"UpdateMessage {\n");
802 if (withdrawn_routes.size() == 0) written +=
_print(indent, to, buf_sz,
"WithdrawnRoutes { }\n");
804 written +=
_print(indent, to, buf_sz,
"WithdrawnRoutes {\n");
806 for (
const Prefix4 &route : withdrawn_routes) {
807 uint32_t prefix = route.getPrefix();
808 written +=
_print(indent, to, buf_sz,
"Prefix4 { %s/%d }\n", inet_ntoa(*(
struct in_addr*) &prefix), route.getLength());
811 written +=
_print(indent, to, buf_sz,
"}\n");
814 if (path_attribute.size() == 0) written +=
_print(indent, to, buf_sz,
"PathAttributes { }\n");
816 written +=
_print(indent, to, buf_sz,
"PathAttributes {\n");
818 for (
const std::shared_ptr<BgpPathAttrib> &attr : path_attribute) {
819 written += attr->doPrint(indent, to, buf_sz);
822 written +=
_print(indent, to, buf_sz,
"}\n");
825 if (nlri.size() == 0) written +=
_print(indent, to, buf_sz,
"NLRI { }\n");
827 written +=
_print(indent, to, buf_sz,
"NLRI {\n");
829 for (
const Prefix4 &route : nlri) {
830 uint32_t prefix = route.getPrefix();
831 written +=
_print(indent, to, buf_sz,
"Prefix4 { %s/%d }\n", inet_ntoa(*(
struct in_addr*) &prefix), route.getLength());
834 written +=
_print(indent, to, buf_sz,
"}\n");
837 written +=
_print(indent, to, buf_sz,
"}\n");
Atomic aggregate attribute.
bool setNextHop(uint32_t nexthop)
Set/Create nexthop attribtue.
bool restoreAsPath()
Restore the AS_PATH attribute to four octets ASN flavor.
BgpPathAttrib * clone(BgpLogHandler *new_logger) const
Clone the attribute and replace logger.
bool updateAttribute(const BgpPathAttrib &attrib)
Add/Update an attribute.
std::vector< uint32_t > value
The segment value.
virtual ssize_t length() const
Get size in bytes required to serialize the object.
MP-BGP ReachNlri IPv6 NLRI class.
bool setWithdrawn4(const std::vector< Prefix4 > &routes)
Set withdrawn routes.
bool is_4b
Is ASNs in the attribute four octets?
BgpPathAttrib & getAttrib(uint8_t type)
Get mutable reference to attribute by typecode.
MP-BGP UnreachNlri container for unknow AFI/SAFI.
virtual ssize_t parse(const uint8_t *from, size_t msg_sz)
Deserialize a BGP update message path attribute.
bool is_4b
Is ASNs in the attribute four octets?
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
static ssize_t _print(size_t indent, uint8_t **to, size_t *buf_left, const char *format,...)
Print helper.
bool setNlri4(const std::vector< Prefix4 > &routes)
Set NLRIs.
AS4_AGGREGATOR attribute.
void log(LogLevel level, const char *format_str,...)
Log a message. Consider using LIBBGP_LOG if logging the message needs a lot of computing power...
std::vector< BgpAsPathSegment > as_paths
The AS Path segments.
bool addWithdrawn4(uint32_t prefix, uint8_t length)
Add withdrawn route.
std::vector< BgpAsPathSegment > as4_paths
The AS4_PATH segments.
bool downgradeAggregator()
Downgrade aggregator to two octets.
uint32_t aggregator_asn4
Aggregator ASN.
bool prepend(uint32_t asn)
Prepend an ASN into AS path.
ssize_t parse(const uint8_t *from, size_t msg_sz)
Deserialize a BGP message body.
uint32_t aggregator_asn
Aggregator ASN.
bool restoreAggregator()
Restore aggregator attribute from as4_aggregator.
bool prepend(uint32_t asn)
Prepend ASN to AS_PATH and AS4_PATH (if in 2b-mode ans AS4_PATH exists)
uint8_t type
Segment type.
The BgpMessage base class.
bool prepend(uint32_t asn)
Prepend an ASN into AS4 path.
IPv4 Route/Prefix related utilities.
void setError(uint8_t err, uint8_t suberr, const uint8_t *data, size_t data_len)
Set the error information.
Buffer operation helpers.
ssize_t write(uint8_t *to, size_t buf_sz) const
Serialize a BGP message body.
bool dropNonTransitive()
Drop all non-transitive attributes from the update message.
An AS_PATH or AS4_PATH segment.
bool dropAttrib(uint8_t type)
Drop (remove) an attribute from the update message.
bool addNlri4(uint32_t prefix, uint8_t length)
Add NLRI route.
bool hasAttrib(uint8_t type) const
Test if update message has an attribute.
uint32_t aggregator
Aggregator in network byte order.
Multi Exit Discriminator attribute.
uint32_t aggregator
Aggregator in network byte order.
BgpUpdateMessage(BgpLogHandler *logger, bool use_4b_asn)
Construct a new Bgp Update Message:: Bgp Update Message object.
uint32_t next_hop
The nexthop in network byte order.
void forwardParseError(const Serializable &other)
Forward error information from other Serializable object.
ssize_t parse(const uint8_t *buffer, size_t buf_sz)
Parse a IPv4 NLRI prefix from buffer.
uint8_t safi
Subsequent Address Family Identifier.
uint8_t type_code
Attribute type code.
bool setAttribs(const std::vector< std::shared_ptr< BgpPathAttrib >> &attrs)
Replace the attributes list with another attribute list.
bool addAttrib(const BgpPathAttrib &attrib)
Add an attribute to the update message.
MP-BGP ReachNlri container for unknow AFI/SAFI.
bool downgradeAsPath()
Downgrade the AS_PATH to two octets flavor.
bool is_4b
Is ASNs in this segment four octets?
static uint8_t GetTypeFromBuffer(const uint8_t *buffer, size_t buffer_sz)
Get type of attribute from buffer.
MP-BGP UnreachNlri IPv6 class.