Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/rtarget/rtarget_address.h"
6 :
7 : #include <algorithm>
8 :
9 : #include "base/parse_object.h"
10 : #include "bgp/bgp_common.h"
11 :
12 : using std::copy;
13 : using std::string;
14 :
15 : RouteTarget RouteTarget::null_rtarget;
16 :
17 1159497 : RouteTarget::RouteTarget() {
18 1159497 : data_.fill(0);
19 1159368 : }
20 :
21 7951153 : RouteTarget::RouteTarget(const bytes_type &data) {
22 7951153 : copy(data.begin(), data.end(), data_.begin());
23 7950737 : }
24 :
25 27370 : RouteTarget::RouteTarget(const Ip4Address &address, uint16_t num) {
26 27370 : data_[0] = 0x1;
27 27370 : data_[1] = 0x2;
28 27370 : put_value(&data_[2], 4, address.to_ulong());
29 27370 : put_value(&data_[6], 2, num);
30 27370 : }
31 :
32 62774 : const uint64_t RouteTarget::GetExtCommunityValue() const {
33 62774 : return get_value(data_.begin(), 8);
34 : }
35 :
36 1153323 : RouteTarget RouteTarget::FromString(const string &str,
37 : boost::system::error_code *errorp) {
38 1153323 : RouteTarget rt;
39 : uint8_t data[RouteTarget::kSize];
40 :
41 : // target:1:2 OR target:1.2.3.4:3
42 1153216 : size_t pos = str.find(':');
43 1153238 : if (pos == string::npos) {
44 1 : if (errorp != NULL) {
45 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
46 : }
47 1 : return RouteTarget::null_rtarget;
48 : }
49 :
50 1153237 : string first(str.substr(0, pos));
51 1153213 : if (first != "target") {
52 5 : if (errorp != NULL) {
53 5 : *errorp = make_error_code(boost::system::errc::invalid_argument);
54 : }
55 5 : return RouteTarget::null_rtarget;
56 : }
57 :
58 1154077 : string rest(str.substr(pos+1));
59 :
60 1153793 : pos = rest.find(':');
61 1154259 : if (pos == string::npos) {
62 3 : if (errorp != NULL) {
63 3 : *errorp = make_error_code(boost::system::errc::invalid_argument);
64 : }
65 3 : return RouteTarget::null_rtarget;
66 : }
67 :
68 1154256 : boost::system::error_code ec;
69 1154256 : string second(rest.substr(0, pos));
70 1153943 : Ip4Address addr = Ip4Address::from_string(second, ec);
71 1153797 : int offset = 6;
72 : char *endptr;
73 1153797 : if (ec.failed()) {
74 1000187 : bool is_as4 = false;
75 : // Not an IP address, try ASN.
76 1000187 : if (second.c_str()[pos - 1] == 'L') {
77 0 : is_as4 = true;
78 0 : second = second.substr(0, pos - 1);
79 : }
80 :
81 1000185 : int64_t asn = strtol(second.c_str(), &endptr, 10);
82 1000175 : if (asn == 0 || asn > 0xFFFFFFFF || *endptr != '\0') {
83 0 : if (errorp != NULL) {
84 : *errorp =
85 2 : make_error_code(boost::system::errc::invalid_argument);
86 : }
87 2 : return RouteTarget::null_rtarget;
88 : }
89 :
90 1000175 : if (asn > AS2_MAX || is_as4) {
91 158 : data[0] = 0x2;
92 158 : put_value(&data[2], 4, asn);
93 : } else {
94 1000017 : data[0] = 0x0;
95 1000017 : put_value(&data[2], 2, asn);
96 999997 : offset = 4;
97 : }
98 1000144 : data[1] = 0x2;
99 : } else {
100 153810 : data[0] = 0x1;
101 153810 : data[1] = 0x2;
102 153810 : uint32_t l_addr = addr.to_ulong();
103 153773 : put_value(&data[2], 4, l_addr);
104 : }
105 :
106 1153899 : string third(rest.substr(pos+1));
107 1153389 : uint64_t value = strtol(third.c_str(), &endptr, 10);
108 1153488 : if (*endptr != '\0') {
109 102 : if (errorp != NULL) {
110 102 : *errorp = make_error_code(boost::system::errc::invalid_argument);
111 : }
112 102 : return RouteTarget::null_rtarget;
113 : }
114 :
115 : // Check assigned number for type 0.
116 1153386 : if (offset == 4 && value > 0xFFFFFFFF) {
117 3 : if (errorp != NULL) {
118 3 : *errorp = make_error_code(boost::system::errc::invalid_argument);
119 : }
120 3 : return RouteTarget::null_rtarget;
121 : }
122 :
123 : // Check assigned number for type 1 and 2
124 1153383 : if (offset == 6 && value > 0xFFFF) {
125 6 : if (errorp != NULL) {
126 6 : *errorp = make_error_code(boost::system::errc::invalid_argument);
127 : }
128 6 : return RouteTarget::null_rtarget;
129 : }
130 :
131 1153377 : put_value(&data[offset], RouteTarget::kSize - offset, value);
132 1153311 : copy(&data[0], &data[RouteTarget::kSize], rt.data_.begin());
133 1153052 : return rt;
134 1153173 : }
135 :
136 4317810 : string RouteTarget::ToString() const {
137 : uint8_t data[RouteTarget::kSize];
138 4317810 : copy(data_.begin(), data_.end(), &data[0]);
139 4317834 : if (data[0] == 0) {
140 1206928 : uint16_t asn = get_value(data + 2, 2);
141 1206943 : uint32_t num = get_value(data + 4, 4);
142 : char temp[50];
143 1206940 : snprintf(temp, sizeof(temp), "target:%u:%u", asn, num);
144 1206940 : return string(temp);
145 3110906 : } else if (data[0] == 2) {
146 6249 : uint32_t asn = get_value(data + 2, 4);
147 6249 : uint16_t num = get_value(data + 6, 2);
148 : char temp[50];
149 6249 : if (asn > AS2_MAX)
150 6245 : snprintf(temp, sizeof(temp), "target:%u:%u", asn, num);
151 : else
152 4 : snprintf(temp, sizeof(temp), "target:%uL:%u", asn, num);
153 6249 : return string(temp);
154 : } else {
155 3104657 : Ip4Address addr(get_value(data + 2, 4));
156 3104650 : uint16_t num = get_value(data + 6, 2);
157 : char temp[50];
158 3104661 : snprintf(temp, sizeof(temp), "target:%s:%u",
159 6209315 : addr.to_string().c_str(), num);
160 3104704 : return string(temp);
161 : }
162 : }
|