* Parses the BGP attributes in the update * * \details * Parses all attributes. Decoded values are updated in 'parsed_data' * * \param [in] data Pointer to the start of the prefixes to be parsed * \param [in] len Length of the data in bytes to be read * \param [out] parsed_data Reference to parsed_update_data; will be updated with all parsed data */
| 246 | * \param [out] parsed_data Reference to parsed_update_data; will be updated with all parsed data |
| 247 | */ |
| 248 | void UpdateMsg::parseAttributes(u_char *data, uint16_t len, parsed_update_data &parsed_data) { |
| 249 | /* |
| 250 | * Per RFC4271 Section 4.3, flat indicates if the length is 1 or 2 octets |
| 251 | */ |
| 252 | u_char attr_flags; |
| 253 | u_char attr_type; |
| 254 | uint16_t attr_len; |
| 255 | |
| 256 | if (len == 0) |
| 257 | return; |
| 258 | |
| 259 | else if (len < 3) { |
| 260 | LOG_WARN("%s: rtr=%s: Cannot parse the attributes due to the data being too short, error in update message. len=%d", |
| 261 | peer_addr.c_str(), router_addr.c_str(), len); |
| 262 | return; |
| 263 | } |
| 264 | |
| 265 | /* |
| 266 | * Iterate through all attributes and parse them |
| 267 | */ |
| 268 | for (int read_size=0; read_size < len; read_size += 2) { |
| 269 | attr_flags = *data++; |
| 270 | attr_type = *data++; |
| 271 | |
| 272 | // Check if the length field is 1 or two bytes |
| 273 | if (ATTR_FLAG_EXTENDED(attr_flags)) { |
| 274 | SELF_DEBUG("%s: rtr=%s: extended length path attribute bit set for an entry", peer_addr.c_str(), router_addr.c_str()); |
| 275 | |
| 276 | memcpy(&attr_len, data, 2); data += 2; read_size += 2; |
| 277 | bgp::SWAP_BYTES(&attr_len); |
| 278 | |
| 279 | } else { |
| 280 | attr_len = *data++; |
| 281 | read_size++; |
| 282 | } |
| 283 | |
| 284 | SELF_DEBUG("%s: rtr=%s: attribute type = %d len_sz = %d", |
| 285 | peer_addr.c_str(), router_addr.c_str(), attr_type, attr_len); |
| 286 | |
| 287 | // Get the attribute data, if we have any; making sure to not overrun buffer |
| 288 | if (attr_len > 0 and (read_size + attr_len) <= len ) { |
| 289 | // Data pointer is currently at the data position of the attribute |
| 290 | |
| 291 | /* |
| 292 | * Parse data based on attribute type |
| 293 | */ |
| 294 | parseAttrData(attr_type, attr_len, data, parsed_data); |
| 295 | data += attr_len; |
| 296 | read_size += attr_len; |
| 297 | |
| 298 | SELF_DEBUG("%s: rtr=%s: parsed attr type=%d, size=%hu", peer_addr.c_str(), router_addr.c_str(), |
| 299 | attr_type, attr_len); |
| 300 | |
| 301 | } else if (attr_len) { |
| 302 | LOG_NOTICE("%s: rtr=%s: Attribute data len of %hu is larger than available data in update message of %hu", |
| 303 | peer_addr.c_str(), router_addr.c_str(), attr_len, (len - read_size)); |
| 304 | return; |
| 305 | } |
nothing calls this directly
no test coverage detected