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 : }
|