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

Generated by: LCOV version 1.14