LCOV - code coverage report
Current view: top level - bgp/extended-community - site_of_origin.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 81 81 100.0 %
Date: 2026-08-03 02:19:58 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14