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