/* For debugging only, will be removed */
-void api_opaque_lsa_print(struct lsa_header *data)
+void api_opaque_lsa_print(struct ospf_lsa *lsa)
{
struct opaque_lsa {
struct lsa_header header;
int opaquelen;
int i;
- ospf_lsa_header_dump(data);
+ ospf_lsa_header_dump(lsa->data);
- olsa = (struct opaque_lsa *)data;
+ olsa = (struct opaque_lsa *)lsa->data;
- opaquelen = ntohs(data->length) - OSPF_LSA_HEADER_SIZE;
+ opaquelen = lsa->size - OSPF_LSA_HEADER_SIZE;
zlog_debug("apiserver_lsa_print: opaquelen=%d", opaquelen);
for (i = 0; i < opaquelen; i++) {
struct msg *msg_dup(struct msg *msg)
{
struct msg *new;
+ size_t size;
assert(msg);
+ size = ntohs(msg->hdr.msglen);
+ if (size > OSPF_MAX_LSA_SIZE)
+ return NULL;
+
new = msg_new(msg->hdr.msgtype, STREAM_DATA(msg->s),
- ntohl(msg->hdr.msgseq), ntohs(msg->hdr.msglen));
+ ntohl(msg->hdr.msgseq), size);
return new;
}
}
/* Allocate new message */
- msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), ntohs(hdr.msglen));
+ msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), bodylen);
return msg;
}
int msg_write(int fd, struct msg *msg)
{
uint8_t buf[OSPF_API_MAX_MSG_SIZE];
- int l;
+ uint16_t l;
int wlen;
assert(msg);
assert(msg->s);
- /* Length of message including header */
- l = sizeof(struct apimsghdr) + ntohs(msg->hdr.msglen);
+ /* Length of OSPF LSA payload */
+ l = ntohs(msg->hdr.msglen);
+ if (l > OSPF_MAX_LSA_SIZE) {
+ zlog_warn("%s: wrong LSA size %d", __func__, l);
+ return -1;
+ }
/* Make contiguous memory buffer for message */
memcpy(buf, &msg->hdr, sizeof(struct apimsghdr));
- memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s),
- ntohs(msg->hdr.msglen));
+ memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), l);
+ /* Total length of OSPF API Message */
+ l += sizeof(struct apimsghdr);
wlen = writen(fd, buf, l);
if (wlen < 0) {
- zlog_warn("msg_write: writen %s", safe_strerror(errno));
+ zlog_warn("%s: writen %s", __func__, safe_strerror(errno));
return -1;
} else if (wlen == 0) {
- zlog_warn("msg_write: Connection closed by peer");
+ zlog_warn("%s: Connection closed by peer", __func__);
return -1;
} else if (wlen != l) {
- zlog_warn("msg_write: Cannot write API message");
+ zlog_warn("%s: Cannot write API message", __func__);
return -1;
}
return 0;
*/
/* For debugging only. */
-extern void api_opaque_lsa_print(struct lsa_header *data);
+extern void api_opaque_lsa_print(struct ospf_lsa *lsa);
/* Messages sent by client */
extern struct msg *new_msg_register_opaque_type(uint32_t seqnum, uint8_t ltype,
struct msg_register_event *rmsg;
int rc;
uint32_t seqnum;
+ size_t size;
rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
/* Free existing filter in apiserv. */
XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
/* Alloc new space for filter. */
+ size = ntohs(msg->hdr.msglen);
+ if (size < OSPF_MAX_LSA_SIZE) {
- apiserv->filter =
- XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen));
+ apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size);
- /* copy it over. */
- memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen));
- rc = OSPF_API_OK;
+ /* copy it over. */
+ memcpy(apiserv->filter, &rmsg->filter, size);
+ rc = OSPF_API_OK;
+ } else
+ rc = OSPF_API_NOMEMORY;
/* Send a reply back to client with return code */
rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);
static void ospf_packet_hello_dump(struct stream *s, uint16_t length)
{
struct ospf_hello *hello;
- int i;
+ int i, len;
hello = (struct ospf_hello *)stream_pnt(s);
zlog_debug(" DRouter %pI4", &hello->d_router);
zlog_debug(" BDRouter %pI4", &hello->bd_router);
- length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE;
- zlog_debug(" # Neighbors %d", length / 4);
- for (i = 0; length > 0; i++, length -= sizeof(struct in_addr))
+ len = length - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE;
+ zlog_debug(" # Neighbors %d", len / 4);
+ for (i = 0; len > 0; i++, len -= sizeof(struct in_addr))
zlog_debug(" Neighbor %pI4", &hello->neighbors[i]);
}
{
char buf[BUFSIZ];
struct router_lsa *rl;
- int i, len;
+ struct router_link *rlnk;
+ int i, len, sum;
rl = (struct router_lsa *)stream_pnt(s);
ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ));
zlog_debug(" # links %d", ntohs(rl->links));
- len = ntohs(rl->header.length) - OSPF_LSA_HEADER_SIZE - 4;
- for (i = 0; len > 0; i++) {
- zlog_debug(" Link ID %pI4", &rl->link[i].link_id);
- zlog_debug(" Link Data %pI4",
- &rl->link[i].link_data);
- zlog_debug(" Type %d", (uint8_t)rl->link[i].type);
- zlog_debug(" TOS %d", (uint8_t)rl->link[i].tos);
- zlog_debug(" metric %d", ntohs(rl->link[i].metric));
-
- len -= 12;
+ len = length - OSPF_LSA_HEADER_SIZE - 4;
+ rlnk = &rl->link[0];
+ sum = 0;
+ for (i = 0; sum < len && rlnk; sum += 12, rlnk = &rl->link[++i]) {
+ zlog_debug(" Link ID %pI4", &rlnk->link_id);
+ zlog_debug(" Link Data %pI4", &rlnk->link_data);
+ zlog_debug(" Type %d", (uint8_t)rlnk->type);
+ zlog_debug(" TOS %d", (uint8_t)rlnk->tos);
+ zlog_debug(" metric %d", ntohs(rlnk->metric));
}
}
struct network_lsa *nl;
int i, cnt;
+ zlog_debug(" Network-LSA");
+
nl = (struct network_lsa *)stream_pnt(s);
- cnt = (ntohs(nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
+ cnt = (length - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
- zlog_debug(" Network-LSA");
/*
zlog_debug ("LSA total size %d", ntohs (nl->header.length));
zlog_debug ("Network-LSA size %d",
static void ospf_summary_lsa_dump(struct stream *s, uint16_t length)
{
struct summary_lsa *sl;
- int size;
- int i;
sl = (struct summary_lsa *)stream_pnt(s);
zlog_debug(" Summary-LSA");
zlog_debug(" Network Mask %pI4", &sl->mask);
-
- size = ntohs(sl->header.length) - OSPF_LSA_HEADER_SIZE - 4;
- for (i = 0; size > 0; size -= 4, i++)
- zlog_debug(" TOS=%d metric %d", sl->tos,
- GET_METRIC(sl->metric));
+ zlog_debug(" TOS=%d metric %d", sl->tos, GET_METRIC(sl->metric));
}
static void ospf_as_external_lsa_dump(struct stream *s, uint16_t length)
{
struct as_external_lsa *al;
- int size;
+ struct as_route *asr;
+ int size, sum;
int i;
al = (struct as_external_lsa *)stream_pnt(s);
zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str);
zlog_debug(" Network Mask %pI4", &al->mask);
- size = ntohs(al->header.length) - OSPF_LSA_HEADER_SIZE - 4;
- for (i = 0; size > 0; size -= 12, i++) {
+ size = length - OSPF_LSA_HEADER_SIZE - 4;
+ asr = &al->e[0];
+ sum = 0;
+ for (i = 0; sum < size && asr; sum += 12, asr = &al->e[++i]) {
zlog_debug(" bit %s TOS=%d metric %d",
- IS_EXTERNAL_METRIC(al->e[i].tos) ? "E" : "-",
- al->e[i].tos & 0x7f, GET_METRIC(al->e[i].metric));
- zlog_debug(" Forwarding address %pI4",
- &al->e[i].fwd_addr);
+ IS_EXTERNAL_METRIC(asr->tos) ? "E" : "-",
+ asr->tos & 0x7f, GET_METRIC(asr->metric));
+ zlog_debug(" Forwarding address %pI4", &asr->fwd_addr);
zlog_debug(" External Route Tag %" ROUTE_TAG_PRI,
- al->e[i].route_tag);
+ asr->route_tag);
}
}
static void ospf_lsa_header_list_dump(struct stream *s, uint16_t length)
{
struct lsa_header *lsa;
+ int len;
zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE);
/* LSA Headers. */
- while (length > 0) {
+ len = length;
+ while (len > 0) {
lsa = (struct lsa_header *)stream_pnt(s);
ospf_lsa_header_dump(lsa);
stream_forward_getp(s, OSPF_LSA_HEADER_SIZE);
- length -= OSPF_LSA_HEADER_SIZE;
+ len -= OSPF_LSA_HEADER_SIZE;
}
}
uint32_t ls_type;
struct in_addr ls_id;
struct in_addr adv_router;
+ int sum;
sp = stream_get_getp(s);
zlog_debug("Link State Request");
zlog_debug(" # Requests %d", length / 12);
- for (; length > 0; length -= 12) {
+ sum = 0;
+ for (; sum < length; sum += 12) {
ls_type = stream_getl(s);
ls_id.s_addr = stream_get_ipv4(s);
adv_router.s_addr = stream_get_ipv4(s);
{
uint32_t sp;
struct lsa_header *lsa;
- int lsa_len;
+ int lsa_len, len;
uint32_t count;
- length -= OSPF_HEADER_SIZE;
+ len = length - OSPF_HEADER_SIZE;
sp = stream_get_getp(s);
count = stream_getl(s);
- length -= 4;
+ len -= 4;
zlog_debug("Link State Update");
zlog_debug(" # LSAs %d", count);
- while (length > 0 && count > 0) {
- if (length < OSPF_HEADER_SIZE || length % 4 != 0) {
+ while (len > 0 && count > 0) {
+ if ((uint16_t)len < OSPF_LSA_HEADER_SIZE || len % 4 != 0) {
zlog_debug(" Remaining %d bytes; Incorrect length.",
- length);
+ len);
break;
}
lsa_len = ntohs(lsa->length);
ospf_lsa_header_dump(lsa);
+ /* Check that LSA length is valid */
+ if (lsa_len > len || lsa_len % 4 != 0) {
+ zlog_debug(" LSA length %d is incorrect!", lsa_len);
+ break;
+ }
switch (lsa->type) {
case OSPF_ROUTER_LSA:
- ospf_router_lsa_dump(s, length);
+ ospf_router_lsa_dump(s, lsa_len);
break;
case OSPF_NETWORK_LSA:
- ospf_network_lsa_dump(s, length);
+ ospf_network_lsa_dump(s, lsa_len);
break;
case OSPF_SUMMARY_LSA:
case OSPF_ASBR_SUMMARY_LSA:
- ospf_summary_lsa_dump(s, length);
+ ospf_summary_lsa_dump(s, lsa_len);
break;
case OSPF_AS_EXTERNAL_LSA:
- ospf_as_external_lsa_dump(s, length);
+ ospf_as_external_lsa_dump(s, lsa_len);
break;
case OSPF_AS_NSSA_LSA:
- ospf_as_external_lsa_dump(s, length);
+ ospf_as_external_lsa_dump(s, lsa_len);
break;
case OSPF_OPAQUE_LINK_LSA:
case OSPF_OPAQUE_AREA_LSA:
case OSPF_OPAQUE_AS_LSA:
- ospf_opaque_lsa_dump(s, length);
+ ospf_opaque_lsa_dump(s, lsa_len);
break;
default:
break;
}
stream_forward_getp(s, lsa_len);
- length -= lsa_len;
+ len -= lsa_len;
count--;
}
* ------------------------------------
*/
+#define check_tlv_size(size, msg) \
+ do { \
+ if (ntohs(tlvh->length) != size) { \
+ vty_out(vty, " Wrong %s TLV size: %d(%d). Abort!\n", \
+ msg, ntohs(tlvh->length), size); \
+ return size + TLV_HDR_SIZE; \
+ } \
+ } while (0)
+
/* Cisco experimental SubTLV */
static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty,
struct tlv_header *tlvh)
{
- struct ext_subtlv_rmt_itf_addr *top;
+ struct ext_subtlv_rmt_itf_addr *top =
+ (struct ext_subtlv_rmt_itf_addr *)tlvh;
- top = (struct ext_subtlv_rmt_itf_addr *)tlvh;
+ check_tlv_size(EXT_SUBTLV_RMT_ITF_ADDR_SIZE, "Remote Itf. Address");
vty_out(vty,
" Remote Interface Address Sub-TLV: Length %u\n Address: %pI4\n",
{
struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh;
+ check_tlv_size(EXT_SUBTLV_ADJ_SID_SIZE, "Adjacency SID");
+
vty_out(vty,
" Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n",
ntohs(top->header.length), top->flags, top->mtid, top->weight,
struct ext_subtlv_lan_adj_sid *top =
(struct ext_subtlv_lan_adj_sid *)tlvh;
+ check_tlv_size(EXT_SUBTLV_LAN_ADJ_SID_SIZE, "Lan-Adjacency SID");
+
vty_out(vty,
" LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: %pI4\n\t%s: %u\n",
ntohs(top->header.length), top->flags, top->mtid, top->weight,
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
+ if (TLV_SIZE(tlvh) > buf_size) {
+ vty_out(vty, " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length));
}
/* Extended Link Sub TLVs */
-static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext)
+static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext,
+ size_t buf_size)
{
struct ext_tlv_link *top = (struct ext_tlv_link *)ext;
struct tlv_header *tlvh;
- uint16_t length = ntohs(top->header.length) - 3 * sizeof(uint32_t);
+ uint16_t length = ntohs(top->header.length);
uint16_t sum = 0;
+ /* Verify that TLV length is valid against remaining buffer size */
+ if (length > buf_size) {
+ vty_out(vty,
+ " Extended Link TLV size %d exceeds buffer size. Abort!\n",
+ length);
+ return buf_size;
+ }
+
vty_out(vty,
" Extended Link TLV: Length %u\n Link Type: 0x%x\n"
" Link ID: %pI4\n",
&top->link_id);
vty_out(vty, " Link data: %pI4\n", &top->link_data);
+ /* Skip Extended TLV and parse sub-TLVs */
+ length -= EXT_TLV_LINK_SIZE;
tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
+ EXT_TLV_LINK_SIZE);
- for (; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
+ for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_SUBTLV_ADJ_SID:
sum += show_vty_ext_link_adj_sid(vty, tlvh);
sum += show_vty_ext_link_rmt_itf_addr(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_TLV_LINK:
- sum += show_vty_link_info(vty, tlvh);
+ sum += show_vty_link_info(vty, tlvh, length - sum);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
struct ext_subtlv_prefix_sid *top =
(struct ext_subtlv_prefix_sid *)tlvh;
+ check_tlv_size(EXT_SUBTLV_PREFIX_SID_SIZE, "Prefix SID");
+
vty_out(vty,
" Prefix SID Sub-TLV: Length %u\n\tAlgorithm: %u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n",
ntohs(top->header.length), top->algorithm, top->flags,
}
/* Extended Prefix SubTLVs */
-static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext)
+static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext,
+ size_t buf_size)
{
struct ext_tlv_prefix *top = (struct ext_tlv_prefix *)ext;
struct tlv_header *tlvh;
- uint16_t length = ntohs(top->header.length) - 2 * sizeof(uint32_t);
+ uint16_t length = ntohs(top->header.length);
uint16_t sum = 0;
+ /* Verify that TLV length is valid against remaining buffer size */
+ if (length > buf_size) {
+ vty_out(vty,
+ " Extended Link TLV size %d exceeds buffer size. Abort!\n",
+ length);
+ return buf_size;
+ }
+
vty_out(vty,
" Extended Prefix TLV: Length %u\n\tRoute Type: %u\n"
"\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %pI4/%u\n",
ntohs(top->header.length), top->route_type, top->af, top->flags,
&top->address, top->pref_length);
+ /* Skip Extended Prefix TLV and parse sub-TLVs */
+ length -= EXT_TLV_PREFIX_SIZE;
tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
+ EXT_TLV_PREFIX_SIZE);
- for (; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
+ for (; sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_SUBTLV_PREFIX_SID:
sum += show_vty_ext_pref_pref_sid(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case EXT_TLV_PREFIX:
- sum += show_vty_pref_info(vty, tlvh);
+ sum += show_vty_pref_info(vty, tlvh, length - sum);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
lsah = (struct lsa_header *)lsa->data;
- length = ntohs(lsah->length);
-
/* Check LSA len */
- if (length <= OSPF_LSA_HEADER_SIZE) {
+ if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
if (IS_DEBUG_OSPF_GR_HELPER)
zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
__func__, length);
return OSPF_GR_FAILURE;
}
- length -= OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len against overall LSA */
lsah = (struct lsa_header *)lsa->data;
- length = ntohs(lsah->length);
-
- if (length <= OSPF_LSA_HEADER_SIZE) {
+ if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
vty_out(vty, "%% Invalid LSA length: %d\n", length);
return;
}
- length -= OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
vty_out(vty, " TLV info:\n");
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len */
if (sum + TLV_SIZE(tlvh) > length) {
new = ospf_lsa_new();
new->data = ospf_lsa_data_new(size);
+ new->size = size;
return new;
}
if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1))
return 1;
- if (l1->data->length != l2->data->length)
+ if (l1->size != l2->size)
return 1;
- if (l1->data->length == 0)
+ if (l1->size == 0)
return 1;
if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED))
return 1; /* May be a stale LSA in the LSBD */
- assert(ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE);
+ assert(l1->size > OSPF_LSA_HEADER_SIZE);
p1 = (char *)l1->data;
p2 = (char *)l2->data;
if (memcmp(p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
- ntohs(l1->data->length) - OSPF_LSA_HEADER_SIZE)
+ l1->size - OSPF_LSA_HEADER_SIZE)
!= 0)
return 1;
#define OSPF_LSA_PREMATURE_AGE 0x40
#define OSPF_LSA_IN_MAXAGE 0x80
- /* LSA data. */
+ /* LSA data. and size */
struct lsa_header *data;
+ size_t size;
/* Received time stamp. */
struct timeval tv_recv;
uint8_t flags;
uint8_t zero;
uint16_t links;
- struct {
+ struct router_link {
struct in_addr link_id;
struct in_addr link_data;
uint8_t type;
struct as_external_lsa {
struct lsa_header header;
struct in_addr mask;
- struct {
+ struct as_route {
uint8_t tos;
uint8_t metric[3];
struct in_addr fwd_addr;
void ospf_opaque_lsa_dump(struct stream *s, uint16_t length)
{
- struct ospf_lsa lsa;
+ struct ospf_lsa lsa = {};
lsa.data = (struct lsa_header *)stream_pnt(s);
+ lsa.size = length;
show_opaque_info_detail(NULL, &lsa, NULL);
return;
}
#define VALID_OPAQUE_INFO_LEN(lsahdr) \
((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \
+ && ((ntohs((lsahdr)->length) < OSPF_MAX_LSA_SIZE)) \
&& ((ntohs((lsahdr)->length) % sizeof(uint32_t)) == 0))
/*
pce->pce_header.header.type = htons(RI_TLV_PCE);
/* Set PCE Address */
pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS);
- pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
- pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4);
+ pce->pce_address.header.length = htons(PCE_ADDRESS_IPV4_SIZE);
+ pce->pce_address.address.type = htons(PCE_ADDRESS_IPV4);
pce->pce_address.address.value = ipv4;
return;
sizeof(struct ri_pce_subtlv_domain));
new->header.type = htons(RI_PCE_SUBTLV_DOMAIN);
- new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
+ new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
new->type = htons(type);
new->value = htonl(domain);
sizeof(struct ri_pce_subtlv_neighbor));
new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR);
- new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4);
+ new->header.length = htons(PCE_ADDRESS_IPV4_SIZE);
new->type = htons(type);
new->value = htonl(domain);
* Followings are vty session control functions.
*------------------------------------------------------------------------*/
+#define check_tlv_size(size, msg) \
+ do { \
+ if (ntohs(tlvh->length) > size) { \
+ if (vty != NULL) \
+ vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ else \
+ zlog_debug(" Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ return size + TLV_HDR_SIZE; \
+ } \
+ } while (0)
+
static uint16_t show_vty_router_cap(struct vty *vty, struct tlv_header *tlvh)
{
struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
+ check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
+
if (vty != NULL)
vty_out(vty, " Router Capabilities: 0x%x\n",
ntohl(top->value));
struct ri_pce_subtlv_address *top =
(struct ri_pce_subtlv_address *)tlvh;
- if (ntohs(top->address.type) == PCE_ADDRESS_TYPE_IPV4) {
+ if (ntohs(top->address.type) == PCE_ADDRESS_IPV4) {
+ check_tlv_size(PCE_ADDRESS_IPV4_SIZE, "PCE Address");
if (vty != NULL)
vty_out(vty, " PCE Address: %pI4\n",
&top->address.value);
else
zlog_debug(" PCE Address: %pI4",
&top->address.value);
- } else {
+ } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
/* TODO: Add support to IPv6 with inet_ntop() */
+ check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
if (vty != NULL)
vty_out(vty, " PCE Address: 0x%x\n",
ntohl(top->address.value.s_addr));
else
zlog_debug(" PCE Address: 0x%x",
ntohl(top->address.value.s_addr));
+ } else {
+ if (vty != NULL)
+ vty_out(vty, " Wrong PCE Address type: 0x%x\n",
+ ntohl(top->address.type));
+ else
+ zlog_debug(" Wrong PCE Address type: 0x%x",
+ ntohl(top->address.type));
}
return TLV_SIZE(tlvh);
struct ri_pce_subtlv_path_scope *top =
(struct ri_pce_subtlv_path_scope *)tlvh;
+ check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
+
if (vty != NULL)
vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
else
struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
struct in_addr tmp;
+ check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
+
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value;
if (vty != NULL)
- vty_out(vty, " PCE domain Area: %pI4\n", &tmp);
+ vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
else
- zlog_debug(" PCE domain Area: %pI4", &tmp);
- } else {
+ zlog_debug(" PCE Domain Area: %pI4", &tmp);
+ } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL)
- vty_out(vty, " PCE domain AS: %d\n",
+ vty_out(vty, " PCE Domain AS: %d\n",
ntohl(top->value));
else
- zlog_debug(" PCE domain AS: %d", ntohl(top->value));
+ zlog_debug(" PCE Domain AS: %d", ntohl(top->value));
+ } else {
+ if (vty != NULL)
+ vty_out(vty, " Wrong PCE Domain type: %d\n",
+ ntohl(top->type));
+ else
+ zlog_debug(" Wrong PCE Domain type: %d",
+ ntohl(top->type));
}
+
return TLV_SIZE(tlvh);
}
(struct ri_pce_subtlv_neighbor *)tlvh;
struct in_addr tmp;
+ check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
+
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value;
if (vty != NULL)
- vty_out(vty, " PCE neighbor Area: %pI4\n",
- &tmp);
+ vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
else
- zlog_debug(" PCE neighbor Area: %pI4", &tmp);
- } else {
+ zlog_debug(" PCE Neighbor Area: %pI4", &tmp);
+ } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL)
- vty_out(vty, " PCE neighbor AS: %d\n",
+ vty_out(vty, " PCE Neighbor AS: %d\n",
ntohl(top->value));
else
- zlog_debug(" PCE neighbor AS: %d",
+ zlog_debug(" PCE Neighbor AS: %d",
ntohl(top->value));
+ } else {
+ if (vty != NULL)
+ vty_out(vty, " Wrong PCE Neighbor type: %d\n",
+ ntohl(top->type));
+ else
+ zlog_debug(" Wrong PCE Neighbor type: %d",
+ ntohl(top->type));
}
+
return TLV_SIZE(tlvh);
}
struct ri_pce_subtlv_cap_flag *top =
(struct ri_pce_subtlv_cap_flag *)tlvh;
+ check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
+
if (vty != NULL)
vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
ntohl(top->value));
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length));
}
static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
- uint32_t total)
+ size_t buf_size)
{
struct tlv_header *tlvh;
+ uint16_t length = ntohs(ri->length);
uint16_t sum = 0;
- for (tlvh = ri; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
+ /* Verify that TLV length is valid against remaining buffer size */
+ if (length > buf_size) {
+ vty_out(vty,
+ " PCE Info TLV size %d exceeds buffer size. Abort!\n",
+ length);
+ return buf_size;
+ }
+
+ for (tlvh = ri; sum < length; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case RI_PCE_SUBTLV_ADDRESS:
sum += show_vty_pce_subtlv_address(vty, tlvh);
sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break;
}
}
(struct ri_sr_tlv_sr_algorithm *)tlvh;
int i;
+ check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
+
if (vty != NULL) {
vty_out(vty, " Segment Routing Algorithm TLV:\n");
for (i = 0; i < ntohs(algo->header.length); i++) {
break;
}
}
- }
-
- else {
+ } else {
zlog_debug(" Segment Routing Algorithm TLV:");
for (i = 0; i < ntohs(algo->header.length); i++)
switch (algo->value[i]) {
struct ri_sr_tlv_sid_label_range *range =
(struct ri_sr_tlv_sid_label_range *)tlvh;
+ check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
+
if (vty != NULL) {
vty_out(vty,
" Segment Routing %s Range TLV:\n"
{
struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
+ check_tlv_size(RI_SR_TLV_NODE_MSD_SIZE, "Node Maximum Stack Depth");
+
if (vty != NULL) {
vty_out(vty,
" Segment Routing MSD TLV:\n"
uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case RI_TLV_CAPABILITIES:
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, length);
break;
}
}
/* RFC4970: Router Information Capabilities TLV */ /* Mandatory */
#define RI_TLV_CAPABILITIES 1
-
+#define RI_TLV_CAPABILITIES_SIZE 4
struct ri_tlv_router_cap {
struct tlv_header header; /* Value length is 4 bytes. */
uint32_t value;
struct ri_pce_subtlv_address {
/* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */
struct tlv_header header;
-#define PCE_ADDRESS_LENGTH_IPV4 8
-#define PCE_ADDRESS_LENGTH_IPV6 20
+#define PCE_ADDRESS_IPV4_SIZE 8
+#define PCE_ADDRESS_IPV6_SIZE 20
struct {
uint16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */
-#define PCE_ADDRESS_TYPE_IPV4 1
-#define PCE_ADDRESS_TYPE_IPV6 2
+#define PCE_ADDRESS_IPV4 1
+#define PCE_ADDRESS_IPV6 2
uint16_t reserved;
struct in_addr value; /* PCE address */
} address;
/* PCE Path-Scope Sub-TLV */ /* Mandatory */
#define RI_PCE_SUBTLV_PATH_SCOPE 2
+#define RI_PCE_SUBTLV_PATH_SCOPE_SIZE 4
struct ri_pce_subtlv_path_scope {
struct tlv_header header; /* Type = 2; Length = 4 bytes. */
/*
};
/* PCE Domain Sub-TLV */ /* Optional */
-#define RI_PCE_SUBTLV_DOMAIN 3
-
#define PCE_DOMAIN_TYPE_AREA 1
-#define PCE_DOMAIN_TYPE_AS 2
+#define PCE_DOMAIN_TYPE_AS 2
+#define RI_PCE_SUBTLV_DOMAIN 3
+#define RI_PCE_SUBTLV_DOMAIN_SIZE 8
struct ri_pce_subtlv_domain {
struct tlv_header header; /* Type = 3; Length = 8 bytes. */
uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
/* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */
#define RI_PCE_SUBTLV_NEIGHBOR 4
+#define RI_PCE_SUBTLV_NEIGHBOR_SIZE 8
struct ri_pce_subtlv_neighbor {
struct tlv_header header; /* Type = 4; Length = 8 bytes. */
uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
/* PCE Capabilities Flags Sub-TLV */ /* Optional */
#define RI_PCE_SUBTLV_CAP_FLAG 5
+#define RI_PCE_SUBTLV_CAP_FLAG_SIZE 4
#define PCE_CAP_GMPLS_LINK 0x0001
#define PCE_CAP_BIDIRECTIONAL 0x0002
*/
/* Extended Link SubTLVs Getter */
-static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
+static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
{
struct sr_link *srl;
struct tlv_header *sub_tlvh;
uint16_t length = 0, sum = 0, i = 0;
+ /* Check TLV size */
+ if ((ntohs(tlvh->length) > size)
+ || ntohs(tlvh->length) < EXT_TLV_LINK_SIZE) {
+ zlog_warn("Wrong Extended Link TLV size. Abort!");
+ return NULL;
+ }
+
srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
/* Initialize TLV browsing */
length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE;
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
+ EXT_TLV_LINK_SIZE);
- for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
+ for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_ADJ_SID:
adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
}
/* Extended Prefix SubTLVs Getter */
-static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh)
+static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
+ size_t size)
{
struct sr_prefix *srp;
struct tlv_header *sub_tlvh;
uint16_t length = 0, sum = 0;
+ /* Check TLV size */
+ if ((ntohs(tlvh->length) > size)
+ || ntohs(tlvh->length) < EXT_TLV_PREFIX_SIZE) {
+ zlog_warn("Wrong Extended Link TLV size. Abort!");
+ return NULL;
+ }
+
srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
/* Initialize TLV browsing */
length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE;
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
+ EXT_TLV_PREFIX_SIZE);
- for (; sum < length; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
+ for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_PREFIX_SID:
psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
/* Collect Router Information Sub TLVs */
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
srgb.range_size = 0;
srgb.lower_bound = 0;
switch (ntohs(tlvh->type)) {
case RI_SR_TLV_SR_ALGORITHM:
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
- sum += TLV_SIZE(tlvh);
break;
case RI_SR_TLV_SRGB_LABEL_RANGE:
ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh;
- sum += TLV_SIZE(tlvh);
break;
case RI_SR_TLV_SRLB_LABEL_RANGE:
ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh;
- sum += TLV_SIZE(tlvh);
break;
case RI_SR_TLV_NODE_MSD:
msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value;
- sum += TLV_SIZE(tlvh);
break;
default:
- sum += TLV_SIZE(tlvh);
break;
}
+ sum += TLV_SIZE(tlvh);
}
/* Check if Segment Routing Capabilities has been found */
struct lsa_header *lsah = lsa->data;
struct sr_link *srl;
- uint16_t length, sum;
+ int length;
osr_debug("SR (%s): Process Extended Link LSA 8.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
}
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
- sum = 0;
- for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
+ for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
if (ntohs(tlvh->type) == EXT_TLV_LINK) {
/* Got Extended Link information */
- srl = get_ext_link_sid(tlvh);
+ srl = get_ext_link_sid(tlvh, length);
/* Update SID if not null */
if (srl != NULL) {
srl->instance = ntohl(lsah->id.s_addr);
update_ext_link_sid(srn, srl, lsa->flags);
}
}
- sum += TLV_SIZE(tlvh);
+ length -= TLV_SIZE(tlvh);
}
}
struct lsa_header *lsah = (struct lsa_header *)lsa->data;
struct sr_prefix *srp;
- uint16_t length, sum;
+ int length;
osr_debug("SR (%s): Process Extended Prefix LSA 7.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
}
/* Initialize TLV browsing */
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
- sum = 0;
- for (tlvh = TLV_HDR_TOP(lsah); sum < length;
+ length = lsa->size - OSPF_LSA_HEADER_SIZE;
+ for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh;
tlvh = TLV_HDR_NEXT(tlvh)) {
if (ntohs(tlvh->type) == EXT_TLV_LINK) {
/* Got Extended Link information */
- srp = get_ext_prefix_sid(tlvh);
+ srp = get_ext_prefix_sid(tlvh, length);
/* Update SID if not null */
if (srp != NULL) {
srp->instance = ntohl(lsah->id.s_addr);
update_ext_prefix_sid(srn, srp);
}
}
- sum += TLV_SIZE(tlvh);
+ length -= TLV_SIZE(tlvh);
}
}
/* RI SID/Label Range TLV used for SRGB & SRLB - section 3.2 & 3.3 */
#define RI_SR_TLV_SRGB_LABEL_RANGE 9
#define RI_SR_TLV_SRLB_LABEL_RANGE 14
+#define RI_SR_TLV_LABEL_RANGE_SIZE 12
struct ri_sr_tlv_sid_label_range {
struct tlv_header header;
/* Only 24 upper most bits are significant */
/* RI Node/MSD TLV as per RFC 8476 */
#define RI_SR_TLV_NODE_MSD 12
+#define RI_SR_TLV_NODE_MSD_SIZE 4
struct ri_sr_tlv_node_msd {
struct tlv_header header;
uint8_t subtype; /* always = 1 */
struct ls_edge *edge;
struct ls_subnet *subnet;
struct listnode *node;
- int len;
+ int len, links;
/* Sanity Check */
if (!ted || !lsa || !lsa->data)
subnet->status = ORPHAN;
/* Then, process Link Information */
- len = ntohs(rl->header.length) - 4;
- for (int i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) {
+ len = lsa->size - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE;
+ links = ntohs(rl->links);
+ for (int i = 0; i < links && len > 0; len -= 12, i++) {
struct prefix p;
uint32_t metric;
/* Initialize TLV browsing */
tlvh = TLV_HDR_TOP(lsa->data);
+ len = lsa->size - OSPF_LSA_HEADER_SIZE;
- uint32_t total_len = TLV_BODY_SIZE(lsa->data) - OSPF_LSA_HEADER_SIZE;
+ /* Check if TE Router-ID TLV is present */
+ if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) {
+ /* if TE Router-ID is alone, we are done ... */
+ if (len == TE_LINK_SUBTLV_DEF_SIZE)
+ return 0;
- /* If TE Router-ID is only TLV we are done */
- if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR
- && total_len == sizeof(struct te_tlv_router_addr))
- return 0;
-
- /* Skip TE Router-ID if present */
- if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
+ /* ... otherwise, skip it */
+ len -= TE_LINK_SUBTLV_DEF_SIZE + TLV_HDR_SIZE;
tlvh = TLV_HDR_NEXT(tlvh);
+ }
- /* Check if we have a TE Link TLV */
- len = TLV_BODY_SIZE(tlvh);
+ /* Check if we have a valid TE Link TLV */
if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
return 0;
&lsa->data->id, &node->router_id);
/* Initialize TLV browsing */
- len = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
+ len = lsa->size - OSPF_LSA_HEADER_SIZE;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;
+ tlvh = TLV_HDR_NEXT(tlvh)) {
struct ri_sr_tlv_sr_algorithm *algo;
struct ri_sr_tlv_sid_label_range *range;
struct ri_sr_tlv_node_msd *msd;
/*------------------------------------------------------------------------*
* Followings are vty session control functions.
*------------------------------------------------------------------------*/
+#define check_tlv_size(size, msg) \
+ do { \
+ if (ntohs(tlvh->length) > size) { \
+ if (vty != NULL) \
+ vty_out(vty, " Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ else \
+ zlog_debug(" Wrong %s TLV size: %d(%d)\n", \
+ msg, ntohs(tlvh->length), size); \
+ return size + TLV_HDR_SIZE; \
+ } \
+ } while(0)
static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
{
struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Router Address");
+
if (vty != NULL)
vty_out(vty, " Router-Address: %pI4\n", &top->value);
else
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_link_header(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
struct te_tlv_link *top = (struct te_tlv_link *)tlvh;
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
if (vty != NULL)
vty_out(vty, " Link: %u octets of data\n",
ntohs(top->header.length));
struct te_link_subtlv_link_type *top;
const char *cp = "Unknown";
+ check_tlv_size(TE_LINK_SUBTLV_TYPE_SIZE, "Link Type");
+
top = (struct te_link_subtlv_link_type *)tlvh;
switch (top->link_type.value) {
case LINK_TYPE_SUBTLV_VALUE_PTP:
{
struct te_link_subtlv_link_id *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link ID");
+
top = (struct te_link_subtlv_link_id *)tlvh;
if (vty != NULL)
vty_out(vty, " Link-ID: %pI4\n", &top->value);
}
static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
- struct tlv_header *tlvh)
+ struct tlv_header *tlvh,
+ size_t buf_size)
{
struct te_link_subtlv_lclif_ipaddr *top;
int i, n;
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
n = ntohs(tlvh->length) / sizeof(top->value[0]);
}
static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty,
- struct tlv_header *tlvh)
+ struct tlv_header *tlvh,
+ size_t buf_size)
{
struct te_link_subtlv_rmtif_ipaddr *top;
int i, n;
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
n = ntohs(tlvh->length) / sizeof(top->value[0]);
if (vty != NULL)
{
struct te_link_subtlv_te_metric *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "TE Metric");
+
top = (struct te_link_subtlv_te_metric *)tlvh;
if (vty != NULL)
vty_out(vty, " Traffic Engineering Metric: %u\n",
struct te_link_subtlv_max_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Bandwidth");
+
top = (struct te_link_subtlv_max_bw *)tlvh;
fval = ntohf(top->value);
struct te_link_subtlv_max_rsv_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Reservable Bandwidth");
+
top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
fval = ntohf(top->value);
float fval1, fval2;
int i;
+ check_tlv_size(TE_LINK_SUBTLV_UNRSV_SIZE, "Unreserved Bandwidth");
+
top = (struct te_link_subtlv_unrsv_bw *)tlvh;
if (vty != NULL)
vty_out(vty,
{
struct te_link_subtlv_rsc_clsclr *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Resource class/color");
+
top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
if (vty != NULL)
vty_out(vty, " Resource class/color: 0x%x\n",
{
struct te_link_subtlv_lrrid *top;
+ check_tlv_size(TE_LINK_SUBTLV_LRRID_SIZE, "Local/Remote Router ID");
+
top = (struct te_link_subtlv_lrrid *)tlvh;
if (vty != NULL) {
{
struct te_link_subtlv_llri *top;
+ check_tlv_size(TE_LINK_SUBTLV_LLRI_SIZE, "Link Local/Remote ID");
+
top = (struct te_link_subtlv_llri *)tlvh;
if (vty != NULL) {
{
struct te_link_subtlv_rip *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote ASBR Address");
+
top = (struct te_link_subtlv_rip *)tlvh;
if (vty != NULL)
{
struct te_link_subtlv_ras *top;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote AS number");
+
top = (struct te_link_subtlv_ras *)tlvh;
if (vty != NULL)
uint32_t delay;
uint32_t anomalous;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Average Link Delay");
+
top = (struct te_link_subtlv_av_delay *)tlvh;
delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
uint32_t low, high;
uint32_t anomalous;
+ check_tlv_size(TE_LINK_SUBTLV_MM_DELAY_SIZE, "Min/Max Link Delay");
+
top = (struct te_link_subtlv_mm_delay *)tlvh;
low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
struct te_link_subtlv_delay_var *top;
uint32_t jitter;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Delay Variation");
+
top = (struct te_link_subtlv_delay_var *)tlvh;
jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
uint32_t anomalous;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Loss");
+
top = (struct te_link_subtlv_pkt_loss *)tlvh;
loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
fval = (float)(loss * LOSS_PRECISION);
struct te_link_subtlv_res_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Residual Bandwidth");
+
top = (struct te_link_subtlv_res_bw *)tlvh;
fval = ntohf(top->value);
struct te_link_subtlv_ava_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Available Bandwidth");
+
top = (struct te_link_subtlv_ava_bw *)tlvh;
fval = ntohf(top->value);
struct te_link_subtlv_use_bw *top;
float fval;
+ check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Utilized Bandwidth");
+
top = (struct te_link_subtlv_use_bw *)tlvh;
fval = ntohf(top->value);
return TLV_SIZE(tlvh);
}
-static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
+static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh,
+ size_t buf_size)
{
+ if (TLV_SIZE(tlvh) > buf_size) {
+ if (vty != NULL)
+ vty_out(vty,
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ else
+ zlog_debug(
+ " TLV size %d exceeds buffer size. Abort!",
+ TLV_SIZE(tlvh));
+ return buf_size;
+ }
+
if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length));
struct tlv_header *tlvh;
uint16_t sum = subtotal;
- for (tlvh = tlvh0; sum < total;
- tlvh = TLV_HDR_NEXT(tlvh)) {
+ for (tlvh = tlvh0; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) {
case TE_LINK_SUBTLV_LINK_TYPE:
sum += show_vty_link_subtlv_link_type(vty, tlvh);
sum += show_vty_link_subtlv_link_id(vty, tlvh);
break;
case TE_LINK_SUBTLV_LCLIF_IPADDR:
- sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh);
+ sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh,
+ total - sum);
break;
case TE_LINK_SUBTLV_RMTIF_IPADDR:
- sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh);
+ sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh,
+ total - sum);
break;
case TE_LINK_SUBTLV_TE_METRIC:
sum += show_vty_link_subtlv_te_metric(vty, tlvh);
sum += show_vty_link_subtlv_use_bw(vty, tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
break;
}
}
uint16_t subtotal, uint16_t total) = NULL;
sum = 0;
- total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ total = lsa->size - OSPF_LSA_HEADER_SIZE;
- for (tlvh = TLV_HDR_TOP(lsah); sum < total;
+ for (tlvh = TLV_HDR_TOP(lsah); sum < total && tlvh;
tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
if (subfunc != NULL) {
sum = (*subfunc)(vty, tlvh, sum, total);
sum += show_vty_router_addr(vty, tlvh);
break;
case TE_TLV_LINK:
- sum += show_vty_link_header(vty, tlvh);
+ sum += show_vty_link_header(vty, tlvh, total - sum);
subfunc = ospf_mpls_te_show_link_subtlv;
next = TLV_DATA(tlvh);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
break;
}
}
show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
if (TLV_TYPE(lp->lclif_ipaddr) != 0)
show_vty_link_subtlv_lclif_ipaddr(
- vty, &lp->lclif_ipaddr.header);
+ vty, &lp->lclif_ipaddr.header,
+ lp->lclif_ipaddr.header.length);
if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
show_vty_link_subtlv_rmtif_ipaddr(
- vty, &lp->rmtif_ipaddr.header);
+ vty, &lp->rmtif_ipaddr.header,
+ lp->rmtif_ipaddr.header.length);
if (TLV_TYPE(lp->rip) != 0)
show_vty_link_subtlv_rip(vty, &lp->rip.header);
if (TLV_TYPE(lp->ras) != 0)
if (lsa != NULL) {
struct network_lsa *nl = (struct network_lsa *)lsa->data;
+ struct in_addr *addr;
show_ip_ospf_database_header(vty, lsa, json);
json_object_int_add(json, "networkMask",
ip_masklen(nl->mask));
- length = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4;
-
- for (i = 0; length > 0; i++, length -= 4)
+ length = lsa->size - OSPF_LSA_HEADER_SIZE - 4;
+ addr = &nl->routers[0];
+ for (i = 0; length > 0 && addr;
+ length -= 4, addr = &nl->routers[++i])
if (!json) {
vty_out(vty, " Attached Router: %pI4\n",
- &nl->routers[i]);
+ addr);
vty_out(vty, "\n");
} else {
json_router = json_object_new_object();
json_object_string_add(
json_router, "attachedRouterId",
- inet_ntop(AF_INET, &nl->routers[i],
- buf, sizeof(buf)));
- json_object_object_add(
- json_attached_rt,
- inet_ntop(AF_INET, &(nl->routers[i]),
- buf, sizeof(buf)),
- json_router);
+ inet_ntop(AF_INET, addr, buf,
+ sizeof(buf)));
+ json_object_object_add(json_attached_rt,
+ inet_ntop(AF_INET, addr,
+ buf,
+ sizeof(buf)),
+ json_router);
}
}