std::string MoveToFront::decode(const encodedResult& input) { size_t N = input.size(); std::string decodedStr(N, '\0'); RadixArray moveToFrontArray(radixArray); for (size_t i = 0; i < N; ++i) { unsigned char curIndex = input[i]; RadixArray::iterator moveToFrontIter = moveToFrontArray.begin(); for (unsigned char index = 0; moveToFrontIter != moveToFrontArray.end(); ++moveToFrontIter, ++index) { if (curIndex == index) { unsigned char symbolToFront = *moveToFrontIter; moveToFrontArray.erase(moveToFrontIter); moveToFrontArray.push_front(symbolToFront); decodedStr[i] = symbolToFront; break; } } } return decodedStr; }
/** * Parses capabilities from buffer * * \details * Reads the capabilities from buffer. The parsed data will be * returned via the out params. * * \param [in] data Pointer to raw bgp payload data, starting at the open/cap message * \param [in] size Size of the data available to read; prevent overrun when reading * \param [out] asn Reference to the ASN that was discovered * \param [out] capabilities Reference to the capabilities list<string> (decoded values) * * \return ZERO is error, otherwise a positive value indicating the number of bytes read */ size_t OpenMsg::parseCapabilities(u_char *data, size_t size, uint32_t &asn, std::list<std::string> &capabilities) { size_t read_size = 0; u_char *bufPtr = data; /* * Loop through the capabilities (will set the 4 byte ASN) */ char capStr[200]; open_param *param; cap_param *cap; for (int i=0; i < size; ) { param = (open_param *)bufPtr; SELF_DEBUG("%s: Open param type=%d len=%d", peer_addr.c_str(), param->type, param->len); if (param->type != BGP_CAP_PARAM_TYPE) { LOG_NOTICE("%s: Open param type %d is not supported, expected type %d", peer_addr.c_str(), param->type, BGP_CAP_PARAM_TYPE); } /* * Process the capabilities if present */ else if (param->len >= 2) { u_char *cap_ptr = bufPtr + 2; for (int c=0; c < param->len; ) { cap = (cap_param *)cap_ptr; SELF_DEBUG("%s: Capability code=%d len=%d", peer_addr.c_str(), cap->code, cap->len); /* * Handle the capability */ switch (cap->code) { case BGP_CAP_4OCTET_ASN : if (cap->len == 4) { memcpy(&asn, cap_ptr + 2, 4); bgp::SWAP_BYTES(&asn); snprintf(capStr, sizeof(capStr), "4 Octet ASN (%d)", BGP_CAP_4OCTET_ASN); capabilities.push_back(capStr); } else { LOG_NOTICE("%s: 4 octet ASN capability length is invalid %d expected 4", peer_addr.c_str(), cap->len); } break; case BGP_CAP_ROUTE_REFRESH: SELF_DEBUG("%s: supports route-refresh", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "Route Refresh (%d)", BGP_CAP_ROUTE_REFRESH); capabilities.push_back(capStr); break; case BGP_CAP_ROUTE_REFRESH_ENHANCED: SELF_DEBUG("%s: supports route-refresh enhanced", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "Route Refresh Enhanced (%d)", BGP_CAP_ROUTE_REFRESH_ENHANCED); capabilities.push_back(capStr); break; case BGP_CAP_ROUTE_REFRESH_OLD: SELF_DEBUG("%s: supports OLD route-refresh", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "Route Refresh Old (%d)", BGP_CAP_ROUTE_REFRESH_OLD); capabilities.push_back(capStr); break; case BGP_CAP_ADD_PATH: SELF_DEBUG("%s: supports add-path", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "ADD Path (%d)", BGP_CAP_ADD_PATH); capabilities.push_back(capStr); break; case BGP_CAP_GRACEFUL_RESTART: SELF_DEBUG("%s: supports graceful restart", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "Graceful Restart (%d)", BGP_CAP_GRACEFUL_RESTART); capabilities.push_back(capStr); break; case BGP_CAP_OUTBOUND_FILTER: SELF_DEBUG("%s: supports outbound filter", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "Outbound Filter (%d)", BGP_CAP_OUTBOUND_FILTER); capabilities.push_back(capStr); break; case BGP_CAP_MULTI_SESSION: SELF_DEBUG("%s: supports multi-session", peer_addr.c_str()); snprintf(capStr, sizeof(capStr), "Multi-session (%d)", BGP_CAP_MULTI_SESSION); capabilities.push_back(capStr); break; case BGP_CAP_MPBGP: { cap_mpbgp_data data; if (cap->len == sizeof(data)) { memcpy(&data, (cap_ptr + 2), sizeof(data)); bgp::SWAP_BYTES(&data.afi); SELF_DEBUG("%s: supports MPBGP afi = %d safi=%d", peer_addr.c_str(), data.afi, data.safi); snprintf(capStr, sizeof(capStr), "MPBGP (%d) : afi=%d safi=%d", BGP_CAP_MPBGP, data.afi, data.safi); /* * Decode the SAFI - http://www.iana.org/assignments/safi-namespace/safi-namespace.xhtml */ std::string decode_str = "unknown"; switch (data.safi) { case bgp::BGP_SAFI_UNICAST : // Unicast IP forwarding decode_str = "Unicast"; break; case bgp::BGP_SAFI_MULTICAST : // Multicast IP forwarding decode_str = "Multicast"; break; case bgp::BGP_SAFI_NLRI_LABEL : // NLRI with MPLS Labels decode_str = "NLRI/MPLS"; break; case bgp::BGP_SAFI_MCAST_VPN : // MCAST VPN decode_str = "MCAST VPN"; break; case bgp::BGP_SAFI_VPLS : // VPLS decode_str = "VPLS"; break; case bgp::BGP_SAFI_MDT : // BGP MDT decode_str = "BGP MDT"; break; case bgp::BGP_SAFI_4over6 : // BGP 4over6 decode_str = "BGP 4over6"; break; case bgp::BGP_SAFI_6over4 : // BGP 6over4 decode_str = "BGP 6over4"; break; case bgp::BGP_SAFI_EVPN : // BGP EVPNs decode_str = "BGP EVPNs"; break; case bgp::BGP_SAFI_BGPLS : // BGP-LS decode_str = "BGP-LS"; break; case bgp::BGP_SAFI_MPLS : // MPLS-Labeled VPN decode_str = "MPLS-Labeled VPN"; break; case bgp::BGP_SAFI_MCAST_MPLS_VPN : // Multicast BGP/MPLS VPN decode_str = "Multicast BGP/MPLS VPN"; break; case bgp::BGP_SAFI_RT_CONSTRAINS : // Route target constrains decode_str = "RT constrains"; break; } // Add decoded string with address family type std::string decodedStr(capStr); decodedStr.append(" : "); decodedStr.append(decode_str); switch (data.afi) { case bgp::BGP_AFI_IPV4 : decodedStr.append(" IPv4"); break; case bgp::BGP_AFI_IPV6 : decodedStr.append(" IPv6"); break; case bgp::BGP_AFI_BGPLS : decodedStr.append(" BGP-LS"); break; default: decodedStr.append(" unknown"); break; } capabilities.push_back(decodedStr); } else { LOG_NOTICE("%s: MPBGP capability but length %d is invalid expected %d.", peer_addr.c_str(), cap->len, sizeof(data)); return 0; } break; } default : snprintf(capStr, sizeof(capStr), "%d", cap->code); capabilities.push_back(capStr); SELF_DEBUG("%s: Ignoring capability %d, not implemented", peer_addr.c_str(), cap->code); break; } // Move the pointer to the next capability c += 2 + cap->len; cap_ptr += 2 + cap->len; } } // Move index to next param i += 2 + param->len; bufPtr += 2 + param->len; read_size += 2 + param->len; } return read_size; }