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/types.h" 7 : #include "bgp/origin-vn/origin_vn.h" 8 : 9 : #include <stdio.h> 10 : 11 : #include <algorithm> 12 : 13 : 14 : using std::copy; 15 : using std::string; 16 : 17 : OriginVn OriginVn::null_originvn; 18 : 19 181 : OriginVn::OriginVn() { 20 181 : data_.fill(0); 21 181 : } 22 : 23 219448 : OriginVn::OriginVn(as_t asn, uint32_t vn_index) { 24 219448 : if (asn <= AS2_MAX) { 25 219444 : data_[0] = BgpExtendedCommunityType::Experimental; 26 219442 : put_value(&data_[2], 2, asn); 27 219442 : put_value(&data_[4], 4, vn_index); 28 : } else { 29 4 : data_[0] = BgpExtendedCommunityType::Experimental4ByteAs; 30 4 : put_value(&data_[2], 4, asn); 31 4 : put_value(&data_[6], 2, vn_index); 32 : } 33 219446 : data_[1] = BgpExtendedCommunityExperimentalSubType::OriginVn; 34 219446 : } 35 : 36 142748 : OriginVn::OriginVn(const bytes_type &data) { 37 142748 : copy(data.begin(), data.end(), data_.begin()); 38 142748 : } 39 : 40 21 : OriginVn OriginVn::FromString(const string &str, 41 : boost::system::error_code *errorp) { 42 21 : OriginVn origin_vn; 43 : uint8_t data[OriginVn::kSize]; 44 21 : size_t pos = str.find(':'); 45 21 : if (pos == string::npos) { 46 1 : if (errorp != NULL) { 47 1 : *errorp = make_error_code(boost::system::errc::invalid_argument); 48 : } 49 1 : return OriginVn::null_originvn; 50 : } 51 : 52 20 : string first(str.substr(0, pos)); 53 20 : if (first != "originvn") { 54 3 : if (errorp != NULL) { 55 3 : *errorp = make_error_code(boost::system::errc::invalid_argument); 56 : } 57 3 : return OriginVn::null_originvn; 58 : } 59 : 60 17 : string rest(str.substr(pos+1)); 61 : 62 17 : pos = rest.find(':'); 63 17 : if (pos == string::npos) { 64 1 : if (errorp != NULL) { 65 1 : *errorp = make_error_code(boost::system::errc::invalid_argument); 66 : } 67 1 : return OriginVn::null_originvn; 68 : } 69 : 70 16 : string second(rest.substr(0, pos)); 71 : char *endptr; 72 16 : int64_t asn = strtol(second.c_str(), &endptr, 10); 73 16 : if (asn == 0 || asn > 0xFFFFFFFF || *endptr != '\0') { 74 1 : if (errorp != NULL) { 75 1 : *errorp = make_error_code(boost::system::errc::invalid_argument); 76 : } 77 1 : return OriginVn::null_originvn; 78 : } 79 : 80 15 : string third(rest.substr(pos+1)); 81 15 : uint64_t value = strtol(third.c_str(), &endptr, 10); 82 15 : if (*endptr != '\0') { 83 2 : if (errorp != NULL) { 84 2 : *errorp = make_error_code(boost::system::errc::invalid_argument); 85 : } 86 2 : return OriginVn::null_originvn; 87 : } 88 : 89 : // Check assigned number. 90 13 : if ((asn > AS2_MAX && value > 0xFFFF) || value > 0xFFFFFFFF) { 91 1 : if (errorp != NULL) { 92 1 : *errorp = make_error_code(boost::system::errc::invalid_argument); 93 : } 94 1 : return OriginVn::null_originvn; 95 : } 96 : 97 12 : if (asn <= AS2_MAX) { 98 6 : data[0] = BgpExtendedCommunityType::Experimental; 99 6 : put_value(&data[2], 2, asn); 100 6 : put_value(&data[4], 4, value); 101 : } else { 102 6 : data[0] = BgpExtendedCommunityType::Experimental4ByteAs; 103 6 : put_value(&data[2], 4, asn); 104 6 : put_value(&data[6], 2, value); 105 : } 106 12 : data[1] = BgpExtendedCommunityExperimentalSubType::OriginVn; 107 12 : copy(&data[0], &data[OriginVn::kSize], origin_vn.data_.begin()); 108 12 : return origin_vn; 109 20 : } 110 : 111 19057 : as_t OriginVn::as_number() const { 112 19057 : if (data_[0] == BgpExtendedCommunityType::Experimental) { 113 19044 : as2_t as_number = get_value(data_.data() + 2, 2); 114 19044 : return as_number; 115 : } 116 13 : if (data_[0] == BgpExtendedCommunityType::Experimental4ByteAs) { 117 13 : as_t as_number = get_value(data_.data() + 2, 4); 118 13 : return as_number; 119 : } 120 0 : return 0; 121 : } 122 : 123 143093 : int OriginVn::vn_index() const { 124 143093 : if (data_[0] == BgpExtendedCommunityType::Experimental) { 125 143073 : int vn_index = get_value(data_.data() + 4, 4); 126 143074 : return vn_index; 127 : } 128 20 : if (data_[0] == BgpExtendedCommunityType::Experimental4ByteAs) { 129 20 : int vn_index = get_value(data_.data() + 6, 2); 130 20 : return vn_index; 131 : } 132 0 : return 0; 133 : } 134 : 135 20306 : bool OriginVn::IsGlobal() const { 136 20306 : return (vn_index() >= kMinGlobalId); 137 : } 138 : 139 499 : string OriginVn::ToString() { 140 : char temp[50]; 141 499 : snprintf(temp, sizeof(temp), "originvn:%u:%u", as_number(), vn_index()); 142 499 : return string(temp); 143 : }