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 1159450 : RouteTarget::RouteTarget() {
18 1159450 : data_.fill(0);
19 1159346 : }
20 :
21 7907745 : RouteTarget::RouteTarget(const bytes_type &data) {
22 7907745 : copy(data.begin(), data.end(), data_.begin());
23 7907339 : }
24 :
25 27381 : RouteTarget::RouteTarget(const Ip4Address &address, uint16_t num) {
26 27381 : data_[0] = 0x1;
27 27381 : data_[1] = 0x2;
28 27381 : put_value(&data_[2], 4, address.to_ulong());
29 27381 : put_value(&data_[6], 2, num);
30 27381 : }
31 :
32 62436 : const uint64_t RouteTarget::GetExtCommunityValue() const {
33 62436 : return get_value(data_.begin(), 8);
34 : }
35 :
36 1153249 : RouteTarget RouteTarget::FromString(const string &str,
37 : boost::system::error_code *errorp) {
38 1153249 : RouteTarget rt;
39 : uint8_t data[RouteTarget::kSize];
40 :
41 : // target:1:2 OR target:1.2.3.4:3
42 1153140 : size_t pos = str.find(':');
43 1153166 : 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 1153165 : string first(str.substr(0, pos));
51 1153128 : 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 1153962 : string rest(str.substr(pos+1));
59 :
60 1153681 : pos = rest.find(':');
61 1154268 : 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 1154265 : boost::system::error_code ec;
69 1154265 : string second(rest.substr(0, pos));
70 1153818 : Ip4Address addr = Ip4Address::from_string(second, ec);
71 1153718 : int offset = 6;
72 : char *endptr;
73 1153718 : if (ec.failed()) {
74 1000104 : bool is_as4 = false;
75 : // Not an IP address, try ASN.
76 1000104 : if (second.c_str()[pos - 1] == 'L') {
77 0 : is_as4 = true;
78 0 : second = second.substr(0, pos - 1);
79 : }
80 :
81 1000106 : int64_t asn = strtol(second.c_str(), &endptr, 10);
82 1000096 : 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 1000099 : if (asn > AS2_MAX || is_as4) {
91 157 : data[0] = 0x2;
92 157 : put_value(&data[2], 4, asn);
93 : } else {
94 999942 : data[0] = 0x0;
95 999942 : put_value(&data[2], 2, asn);
96 999930 : offset = 4;
97 : }
98 1000077 : data[1] = 0x2;
99 : } else {
100 153790 : data[0] = 0x1;
101 153790 : data[1] = 0x2;
102 153790 : uint32_t l_addr = addr.to_ulong();
103 153771 : put_value(&data[2], 4, l_addr);
104 : }
105 :
106 1153835 : string third(rest.substr(pos+1));
107 1153376 : uint64_t value = strtol(third.c_str(), &endptr, 10);
108 1153496 : 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 1153394 : 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 1153391 : 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 1153385 : put_value(&data[offset], RouteTarget::kSize - offset, value);
132 1153333 : copy(&data[0], &data[RouteTarget::kSize], rt.data_.begin());
133 1153098 : return rt;
134 1153219 : }
135 :
136 4317995 : string RouteTarget::ToString() const {
137 : uint8_t data[RouteTarget::kSize];
138 4317995 : copy(data_.begin(), data_.end(), &data[0]);
139 4318008 : if (data[0] == 0) {
140 1207060 : uint16_t asn = get_value(data + 2, 2);
141 1207059 : uint32_t num = get_value(data + 4, 4);
142 : char temp[50];
143 1207060 : snprintf(temp, sizeof(temp), "target:%u:%u", asn, num);
144 1207060 : return string(temp);
145 3110948 : } 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 3104699 : Ip4Address addr(get_value(data + 2, 4));
156 3104694 : uint16_t num = get_value(data + 6, 2);
157 : char temp[50];
158 3104676 : snprintf(temp, sizeof(temp), "target:%s:%u",
159 6209371 : addr.to_string().c_str(), num);
160 3104749 : return string(temp);
161 : }
162 : }
|