Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/extended-community/site_of_origin.h"
6 :
7 : #include <algorithm>
8 :
9 : #include "base/address.h"
10 : #include "bgp/bgp_common.h"
11 :
12 : using std::copy;
13 : using std::string;
14 :
15 : SiteOfOrigin SiteOfOrigin::null_soo;
16 :
17 37602 : SiteOfOrigin::SiteOfOrigin() {
18 37602 : data_.fill(0);
19 37602 : }
20 :
21 347 : SiteOfOrigin::SiteOfOrigin(const bytes_type &data) {
22 347 : copy(data.begin(), data.end(), data_.begin());
23 347 : }
24 :
25 24 : string SiteOfOrigin::ToString() const {
26 : uint8_t data[SiteOfOrigin::kSize];
27 24 : copy(data_.begin(), data_.end(), &data[0]);
28 24 : if (data[0] == 0) {
29 8 : uint16_t asn = get_value(data + 2, 2);
30 8 : uint32_t num = get_value(data + 4, 4);
31 : char temp[50];
32 8 : snprintf(temp, sizeof(temp), "soo:%u:%u", asn, num);
33 8 : return string(temp);
34 16 : } else if (data[0] == 2) {
35 8 : uint32_t asn = get_value(data + 2, 4);
36 8 : uint16_t num = get_value(data + 6, 2);
37 : char temp[50];
38 8 : snprintf(temp, sizeof(temp), "soo:%u:%u", asn, num);
39 8 : return string(temp);
40 : } else {
41 8 : Ip4Address addr(get_value(data + 2, 4));
42 8 : uint16_t num = get_value(data + 6, 2);
43 : char temp[50];
44 8 : snprintf(temp, sizeof(temp), "soo:%s:%u",
45 16 : addr.to_string().c_str(), num);
46 8 : return string(temp);
47 : }
48 : }
49 :
50 73 : SiteOfOrigin SiteOfOrigin::FromString(const string &str,
51 : boost::system::error_code *errorp) {
52 73 : SiteOfOrigin soo;
53 : uint8_t data[SiteOfOrigin::kSize];
54 :
55 : // soo:1:2 OR soo:1.2.3.4:3
56 73 : size_t pos = str.find(':');
57 73 : if (pos == string::npos) {
58 1 : if (errorp != NULL) {
59 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
60 : }
61 1 : return SiteOfOrigin::null_soo;
62 : }
63 :
64 72 : string first(str.substr(0, pos));
65 72 : if (first != "soo") {
66 3 : if (errorp != NULL) {
67 3 : *errorp = make_error_code(boost::system::errc::invalid_argument);
68 : }
69 3 : return SiteOfOrigin::null_soo;
70 : }
71 :
72 69 : string rest(str.substr(pos+1));
73 :
74 69 : pos = rest.find(':');
75 69 : if (pos == string::npos) {
76 1 : if (errorp != NULL) {
77 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
78 : }
79 1 : return SiteOfOrigin::null_soo;
80 : }
81 :
82 68 : boost::system::error_code ec;
83 68 : string second(rest.substr(0, pos));
84 68 : Ip4Address addr = Ip4Address::from_string(second, ec);
85 : int offset;
86 : char *endptr;
87 68 : if (ec.failed()) {
88 : // Not an IP address. Try ASN
89 61 : int64_t asn = strtol(second.c_str(), &endptr, 10);
90 61 : if (asn == 0 || asn > 0xFFFFFFFF || *endptr != '\0') {
91 2 : if (errorp != NULL) {
92 : *errorp =
93 2 : make_error_code(boost::system::errc::invalid_argument);
94 : }
95 2 : return SiteOfOrigin::null_soo;
96 : }
97 :
98 59 : if (asn > AS2_MAX) {
99 4 : data[0] = BgpExtendedCommunityType::FourOctetAS;
100 4 : put_value(&data[2], 4, asn);
101 4 : offset = 6;
102 : } else {
103 55 : data[0] = BgpExtendedCommunityType::TwoOctetAS;
104 55 : put_value(&data[2], 2, asn);
105 55 : offset = 4;
106 : }
107 59 : data[1] = BgpExtendedCommunitySubType::RouteOrigin;
108 : } else {
109 7 : data[0] = BgpExtendedCommunityType::IPv4Address;
110 7 : data[1] = BgpExtendedCommunitySubType::RouteOrigin;
111 7 : uint32_t l_addr = addr.to_ulong();
112 7 : put_value(&data[2], 4, l_addr);
113 7 : offset = 6;
114 : }
115 :
116 66 : string third(rest.substr(pos+1));
117 66 : uint64_t value = strtol(third.c_str(), &endptr, 10);
118 66 : if (*endptr != '\0') {
119 4 : if (errorp != NULL) {
120 4 : *errorp = make_error_code(boost::system::errc::invalid_argument);
121 : }
122 4 : return SiteOfOrigin::null_soo;
123 : }
124 :
125 : // Check assigned number for type 0.
126 62 : if (offset == 4 && value > 0xFFFFFFFF) {
127 1 : if (errorp != NULL) {
128 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
129 : }
130 1 : return SiteOfOrigin::null_soo;
131 : }
132 :
133 : // Check assigned number for type 1.
134 61 : if (offset == 6 && value > 0xFFFF) {
135 1 : if (errorp != NULL) {
136 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
137 : }
138 1 : return SiteOfOrigin::null_soo;
139 : }
140 :
141 60 : put_value(&data[offset], SiteOfOrigin::kSize - offset, value);
142 60 : copy(&data[0], &data[SiteOfOrigin::kSize], soo.data_.begin());
143 60 : return soo;
144 72 : }
|