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 1158006 : RouteTarget::RouteTarget() {
18 1158006 : data_.fill(0);
19 1157805 : }
20 :
21 8140362 : RouteTarget::RouteTarget(const bytes_type &data) {
22 8140362 : copy(data.begin(), data.end(), data_.begin());
23 8140279 : }
24 :
25 27414 : RouteTarget::RouteTarget(const Ip4Address &address, uint16_t num) {
26 27414 : data_[0] = 0x1;
27 27414 : data_[1] = 0x2;
28 27414 : put_value(&data_[2], 4, address.to_ulong());
29 27414 : put_value(&data_[6], 2, num);
30 27414 : }
31 :
32 62983 : const uint64_t RouteTarget::GetExtCommunityValue() const {
33 62983 : return get_value(data_.begin(), 8);
34 : }
35 :
36 1151938 : RouteTarget RouteTarget::FromString(const string &str,
37 : boost::system::error_code *errorp) {
38 1151938 : RouteTarget rt;
39 : uint8_t data[RouteTarget::kSize];
40 :
41 : // target:1:2 OR target:1.2.3.4:3
42 1151700 : size_t pos = str.find(':');
43 1151746 : 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 1151745 : string first(str.substr(0, pos));
51 1151689 : 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 1152766 : string rest(str.substr(pos+1));
59 :
60 1152338 : pos = rest.find(':');
61 1153440 : 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 1153437 : boost::system::error_code ec;
69 1153437 : string second(rest.substr(0, pos));
70 1152561 : Ip4Address addr = Ip4Address::from_string(second, ec);
71 1152575 : int offset = 6;
72 : char *endptr;
73 1152575 : if (ec.failed()) {
74 999216 : bool is_as4 = false;
75 : // Not an IP address, try ASN.
76 999216 : if (second.c_str()[pos - 1] == 'L') {
77 0 : is_as4 = true;
78 0 : second = second.substr(0, pos - 1);
79 : }
80 :
81 999215 : int64_t asn = strtol(second.c_str(), &endptr, 10);
82 999204 : 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 999214 : if (asn > AS2_MAX || is_as4) {
91 181 : data[0] = 0x2;
92 181 : put_value(&data[2], 4, asn);
93 : } else {
94 999033 : data[0] = 0x0;
95 999033 : put_value(&data[2], 2, asn);
96 999003 : offset = 4;
97 : }
98 999146 : data[1] = 0x2;
99 : } else {
100 153504 : data[0] = 0x1;
101 153504 : data[1] = 0x2;
102 153504 : uint32_t l_addr = addr.to_ulong();
103 153448 : put_value(&data[2], 4, l_addr);
104 : }
105 :
106 1152564 : string third(rest.substr(pos+1));
107 1151995 : uint64_t value = strtol(third.c_str(), &endptr, 10);
108 1152119 : 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 1152017 : 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 1152014 : 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 1152008 : put_value(&data[offset], RouteTarget::kSize - offset, value);
132 1151926 : copy(&data[0], &data[RouteTarget::kSize], rt.data_.begin());
133 1151475 : return rt;
134 1151596 : }
135 :
136 4317596 : string RouteTarget::ToString() const {
137 : uint8_t data[RouteTarget::kSize];
138 4317596 : copy(data_.begin(), data_.end(), &data[0]);
139 4317651 : if (data[0] == 0) {
140 1206697 : uint16_t asn = get_value(data + 2, 2);
141 1206693 : uint32_t num = get_value(data + 4, 4);
142 : char temp[50];
143 1206694 : snprintf(temp, sizeof(temp), "target:%u:%u", asn, num);
144 1206694 : return string(temp);
145 3110954 : } 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 3104705 : Ip4Address addr(get_value(data + 2, 4));
156 3104696 : uint16_t num = get_value(data + 6, 2);
157 : char temp[50];
158 3104632 : snprintf(temp, sizeof(temp), "target:%s:%u",
159 6209332 : addr.to_string().c_str(), num);
160 3104776 : return string(temp);
161 : }
162 : }
|