LCOV - code coverage report
Current view: top level - bgp/extended-community - source_as.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 69 82 84.1 %
Date: 2026-11-09 02:10:49 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/extended-community/source_as.h"
       7             : 
       8             : #include <algorithm>
       9             : 
      10             : #include "base/address.h"
      11             : #include "bgp/bgp_common.h"
      12             : 
      13             : using std::copy;
      14             : using std::string;
      15             : 
      16             : SourceAs SourceAs::null_sas;
      17             : 
      18         331 : SourceAs::SourceAs() {
      19         331 :     data_.fill(0);
      20         331 : }
      21             : 
      22         164 : SourceAs::SourceAs(const bytes_type &data) {
      23         164 :     copy(data.begin(), data.end(), data_.begin());
      24         164 : }
      25             : 
      26         156 : uint32_t SourceAs::GetAsn() const {
      27         156 :     if (data_[0] == BgpExtendedCommunityType::TwoOctetAS) {
      28         156 :         return get_value(&data_[2], 2);
      29             :     }
      30             : 
      31           0 :     if (data_[0] == BgpExtendedCommunityType::FourOctetAS) {
      32           0 :         return get_value(&data_[2], 4);
      33             :     }
      34             : 
      35           0 :     return 0;
      36             : }
      37             : 
      38         194 : SourceAs::SourceAs(const uint32_t asn, const uint32_t ri_index) {
      39         194 :     if (asn <= AS2_MAX) {
      40         194 :         data_[0] = BgpExtendedCommunityType::TwoOctetAS;
      41         194 :         put_value(&data_[2], 2, asn);
      42         194 :         put_value(&data_[4], 4, ri_index);
      43             :     } else {
      44           0 :         data_[0] = BgpExtendedCommunityType::FourOctetAS;
      45           0 :         put_value(&data_[2], 4, asn);
      46           0 :         put_value(&data_[6], 2, ri_index);
      47             :     }
      48         194 :     data_[1] = BgpExtendedCommunitySubType::SourceAS;
      49         194 : }
      50             : 
      51          17 : string SourceAs::ToString() const {
      52             :     uint8_t data[SourceAs::kSize];
      53          17 :     copy(data_.begin(), data_.end(), &data[0]);
      54             :     char temp[50];
      55          17 :     if (data[0] == BgpExtendedCommunityType::TwoOctetAS) {
      56           9 :         uint16_t asn = get_value(data + 2, 2);
      57           9 :         uint32_t num = get_value(data + 4, 4);
      58           9 :         snprintf(temp, sizeof(temp), "source-as:%u:%u", asn, num);
      59           9 :         return string(temp);
      60           8 :     } else if (data[0] == BgpExtendedCommunityType::FourOctetAS) {
      61           8 :         uint32_t asn = get_value(data + 2, 4);
      62           8 :         uint16_t num = get_value(data + 6, 2);
      63           8 :         snprintf(temp, sizeof(temp), "source-as:%u:%u", asn, num);
      64           8 :         return string(temp);
      65             :     }
      66           0 :     return "";
      67             : }
      68             : 
      69          15 : SourceAs SourceAs::FromString(const string &str,
      70             :     boost::system::error_code *errorp) {
      71          15 :     SourceAs sas;
      72             :     uint8_t data[SourceAs::kSize];
      73             : 
      74             :     // source-as:1:2
      75          15 :     size_t pos = str.find(':');
      76          15 :     if (pos == string::npos) {
      77           0 :         if (errorp != NULL) {
      78           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      79             :         }
      80           0 :         return SourceAs::null_sas;
      81             :     }
      82             : 
      83          15 :     string first(str.substr(0, pos));
      84          15 :     if (first != "source-as") {
      85           0 :         if (errorp != NULL) {
      86           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      87             :         }
      88           0 :         return SourceAs::null_sas;
      89             :     }
      90             : 
      91          15 :     string rest(str.substr(pos+1));
      92             : 
      93          15 :     pos = rest.find(':');
      94          15 :     if (pos == string::npos) {
      95           1 :         if (errorp != NULL) {
      96           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      97             :         }
      98           1 :         return SourceAs::null_sas;
      99             :     }
     100             : 
     101          14 :     boost::system::error_code ec;
     102          14 :     string second(rest.substr(0, pos));
     103             :     int offset;
     104             :     char *endptr;
     105             :     // Get ASN
     106          14 :     int64_t asn = strtol(second.c_str(), &endptr, 10);
     107          14 :     if (asn == 0 || asn > 0xffffffff || *endptr != '\0') {
     108           2 :         if (errorp != NULL) {
     109           2 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     110             :        }
     111           2 :        return SourceAs::null_sas;
     112             :     }
     113             : 
     114          12 :     string third(rest.substr(pos+1));
     115          12 :     uint64_t value = strtol(third.c_str(), &endptr, 10);
     116          12 :     if (*endptr != '\0') {
     117           2 :         if (errorp != NULL) {
     118           2 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     119             :         }
     120           2 :         return SourceAs::null_sas;
     121             :     }
     122             : 
     123             :     // Check assigned number.
     124          10 :     if ((asn > AS2_MAX && value > 0xFFFF) || value > 0xFFFFFFFF) {
     125           1 :         if (errorp != NULL) {
     126           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     127             :         }
     128           1 :         return SourceAs::null_sas;
     129             :     }
     130             : 
     131           9 :     if (asn <= AS2_MAX) {
     132           5 :         data[0] = BgpExtendedCommunityType::TwoOctetAS;
     133           5 :         put_value(&data[2], 2, asn);
     134           5 :         offset = 4;
     135             :     } else {
     136           4 :         data[0] = BgpExtendedCommunityType::FourOctetAS;
     137           4 :         put_value(&data[2], 4, asn);
     138           4 :         offset = 6;
     139             :     }
     140             : 
     141           9 :     data[1] = BgpExtendedCommunitySubType::SourceAS;
     142           9 :     put_value(&data[offset], SourceAs::kSize - offset, value);
     143           9 :     copy(&data[0], &data[SourceAs::kSize], sas.data_.begin());
     144           9 :     return sas;
     145          15 : }

Generated by: LCOV version 1.14