libbgp  0.6
A C++ BGP Library.
bgp-update-message.cc
Go to the documentation of this file.
1 
11 #include "bgp-update-message.h"
12 #include "bgp-errcode.h"
13 #include "bgp-afi.h"
14 #include "value-op.h"
15 #include <arpa/inet.h>
16 
17 namespace libbgp {
18 
25 BgpUpdateMessage::BgpUpdateMessage(BgpLogHandler *logger, bool use_4b_asn) : BgpMessage(logger) {
26  type = UPDATE;
27  this->use_4b_asn = use_4b_asn;
28 }
29 
38  for (std::shared_ptr<BgpPathAttrib> attrib : path_attribute) {
39  if (attrib->type_code == type) return *attrib;
40  }
41 
42  throw "no such attribute";
43 }
44 
52 const BgpPathAttrib& BgpUpdateMessage::getAttrib(uint8_t type) const {
53  for (const std::shared_ptr<BgpPathAttrib> &attrib : path_attribute) {
54  if (attrib->type_code == type) return *attrib;
55  }
56 
57  throw "no such attribute";
58 }
59 
67 bool BgpUpdateMessage::hasAttrib(uint8_t type) const {
68  for (const std::shared_ptr<BgpPathAttrib> &attrib : path_attribute) {
69  if (attrib->type_code == type) return true;
70  }
71 
72  return false;
73 }
74 
84  if (hasAttrib(attrib.type_code)) return false;
85 
86  path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(attrib.clone(logger)));
87  return true;
88 }
89 
97 bool BgpUpdateMessage::setAttribs(const std::vector<std::shared_ptr<BgpPathAttrib>> &attrs) {
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)));
101  }
102  return true;
103 }
104 
113 bool BgpUpdateMessage::dropAttrib(uint8_t type) {
114  for (auto attr = path_attribute.begin(); attr != path_attribute.end(); attr++) {
115  if ((*attr)->type_code == type) {
116  path_attribute.erase(attr);
117  return true;
118  }
119  }
120 
121  return false;
122 }
123 
131  bool removed = false;
132 
133  for (auto attr = path_attribute.begin(); attr != path_attribute.end();) {
134  if (!(*attr)->transitive) {
135  removed = true;
136  path_attribute.erase(attr);
137  } else attr++;
138  }
139 
140  return removed;
141 }
142 
151  dropAttrib(attrib.type_code);
152  return addAttrib(attrib);
153 }
154 
162 bool BgpUpdateMessage::setNextHop(uint32_t nexthop) {
164  nh.next_hop = nexthop;
165  return updateAttribute(nh);
166 }
167 
180 bool BgpUpdateMessage::prepend(uint32_t asn) {
181  if (use_4b_asn) {
182  // in 4b mode, prepend 4b asn to AS_PATH directly.
183 
184  // AS4_PATH can't exist in 4b mode
185  if (hasAttrib(AS4_PATH)) {
186  logger->log(ERROR, "BgpUpdateMessage::prepend: we have AS4_PATH attribute but we are running in 4b mode. "
187  "consider restoreAsPath().\n");
188  return false;
189  }
190 
191  if (!hasAttrib(AS_PATH)) {
192  BgpPathAttribAsPath *path = new BgpPathAttribAsPath(logger, use_4b_asn);
193  path->prepend(asn);
194  path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(path));
195  return true;
196  }
197 
198  BgpPathAttribAsPath &path = dynamic_cast<BgpPathAttribAsPath &>(getAttrib(AS_PATH));
199  if (!path.is_4b) {
200  logger->log(ERROR, "BgpUpdateMessage::prepend: existing AS_PATH is 2b but we are running in 4b mode. "
201  "consider restoreAsPath().\n");
202  return false;
203  }
204 
205  return path.prepend(asn);
206  } else {
207  // in 2b-mode, prepend 2b asn to AS_PATH and update AS4_PATH.
208  // (yes, you don't update AS4_PATH as a 2b-speaker, but simplicity we do that for now)
209  // FIXME: don't change as4_path if both side disabled 4b support
210 
211  uint16_t prep_asn = asn >= 0xffff ? 23456 : asn;
212 
213  if (!hasAttrib(AS_PATH)) {
214  BgpPathAttribAsPath *path = new BgpPathAttribAsPath(logger, use_4b_asn);
215  path->prepend(prep_asn);
216  path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(path));
217  } else {
218  BgpPathAttribAsPath &path = dynamic_cast<BgpPathAttribAsPath &>(getAttrib(AS_PATH));
219  if (path.is_4b) {
220  logger->log(ERROR, "BgpUpdateMessage::prepend: existing AS_PATH is 4b but we are running in 2b mode. "
221  "consider downgradeAsPath().\n");
222  return false;
223  }
224  if(!path.prepend(prep_asn)) return false;
225  }
226 
227  if (hasAttrib(AS4_PATH)) {
228  BgpPathAttribAs4Path &path4 = dynamic_cast<BgpPathAttribAs4Path &>(getAttrib(AS4_PATH));
229  if(!path4.prepend(prep_asn)) return false;
230  }
231 
232  return true;
233  }
234 }
235 
246  if (!hasAttrib(AS_PATH)) return true;
247 
248  BgpPathAttribAsPath &path = dynamic_cast<BgpPathAttribAsPath &>(getAttrib(AS_PATH));
249  if (path.is_4b) return true;
250 
251  // no AS4_PATH, just make AS_PATH 4b
252  if (!hasAttrib(AS4_PATH)) {
253  std::vector<BgpAsPathSegment> new_segs;
254 
255  for (const BgpAsPathSegment &seg2 : path.as_paths) {
256  if (seg2.is_4b) {
257  logger->log(ERROR, "BgpUpdateMessage::restoreAsPath: 4b seg found in 2b attrib.\n");
258  return false;
259  }
260 
261  BgpAsPathSegment new_seg (true, seg2.type);
262  for (uint16_t asn : seg2.value) {
263  if (asn == 23456) {
264  logger->log(ERROR, "BgpUpdateMessage::restoreAsPath: warning: AS_TRANS found but no AS4_PATH.\n");
265  }
266  new_seg.value.push_back(asn);
267  }
268 
269  new_segs.push_back(new_seg);
270  }
271 
272  path.as_paths = new_segs;
273  path.is_4b = true;
274  return true;
275  }
276 
277  // we have AS4_PATH recorver AS_TRANS.
278  std::vector<uint32_t> full_as_path;
279  const BgpPathAttribAs4Path &as4_path = dynamic_cast<const BgpPathAttribAs4Path &>(getAttrib(AS4_PATH));
280  for (const BgpAsPathSegment &seg4 : as4_path.as4_paths) {
281  if (!seg4.is_4b) {
282  logger->log(ERROR, "BgpUpdateMessage::restoreAsPath: bad as4_path: found 2b seg.\n");
283  return false;
284  }
285 
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());
289  }
290  }
291 
292  // AS4_PATH should be removed.
293  dropAttrib(AS4_PATH);
294 
295  bool has_4b = false;
296 
297  // find the iterator to first asn > 0xffff
298  std::vector<uint32_t>::const_iterator iter_4b = full_as_path.begin();
299 
300  for(; iter_4b != full_as_path.end(); iter_4b++) {
301  has_4b = true;
302  if (*iter_4b > 0xffff) break;
303  }
304 
305  std::vector<BgpAsPathSegment> new_segs;
306 
307  for (const BgpAsPathSegment &seg2 : path.as_paths) {
308  std::vector<uint32_t>::const_iterator local_iter = iter_4b;
309  if (seg2.is_4b) {
310  logger->log(ERROR, "BgpUpdateMessage::restoreAsPath: 4b seg found in 2b attrib.\n");
311  return false;
312  }
313 
314  BgpAsPathSegment new_seg (true, seg2.type);
315 
316  // increment the local_iter iterator?
317  bool incr_iter = false;
318  for (uint16_t asn : seg2.value) {
319  uint32_t new_asn = asn;
320 
321  // AS4_PATH avaliale & not ended?
322  if (has_4b && local_iter != full_as_path.end()) {
323 
324  // we found AS_TRANS, we need to replace it with last asn in AS_TRANS
325  if (new_asn == 23456) {
326 
327  // we have hit our first AS_TRANS. from now on, we need to move the AS4_PATH
328  // iterator too.
329  incr_iter = true;
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");
333  }
334 
335  if (incr_iter) local_iter++;
336  }
337 
338  new_seg.value.push_back(new_asn);
339  }
340 
341  new_segs.push_back(new_seg);
342  }
343 
344  path.is_4b = true;
345  path.as_paths = new_segs;
346  return true;
347 
348 }
349 
360  if (!hasAttrib(AS_PATH)) return true;
361 
362  BgpPathAttribAsPath &path = dynamic_cast<BgpPathAttribAsPath &>(getAttrib(AS_PATH));
363  if (!path.is_4b) return true;
364 
365  std::vector<BgpAsPathSegment> new_segs;
367 
368  for (const BgpAsPathSegment &seg4 : path.as_paths) {
369  if (!seg4.is_4b) {
370  logger->log(ERROR, "BgpUpdateMessage::downgradeAsPath: 2b seg found in 4b attrib.\n");
371  return false;
372  }
373 
374  BgpAsPathSegment new_seg (false, seg4.type);
375  for (uint32_t asn : seg4.value) {
376  uint16_t new_as = asn >= 0xffff ? 23456 : asn;
377  new_seg.value.push_back(new_as);
378  }
379 
380  path4.as4_paths.push_back(seg4);
381  new_segs.push_back(new_seg);
382  }
383 
384  updateAttribute(path4);
385  path.is_4b = false;
386  path.as_paths = new_segs;
387  return true;
388 }
389 
397  if (!hasAttrib(AGGREATOR)) return true;
398 
399  BgpPathAttribAggregator &aggr = dynamic_cast<BgpPathAttribAggregator &>(getAttrib(AGGREATOR));
400  aggr.is_4b = true;
401 
402  if (!hasAttrib(AS4_AGGREGATOR)) return true;
403 
404  const BgpPathAttribAs4Aggregator &aggr4 = dynamic_cast<const BgpPathAttribAs4Aggregator &>(getAttrib(AS4_AGGREGATOR));
405  aggr.aggregator = aggr4.aggregator;
406  aggr.aggregator_asn = aggr4.aggregator_asn4;
407 
408  return true;
409 }
410 
418  if (!hasAttrib(AGGREATOR)) return true;
419 
420  BgpPathAttribAggregator &aggr = dynamic_cast<BgpPathAttribAggregator &>(getAttrib(AGGREATOR));
421  aggr.is_4b = false;
422 
424  aggr4.aggregator = aggr.aggregator;
425  aggr4.aggregator_asn4 = aggr.aggregator_asn;
426  updateAttribute(aggr4);
427 
428  if (aggr.aggregator_asn >= 0xffff) aggr.aggregator_asn = 23456;
429 
430  return true;
431 }
432 
440 bool BgpUpdateMessage::setWithdrawn4(const std::vector<Prefix4> &routes) {
441  withdrawn_routes = routes;
442  return true;
443 }
444 
453 bool BgpUpdateMessage::addWithdrawn4(uint32_t prefix, uint8_t length) {
454  Prefix4 route (prefix, length);
455  withdrawn_routes.push_back(route);
456  return true;
457 }
458 
467  withdrawn_routes.push_back(route);
468  return true;
469 }
470 
478 bool BgpUpdateMessage::setNlri4(const std::vector<Prefix4> &routes) {
479  nlri = routes;
480  return true;
481 }
482 
491 bool BgpUpdateMessage::addNlri4(uint32_t prefix, uint8_t length) {
492  Prefix4 route(prefix, length);
493  nlri.push_back(route);
494  return true;
495 }
496 
505  nlri.push_back(route);
506  return true;
507 }
508 
509 bool BgpUpdateMessage::validateAttribs() {
510  bool has_origin = false;
511  bool has_nexthop = false;
512  bool has_as_path = false;
513 
514  uint32_t typecode_bitsmap = 0;
515 
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;
519 
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;
523 
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);
527  return false;
528  }
529 
530  typecode_bitsmap &= ~(1UL << type_code);
531  }
532 
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);
536  return false;
537  }
538 
539  return true;
540 }
541 
542 bool BgpUpdateMessage::setWithdrawn6(const std::vector<Prefix6> &routes) {
543  BgpPathAttribMpUnreachNlriIpv6 unr6 (logger);
544  unr6.safi = UNICAST;
545  unr6.withdrawn_routes = routes;
546  updateAttribute(unr6);
547 
548  return true;
549 }
550 
551 bool BgpUpdateMessage::setNlri6(const std::vector<Prefix6> &routes, const uint8_t nexthop_global[16], const uint8_t nexthop_linklocal[16]) {
552  BgpPathAttribMpReachNlriIpv6 r6 (logger);
553  r6.safi = UNICAST;
554  r6.nlri = routes;
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);
559  updateAttribute(r6);
560 
561  return true;
562 }
563 
564 ssize_t BgpUpdateMessage::parse(const uint8_t *from, size_t msg_sz) {
565  if (msg_sz < 4) {
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);
569  return -1;
570  }
571 
572  const uint8_t *buffer = from;
573 
574  uint16_t withdrawn_len = ntohs(getValue<uint16_t>(&buffer)); // len: 2
575 
576  if (withdrawn_len > msg_sz - 4) { // -4: two length fields (withdrawn len + attrib len)
577  logger->log(ERROR, "BgpUpdateMessage::parse: withdrawn routes length overflows message.\n");
578  setError(E_UPDATE, E_UNSPEC, NULL, 0);
579  return -1;
580  }
581 
582  uint16_t parsed_withdrawn_len = 0;
583 
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);
588  return -1;
589  }
590 
591  Prefix4 route = Prefix4();
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);
596  return -1;
597  }
598  parsed_withdrawn_len += route_read_ret;
599  buffer += route_read_ret;
600 
601  withdrawn_routes.push_back(route);
602  }
603 
604  if (parsed_withdrawn_len != withdrawn_len) throw "bad_parse";
605 
606  uint16_t attribute_len = ntohs(getValue<uint16_t>(&buffer)); // len: 2
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);
610  return -1;
611  }
612 
613  uint16_t parsed_attribute_len = 0;
614 
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);
619  return -1;
620  }
621 
622  uint8_t attr_type = BgpPathAttrib::GetTypeFromBuffer(buffer, attribute_len - parsed_attribute_len);
623 
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);
627  return -1;
628  }
629 
630  BgpPathAttrib *attrib = NULL;
631 
632  switch(attr_type) {
633  case ORIGIN: attrib = new BgpPathAttribOrigin(logger); break;
634  case AS_PATH: attrib = new BgpPathAttribAsPath(logger, use_4b_asn); break;
635  case NEXT_HOP: attrib = new BgpPathAttribNexthop(logger); break;
636  case MULTI_EXIT_DISC: attrib = new BgpPathAttribMed(logger); break;
637  case LOCAL_PREF: attrib = new BgpPathAttribLocalPref(logger); break;
638  case ATOMIC_AGGREGATE: attrib = new BgpPathAttribAtomicAggregate(logger); break;
639  case AGGREATOR: attrib = new BgpPathAttribAggregator(logger, use_4b_asn); break;
640  case COMMUNITY: attrib = new BgpPathAttribCommunity(logger); break;
641  case AS4_PATH: attrib = new BgpPathAttribAs4Path(logger); break;
642  case AS4_AGGREGATOR: attrib = new BgpPathAttribAs4Aggregator(logger); break;
643  case MP_REACH_NLRI:
644  case MP_UNREACH_NLRI: {
645  int16_t afi = BgpPathAttribMpNlriBase::GetAfiFromBuffer(buffer, attribute_len - parsed_attribute_len);
646  if (afi < 0) {
647  logger->log(ERROR, "BgpUpdateMessage::parse: failed to parse mp-bgp afi.\n");
648  setError(E_UPDATE, E_UNSPEC, NULL, 0);
649  return -1;
650  }
651 
652  if (afi == IPV6 && attr_type == MP_REACH_NLRI) {
653  attrib = new BgpPathAttribMpReachNlriIpv6(logger);
654  break;
655  }
656 
657  if (afi == IPV6 && attr_type == MP_UNREACH_NLRI) {
658  attrib = new BgpPathAttribMpUnreachNlriIpv6(logger);
659  break;
660  }
661 
662  if (attr_type == MP_REACH_NLRI) attrib = new BgpPathAttribMpReachNlriUnknow(logger);
663  else attrib = new BgpPathAttribMpUnreachNlriUnknow(logger);
664 
665  break;
666  }
667  default: attrib = new BgpPathAttrib(logger); break;
668  }
669 
670  if (attrib == NULL) throw "bad_parse";
671 
672  ssize_t attrib_parsed = attrib->parse(buffer, attribute_len - parsed_attribute_len);
673 
674  if (attrib_parsed < 0) {
675  forwardParseError(*attrib);
676  delete attrib;
677  return -1;
678  }
679 
680  buffer += attrib_parsed;
681  parsed_attribute_len += attrib_parsed;
682  path_attribute.push_back(std::shared_ptr<BgpPathAttrib>(attrib));
683  }
684 
685  if (parsed_attribute_len != attribute_len) throw "bad_parse";
686 
687  // 4: len fields (withdrawn len & attrib len)
688  size_t nlri_len = msg_sz - 4 - parsed_attribute_len - parsed_withdrawn_len;
689  size_t parsed_nlri_len = 0;
690 
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);
695  return -1;
696  }
697 
698  Prefix4 route = Prefix4();
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);
703  return -1;
704  }
705  parsed_nlri_len += route_read_ret;
706  buffer += route_read_ret;
707 
708  nlri.push_back(route);
709  }
710 
711  if (parsed_nlri_len + parsed_attribute_len + parsed_withdrawn_len + 4 != msg_sz) {
712  throw "bad_parse";
713  }
714 
715  if (nlri.size() > 0 && !validateAttribs()) return -1;
716 
717  return msg_sz;
718 }
719 
720 ssize_t BgpUpdateMessage::write(uint8_t *to, size_t buf_sz) const {
721  if (buf_sz < 4) {
722  logger->log(ERROR, "BgpUpdateMessage::write: destination buffer too small.\n");
723  return -1;
724  }
725 
726  size_t tot_written = 0;
727  uint8_t *buffer = to;
728 
729  // keep a pointer to len field to write length to later
730  uint8_t *withdrawn_routes_len_ptr = buffer;
731  buffer += 2; // skip the length field for now
732 
733  size_t written_withdrawn_length = 0;
734 
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);
738 
739  if (route_write_ret < 0) {
740  logger->log(ERROR, "BgpUpdateMessage::write: failed to write withdraw entry.\n");
741  return -1;
742  }
743 
744  buffer += route_write_ret;
745  written_withdrawn_length += route_write_ret;
746  }
747 
748  // now, put the length
749  putValue<uint16_t>(&withdrawn_routes_len_ptr, htons(written_withdrawn_length));
750 
751  tot_written += written_withdrawn_length + 2; // + 2: the length field
752 
753  // keep a pointer to len field to write length to later
754  uint8_t *route_attrib_len_ptr = buffer;
755  buffer += 2;
756 
757  size_t written_attrib_length = 0;
758 
759  for (const std::shared_ptr<BgpPathAttrib> &attr : path_attribute) {
760  ssize_t buf_left = buf_sz - written_attrib_length - tot_written;
761  if (buf_left < 0) {
762  logger->log(ERROR, "BgpUpdateMessage::write: unexpected end of buffer.\n");
763  return -1;
764  }
765 
766  ssize_t write_ret = attr->write(buffer, buf_left);
767 
768  if (write_ret < 0) return -1;
769  buffer += write_ret;
770  written_attrib_length += write_ret;
771  }
772 
773  // put the length
774  putValue<uint16_t>(&route_attrib_len_ptr, htons(written_attrib_length));
775 
776  tot_written += written_attrib_length + 2;
777 
778  size_t written_nlri_len = 0;
779 
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);
783 
784  if (route_write_ret < 0) {
785  logger->log(ERROR, "BgpUpdateMessage::write: failed to write nlri entry.\n");
786  return -1;
787  }
788 
789  buffer += route_write_ret;
790  written_nlri_len += route_write_ret;
791  }
792 
793  tot_written += written_nlri_len;
794 
795  return tot_written;
796 }
797 
798 ssize_t BgpUpdateMessage::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
799  size_t written = 0;
800  written += _print(indent, to, buf_sz, "UpdateMessage {\n");
801  indent++; {
802  if (withdrawn_routes.size() == 0) written += _print(indent, to, buf_sz, "WithdrawnRoutes { }\n");
803  else {
804  written += _print(indent, to, buf_sz, "WithdrawnRoutes {\n");
805  indent++; {
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());
809  }
810  }; indent--;
811  written += _print(indent, to, buf_sz, "}\n");
812  }
813 
814  if (path_attribute.size() == 0) written += _print(indent, to, buf_sz, "PathAttributes { }\n");
815  else {
816  written += _print(indent, to, buf_sz, "PathAttributes {\n");
817  indent++; {
818  for (const std::shared_ptr<BgpPathAttrib> &attr : path_attribute) {
819  written += attr->doPrint(indent, to, buf_sz);
820  }
821  }; indent--;
822  written += _print(indent, to, buf_sz, "}\n");
823  }
824 
825  if (nlri.size() == 0) written += _print(indent, to, buf_sz, "NLRI { }\n");
826  else {
827  written += _print(indent, to, buf_sz, "NLRI {\n");
828  indent++; {
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());
832  }
833  }; indent--;
834  written += _print(indent, to, buf_sz, "}\n");
835  }
836  }; indent--;
837  written += _print(indent, to, buf_sz, "}\n");
838  return written;
839 }
840 
841 }
842 
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.
The BgpPathAttrib class.
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.
The BGP AFI/SAFI.
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.
Local Pref attribute.
The BgpMessage base class.
Definition: bgp-message.h:35
bool prepend(uint32_t asn)
Prepend an ASN into AS4 path.
IPv4 Route/Prefix related utilities.
Definition: prefix4.h:25
void setError(uint8_t err, uint8_t suberr, const uint8_t *data, size_t data_len)
Set the error information.
Definition: serializable.cc:61
Buffer operation helpers.
Definition: bgp-afi.h:14
The BgpLogHandler class.
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.
The BGP update message.
uint32_t aggregator
Aggregator in network byte order.
Multi Exit Discriminator attribute.
BGP community 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.
BGP error codes.
uint32_t next_hop
The nexthop in network byte order.
void forwardParseError(const Serializable &other)
Forward error information from other Serializable object.
Definition: serializable.cc:97
ssize_t parse(const uint8_t *buffer, size_t buf_sz)
Parse a IPv4 NLRI prefix from buffer.
Definition: prefix4.cc:84
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.