15 #include <arpa/inet.h> 28 this->use_4b_asn = use_4b_asn;
31 BgpOpenMessage::~BgpOpenMessage() { }
44 this->my_asn = my_asn;
45 this->hold_time = hold_time;
46 this->bgp_id = bgp_id;
47 this->use_4b_asn = use_4b_asn;
48 if (use_4b_asn)
setAsn(my_asn);
62 this->my_asn = my_asn;
63 this->hold_time = hold_time;
64 this->use_4b_asn = use_4b_asn;
65 if (use_4b_asn)
setAsn(my_asn);
66 inet_pton(AF_INET, bgp_id, &(this->bgp_id));
81 uint8_t _err_data = msg_sz;
82 setError(E_HEADER, E_LENGTH, &_err_data,
sizeof(uint8_t));
83 logger->
log(ERROR,
"BgpOpenMessage::parse: invalid open message size: %d.\n", msg_sz);
87 const uint8_t *buffer = from;
89 version = getValue<uint8_t> (&buffer);
90 my_asn = ntohs(getValue<uint16_t> (&buffer));
91 hold_time = ntohs(getValue<uint16_t> (&buffer));
92 bgp_id = getValue<uint32_t> (&buffer);
94 uint8_t opt_params_len = getValue<uint8_t> (&buffer);
97 if (opt_params_len != msg_sz - 10 || (opt_params_len < 2 && opt_params_len != 0)) {
98 setError(E_OPEN, E_UNSPEC_OPEN, NULL, 0);
99 if (opt_params_len + 10 != (uint8_t) msg_sz)
100 logger->
log(ERROR,
"BgpOpenMessage::parse: size of rest of message (%d) != length of opt_param (%d).\n", msg_sz - 10, opt_params_len);
101 if (opt_params_len < 2)
102 logger->
log(ERROR,
"BgpOpenMessage::parse: opt params size < 2: %d.\n", opt_params_len);
106 uint8_t parsed_opt_params_len = 0;
107 uint8_t opt_params_len_left = 0;
109 while ((opt_params_len_left = opt_params_len - parsed_opt_params_len) > 0) {
110 if (opt_params_len_left < 2) {
111 setError(E_OPEN, E_UNSPEC_OPEN, NULL, 0);
112 logger->
log(ERROR,
"BgpOpenMessage::parse: unexpected end of opt param list.\n");
116 uint8_t param_type = getValue<uint8_t> (&buffer);
117 uint8_t param_length = getValue<uint8_t> (&buffer);
120 parsed_opt_params_len += 2;
123 if (parsed_opt_params_len + param_length > opt_params_len) {
124 setError(E_OPEN, E_UNSPEC_OPEN, NULL, 0);
125 logger->
log(ERROR,
"BgpOpenMessage::parse: opt param size exceed opt_params_len.\n");
130 if (param_type != 2) {
131 setError(E_OPEN, E_OPT_PARAM, NULL, 0);
132 logger->
log(ERROR,
"BgpOpenMessage::parse: unknow opt param type: %d.\n", param_type);
137 if (param_length < 2) {
138 setError(E_OPEN, E_UNSPEC_OPEN, NULL, 0);
139 logger->
log(ERROR,
"BgpOpenMessage::parse: invalid capability opt param length: %d.\n", param_length);
143 uint8_t parsed_capa_param_len = 0;
144 uint8_t capa_param_left = 0;
146 while ((capa_param_left = param_length - parsed_capa_param_len) > 0) {
147 if (capa_param_left < 2) {
148 setError(E_OPEN, E_UNSPEC_OPEN, NULL, 0);
149 logger->
log(ERROR,
"BgpOpenMessage::parse: unexpected end of capa list.\n");
153 const uint8_t *capa_ptr = buffer;
154 uint8_t capa_code = getValue<uint8_t> (&buffer);
155 uint8_t capa_len = getValue<uint8_t> (&buffer);
165 ssize_t capa_parsed_len = cap->parse(capa_ptr, capa_len + 2);
167 if (capa_parsed_len < 0) {
173 if (capa_parsed_len != capa_len + 2) {
174 logger->
log(FATAL,
"BgpOpenMessage::parse: parsed capability length mismatch but no error reported.\n");
178 capabilities.push_back(std::shared_ptr<BgpCapability> (cap));
179 parsed_capa_param_len += capa_parsed_len;
180 buffer += capa_parsed_len - 2;
183 if (parsed_capa_param_len != param_length) {
184 logger->
log(FATAL,
"BgpOpenMessage::parse: parsed capabilities length mismatch but no error reported.\n");
188 parsed_opt_params_len += parsed_capa_param_len;
191 if (parsed_opt_params_len != opt_params_len) {
192 logger->
log(FATAL,
"BgpOpenMessage::parse: parsed opt params length mismatch but no error reported.\n");
196 if ((
size_t) (parsed_opt_params_len + 10) != msg_sz) {
197 logger->
log(ERROR,
"BgpOpenMessage::parse: buffer does not end after parsing finished.\n");
198 setError(E_OPEN, E_UNSPEC, NULL, 0);
202 return parsed_opt_params_len + 10;
207 logger->
log(ERROR,
"BgpOpenMessage::write: buffer size too small (need 10, avaliable %d).\n", buf_sz);
211 uint8_t *buffer = to;
213 putValue<uint8_t>(&buffer, version);
214 putValue<uint16_t>(&buffer, htons(my_asn));
215 putValue<uint16_t>(&buffer, htons(hold_time));
216 putValue<uint32_t>(&buffer, bgp_id);
218 if (capabilities.size() == 0) {
219 putValue<uint8_t>(&buffer, 0);
223 uint8_t *params_len_ptr = buffer;
228 logger->
log(ERROR,
"BgpOpenMessage::write: buffer size too small.\n", buf_sz);
232 size_t opt_params_len = 2;
234 putValue<uint8_t>(&buffer, 2);
236 uint8_t *param_len_ptr = buffer;
239 size_t opt_param_len = 0;
240 for (
const std::shared_ptr<BgpCapability> &capa : capabilities) {
241 ssize_t capa_wrt_ret = capa->write(buffer, buf_sz - opt_params_len - 10);
242 if (capa_wrt_ret < 0) {
246 opt_param_len += capa_wrt_ret;
247 buffer += capa_wrt_ret;
250 putValue<uint8_t>(¶m_len_ptr, opt_param_len);
252 opt_params_len += opt_param_len;
253 putValue<uint8_t>(¶ms_len_ptr, opt_params_len);
255 return opt_params_len + 10;
260 written +=
_print(indent, to, buf_left,
"OpenMessage {\n");
263 written +=
_print(indent, to, buf_left,
"Version { %d }\n", version);
264 written +=
_print(indent, to, buf_left,
"MyAsn { %d }\n", my_asn);
265 written +=
_print(indent, to, buf_left,
"BgpId { %s }\n", inet_ntoa(*(
const struct in_addr*) &bgp_id));
266 written +=
_print(indent, to, buf_left,
"HoldTimer { %d }\n", hold_time);
267 if (capabilities.size() == 0) written +=
_print(indent, to, buf_left,
"Capabilities { }\n");
269 _print(indent, to, buf_left,
"Capabilities {\n");
271 for (
const std::shared_ptr<BgpCapability> &capa : capabilities) {
272 ssize_t capa_written = capa->print(indent, *to, *buf_left);
273 if (capa_written < 0)
return capa_written;
275 *buf_left -= capa_written;
276 written += capa_written;
279 _print(indent, to, buf_left,
"}\n");
283 written +=
_print(indent, to, buf_left,
"}\n");
297 if (!use_4b_asn)
return my_asn;
299 for (
const std::shared_ptr<BgpCapability> &capa : capabilities) {
300 if (capa->code == ASN_4B) {
320 this->my_asn = my_asn >= 0xffff ? 23456 : my_asn;
322 if (!use_4b_asn)
return true;
324 for (std::shared_ptr<BgpCapability> &capa : capabilities) {
325 if (capa->code == ASN_4B) {
335 capabilities.push_back(std::shared_ptr<BgpCapability>(as4_cap));
348 for (
const std::shared_ptr<BgpCapability> cap : capabilities) {
349 if (cap->code == code)
return true;
372 capabilities.push_back(capability);
ssize_t parse(const uint8_t *from, size_t msg_sz)
Parse a BGP open message body.
bool setAsn(uint32_t my_asn)
Set ASN.
The BgpOpenMessage class.
The BgpCapabilityMpBgp class.
The BgpCapabilityUnknow class.
The BgpCapability base class.
static ssize_t _print(size_t indent, uint8_t **to, size_t *buf_left, const char *format,...)
Print helper.
BgpOpenMessage(BgpLogHandler *logger, bool use_4b_asn)
Construct a new Bgp Open Message:: Bgp Open Message object.
The BgpCapability4BytesAsn class.
void log(LogLevel level, const char *format_str,...)
Log a message. Consider using LIBBGP_LOG if logging the message needs a lot of computing power...
const std::vector< std::shared_ptr< BgpCapability > > & getCapabilities() const
Get capabilities list.
The BgpMessage base class.
void setError(uint8_t err, uint8_t suberr, const uint8_t *data, size_t data_len)
Set the error information.
Buffer operation helpers.
ssize_t write(uint8_t *to, size_t buf_sz) const
Serialize a BGP message body.
bool hasCapability(uint8_t code) const
Check if open message has a capability.
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
uint32_t getAsn() const
Get ASN.
void forwardParseError(const Serializable &other)
Forward error information from other Serializable object.
bool addCapability(std::shared_ptr< BgpCapability > capability)
Add a capability.