libbgp  0.6
A C++ BGP Library.
bgp-packet.cc
Go to the documentation of this file.
1 
11 #include "bgp-packet.h"
12 #include "bgp.h"
13 #include "value-op.h"
14 #include <string.h>
15 #include <arpa/inet.h>
16 
17 namespace libbgp {
18 
25 BgpPacket::BgpPacket(BgpLogHandler *logger, bool is_4b) : Serializable(logger) {
26  msg = NULL;
27  m_msg = NULL;
28  is_message_owner = true;
29  this->is_4b = is_4b;
30 }
31 
39 BgpPacket::BgpPacket(BgpLogHandler *logger, bool is_4b, const BgpMessage *msg) : Serializable(logger) {
40  this->msg = msg;
41  m_msg = NULL;
42  this->is_4b = is_4b;
43  is_message_owner = false;
44 }
45 
46 BgpPacket::~BgpPacket() {
47  if (m_msg != NULL && is_message_owner) delete m_msg;
48 }
49 
50 ssize_t BgpPacket::doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const {
51  ssize_t written = -1;
52 
53  if (is_message_owner) written = m_msg->print(indent, *to, *buf_sz);
54  else written = msg->print(indent, *to, *buf_sz);
55  if (written < 0) return 0;
56 
57  *to += written;
58  *buf_sz += written;
59  return written;
60 }
61 
75 ssize_t BgpPacket::parse(const uint8_t *from, size_t buf_sz) {
76  if (buf_sz < 19 && buf_sz > 4096) {
77  logger->log(ERROR, "BgpPacket::parse: got a packet with invalid size.\n");
78  return -1;
79  }
80 
81  if (!is_message_owner) {
82  logger->log(FATAL, "BgpPacket::parse: can't parse: read-only packet.\n");
83  throw "invalid_op";
84  }
85 
86  if (is_message_owner && m_msg != NULL) {
87  logger->log(FATAL, "BgpPacket::parse: can't parse: message pointer not NULL.\n");
88  throw "invalid_op";
89  }
90 
91  const uint8_t *buffer = from + 18;
92  uint8_t msg_type = getValue<uint8_t>(&buffer);
93 
94  switch (msg_type) {
95  case OPEN: m_msg = new BgpOpenMessage(logger, is_4b); break;
96  case UPDATE: m_msg = new BgpUpdateMessage(logger, is_4b); break;
97  case KEEPALIVE: m_msg = new BgpKeepaliveMessage(logger); break;
98  case NOTIFICATION: m_msg = new BgpNotificationMessage(logger); break;
99  default: m_msg = new BgpBadMessage(logger, msg_type); break;
100  }
101 
102  size_t msg_sz = buf_sz - 19;
103  ssize_t parsed_len = m_msg->parse(buffer, msg_sz);
104 
105  if (parsed_len < 0) {
106  forwardParseError(*m_msg);
107  return parsed_len;
108  }
109 
110  if (msg_sz != (size_t) parsed_len) {
111  logger->log(FATAL, "BgpPacket::parse: parsed message length invalid but no error reported.\n");
112  throw "bad_parse";
113  }
114 
115  return parsed_len + 19;
116 }
117 
128 ssize_t BgpPacket::write(uint8_t *to, size_t buf_sz) const {
129  if (is_message_owner && m_msg == NULL) {
130  logger->log(FATAL, "BgpPacket::write: can't write: message pointer NULL.\n");
131  throw "invalid_op";
132  }
133 
134  if (!is_message_owner && msg == NULL) {
135  logger->log(FATAL, "BgpPacket::write: can't write: message pointer NULL.\n");
136  throw "invalid_op";
137  }
138 
139  if (buf_sz < 19) {
140  logger->log(ERROR, "BgpPacket::write: dst buffer too small.\n");
141  return -1;
142  }
143 
144  uint8_t *buffer = to;
145  memset(buffer, '\xff', 16);
146  buffer += 16;
147 
148  // we do not know length yet, just keep a pointer to the field
149  uint8_t *pkt_len_ptr = buffer;
150  // and skip ahread.
151  buffer += 2;
152 
153  putValue<uint8_t> (&buffer, is_message_owner ? m_msg->type : msg->type);
154  ssize_t msg_len = -1;
155 
156  if (is_message_owner) msg_len = m_msg->write(buffer, buf_sz - 19);
157  else msg_len = msg->write(buffer, buf_sz - 19);
158 
159  if (msg_len < 0) return msg_len;
160 
161  size_t pkt_len = msg_len + 19;
162  putValue<uint16_t>(&pkt_len_ptr, htons(pkt_len));
163 
164  return pkt_len;
165 }
166 
173  return is_message_owner ? m_msg : msg;
174 }
175 
176 }
The BgpOpenMessage class.
BgpPacket(BgpLogHandler *logger, bool is_4b, const BgpMessage *msg)
Construct a new BgpPacket object for serializing BGP message.
Definition: bgp-packet.cc:39
ssize_t doPrint(size_t indent, uint8_t **to, size_t *buf_sz) const
Print implementation.
Definition: bgp-packet.cc:50
The BgpNotificationMessage object.
The serializable base class.
Definition: serializable.h:26
ssize_t print(uint8_t *to, size_t buf_sz) const
Print the Serializable object as human readable string.
const BgpMessage * getMessage() const
Get pointer to the contained message.
Definition: bgp-packet.cc:172
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...
ssize_t parse(const uint8_t *from, size_t buf_sz)
Deserialize a BGP message.
Definition: bgp-packet.cc:75
The BgpMessage base class.
Definition: bgp-message.h:35
Buffer operation helpers.
Top level deserialization/serialization entry point for BGP messages.
The BgpKeepaliveMessage class.
Definition: bgp-afi.h:14
The BgpLogHandler class.
The BgpBadMessage class.
virtual ssize_t write(uint8_t *to, size_t buf_sz) const =0
Serialize a BGP message body.
virtual ssize_t parse(const uint8_t *from, size_t msg_sz)=0
Deserialize a BGP message body.
void forwardParseError(const Serializable &other)
Forward error information from other Serializable object.
Definition: serializable.cc:97
ssize_t write(uint8_t *to, size_t buf_sz) const
Serialize a BGP message.
Definition: bgp-packet.cc:128
BGP protocol serializers/deserializers.
The BgpUpdateMessage class.