* Parse attribute AS_PATH data * * \param [in] attr_len Length of the attribute data * \param [in] data Pointer to the attribute data * \param [out] attrs Reference to the parsed attr map - will be updated */
| 574 | * \param [out] attrs Reference to the parsed attr map - will be updated |
| 575 | */ |
| 576 | void UpdateMsg::parseAttr_AsPath(uint16_t attr_len, u_char *data, parsed_attrs_map &attrs) { |
| 577 | std::string decoded_path; |
| 578 | int path_len = attr_len; |
| 579 | uint16_t as_path_cnt = 0; |
| 580 | |
| 581 | u_char seg_type; |
| 582 | u_char seg_len; |
| 583 | uint32_t seg_asn = 0; |
| 584 | |
| 585 | u_char *data_ptr = data; |
| 586 | |
| 587 | /* |
| 588 | * We first must try to parse using four octet since the RFC says that the peer header |
| 589 | * defines the encoding and not the capabilities. four_octet_asn represents |
| 590 | * the capabilities only. |
| 591 | */ |
| 592 | char asn_octet_size = (peer_info->using_2_octet_asn /* and not four_octet_asn */) ? 2 : 4; |
| 593 | |
| 594 | if (path_len < asn_octet_size) // Nothing to parse if length doesn't include at least one asn |
| 595 | return; |
| 596 | |
| 597 | /* |
| 598 | * Loop through each path segment |
| 599 | */ |
| 600 | while (path_len > 0) { |
| 601 | |
| 602 | seg_type = *data++; |
| 603 | seg_len = *data++; // Count of AS's, not bytes |
| 604 | path_len -= 2; |
| 605 | |
| 606 | if (seg_type == 1) { // If AS-SET open with a brace |
| 607 | decoded_path.append(" {"); |
| 608 | } |
| 609 | |
| 610 | SELF_DEBUG("%s: rtr=%s: as_path seg_len = %d seg_type = %d, path_len = %d total_len = %d as_octet_size = %d", |
| 611 | peer_addr.c_str(), router_addr.c_str(), |
| 612 | seg_len, seg_type, path_len, attr_len, asn_octet_size); |
| 613 | |
| 614 | if ((seg_len * asn_octet_size) > path_len){ |
| 615 | |
| 616 | LOG_NOTICE("%s: rtr=%s: Could not parse the AS PATH due to update message buffer being too short when using ASN octet size %d (%d > %d)", |
| 617 | peer_addr.c_str(), router_addr.c_str(), asn_octet_size, (seg_len * asn_octet_size), path_len); |
| 618 | |
| 619 | if (not peer_info->using_2_octet_asn) { |
| 620 | LOG_NOTICE("%s: rtr=%s: switching encoding size to 2-octet", |
| 621 | peer_addr.c_str(), router_addr.c_str()); |
| 622 | |
| 623 | peer_info->using_2_octet_asn = true; |
| 624 | |
| 625 | parseAttr_AsPath(attr_len, data_ptr, attrs); |
| 626 | } |
| 627 | return; |
| 628 | } |
| 629 | |
| 630 | // The rest of the data is the as path sequence, in blocks of 2 or 4 bytes |
| 631 | for (; seg_len > 0; seg_len--) { |
| 632 | seg_asn = 0; |
| 633 | memcpy(&seg_asn, data, asn_octet_size); data += asn_octet_size; |
nothing calls this directly
no test coverage detected