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/rtarget/rtarget_address.h"
7 :
8 : #include <algorithm>
9 :
10 : #include "base/parse_object.h"
11 : #include "bgp/bgp_common.h"
12 :
13 : using std::copy;
14 : using std::string;
15 :
16 : RouteTarget RouteTarget::null_rtarget;
17 :
18 1157690 : RouteTarget::RouteTarget() {
19 1157690 : data_.fill(0);
20 1157455 : }
21 :
22 8147022 : RouteTarget::RouteTarget(const bytes_type &data) {
23 8147022 : copy(data.begin(), data.end(), data_.begin());
24 8146530 : }
25 :
26 27376 : RouteTarget::RouteTarget(const Ip4Address &address, uint16_t num) {
27 27376 : data_[0] = 0x1;
28 27376 : data_[1] = 0x2;
29 27376 : put_value(&data_[2], 4, address.to_ulong());
30 27376 : put_value(&data_[6], 2, num);
31 27376 : }
32 :
33 62855 : const uint64_t RouteTarget::GetExtCommunityValue() const {
34 62855 : return get_value(data_.begin(), 8);
35 : }
36 :
37 1151599 : RouteTarget RouteTarget::FromString(const string &str,
38 : boost::system::error_code *errorp) {
39 1151599 : RouteTarget rt;
40 : uint8_t data[RouteTarget::kSize];
41 :
42 : // target:1:2 OR target:1.2.3.4:3
43 1151343 : size_t pos = str.find(':');
44 1151411 : if (pos == string::npos) {
45 1 : if (errorp != NULL) {
46 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
47 : }
48 1 : return RouteTarget::null_rtarget;
49 : }
50 :
51 1151410 : string first(str.substr(0, pos));
52 1151452 : if (first != "target") {
53 5 : if (errorp != NULL) {
54 5 : *errorp = make_error_code(boost::system::errc::invalid_argument);
55 : }
56 5 : return RouteTarget::null_rtarget;
57 : }
58 :
59 1152960 : string rest(str.substr(pos+1));
60 :
61 1152396 : pos = rest.find(':');
62 1153413 : if (pos == string::npos) {
63 3 : if (errorp != NULL) {
64 3 : *errorp = make_error_code(boost::system::errc::invalid_argument);
65 : }
66 3 : return RouteTarget::null_rtarget;
67 : }
68 :
69 1153410 : boost::system::error_code ec;
70 1153410 : string second(rest.substr(0, pos));
71 1152775 : Ip4Address addr = Ip4Address::from_string(second, ec);
72 1152715 : int offset = 6;
73 : char *endptr;
74 1152715 : if (ec.failed()) {
75 999288 : bool is_as4 = false;
76 : // Not an IP address, try ASN.
77 999288 : if (second.c_str()[pos - 1] == 'L') {
78 0 : is_as4 = true;
79 0 : second = second.substr(0, pos - 1);
80 : }
81 :
82 999289 : int64_t asn = strtol(second.c_str(), &endptr, 10);
83 999285 : if (asn == 0 || asn > 0xFFFFFFFF || *endptr != '\0') {
84 0 : if (errorp != NULL) {
85 : *errorp =
86 2 : make_error_code(boost::system::errc::invalid_argument);
87 : }
88 2 : return RouteTarget::null_rtarget;
89 : }
90 :
91 999289 : if (asn > AS2_MAX || is_as4) {
92 189 : data[0] = 0x2;
93 189 : put_value(&data[2], 4, asn);
94 : } else {
95 999100 : data[0] = 0x0;
96 999100 : put_value(&data[2], 2, asn);
97 999075 : offset = 4;
98 : }
99 999226 : data[1] = 0x2;
100 : } else {
101 153483 : data[0] = 0x1;
102 153483 : data[1] = 0x2;
103 153483 : uint32_t l_addr = addr.to_ulong();
104 153409 : put_value(&data[2], 4, l_addr);
105 : }
106 :
107 1152585 : string third(rest.substr(pos+1));
108 1151905 : uint64_t value = strtol(third.c_str(), &endptr, 10);
109 1152089 : if (*endptr != '\0') {
110 102 : if (errorp != NULL) {
111 102 : *errorp = make_error_code(boost::system::errc::invalid_argument);
112 : }
113 102 : return RouteTarget::null_rtarget;
114 : }
115 :
116 : // Check assigned number for type 0.
117 1151987 : if (offset == 4 && value > 0xFFFFFFFF) {
118 3 : if (errorp != NULL) {
119 3 : *errorp = make_error_code(boost::system::errc::invalid_argument);
120 : }
121 3 : return RouteTarget::null_rtarget;
122 : }
123 :
124 : // Check assigned number for type 1 and 2
125 1151984 : if (offset == 6 && value > 0xFFFF) {
126 6 : if (errorp != NULL) {
127 6 : *errorp = make_error_code(boost::system::errc::invalid_argument);
128 : }
129 6 : return RouteTarget::null_rtarget;
130 : }
131 :
132 1151978 : put_value(&data[offset], RouteTarget::kSize - offset, value);
133 1151887 : copy(&data[0], &data[RouteTarget::kSize], rt.data_.begin());
134 1151366 : return rt;
135 1151487 : }
136 :
137 4318116 : string RouteTarget::ToString() const {
138 : uint8_t data[RouteTarget::kSize];
139 4318116 : copy(data_.begin(), data_.end(), &data[0]);
140 4318095 : if (data[0] == 0) {
141 1207068 : uint16_t asn = get_value(data + 2, 2);
142 1207064 : uint32_t num = get_value(data + 4, 4);
143 : char temp[50];
144 1207061 : snprintf(temp, sizeof(temp), "target:%u:%u", asn, num);
145 1207061 : return string(temp);
146 3111027 : } else if (data[0] == 2) {
147 6249 : uint32_t asn = get_value(data + 2, 4);
148 6249 : uint16_t num = get_value(data + 6, 2);
149 : char temp[50];
150 6249 : if (asn > AS2_MAX)
151 6245 : snprintf(temp, sizeof(temp), "target:%u:%u", asn, num);
152 : else
153 4 : snprintf(temp, sizeof(temp), "target:%uL:%u", asn, num);
154 6249 : return string(temp);
155 : } else {
156 3104778 : Ip4Address addr(get_value(data + 2, 4));
157 3104774 : uint16_t num = get_value(data + 6, 2);
158 : char temp[50];
159 3104742 : snprintf(temp, sizeof(temp), "target:%s:%u",
160 6209508 : addr.to_string().c_str(), num);
161 3104831 : return string(temp);
162 : }
163 : }
|