libbgp  0.6
A C++ BGP Library.
bgp-path-attrib.cc
Go to the documentation of this file.
1 
11 #include "bgp-path-attrib.h"
12 #include "bgp-errcode.h"
13 #include "bgp-afi.h"
14 #include "value-op.h"
15 #include <stdlib.h>
16 #include <arpa/inet.h>
17 
18 namespace libbgp {
19 
29 uint8_t BgpPathAttrib::GetTypeFromBuffer(const uint8_t *from, size_t buffer_sz) {
30  if (buffer_sz < 3) return -1;
31  return *((uint8_t *) (from + 1));
32 }
33 
40  optional = transitive = partial = extended = false;
41  value_ptr = NULL;
42 }
43 
51 BgpPathAttrib::BgpPathAttrib(BgpLogHandler *logger, const uint8_t *value, uint16_t val_len) : BgpPathAttrib(logger) {
52  if (value_len > 0) {
53  logger->log(FATAL, "BgpPathAttrib::BgpPathAttrib: unknow attribute created with length != 0 but buffer NULL.\n");
54  throw "bad_value_buffer";
55  }
56 
57  value_ptr = (uint8_t *) malloc(val_len);
58  memcpy(value_ptr, value, value_len);
59 }
60 
66  if (value_ptr != NULL) free(value_ptr);
67 }
68 
70  BgpPathAttrib* cloned = clone();
71  cloned->setLogger(new_logger);
72  return cloned;
73 }
74 
76  if(hasError()) {
77  logger->log(FATAL, "BgpPathAttrib::clone: can't clone an attribute with error.\n");
78  throw "has_error";
79  }
80  BgpPathAttrib *attr = new BgpPathAttrib(logger, value_ptr, value_len);
81  attr->transitive = transitive;
82  attr->optional = optional;
83  attr->partial = partial;
84  attr->extended = attr->extended;
85  return attr;
86 }
87 
96 ssize_t BgpPathAttrib::printFlags(size_t indent, uint8_t **to, size_t *buf_sz) const {
97  size_t written = 0;
98 
99  if (!(transitive || optional || partial || extended)) {
100  written += _print(indent, to, buf_sz, "Flags { }\n");
101  return written;
102  }
103 
104  written += _print(indent, to, buf_sz, "Flags {\n");
105  indent++; {
106  if (optional) written += _print(indent, to, buf_sz, "Optional\n");
107  if (transitive) written += _print(indent, to, buf_sz, "Transitive\n");
108  if (partial) written += _print(indent, to, buf_sz, "Partial\n");
109  if (extended) written += _print(indent, to, buf_sz, "Extended\n");
110  }; indent--;
111  written += _print(indent, to, buf_sz, "}\n");
112 
113  return written;
114 }
115 
116 ssize_t BgpPathAttrib::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
117  size_t written = 0;
118 
119  written += _print(indent, to, buf_sz, "UnknowAttribute {\n");
120  indent++; {
121  written += printFlags(indent, to, buf_sz);
122  written += _print(indent, to, buf_sz, "TypeCode { %d }\n", type_code);
123  }; indent--;
124  written += _print(indent, to, buf_sz, "}\n");
125 
126  return written;
127 }
128 
129 ssize_t BgpPathAttrib::parse(const uint8_t *from, size_t length) {
130  ssize_t header_len = parseHeader(from, length);
131 
132  if (header_len < 0) return -1;
133 
134  const uint8_t *buffer = from + 3;
135 
136  // Well-Known, Mandatory = !optional, transitive
137  // Well-Known, Discretionary = !optional, !transitive
138  // Optional, Transitive = optional, transitive
139  // Optional, Non-Transitive = optional, !transitive
140  if (!optional && transitive) {
141  // well-known mandatory, but not recognized
142  setError(E_UPDATE, E_BAD_WELL_KNOWN, from, value_len + header_len);
143  logger->log(ERROR, "BgpPathAttrib::parse: flag indicates well-known, mandatory but this attribute is unknown.\n");
144  // set value_len = 0, so we won't free() nullptr when destruct.
145  value_len = 0;
146  return -1;
147  }
148 
149  if (optional && !transitive && partial) {
150  // optional non-transitive must not be partial
151  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_len);
152  logger->log(ERROR, "BgpPathAttrib::parse: optional non-transitive must not be partial.\n");
153  // set value_len = 0, so we won't free() nullptr when destruct.
154  value_len = 0;
155  return -1;
156  }
157 
158  value_ptr = (uint8_t *) malloc(value_len);
159  memcpy(value_ptr, buffer, value_len);
160 
161  return value_len + header_len;
162 }
163 
164 ssize_t BgpPathAttrib::length() const {
165  return value_len + (extended ? 4 : 3);
166 }
167 
168 ssize_t BgpPathAttrib::write(uint8_t *to, size_t buffer_sz) const {
169  if (buffer_sz < (size_t) (value_len + 3)) {
170  logger->log(ERROR, "BgpPathAttrib::write: destination buffer size too small.\n");
171  return -1;
172  }
173 
174  if (!extended && value_len >= 0xffff) {
175  logger->log(ERROR, "BgpPathAttrib::write: non-extended value has size > 65535: %d\n", value_len);
176  return -1;
177  }
178 
179  if (writeHeader(to, buffer_sz) < 2) return -1;
180 
181  uint8_t *buffer = to + 2;
182  if (extended) putValue<uint16_t>(&buffer, htons(value_len));
183  else putValue<uint8_t>(&buffer, value_len);
184 
185  if (value_len > 0) memcpy(buffer, value_ptr, value_len);
186 
187  return value_len + 3;
188 }
189 
200 ssize_t BgpPathAttrib::parseHeader(const uint8_t *from, size_t buffer_sz) {
201  if (buffer_sz < 3) {
202  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
203  logger->log(ERROR, "BgpPathAttrib::parseHeader: invalid attribute header size.\n");
204  return -1;
205  }
206  const uint8_t *buffer = from;
207 
208  uint8_t flags = getValue<uint8_t>(&buffer);
209 
210  optional = (flags >> 7) & 0x1;
211  transitive = (flags >> 6) & 0x1;
212  partial = (flags >> 5) & 0x1;
213  extended = (flags >> 4) & 0x1;
214  type_code = getValue<uint8_t>(&buffer);
215  if (extended && buffer_sz < 4) {
216  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
217  logger->log(ERROR, "BgpPathAttrib::parseHeader: invalid attribute header size (extended but size < 4).\n");
218  return -1;
219  }
220 
221  if (extended) value_len = ntohs(getValue<uint16_t>(&buffer));
222  else value_len = getValue<uint8_t>(&buffer);
223 
224  if (value_len > buffer_sz - 3) {
225  err_code = E_UPDATE;
226  // This is kind of "invalid length", but we are not using E_ATTR_LEN.
227  // E_ATTR_LEN: "Attribute Length that conflict with the expected length
228  // (based on the attribute type code)." This is not based on type code,
229  // but it is buffer overflow, so we set subcode to E_UNSPEC,
230  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
231  logger->log(ERROR, "BgpPathAttrib::parseHeader: value_length (%d) < buffer left (%d).\n", value_len, buffer_sz - 3);
232  return -1;
233  }
234 
235  return extended ? 4 : 3;
236 }
237 
251 ssize_t BgpPathAttrib::writeHeader(uint8_t *to, size_t buffer_sz) const {
252  if (buffer_sz < (extended ? 3 : 4)) {
253  logger->log(ERROR, "BgpPathAttrib::writeHeader: dst buffer too small: %d\n", buffer_sz);
254  return -1;
255  }
256 
257  uint8_t *buffer = to;
258  uint8_t flags = (optional << 7) | (transitive << 6)| (partial << 5) | (extended << 4);
259  putValue<uint8_t>(&buffer, flags);
260  putValue<uint8_t>(&buffer, type_code);
261  return 2;
262 }
269  transitive = true;
270  type_code = ORIGIN;
271 }
272 
274  if(hasError()) {
275  logger->log(FATAL, "BgpPathAttribOrigin::clone: can't clone an attribute with error.\n");
276  throw "has_error";
277  }
278  return new BgpPathAttribOrigin(*this);
279 }
280 
281 ssize_t BgpPathAttribOrigin::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
282  const char *origin_name = NULL;
283 
284  switch(origin) {
285  case 0: origin_name = "IGP"; break;
286  case 1: origin_name= "EGP"; break;
287  case 2: origin_name = "Incomplete"; break;
288  default: origin_name = "Invalid"; break;
289  }
290 
291  size_t written = 0;
292  written += _print(indent, to, buf_sz, "OriginAttribute {\n");
293  indent++; {
294  written += printFlags(indent, to, buf_sz);
295  written += _print(indent, to, buf_sz, "Origin { %s }\n", origin_name);
296  }; indent--;
297 
298  written += _print(indent, to, buf_sz, "}\n");
299 
300  return written;
301 }
302 
303 ssize_t BgpPathAttribOrigin::parse(const uint8_t *from, size_t length) {
304  ssize_t header_length = parseHeader(from, length);
305  if (header_length < 0) return -1;
306 
307  if (type_code != ORIGIN) {
308  logger->log(FATAL, "BgpPathAttribOrigin::parse: type in header mismatch.\n");
309  throw "bad_type";
310  }
311 
312  const uint8_t *buffer = from + 3;
313 
314  if (value_len < 1) {
315  logger->log(ERROR, "BgpPathAttribOrigin::parse: incomplete attrib.\n");
316  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
317  return -1;
318  }
319 
320  if (value_len != 1) {
321  logger->log(ERROR, "BgpPathAttribOrigin::parse: bad length, want 1, saw %d.\n", value_len);
322  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
323  return -1;
324  }
325 
326  if (optional || !transitive || extended || partial) {
327  logger->log(ERROR, "BgpPathAttribOrigin::parse: bad flag bits, must be !optional, !extended, !partial, transitive.\n");
328  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
329  return -1;
330  }
331 
332  origin = getValue<uint8_t>(&buffer);
333 
334  if (origin > 2) {
335  setError(E_UPDATE, E_ORIGIN, from, 4);
336  logger->log(ERROR, "BgpPathAttribOrigin::parse: Bad Origin Value: %d.\n", origin);
337  return -1;
338  }
339 
340  return 4;
341 }
342 
343 ssize_t BgpPathAttribOrigin::write(uint8_t *to, size_t buffer_sz) const {
344  if (buffer_sz < 4) {
345  logger->log(ERROR, "BgpPathAttribOrigin::write: destination buffer size too small.\n");
346  return -1;
347  }
348 
349  if (writeHeader(to, buffer_sz) < 0) return -1;
350  uint8_t *buffer = to + 2;
351 
352  putValue<uint8_t>(&buffer, 1); // length = 1
353  putValue<uint8_t>(&buffer, origin);
354  return 4;
355 }
356 
358  return 4;
359 }
360 
368  this->is_4b = is_4b;
369  transitive = true;
370  type_code = AS_PATH;
371 }
372 
380  this->is_4b = is_4b;
381  this->type = type;
382 }
383 
390  return value.size();
391 }
392 
400 bool BgpAsPathSegment::prepend(uint32_t asn) {
401  if (value.size() >= (is_4b ? 127 : 255)) return false;
402  uint32_t prepend_asn = is_4b ? asn : (asn >= 0xffff ? 23456 : asn);
403 
404  value.insert(value.begin(), prepend_asn);
405  return true;
406 }
407 
409  if(hasError()) {
410  logger->log(FATAL, "BgpPathAttribAsPath::clone: can't clone an attribute with error.\n");
411  throw "has_error";
412  }
413  return new BgpPathAttribAsPath(*this);
414 }
415 
416 ssize_t BgpPathAttribAsPath::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
417  size_t written = 0;
418  written += _print(indent, to, buf_sz, "AsPathAttribute {\n");
419  indent++; {
420  written += _print(indent, to, buf_sz, "FourOctet { %s }\n", is_4b ? "true" : "false");
421  written += printFlags(indent, to, buf_sz);
422  if (as_paths.size() == 0) written += _print(indent, to, buf_sz, "AsPathSegments { } \n");
423  else {
424  written += _print(indent, to, buf_sz, "AsPathSegments {\n");
425  indent++; {
426  for (const BgpAsPathSegment &seg : as_paths) {
427  switch (seg.type) {
428  case 1: written += _print(indent, to, buf_sz, "AsSet {\n"); break;
429  case 2: written += _print(indent, to, buf_sz, "AsSequence {\n"); break;
430  default: written += _print(indent, to, buf_sz, "Invalid {\n"); break;
431  }
432  indent++; {
433  for (uint32_t asn : seg.value) {
434  written += _print(indent, to, buf_sz, "%d\n", asn);
435  }
436  }; indent--;
437  written += _print(indent, to, buf_sz, "}\n");
438  }
439  }; indent--;
440  written += _print(indent, to, buf_sz, "}\n");
441  }
442  }; indent--;
443  written += _print(indent, to, buf_sz, "}\n");
444 
445  return written;
446 }
447 
448 ssize_t BgpPathAttribAsPath::parse(const uint8_t *from, size_t length) {
449  ssize_t header_length = parseHeader(from, length);
450  if (header_length < 0) return -1;
451 
452  if (type_code != AS_PATH) {
453  logger->log(FATAL, "BgpPathAttribAsPath::parse: type in header mismatch.\n");
454  throw "bad_type";
455  }
456 
457  if (optional || !transitive || extended || partial) {
458  logger->log(ERROR, "BgpPathAttribAsPath::parse: bad flag bits, must be !optional, !extended, !partial, transitive.\n");
459  setError(E_UPDATE, E_ATTR_FLAG, from , value_len + header_length);
460  return -1;
461  }
462 
463  const uint8_t *buffer = from + 3;
464 
465  // empty as_path
466  if (value_len == 0) return 3;
467 
468  uint8_t parsed_len = 0;
469 
470  while (parsed_len < value_len) {
471  // bad as_path
472  if (value_len - parsed_len < 3) {
473  logger->log(ERROR, "BgpPathAttribAsPath::parse: incomplete as_path segment.\n");
474  setError(E_UPDATE, E_AS_PATH, NULL, 0);
475  return -1;
476  }
477 
478  uint8_t type = getValue<uint8_t>(&buffer);
479  uint8_t n_asn = getValue<uint8_t>(&buffer);
480 
481  // type & count
482  parsed_len += 2;
483 
484  uint8_t asns_length = is_4b ? n_asn * sizeof(uint32_t) : n_asn * sizeof(uint16_t);
485 
486  // overflow
487  if (parsed_len + asns_length > value_len) {
488  logger->log(ERROR, "BgpPathAttribAsPath::parse: as_path overflow attribute length.\n");
489  setError(E_UPDATE, E_AS_PATH, NULL, 0);
490  return -1;
491  }
492 
493  BgpAsPathSegment path(is_4b, type);
494  if (is_4b) for (int i = 0; i < n_asn; i++) path.value.push_back(ntohl(getValue<uint32_t>(&buffer)));
495  else for (int i = 0; i < n_asn; i++) path.value.push_back(ntohs(getValue<uint16_t>(&buffer)));
496  as_paths.push_back(path);
497 
498  // parsed asns
499  parsed_len += asns_length;
500  }
501 
502  if (parsed_len != value_len) {
503  logger->log(FATAL, "BgpPathAttribAsPath::parse: parsed length and value length mismatch, but no error reported.\n");
504  throw "bad_parse";
505  }
506 
507  return parsed_len + 3;
508 }
509 
511  size_t len = 3; // header len = 3
512 
513  for (const BgpAsPathSegment &seg : as_paths) {
514  len += (seg.is_4b ? 4 : 2) * seg.value.size() + 2;
515  }
516 
517  return len;
518 }
519 
525 void BgpPathAttribAsPath::addSeg(uint32_t asn) {
526  BgpAsPathSegment segment(is_4b, AS_SEQUENCE);
527  segment.prepend(asn);
528  as_paths.push_back(segment);
529 }
530 
543 bool BgpPathAttribAsPath::prepend(uint32_t asn) {
544  if (as_paths.size() == 0) {
545  // nothing here yet, add a new sequence. (5.1.2.b.3)
546  addSeg(asn);
547  return true;
548  }
549 
550  // something here already. what to do?
551  BgpAsPathSegment *segment = as_paths.data();
552 
553  if (segment->type == AS_SET) {
554  // seg is set, create a new segment of type AS_SEQUENCE (5.1.2.b.2)
555  // FIXME: checks needed: really create a new segment?
556  addSeg(asn);
557  return true;
558  } else if (segment->type == AS_SEQUENCE) {
559  if (segment->getCount() >= (is_4b ? 127 : 255)) {
560  // seg full, create a new segment of type AS_SEQUENCE (5.1.2.b.1)
561  addSeg(asn);
562  return true;
563  } else {
564  segment->prepend(asn);
565  return true;
566  }
567  }
568 
569  logger->log(ERROR, "BgpPathAttribAsPath::prepend: unknow first segment type: %d, can't append.\n", segment->type);
570  return false;
571 }
572 
573 ssize_t BgpPathAttribAsPath::write(uint8_t *to, size_t buffer_sz) const {
574  if (buffer_sz < 3) {
575  logger->log(ERROR, "BgpPathAttribAsPath::write: destination buffer size too small.\n");
576  return -1;
577  }
578 
579  if (writeHeader(to, buffer_sz) < 0) return -1;
580  uint8_t *buffer = to + 2;
581 
582  // keep track of length field so we can write it later
583  uint8_t *len_field = buffer;
584 
585  // skip length field for now
586  buffer++;
587 
588  uint8_t written_len = 0;
589 
590  for (const BgpAsPathSegment &seg : as_paths) {
591  if (seg.is_4b != is_4b) { // maybe allow 2b-seg in 4b-mode?
592  logger->log(ERROR, "BgpPathAttribAsPath::write: segment 4b-mode and message 4b-mode mismatch.\n");
593  return -1;
594  }
595 
596  size_t asn_count = seg.value.size();
597 
598  if (asn_count >= (is_4b ? 127 : 255)) {
599  logger->log(ERROR, "BgpPathAttribAsPath::write: segment size too big: %d\n", asn_count);
600  return -1;
601  }
602 
603  size_t bytes_need = asn_count * (is_4b ? sizeof(uint32_t) : sizeof(uint16_t)) + 2;
604 
605  if (written_len + bytes_need > buffer_sz) {
606  logger->log(ERROR, "BgpPathAttribAsPath::write: destination buffer size too small.\n");
607  return -1;
608  }
609 
610  putValue<uint8_t>(&buffer, seg.type);
611  putValue<uint8_t>(&buffer, asn_count);
612 
613  if (seg.is_4b) for (uint32_t asn : seg.value) putValue<uint32_t>(&buffer, htonl(asn));
614  else for (uint16_t asn : seg.value) putValue<uint16_t>(&buffer, htons(asn));
615 
616  written_len += bytes_need;
617  }
618 
619  // fill in the length.
620  putValue<uint8_t>(&len_field, written_len);
621 
622  // written_len: the as_paths, 3: attr header (flag, typecode, length)
623  return written_len + 3;
624 }
625 
632  type_code = NEXT_HOP;
633  transitive = true;
634 }
635 
636 ssize_t BgpPathAttribNexthop::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
637  size_t written = 0;
638  written += _print(indent, to, buf_sz, "NexthopAttribute {\n");
639  indent++; {
640  written += printFlags(indent, to, buf_sz);
641  written += _print(indent, to, buf_sz, "Nexthop { %s }\n", inet_ntoa(*(struct in_addr*) &next_hop));
642  }; indent--;
643 
644  written += _print(indent, to, buf_sz, "}\n");
645 
646  return written;
647 }
648 
650  if(hasError()) {
651  logger->log(FATAL, "BgpPathAttribNexthop::clone: can't clone an attribute with error.\n");
652  throw "has_error";
653  }
654  return new BgpPathAttribNexthop(*this);
655 }
656 
657 ssize_t BgpPathAttribNexthop::parse(const uint8_t *from, size_t length) {
658  ssize_t header_length = parseHeader(from, length);
659  if (header_length < 0) return -1;
660 
661  if (type_code != NEXT_HOP) {
662  logger->log(FATAL, "BgpPathAttribNexthop::parse: type in header mismatch.\n");
663  throw "bad_type";
664  }
665 
666  const uint8_t *buffer = from + 3;
667 
668  if (value_len < 4) {
669  logger->log(ERROR, "BgpPathAttribNexthop::parse: incomplete attrib.\n");
670  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
671  return -1;
672  }
673 
674  if (value_len != 4) {
675  logger->log(ERROR, "BgpPathAttribNexthop::parse: bad length, want 4, saw %d.\n", value_len);
676  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
677  return -1;
678  }
679 
680  if (optional || !transitive || extended || partial) {
681  logger->log(ERROR, "BgpPathAttribNexthop::parse: bad flag bits, must be !optional, !extended, !partial, transitive.\n");
682  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
683  return -1;
684  }
685 
686  next_hop = getValue<uint32_t>(&buffer);
687 
688  return 7;
689 }
690 
691 ssize_t BgpPathAttribNexthop::write(uint8_t *to, size_t buffer_sz) const {
692  if (buffer_sz < 7) {
693  logger->log(ERROR, "BgpPathAttribNexthop::write: destination buffer size too small.\n");
694  return -1;
695  }
696 
697  if (writeHeader(to, buffer_sz) < 0) return -1;
698  uint8_t *buffer = to + 2;
699 
700  putValue<uint8_t>(&buffer, 4); // length = 4
701  putValue<uint32_t>(&buffer, next_hop);
702  return 7;
703 }
704 
706  return 7;
707 }
708 
715  type_code = MULTI_EXIT_DISC;
716  optional = true;
717 }
718 
719 ssize_t BgpPathAttribMed::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
720  size_t written = 0;
721  written += _print(indent, to, buf_sz, "MedAttribute {\n");
722  indent++; {
723  written += printFlags(indent, to, buf_sz);
724  written += _print(indent, to, buf_sz, "Med { %d }\n", med);
725  }; indent--;
726 
727  written += _print(indent, to, buf_sz, "}\n");
728 
729  return written;
730 }
731 
733  if(hasError()) {
734  logger->log(FATAL, "BgpPathAttribMed::clone: can't clone an attribute with error.\n");
735  throw "has_error";
736  }
737  return new BgpPathAttribMed(*this);
738 }
739 
740 ssize_t BgpPathAttribMed::parse(const uint8_t *from, size_t length) {
741  ssize_t header_length = parseHeader(from, length);
742  if (header_length < 0) return -1;
743 
744  if (type_code != MULTI_EXIT_DISC) {
745  logger->log(FATAL, "BgpPathAttribMed::parse: type in header mismatch.\n");
746  throw "bad_type";
747  }
748 
749  const uint8_t *buffer = from + 3;
750 
751  if (value_len < 4) {
752  logger->log(ERROR, "BgpPathAttribMed::parse: incomplete attrib.\n");
753  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
754  return -1;
755  }
756 
757  if (value_len != 4) {
758  logger->log(ERROR, "BgpPathAttribMed::parse: bad length, want 4, saw %d.\n", value_len);
759  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
760  return -1;
761  }
762 
763  if (!optional || transitive || extended || partial) {
764  logger->log(ERROR, "BgpPathAttribMed::parse: bad flag bits, must be optional, !extended, !partial, !transitive.\n");
765  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
766  return -1;
767  }
768 
769  med = ntohl(getValue<uint32_t>(&buffer));
770 
771  return 7;
772 }
773 
774 ssize_t BgpPathAttribMed::write(uint8_t *to, size_t buffer_sz) const {
775  if (buffer_sz < 7) {
776  logger->log(ERROR, "BgpPathAttribMed::write: destination buffer size too small.\n");
777  return -1;
778  }
779 
780  if (writeHeader(to, buffer_sz) < 0) return -1;
781  uint8_t *buffer = to + 2;
782 
783  putValue<uint8_t>(&buffer, 4); // length = 4
784  putValue<uint32_t>(&buffer, htonl(med));
785  return 7;
786 }
787 
788 ssize_t BgpPathAttribMed::length() const {
789  return 7;
790 }
791 
798  type_code = LOCAL_PREF;
799 }
800 
801 ssize_t BgpPathAttribLocalPref::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
802  size_t written = 0;
803  written += _print(indent, to, buf_sz, "LocalPrefAttribute {\n");
804  indent++; {
805  written += printFlags(indent, to, buf_sz);
806  written += _print(indent, to, buf_sz, "LocalPref { %d }\n", local_pref);
807  }; indent--;
808 
809  written += _print(indent, to, buf_sz, "}\n");
810 
811  return written;
812 }
813 
815  if(hasError()) {
816  logger->log(FATAL, "BgpPathAttribLocalPref::clone: can't clone an attribute with error.\n");
817  throw "has_error";
818  }
819  return new BgpPathAttribLocalPref(*this);
820 }
821 
822 ssize_t BgpPathAttribLocalPref::parse(const uint8_t *from, size_t length) {
823  ssize_t header_length = parseHeader(from, length);
824  if (header_length < 0) return -1;
825 
826  if (type_code != LOCAL_PREF) {
827  logger->log(FATAL, "BgpPathAttribLocalPref::parse: type in header mismatch.\n");
828  throw "bad_type";
829  }
830 
831  const uint8_t *buffer = from + 3;
832 
833  if (value_len < 4) {
834  logger->log(ERROR, "BgpPathAttribLocalPref::parse: incomplete attrib.\n");
835  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
836  return -1;
837  }
838 
839  if (value_len != 4) {
840  logger->log(ERROR, "BgpPathAttribLocalPref::parse: bad length, want 4, saw %d.\n", value_len);
841  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
842  return -1;
843  }
844 
845  if (optional || transitive || extended || partial) {
846  logger->log(ERROR, "BgpPathAttribLocalPref::parse: bad flag bits, must be !optional, !extended, !partial, !transitive.\n");
847  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
848  return -1;
849  }
850 
851  local_pref = ntohl(getValue<uint32_t>(&buffer));
852 
853  return 7;
854 }
855 
856 ssize_t BgpPathAttribLocalPref::write(uint8_t *to, size_t buffer_sz) const {
857  if (buffer_sz < 7) {
858  logger->log(ERROR, "BgpPathAttribLocalPref::write: destination buffer size too small.\n");
859  return -1;
860  }
861 
862  if (writeHeader(to, buffer_sz) < 0) return -1;
863  uint8_t *buffer = to + 2;
864 
865  putValue<uint8_t>(&buffer, 4); // length = 4
866  putValue<uint32_t>(&buffer, htonl(local_pref));
867  return 7;
868 }
869 
871  return 7;
872 }
873 
880  type_code = ATOMIC_AGGREGATE;
881  transitive = true;
882 }
883 
884 ssize_t BgpPathAttribAtomicAggregate::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
885  size_t written = 0;
886  written += _print(indent, to, buf_sz, "AtomicAggregateAttribute {\n");
887  indent++; {
888  written += printFlags(indent, to, buf_sz);
889  }; indent--;
890 
891  written += _print(indent, to, buf_sz, "}\n");
892 
893  return written;
894 }
895 
897  if(hasError()) {
898  logger->log(FATAL, "BgpPathAttribAtomicAggregate::clone: can't clone an attribute with error.\n");
899  throw "has_error";
900  }
901  return new BgpPathAttribAtomicAggregate(*this);
902 }
903 
904 ssize_t BgpPathAttribAtomicAggregate::parse(const uint8_t *from, size_t length) {
905  ssize_t header_length = parseHeader(from, length);
906  if (header_length < 0) return -1;
907 
908  if (type_code != ATOMIC_AGGREGATE) {
909  logger->log(FATAL, "BgpPathAttribAtomicAggregate::parse: type in header mismatch.\n");
910  throw "bad_type";
911  }
912 
913  if (value_len != 0) {
914  logger->log(ERROR, "BgpPathAttribAtomicAggregate::parse: bad length, want 0, saw %d.\n", value_len);
915  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
916  return -1;
917  }
918 
919  if (optional || !transitive || extended || partial) {
920  logger->log(ERROR, "BgpPathAttribAtomicAggregate::parse: bad flag bits, must be !optional, !extended, !partial, transitive.\n");
921  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
922  return -1;
923  }
924 
925  return 3;
926 }
927 
928 ssize_t BgpPathAttribAtomicAggregate::write(uint8_t *to, size_t buffer_sz) const {
929  if (buffer_sz < 3) {
930  logger->log(ERROR, "BgpPathAttribAtomicAggregate::write: destination buffer size too small.\n");
931  return -1;
932  }
933 
934  if (writeHeader(to, buffer_sz) < 0) return -1;
935  uint8_t *buffer = to + 2;
936 
937  putValue<uint8_t>(&buffer, 0); // length = 0
938 
939  return 3;
940 }
941 
943  return 3;
944 }
945 
953  this->is_4b = is_4b;
954  type_code = AGGREATOR;
955  optional = true;
956  transitive = true;
957 }
958 
959 ssize_t BgpPathAttribAggregator::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
960  size_t written = 0;
961  written += _print(indent, to, buf_sz, "AggregatorAttribute {\n");
962  indent++; {
963  written += printFlags(indent, to, buf_sz);
964  written += _print(indent, to, buf_sz, "Aggregator { %s }\n", inet_ntoa(*(struct in_addr*) &aggregator));
965  written += _print(indent, to, buf_sz, "AggregatorAsn { %d }\n", aggregator_asn);
966  }; indent--;
967 
968  written += _print(indent, to, buf_sz, "}\n");
969 
970  return written;
971 }
972 
974  if(hasError()) {
975  logger->log(FATAL, "BgpPathAttribAggregator::clone: can't clone an attribute with error.\n");
976  throw "has_error";
977  }
978  return new BgpPathAttribAggregator(*this);
979 }
980 
981 ssize_t BgpPathAttribAggregator::parse(const uint8_t *from, size_t length) {
982  ssize_t header_length = parseHeader(from, length);
983  if (header_length < 0) return -1;
984 
985  if (type_code != AGGREATOR) {
986  logger->log(FATAL, "BgpPathAttribAggregator::parse: type in header mismatch.\n");
987  throw "bad_type";
988  }
989 
990  const uint8_t *buffer = from + 3;
991  const uint8_t want_len = (is_4b ? 8 : 6);
992 
993  if (value_len < want_len) {
994  logger->log(ERROR, "BgpPathAttribAggregator::parse: incomplete attrib.\n");
995  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
996  return -1;
997  }
998 
999  if (value_len != want_len) {
1000  logger->log(ERROR, "BgpPathAttribAggregator::parse: bad length, want %d, saw %d.\n", want_len, value_len);
1001  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
1002  return -1;
1003  }
1004 
1005  if (!optional || !transitive || extended || partial) {
1006  logger->log(ERROR, "BgpPathAttribAggregator::parse: bad flag bits, must be optional, !extended, !partial, transitive.\n");
1007  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
1008  return -1;
1009  }
1010 
1011  if (is_4b) aggregator_asn = ntohl(getValue<uint32_t>(&buffer));
1012  else aggregator_asn = ntohs(getValue<uint16_t>(&buffer));
1013  aggregator = getValue<uint32_t>(&buffer);
1014 
1015  return 3 + want_len;
1016 }
1017 
1018 ssize_t BgpPathAttribAggregator::write(uint8_t *to, size_t buffer_sz) const {
1019  uint8_t write_value_sz = (is_4b ? 6 : 8);
1020 
1021  if (buffer_sz < (size_t) (write_value_sz + 3)) {
1022  logger->log(ERROR, "BgpPathAttribAggregator::write: destination buffer size too small.\n");
1023  return -1;
1024  }
1025 
1026  if (writeHeader(to, buffer_sz) < 0) return -1;
1027  uint8_t *buffer = to + 2;
1028 
1029  putValue<uint8_t>(&buffer, write_value_sz);
1030 
1031  if (!is_4b && aggregator_asn >= 0xffff) {
1032  logger->log(ERROR, "BgpPathAttribAggregator::write: bad asn. not 4b but asn is %d.\n", aggregator_asn);
1033  return -1;
1034  }
1035 
1036  if (is_4b) putValue<uint32_t>(&buffer, htonl(aggregator_asn));
1037  else putValue<uint16_t>(&buffer, htons(aggregator_asn));
1038  putValue<uint32_t>(&buffer, aggregator);
1039 
1040  return write_value_sz + 3;
1041 }
1042 
1044  return 3 + (is_4b ? 6 : 8);
1045 }
1046 
1053  optional = true;
1054  transitive = true;
1055  type_code = AS4_PATH;
1056 }
1057 
1058 ssize_t BgpPathAttribAs4Path::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
1059  size_t written = 0;
1060  written += _print(indent, to, buf_sz, "As4PathAttribute {\n");
1061  indent++; {
1062  written += printFlags(indent, to, buf_sz);
1063  if (as4_paths.size() == 0) written += _print(indent, to, buf_sz, "As4PathSegments { } \n");
1064  else {
1065  written += _print(indent, to, buf_sz, "As4PathSegments {\n");
1066  indent++; {
1067  for (const BgpAsPathSegment &seg : as4_paths) {
1068  switch (seg.type) {
1069  case 1: written += _print(indent, to, buf_sz, "AsSet {\n"); break;
1070  case 2: written += _print(indent, to, buf_sz, "AsSequence {\n"); break;
1071  default: written += _print(indent, to, buf_sz, "Invalid {\n"); break;
1072  }
1073  indent++; {
1074  for (uint32_t asn : seg.value) {
1075  written += _print(indent, to, buf_sz, "%d\n", asn);
1076  }
1077  }; indent--;
1078  written += _print(indent, to, buf_sz, "}\n");
1079  }
1080  }; indent--;
1081  written += _print(indent, to, buf_sz, "}\n");
1082  }
1083  }; indent--;
1084  written += _print(indent, to, buf_sz, "}\n");
1085 
1086  return written;
1087 }
1088 
1090  if(hasError()) {
1091  logger->log(FATAL, "BgpPathAttribAs4Path::clone: can't clone an attribute with error.\n");
1092  throw "has_error";
1093  }
1094  return new BgpPathAttribAs4Path(*this);
1095 }
1096 
1097 ssize_t BgpPathAttribAs4Path::parse(const uint8_t *from, size_t length) {
1098  ssize_t header_length = parseHeader(from, length);
1099  if (header_length < 0) return -1;
1100 
1101  if (type_code != AS4_PATH) {
1102  logger->log(FATAL, "BgpPathAttribAs4Path::parse: type in header mismatch.\n");
1103  throw "bad_type";
1104  }
1105 
1106  if (!optional || !transitive || extended || partial) {
1107  logger->log(ERROR, "BgpPathAttribAs4Path::parse: bad flag bits, must be optional, !extended, !partial, transitive.\n");
1108  setError(E_UPDATE, E_ATTR_FLAG, from , value_len + header_length);
1109  return -1;
1110  }
1111 
1112  const uint8_t *buffer = from + 3;
1113 
1114  // empty as_path
1115  if (value_len == 0) return 3;
1116 
1117  uint8_t parsed_len = 0;
1118 
1119  while (parsed_len < value_len) {
1120  // bad as_path
1121  if (value_len - parsed_len < 3) {
1122  logger->log(ERROR, "BgpPathAttribAs4Path::parse: incomplete as_path segment.\n");
1123  setError(E_UPDATE, E_AS_PATH, NULL, 0);
1124  return -1;
1125  }
1126 
1127  uint8_t type = getValue<uint8_t>(&buffer);
1128  uint8_t n_asn = getValue<uint8_t>(&buffer);
1129 
1130  // type & count
1131  parsed_len += 2;
1132 
1133  uint8_t asns_length = n_asn * sizeof(uint32_t);
1134 
1135  // overflow
1136  if (parsed_len + asns_length > value_len) {
1137  logger->log(ERROR, "BgpPathAttribAs4Path::parse: as_path overflow attribute length.\n");
1138  setError(E_UPDATE, E_AS_PATH, NULL, 0);
1139  return -1;
1140  }
1141 
1142  BgpAsPathSegment path(true, type);
1143  for (int i = 0; i < n_asn; i++) path.value.push_back(ntohl(getValue<uint32_t>(&buffer)));
1144  as4_paths.push_back(path);
1145 
1146  // parsed asns
1147  parsed_len += asns_length;
1148  }
1149 
1150  if (parsed_len != value_len) {
1151  logger->log(FATAL, "BgpPathAttribAs4Path::parse: parsed length and value length mismatch, but no error reported.\n");
1152  throw "bad_parse";
1153  }
1154 
1155  return parsed_len + 3;
1156 }
1157 
1159  size_t len = 3; // header len = 3
1160 
1161  for (const BgpAsPathSegment &seg : as4_paths) {
1162  len += 4 * seg.value.size() + 2;
1163  }
1164 
1165  return len;
1166 }
1167 
1173 void BgpPathAttribAs4Path::addSeg(uint32_t asn) {
1174  BgpAsPathSegment segment(true, AS_SEQUENCE);
1175  segment.prepend(asn);
1176  as4_paths.push_back(segment);
1177 }
1178 
1191 bool BgpPathAttribAs4Path::prepend(uint32_t asn) {
1192  if (as4_paths.size() == 0) {
1193  // nothing here yet, add a new sequence. (5.1.2.b.3)
1194  addSeg(asn);
1195  return true;
1196  }
1197 
1198  // something here already. what to do?
1199  BgpAsPathSegment *segment = as4_paths.data();
1200 
1201  if (segment->type == AS_SET) {
1202  // seg is set, create a new segment of type AS_SEQUENCE (5.1.2.b.2)
1203  // FIXME: checks needed: really create a new segment?
1204  addSeg(asn);
1205  return true;
1206  } else if (segment->type == AS_SEQUENCE) {
1207  if (segment->getCount() >= 127) {
1208  // seg full, create a new segment of type AS_SEQUENCE (5.1.2.b.1)
1209  addSeg(asn);
1210  return true;
1211  } else {
1212  segment->prepend(asn);
1213  return true;
1214  }
1215  }
1216 
1217  logger->log(ERROR, "BgpPathAttribAs4Path::prepend: unknow first segment type: %d, can't append.\n", segment->type);
1218  return false;
1219 }
1220 
1221 ssize_t BgpPathAttribAs4Path::write(uint8_t *to, size_t buffer_sz) const {
1222  if (buffer_sz < 3) {
1223  logger->log(ERROR, "BgpPathAttribAs4Path::write: destination buffer size too small.\n");
1224  return -1;
1225  }
1226 
1227  if (writeHeader(to, buffer_sz) < 0) return -1;
1228  uint8_t *buffer = to + 2;
1229 
1230  // keep track of length field so we can write it later
1231  uint8_t *len_field = buffer;
1232 
1233  // skip length field for now
1234  buffer++;
1235 
1236  uint8_t written_len = 0;
1237 
1238  for (const BgpAsPathSegment &seg4 : as4_paths) {
1239  size_t asn_count = seg4.value.size();
1240 
1241  if (asn_count > 127) {
1242  logger->log(ERROR, "BgpPathAttribAs4Path::write: segment size too big: %d\n", asn_count);
1243  return -1;
1244  }
1245 
1246  // asn list + seg type & asn count
1247  size_t bytes_need = asn_count * sizeof(uint32_t) + 2;
1248 
1249  if (written_len + bytes_need > buffer_sz) {
1250  logger->log(ERROR, "BgpPathAttribAs4Path::write: destination buffer size too small.\n");
1251  return -1;
1252  }
1253 
1254  // put type
1255  putValue<uint8_t>(&buffer, seg4.type);
1256 
1257  // put asn count
1258  putValue<uint8_t>(&buffer, asn_count);
1259 
1260  // put asns
1261  for (uint32_t asn : seg4.value) {
1262  putValue<uint32_t>(&buffer, htonl(asn));
1263  }
1264 
1265  written_len += bytes_need;
1266  }
1267 
1268  // fill in the length.
1269  putValue<uint8_t>(&len_field, written_len);
1270 
1271  // written_len: the as_paths, 3: attr header (flag, typecode, length)
1272  return written_len + 3;
1273 }
1274 
1276  if(hasError()) {
1277  logger->log(FATAL, "BgpPathAttribAs4Aggregator::clone: can't clone an attribute with error.\n");
1278  throw "has_error";
1279  }
1280  return new BgpPathAttribAs4Aggregator(*this);
1281 }
1282 
1289  type_code = AS4_AGGREGATOR;
1290  optional = true;
1291  transitive = true;
1292 }
1293 
1294 ssize_t BgpPathAttribAs4Aggregator::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
1295  size_t written = 0;
1296  written += _print(indent, to, buf_sz, "Aggregator4Attribute {\n");
1297  indent++; {
1298  written += printFlags(indent, to, buf_sz);
1299  written += _print(indent, to, buf_sz, "Aggregator { %s }\n", inet_ntoa(*(struct in_addr*) &aggregator));
1300  written += _print(indent, to, buf_sz, "AggregatorAsn { %d }\n", aggregator_asn4);
1301  }; indent--;
1302 
1303  written += _print(indent, to, buf_sz, "}\n");
1304 
1305  return written;
1306 }
1307 
1308 ssize_t BgpPathAttribAs4Aggregator::parse(const uint8_t *from, size_t length) {
1309  ssize_t header_length = parseHeader(from, length);
1310  if (header_length < 0) return -1;
1311 
1312  if (type_code != AS4_AGGREGATOR) {
1313  logger->log(FATAL, "BgpPathAttribAs4Aggregator::parse: type in header mismatch.\n");
1314  throw "bad_type";
1315  }
1316 
1317  const uint8_t *buffer = from + 3;
1318 
1319  if (value_len < 8) {
1320  logger->log(ERROR, "BgpPathAttribAs4Aggregator::parse: incomplete attrib.\n");
1321  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
1322  return -1;
1323  }
1324 
1325  if (value_len != 8) {
1326  logger->log(ERROR, "BgpPathAttribAs4Aggregator::parse: bad length, want 8, saw %d.\n", value_len);
1327  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
1328  return -1;
1329  }
1330 
1331  if (!optional || !transitive || extended || partial) {
1332  logger->log(ERROR, "BgpPathAttribAs4Aggregator::parse: bad flag bits, must be optional, !extended, !partial, transitive.\n");
1333  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
1334  return -1;
1335  }
1336 
1337  aggregator_asn4 = ntohl(getValue<uint32_t>(&buffer));
1338  aggregator = getValue<uint32_t>(&buffer);
1339 
1340  return 11;
1341 }
1342 
1343 ssize_t BgpPathAttribAs4Aggregator::write(uint8_t *to, size_t buffer_sz) const {
1344  if (buffer_sz < 11) {
1345  logger->log(ERROR, "BgpPathAttribAs4Aggregator::write: destination buffer size too small.\n");
1346  return -1;
1347  }
1348 
1349  if (writeHeader(to, buffer_sz) < 0) return -1;
1350  uint8_t *buffer = to + 2;
1351 
1352  putValue<uint8_t>(&buffer, 11);
1353 
1354  putValue<uint32_t>(&buffer, htonl(aggregator_asn4));
1355  putValue<uint32_t>(&buffer, aggregator);
1356 
1357  return 11;
1358 }
1359 
1361  return 11;
1362 }
1363 
1370  type_code = COMMUNITY;
1371  optional = true;
1372  transitive = true;
1373 }
1374 
1375 ssize_t BgpPathAttribCommunity::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
1376  size_t written = 0;
1377  written += _print(indent, to, buf_sz, "CommunityAttribute {\n");
1378  indent++; {
1379  written += printFlags(indent, to, buf_sz);
1380  written += _print(indent, to, buf_sz, "Community {\n");
1381  indent++; {
1382  for (uint32_t community : communites) {
1383  uint16_t community_[2];
1384  memcpy(community_, &community, 4);
1385  written += _print(indent, to, buf_sz, "%d:%d\n", ntohs(community_[0]), ntohs(community_[1]));
1386  }
1387  }; indent--;
1388  written += _print(indent, to, buf_sz, "}\n");
1389  }; indent--;
1390  written += _print(indent, to, buf_sz, "}\n");
1391 
1392  return written;
1393 }
1394 
1396  if(hasError()) {
1397  logger->log(FATAL, "BgpPathAttribCommunity::clone: can't clone an attribute with error.\n");
1398  throw "has_error";
1399  }
1400  return new BgpPathAttribCommunity(*this);
1401 }
1402 
1403 ssize_t BgpPathAttribCommunity::parse(const uint8_t *from, size_t length) {
1404  ssize_t header_length = parseHeader(from, length);
1405  if (header_length < 0) return -1;
1406 
1407  if (type_code != COMMUNITY) {
1408  logger->log(FATAL, "BgpPathAttribCommunity::parse: type in header mismatch.\n");
1409  throw "bad_type";
1410  }
1411 
1412  const uint8_t *buffer = from + 3;
1413 
1414  if (value_len < 4) {
1415  logger->log(ERROR, "BgpPathAttribCommunity::parse: incomplete attrib.\n");
1416  setError(E_UPDATE, E_UNSPEC_UPDATE, NULL, 0);
1417  return -1;
1418  }
1419 
1420  if (value_len % 4 != 0) {
1421  logger->log(ERROR, "BgpPathAttribCommunity::parse: bad length, want multiple of 4, saw %d.\n", value_len);
1422  setError(E_UPDATE, E_ATTR_LEN, from, value_len + header_length);
1423  return -1;
1424  }
1425 
1426  if (!optional || !transitive || extended || partial) {
1427  logger->log(ERROR, "BgpPathAttribCommunity::parse: bad flag bits, must be optional, !extended, !partial, transitive.\n");
1428  setError(E_UPDATE, E_ATTR_FLAG, from, value_len + header_length);
1429  return -1;
1430  }
1431 
1432  size_t read_len = 0;
1433 
1434  while (read_len < value_len) {
1435  communites.push_back(getValue<uint32_t>(&buffer));
1436  read_len += 4;
1437  }
1438 
1439  if (read_len != value_len) {
1440  logger->log(FATAL, " BgpPathAttribCommunity::parse: parse ends with read_len != value_len.\n");
1441  throw "bad_parse";
1442  }
1443 
1444  return value_len + 3;
1445 }
1446 
1447 ssize_t BgpPathAttribCommunity::write(uint8_t *to, size_t buffer_sz) const {
1448  if (buffer_sz < 7) {
1449  logger->log(ERROR, "BgpPathAttribCommunity::write: destination buffer size too small.\n");
1450  return -1;
1451  }
1452 
1453  if (writeHeader(to, buffer_sz) < 0) return -1;
1454  uint8_t *buffer = to + 2;
1455 
1456  putValue<uint8_t>(&buffer, 4 * communites.size()); // length = 4 * nCommunity
1457 
1458  size_t write_len = 0;
1459 
1460  for (uint32_t community : communites) {
1461  write_len += putValue<uint32_t>(&buffer, community);
1462  }
1463 
1464  return 3 + write_len;
1465 }
1466 
1468  return 3 + 4 * communites.size();
1469 }
1470 
1471 BgpPathAttribMpNlriBase::BgpPathAttribMpNlriBase(BgpLogHandler *logger) : BgpPathAttrib(logger) {
1472  optional = true;
1473 }
1474 
1475 int16_t BgpPathAttribMpNlriBase::GetAfiFromBuffer(const uint8_t *buffer, size_t length) {
1476  if (length < 3) return -1;
1477  const uint8_t *ptr = buffer + 3;
1478  return ntohs(getValue<uint16_t>(&ptr));
1479 }
1480 
1481 ssize_t BgpPathAttribMpNlriBase::parseHeader(const uint8_t *from, size_t length) {
1482  ssize_t hdr_len = BgpPathAttrib::parseHeader(from, length);
1483 
1484  if (hdr_len < 0) return -1;
1485 
1486  if (!optional || transitive || extended || extended) {
1487  logger->log(ERROR, "BgpPathAttribMpNlriBase::parse: bad flag bits, must be optional, !extended, !partial, !transitive.\n");
1488  setError(E_UPDATE, E_ATTR_FLAG, from , value_len + hdr_len);
1489  return -1;
1490  }
1491 
1492  if (type_code != MP_REACH_NLRI && type_code != MP_UNREACH_NLRI) {
1493  logger->log(FATAL, "BgpPathAttribMpNlriBase::parseHeader: type in header mismatch.\n");
1494  throw "bad_type";
1495  }
1496 
1497  if (value_len < 5) {
1498  logger->log(ERROR, "BgpPathAttribMpNlriBase::parseHeader: incompete attribute.\n");
1499  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1500  return -1;
1501  }
1502 
1503  const uint8_t *buffer = from + hdr_len;
1504  afi = ntohs(getValue<uint16_t>(&buffer));
1505  safi = getValue<uint8_t>(&buffer);
1506 
1507  return hdr_len + 3;
1508 }
1509 
1510 BgpPathAttribMpReachNlriIpv6::BgpPathAttribMpReachNlriIpv6(BgpLogHandler *logger) : BgpPathAttribMpNlriBase(logger) {
1511  afi = IPV6;
1512 }
1513 
1515  if (hasError()) {
1516  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::clone: can't clone an attribute with error.\n");
1517  throw "has_error";
1518  }
1519  return new BgpPathAttribMpReachNlriIpv6(*this);
1520 }
1521 
1522 ssize_t BgpPathAttribMpReachNlriIpv6::parse(const uint8_t *from, size_t length) {
1523  ssize_t hdr_len = parseHeader(from, length);
1524 
1525  if (hdr_len < 0) return -1;
1526 
1527  if (afi != IPV6) {
1528  logger->log(FATAL, "BgpPathAttribMpReachNlriIpv6::parse: afi mismatch.\n");
1529  throw "bad_type";
1530  }
1531 
1532  const uint8_t *buffer = from + hdr_len;
1533  uint8_t nexthop_length = getValue<uint8_t>(&buffer);
1534 
1535  if (nexthop_length != 16 && nexthop_length != 32) {
1536  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::parse: bad nexthop length %d (want 16 or 32).\n", nexthop_length);
1537  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1538  return -1;
1539  }
1540 
1541  ssize_t buf_left = value_len - hdr_len - 1 + 3; // 3: attr headers
1542 
1543  if (buf_left < (ssize_t) nexthop_length) {
1544  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::parse: nexthop overflows buffer.\n");
1545  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1546  return -1;
1547  }
1548 
1549  memcpy(nexthop_global, buffer, 16); buffer += 16;
1550  if (nexthop_length == 32) {
1551  memcpy(nexthop_linklocal, buffer, 16); buffer += 16;
1552  } else memset(nexthop_linklocal, 0, 16);
1553 
1554  buf_left -= nexthop_length;
1555 
1556  if (buf_left < 1) {
1557  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::parse: reserved bits overflows buffer.\n");
1558  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1559  return -1;
1560  }
1561 
1562  uint8_t res = getValue<uint8_t>(&buffer);
1563  buf_left--;
1564 
1565  if (res != 0) {
1566  logger->log(WARN, "BgpPathAttribMpReachNlriIpv6::parse: reserved bits != 0\n");
1567  }
1568 
1569  while (buf_left > 0) {
1570  Prefix6 this_prefix = Prefix6();
1571  ssize_t pfx_read_len = this_prefix.parse(buffer, buf_left);
1572 
1573  if (pfx_read_len < 0) {
1574  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::parse: error parsing nlri entry.\n");
1575  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1576  return -1;
1577  }
1578 
1579  buffer += pfx_read_len;
1580  buf_left -= pfx_read_len;
1581  nlri.push_back(this_prefix);
1582  }
1583 
1584  if (buf_left != 0) {
1585  logger->log(FATAL, "BgpPathAttribMpReachNlriIpv6::parse: parsed end with non-zero buf_left (%d).\n", buf_left);
1586  throw "bad_parse";
1587  }
1588 
1589  return value_len + hdr_len - 3; // 3: afi/safi, already part of "value_len"
1590 }
1591 
1592 ssize_t BgpPathAttribMpReachNlriIpv6::write(uint8_t *to, size_t buffer_sz) const {
1593  ssize_t header_len = writeHeader(to, buffer_sz);
1594 
1595  if (header_len < 0) return -1;
1596  uint8_t *attr_len_field = to + header_len;
1597  uint8_t *buffer = attr_len_field + 1;
1598 
1599  if (buffer_sz - header_len < 5) {
1600  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::write: dst buffer too small.\n");
1601  return -1;
1602  }
1603 
1604  size_t written_len = header_len + 1;
1605 
1606  putValue<uint16_t>(&buffer, htons(afi));
1607  putValue<uint8_t>(&buffer, safi);
1608 
1609  bool has_linklocak = !v6addr_is_zero(nexthop_linklocal);
1610 
1611  putValue<uint8_t>(&buffer, has_linklocak ? 32 : 16);
1612  written_len += 4;
1613 
1614  if ((has_linklocak && buffer_sz - written_len < 32) || (!has_linklocak && buffer_sz - written_len < 16)) {
1615  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::write: dst buffer too small.\n");
1616  return -1;
1617  }
1618 
1619  memcpy(buffer, nexthop_global, 16); buffer += 16; written_len += 16;
1620  if (has_linklocak) {
1621  memcpy(buffer, nexthop_linklocal, 16); buffer += 16; written_len += 16;
1622  }
1623 
1624  putValue<uint8_t>(&buffer, 0);
1625  written_len++;
1626 
1627  for (const Prefix6 &route : nlri) {
1628  ssize_t rou_wrt_len = route.write(buffer, buffer_sz - written_len);
1629  if (rou_wrt_len < 0) {
1630  logger->log(ERROR, "BgpPathAttribMpReachNlriIpv6::write: failed to write nlri.\n");
1631  return -1;
1632  }
1633  written_len += rou_wrt_len;
1634  buffer += rou_wrt_len;
1635  }
1636 
1637  putValue<uint8_t>(&attr_len_field, written_len - 3);
1638 
1639  if (written_len != (size_t) (buffer - to)) {
1640  logger->log(FATAL, "BgpPathAttribMpReachNlriIpv6::write: inconsistent written size (len=%d, diff=%d)\n", written_len, buffer - to);
1641  return -1;
1642  }
1643 
1644  return written_len;
1645 }
1646 
1647 ssize_t BgpPathAttribMpReachNlriIpv6::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
1648  size_t written = 0;
1649  written += _print(indent, to, buf_sz, "MpReachNlriAttribute {\n");
1650  indent++; {
1651  written += printFlags(indent, to, buf_sz);
1652  const char *safi_str = "Unknow";
1653  if (safi == UNICAST) safi_str = "Unicast";
1654  if (safi == MULTICAST) safi_str = "Multicast";
1655  written += _print(indent, to, buf_sz, "AFI { IPv6 }\n");
1656  written += _print(indent, to, buf_sz, "SAFI { %s }\n", safi_str);
1657  char nh_global_str[INET6_ADDRSTRLEN];
1658  inet_ntop(AF_INET6, nexthop_global, nh_global_str, INET6_ADDRSTRLEN);
1659 
1660  written += _print(indent, to, buf_sz, "Nexthops {\n");
1661  indent++; {
1662  written += _print(indent, to, buf_sz, "%s\n", nh_global_str);
1663  if (!v6addr_is_zero(nexthop_linklocal)) {
1664  char nh_linklocal_str[INET6_ADDRSTRLEN];
1665  inet_ntop(AF_INET6, nexthop_linklocal, nh_linklocal_str, INET6_ADDRSTRLEN);
1666  written += _print(indent, to, buf_sz, "%s\n", nh_linklocal_str);
1667  }
1668  }; indent--;
1669  written += _print(indent, to, buf_sz, "}\n");
1670 
1671  written += _print(indent, to, buf_sz, "NLRI {\n");
1672  indent++; {
1673  for (const Prefix6 &route : nlri) {
1674  uint8_t prefix[16];
1675  route.getPrefix(prefix);
1676  char prefix_str[INET6_ADDRSTRLEN];
1677  inet_ntop(AF_INET6, prefix, prefix_str, INET6_ADDRSTRLEN);
1678  written += _print(indent, to, buf_sz, "%s/%d\n", prefix_str, route.getLength());
1679  }
1680  }; indent--;
1681  written += _print(indent, to, buf_sz, "}\n");
1682 
1683  }; indent--;
1684 
1685  written += _print(indent, to, buf_sz, "}\n");
1686 
1687  return written;
1688 }
1689 
1691  size_t len = 3 + 5; // 3: attribute headers, 5: afi, safi, nh_len, res
1692  bool has_linklocak = !v6addr_is_zero(nexthop_linklocal);
1693  len += (has_linklocak ? 32 : 16);
1694  for (const Prefix6 &route : nlri) {
1695  len += (1 + (route.getLength() + 7) / 8);
1696  }
1697  return len;
1698 }
1699 
1700 BgpPathAttribMpReachNlriUnknow::BgpPathAttribMpReachNlriUnknow(BgpLogHandler *logger) : BgpPathAttribMpNlriBase(logger) {
1701  nexthop = NULL;
1702  nexthop_len = 0;
1703  nlri = NULL;
1704  nlri_len = 0;
1705 }
1706 
1707 BgpPathAttribMpReachNlriUnknow::BgpPathAttribMpReachNlriUnknow(BgpLogHandler *logger, const uint8_t *nexthop, size_t nexthop_len, const uint8_t *nlri, size_t nlri_len) : BgpPathAttribMpNlriBase(logger) {
1708  if (nexthop_len > 0) {
1709  this->nexthop = (uint8_t *) malloc(nexthop_len);
1710  memcpy(this->nexthop, nexthop, nexthop_len);
1711  }
1712 
1713  if (nlri_len > 0) {
1714  this->nlri = (uint8_t *) malloc(nlri_len);
1715  memcpy(this->nlri, nlri, nlri_len);
1716  }
1717  this->nexthop_len = nexthop_len;
1718  this->nlri_len = nlri_len;
1719 }
1720 
1721 BgpPathAttribMpReachNlriUnknow::~BgpPathAttribMpReachNlriUnknow() {
1722  if (nlri_len != 0) free(nlri);
1723  if (nexthop_len != 0) free(nexthop);
1724 }
1725 
1727  if (hasError()) {
1728  logger->log(FATAL, "BgpPathAttribMpReachNlriUnknow::clone: can't clone an attribute with error.\n");
1729  throw "has_error";
1730  }
1731 
1732  if (nexthop_len == 0 && nlri_len == 0) return new BgpPathAttribMpReachNlriUnknow(logger);
1733  return new BgpPathAttribMpReachNlriUnknow(logger, nexthop, nexthop_len, nlri, nlri_len);
1734 }
1735 
1736 ssize_t BgpPathAttribMpReachNlriUnknow::parse(const uint8_t *from, size_t length) {
1737  ssize_t hdr_len = parseHeader(from, length);
1738  if (hdr_len < 0) return -1;
1739 
1740  if (nexthop_len != 0) free(nexthop);
1741 
1742  const uint8_t *buffer = from + hdr_len;
1743  nexthop_len = getValue<uint8_t>(&buffer);
1744  size_t parsed_len = hdr_len + 1;
1745 
1746  if (length < parsed_len + nexthop_len) {
1747  logger->log(FATAL, "BgpPathAttribMpReachNlriUnknow::parse: unexpected end of attribute.\n");
1748  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1749  return -1;
1750  }
1751 
1752  parsed_len += nexthop_len;
1753  nexthop = (uint8_t *) malloc(nexthop_len);
1754  memcpy(nexthop, buffer, nexthop_len);
1755  buffer += nexthop_len;
1756 
1757  uint8_t res = getValue<uint8_t>(&buffer);
1758  parsed_len++;
1759 
1760  if (res != 0) {
1761  logger->log(WARN, "BgpPathAttribMpReachNlriIpv6::parse: reserved bits != 0\n");
1762  }
1763 
1764  if (nlri_len != 0) free(nlri);
1765 
1766  nlri_len = value_len - parsed_len - 3; // 3: attr header
1767  parsed_len += nlri_len;
1768  nlri = (uint8_t *) malloc(nlri_len);
1769  memcpy(nlri, buffer, nlri_len);
1770 
1771  return parsed_len;
1772 }
1773 
1774 ssize_t BgpPathAttribMpReachNlriUnknow::write(uint8_t *to, size_t buffer_sz) const {
1775  size_t expected_len = 3 + 5 + nexthop_len + nlri_len;
1776 
1777  if (buffer_sz < expected_len) {
1778  logger->log(ERROR, "BgpPathAttribMpReachNlriUnknow::write: dst buffer too small.\n");
1779  return -1;
1780  }
1781 
1782  ssize_t hdr_len = writeHeader(to, buffer_sz);
1783  if (hdr_len < 0) return -1;
1784  uint8_t *buffer = to + hdr_len;
1785 
1786  putValue<uint8_t>(&buffer, expected_len - 3);
1787  putValue<uint16_t>(&buffer, htons(afi));
1788  putValue<uint8_t>(&buffer, safi);
1789  putValue<uint8_t>(&buffer, nexthop_len);
1790  memcpy(buffer, nexthop, nexthop_len); buffer += nexthop_len;
1791  putValue<uint8_t>(&buffer, 0);
1792  memcpy(buffer, nlri, nlri_len);
1793 
1794  if ((size_t) (buffer - to) != expected_len) {
1795  logger->log(ERROR, "BgpPathAttribMpReachNlriUnknow::write: unexpected written length.\n");
1796  return -1;
1797  }
1798 
1799  return expected_len;
1800 }
1801 
1802 ssize_t BgpPathAttribMpReachNlriUnknow::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
1803  size_t written = 0;
1804  written += _print(indent, to, buf_sz, "MpReachNlriAttribute {\n");
1805  indent++; {
1806  written += printFlags(indent, to, buf_sz);
1807  written += _print(indent, to, buf_sz, "AFI { %d }\n", afi);
1808  written += _print(indent, to, buf_sz, "SAFI { %d }\n", safi);
1809  }; indent--;
1810  written += _print(indent, to, buf_sz, "}\n");
1811  return written;
1812 }
1813 
1815  return 3 + 5 + nexthop_len + nlri_len;
1816 }
1817 
1818 const uint8_t* BgpPathAttribMpReachNlriUnknow::getNexthop() const {
1819  return nexthop;
1820 }
1821 
1822 const uint8_t* BgpPathAttribMpReachNlriUnknow::getNlri() const {
1823  return nlri;
1824 }
1825 
1826 size_t BgpPathAttribMpReachNlriUnknow::getNexthopLength() const {
1827  return nexthop_len;
1828 }
1829 
1830 size_t BgpPathAttribMpReachNlriUnknow::getNlriLength() const {
1831  return nlri_len;
1832 }
1833 
1834 BgpPathAttribMpUnreachNlriIpv6::BgpPathAttribMpUnreachNlriIpv6(BgpLogHandler *logger) : BgpPathAttribMpNlriBase(logger) {
1835  afi = IPV6;
1836 }
1837 
1839  if (hasError()) {
1840  logger->log(FATAL, "BgpPathAttribMpUnreachNlriIpv6::clone: can clone attribute with error.\n");
1841  throw "has_error";
1842  }
1843 
1844  return new BgpPathAttribMpUnreachNlriIpv6(*this);
1845 }
1846 
1847 ssize_t BgpPathAttribMpUnreachNlriIpv6::parse(const uint8_t *from, size_t length) {
1848  ssize_t hdr_len = parseHeader(from ,length);
1849  if (hdr_len < 0) return -1;
1850 
1851  if (afi != IPV6) {
1852  logger->log(FATAL, "BgpPathAttribMpUnreachNlriIpv6::parse: afi mismatch.\n");
1853  throw "bad_type";
1854  }
1855 
1856  size_t buf_left = value_len - hdr_len + 3; // 3: attrib headers
1857  const uint8_t *buffer = from + hdr_len;
1858 
1859  while (buf_left > 0) {
1860  Prefix6 this_prefix = Prefix6();
1861  ssize_t pfx_read_len = this_prefix.parse(buffer, buf_left);
1862 
1863  if (pfx_read_len < 0) {
1864  logger->log(ERROR, "BgpPathAttribMpUnreachNlriIpv6::parse: error parsing withdrawn entry.\n");
1865  setError(E_UPDATE, E_OPT_ATTR, NULL, 0);
1866  return -1;
1867  }
1868 
1869  buffer += pfx_read_len;
1870  buf_left -= pfx_read_len;
1871  withdrawn_routes.push_back(this_prefix);
1872  }
1873 
1874  if (buf_left != 0) {
1875  logger->log(FATAL, "BgpPathAttribMpUnreachNlriIpv6::parse: parsed end with non-zero buf_left (%d).\n", buf_left);
1876  throw "bad_parse";
1877  }
1878 
1879  return hdr_len + value_len - 3; // 3: afi/safi, already part of "value_len"
1880 }
1881 
1882 ssize_t BgpPathAttribMpUnreachNlriIpv6::write(uint8_t *to, size_t buffer_sz) const {
1883  if (buffer_sz < 3 + 3) {
1884  logger->log(ERROR, "BgpPathAttribMpUnreachNlriIpv6::write: dst buffer too small.\n");
1885  return -1;
1886  }
1887 
1888  ssize_t hdr_len = writeHeader(to, buffer_sz);
1889  if (hdr_len < 0) return -1;
1890 
1891  uint8_t *len_field = to + hdr_len;
1892  uint8_t *buffer = len_field + 1;
1893 
1894  putValue<uint16_t>(&buffer, htons(afi));
1895  putValue<uint8_t>(&buffer, safi);
1896  size_t written_val_len = 3;
1897 
1898  for (const Prefix6 &route : withdrawn_routes) {
1899  ssize_t pfx_wrt_ret = route.write(buffer, buffer_sz - 3 - written_val_len);
1900  if (pfx_wrt_ret < 0) {
1901  logger->log(ERROR, "BgpPathAttribMpUnreachNlriIpv6::write: error writing withdrawn routes.\n");
1902  return -1;
1903  }
1904 
1905  buffer += pfx_wrt_ret;
1906  written_val_len += pfx_wrt_ret;
1907  }
1908 
1909  return 3 + written_val_len;
1910 }
1911 
1912 ssize_t BgpPathAttribMpUnreachNlriIpv6::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
1913  size_t written = 0;
1914 
1915  written += _print(indent, to, buf_sz, "MpUnreachNlriAttribute {\n");
1916  indent++; {
1917  written += printFlags(indent, to, buf_sz);
1918  const char *safi_str = "Unknow";
1919  if (safi == UNICAST) safi_str = "Unicast";
1920  if (safi == MULTICAST) safi_str = "Multicast";
1921  written += _print(indent, to, buf_sz, "AFI { IPv6 }\n");
1922  written += _print(indent, to, buf_sz, "SAFI { %s }\n", safi_str);
1923  written += _print(indent, to, buf_sz, "WithdrawnRoutes {\n");
1924  indent++; {
1925  for (const Prefix6 &route : withdrawn_routes) {
1926  uint8_t prefix[16];
1927  route.getPrefix(prefix);
1928  char prefix_str[INET6_ADDRSTRLEN];
1929  inet_ntop(AF_INET6, prefix, prefix_str, INET6_ADDRSTRLEN);
1930  written += _print(indent, to, buf_sz, "%s/%d\n", prefix_str, route.getLength());
1931  }
1932  }; indent--;
1933  written += _print(indent, to, buf_sz, "}\n");
1934  }; indent--;
1935  _print(indent, to, buf_sz, "}\n");
1936 
1937  return written;
1938 }
1939 
1941  size_t len = 3 + 3; // 3: attribute headers, 3: afi, safi
1942  for (const Prefix6 &route : withdrawn_routes) {
1943  len += (1 + (route.getLength() + 7) / 8);
1944  }
1945  return len;
1946 }
1947 
1948 BgpPathAttribMpUnreachNlriUnknow::BgpPathAttribMpUnreachNlriUnknow(BgpLogHandler *logger) : BgpPathAttribMpNlriBase(logger) {
1949  withdrawn_routes_len = 0;
1950  withdrawn_routes = NULL;
1951 }
1952 
1953 BgpPathAttribMpUnreachNlriUnknow::BgpPathAttribMpUnreachNlriUnknow(BgpLogHandler *logger, const uint8_t *withdrawn, size_t len) : BgpPathAttribMpNlriBase(logger) {
1954  withdrawn_routes_len = len;
1955 
1956  if (len > 0) {
1957  withdrawn_routes = (uint8_t *) malloc(len);
1958  memcpy(withdrawn_routes, withdrawn, len);
1959  }
1960 }
1961 
1962 BgpPathAttribMpUnreachNlriUnknow::~BgpPathAttribMpUnreachNlriUnknow() {
1963  if (withdrawn_routes_len > 0) free(withdrawn_routes);
1964 }
1965 
1967  if (hasError()) {
1968  logger->log(FATAL, "BgpPathAttribMpUnreachNlriUnknow::clone: can clone attribute with error.\n");
1969  throw "has_error";
1970  }
1971 
1972  if (withdrawn_routes_len == 0) return new BgpPathAttribMpUnreachNlriUnknow(logger);
1973  return new BgpPathAttribMpUnreachNlriUnknow(logger, withdrawn_routes, withdrawn_routes_len);
1974 }
1975 
1976 ssize_t BgpPathAttribMpUnreachNlriUnknow::parse(const uint8_t *from, size_t length) {
1977  ssize_t hdr_len = parseHeader(from, length);
1978  if (hdr_len < 0) return -1;
1979 
1980  if (withdrawn_routes_len > 0) free(withdrawn_routes);
1981 
1982  withdrawn_routes_len = value_len - hdr_len;
1983  const uint8_t *buffer = from + hdr_len;
1984 
1985  withdrawn_routes = (uint8_t *) malloc(withdrawn_routes_len);
1986  memcpy(withdrawn_routes, buffer, withdrawn_routes_len);
1987 
1988  return hdr_len + value_len - 3; // 3: afi/safi, already part of "value_len"
1989 }
1990 
1991 ssize_t BgpPathAttribMpUnreachNlriUnknow::write(uint8_t *to, size_t buffer_sz) const {
1992  size_t expected_len = 3 + 3 + withdrawn_routes_len;
1993  if (buffer_sz < expected_len) {
1994  logger->log(ERROR, "BgpPathAttribMpUnreachNlriUnknow::write: dst buffer too small.\n");
1995  return -1;
1996  }
1997 
1998  ssize_t hdr_len = writeHeader(to, buffer_sz);
1999  if (hdr_len < 0) return -1;
2000 
2001  uint8_t *buffer = to + hdr_len;
2002  putValue<uint8_t>(&buffer, expected_len - 3);
2003  putValue<uint16_t>(&buffer, htons(afi));
2004  putValue<uint8_t>(&buffer, safi);
2005  memcpy(buffer, withdrawn_routes, withdrawn_routes_len);
2006 
2007  return expected_len;
2008 }
2009 
2010 ssize_t BgpPathAttribMpUnreachNlriUnknow::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
2011  size_t written = 0;
2012  written += _print(indent, to, buf_sz, "MpUnreachNlriAttribute {\n");
2013  indent++; {
2014  written += printFlags(indent, to, buf_sz);
2015  written += _print(indent, to, buf_sz, "AFI { %d }\n", afi);
2016  written += _print(indent, to, buf_sz, "SAFI { %d }\n", safi);
2017  }; indent--;
2018  written += _print(indent, to, buf_sz, "}\n");
2019  return written;
2020 }
2021 
2023  return 3 + 3 + withdrawn_routes_len;
2024 }
2025 
2026 const uint8_t* BgpPathAttribMpUnreachNlriUnknow::getWithdrawnRoutes() const {
2027  return withdrawn_routes;
2028 }
2029 
2030 size_t BgpPathAttribMpUnreachNlriUnknow::getWithdrawnRoutesLength() const {
2031  return withdrawn_routes_len;
2032 }
2033 
2034 }
ssize_t printFlags(size_t indent, uint8_t **to, size_t *buf_sz) const
Utility function to print flags for attribute.
IPv6 Route/Prefix related utilities.
Definition: prefix6.h:27
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
bool partial
Attribute flag: partial.
ssize_t writeHeader(uint8_t *buffer, size_t buffer_sz) const
Write attribute header to buffer. (Flag, Type)
The BGP path attributes.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
ssize_t length() const
Get size in bytes required to serialize the object.
std::vector< uint32_t > value
The segment value.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
The BgpPathAttrib class.
virtual ssize_t length() const
Get size in bytes required to serialize the object.
BgpPathAttrib(BgpLogHandler *logger)
Construct a new Bgp Path Attrib:: Bgp Path Attrib object.
MP-BGP ReachNlri IPv6 NLRI class.
bool is_4b
Is ASNs in the attribute four octets?
BgpPathAttribMed(BgpLogHandler *logger)
Construct a new Bgp Path Attrib Med:: Bgp Path Attrib Med object.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
size_t getCount() const
Get number of ASNs in the segment.
ssize_t length() const
Get size in bytes required to serialize the object.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
BgpPathAttrib * clone() const
Clone the attribute.
MP-BGP UnreachNlri container for unknow AFI/SAFI.
bool optional
Attribute flag: Optional.
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 length() const
Get size in bytes required to serialize the object.
BgpPathAttribAs4Path(BgpLogHandler *logger)
Construct a new Bgp Path Attrib As 4 Path:: Bgp Path Attrib As 4 Path object.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
BgpPathAttrib * clone() const
Clone the attribute.
std::vector< uint32_t > communites
Raw community attribute in network byte order.
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.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
bool hasError() const
Check if error information available.
Definition: serializable.cc:45
ssize_t length() const
Get size in bytes required to serialize the object.
BgpAsPathSegment(bool is_4b, uint8_t type)
Construct a new Bgp As Path Segment:: Bgp As Path Segment object.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
ssize_t parseHeader(const uint8_t *buffer, size_t length)
Utility function to parse attribute header. (Flag, type, length)
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
BgpPathAttribCommunity(BgpLogHandler *logger)
Construct a new Bgp Path Attrib Community:: Bgp Path Attrib Community object.
BgpPathAttribOrigin(BgpLogHandler *logger)
Construct a new Bgp Path Attrib Origin:: Bgp Path Attrib Origin object.
BgpPathAttrib * clone() const
Clone the attribute.
The serializable base class.
Definition: serializable.h:26
ssize_t length() const
Get size in bytes required to serialize the object.
BgpPathAttrib * clone() const
Clone the attribute.
uint16_t value_len
Attribute length. Length field is only used in deserialization for parseHeader() to pass length field...
AS4_AGGREGATOR attribute.
bool transitive
Attribute flag: Transitive.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
The BGP AFI/SAFI.
uint32_t local_pref
Local Pref.
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.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
std::vector< BgpAsPathSegment > as4_paths
The AS4_PATH segments.
BgpPathAttrib * clone() const
Clone the attribute.
BgpPathAttribAtomicAggregate(BgpLogHandler *logger)
Construct a new Bgp Path Attrib Atomic Aggregate:: Bgp Path Attrib Atomic Aggregate object...
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
BgpPathAttrib * clone() const
Clone the attribute.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
uint32_t aggregator_asn4
Aggregator ASN.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
bool prepend(uint32_t asn)
Prepend an ASN into AS path.
uint32_t aggregator_asn
Aggregator ASN.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
BgpPathAttribAggregator(BgpLogHandler *logger, bool is_4b)
Construct a new Bgp Path Attrib Aggregator:: Bgp Path Attrib Aggregator object.
BgpPathAttrib * clone() const
Clone the attribute.
ssize_t length() const
Get size in bytes required to serialize the object.
BgpPathAttrib * clone() const
Clone the attribute.
ssize_t length() const
Get size in bytes required to serialize the object.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
uint8_t type
Segment type.
void setLogger(BgpLogHandler *logger)
Replace logger for this object.
ssize_t length() const
Get size in bytes required to serialize the object.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
BgpPathAttrib * clone() const
Clone the attribute.
bool extended
Attribute flag: extended.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
bool prepend(uint32_t asn)
Prepend an ASN into AS4 path.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
bool v6addr_is_zero(const uint8_t prefix[16])
Test if a IPv6 addresss is all zero.
Definition: prefix6.cc:195
void setError(uint8_t err, uint8_t suberr, const uint8_t *data, size_t data_len)
Set the error information.
Definition: serializable.cc:61
ssize_t length() const
Get size in bytes required to serialize the object.
Buffer operation helpers.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
virtual BgpPathAttrib * clone() const
Clone the attribute.
bool prepend(uint32_t asn)
Prepend ASN to AS segment.
Definition: bgp-afi.h:14
BgpPathAttrib * clone() const
Clone the attribute.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
MP-BGP Reach/Unreach NLRI base class.
ssize_t parse(const uint8_t *buffer, size_t buf_sz)
Parse a IPv6 NLRI prefix from buffer.
Definition: prefix6.cc:242
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
ssize_t length() const
Get size in bytes required to serialize the object.
The BgpLogHandler class.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
ssize_t write(uint8_t *buffer, size_t buffer_sz) const
Serialize a BGP update message path attribute.
BgpPathAttribNexthop(BgpLogHandler *logger)
Construct a new Bgp Path Attrib Nexthop:: Bgp Path Attrib Nexthop object.
An AS_PATH or AS4_PATH segment.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
BgpPathAttrib * clone() const
Clone the attribute.
BgpPathAttribAs4Aggregator(BgpLogHandler *logger)
Construct a new Bgp Path Attrib As 4 Aggregator:: Bgp Path Attrib As 4 Aggregator object...
BgpPathAttrib * clone() const
Clone the attribute.
uint32_t aggregator
Aggregator in network byte order.
ssize_t length() const
Get size in bytes required to serialize the object.
BgpPathAttrib * clone() const
Clone the attribute.
virtual ssize_t write(uint8_t *to, size_t buf_sz) const
Serialize a BGP update message path attribute.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
uint32_t aggregator
Aggregator in network byte order.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
ssize_t length() const
Get size in bytes required to serialize the object.
BGP error codes.
BgpPathAttribAsPath(BgpLogHandler *logger, bool is_4b)
Construct a new Bgp Path Attrib As Path:: Bgp Path Attrib As Path object.
uint32_t next_hop
The nexthop in network byte order.
ssize_t length() const
Get size in bytes required to serialize the object.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
BgpPathAttribLocalPref(BgpLogHandler *logger)
Construct a new Bgp Path Attrib Local Pref:: Bgp Path Attrib Local Pref object.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
uint8_t type_code
Attribute type code.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
MP-BGP ReachNlri container for unknow AFI/SAFI.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
BgpPathAttrib * clone() const
Clone the attribute.
ssize_t parse(const uint8_t *buffer, size_t length)
Deserialize a BGP update message path attribute.
static uint8_t GetTypeFromBuffer(const uint8_t *buffer, size_t buffer_sz)
Get type of attribute from buffer.
MP-BGP UnreachNlri IPv6 class.
ssize_t length() const
Get size in bytes required to serialize the object.
virtual ~BgpPathAttrib()
Destroy the Bgp Path Attrib:: Bgp Path Attrib object.