Merge pull request #8408 from Orange-OpenSource/TE

ospfd: Correct Coverity defects
This commit is contained in:
Igor Ryzhov 2021-05-19 17:04:48 +03:00 committed by GitHub
commit 1f25f6c768
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 465 additions and 204 deletions

View File

@ -58,7 +58,7 @@
/* For debugging only, will be removed */ /* 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 opaque_lsa {
struct lsa_header header; struct lsa_header header;
@ -69,11 +69,11 @@ void api_opaque_lsa_print(struct lsa_header *data)
int opaquelen; int opaquelen;
int i; 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); zlog_debug("apiserver_lsa_print: opaquelen=%d", opaquelen);
for (i = 0; i < opaquelen; i++) { for (i = 0; i < opaquelen; i++) {
@ -111,11 +111,16 @@ struct msg *msg_new(uint8_t msgtype, void *msgbody, uint32_t seqnum,
struct msg *msg_dup(struct msg *msg) struct msg *msg_dup(struct msg *msg)
{ {
struct msg *new; struct msg *new;
size_t size;
assert(msg); 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), 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; return new;
} }
@ -400,7 +405,7 @@ struct msg *msg_read(int fd)
} }
/* Allocate new message */ /* 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; return msg;
} }
@ -408,29 +413,34 @@ struct msg *msg_read(int fd)
int msg_write(int fd, struct msg *msg) int msg_write(int fd, struct msg *msg)
{ {
uint8_t buf[OSPF_API_MAX_MSG_SIZE]; uint8_t buf[OSPF_API_MAX_MSG_SIZE];
int l; uint16_t l;
int wlen; int wlen;
assert(msg); assert(msg);
assert(msg->s); assert(msg->s);
/* Length of message including header */ /* Length of OSPF LSA payload */
l = sizeof(struct apimsghdr) + ntohs(msg->hdr.msglen); 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 */ /* Make contiguous memory buffer for message */
memcpy(buf, &msg->hdr, sizeof(struct apimsghdr)); memcpy(buf, &msg->hdr, sizeof(struct apimsghdr));
memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), l);
ntohs(msg->hdr.msglen));
/* Total length of OSPF API Message */
l += sizeof(struct apimsghdr);
wlen = writen(fd, buf, l); wlen = writen(fd, buf, l);
if (wlen < 0) { if (wlen < 0) {
zlog_warn("msg_write: writen %s", safe_strerror(errno)); zlog_warn("%s: writen %s", __func__, safe_strerror(errno));
return -1; return -1;
} else if (wlen == 0) { } else if (wlen == 0) {
zlog_warn("msg_write: Connection closed by peer"); zlog_warn("%s: Connection closed by peer", __func__);
return -1; return -1;
} else if (wlen != l) { } else if (wlen != l) {
zlog_warn("msg_write: Cannot write API message"); zlog_warn("%s: Cannot write API message", __func__);
return -1; return -1;
} }
return 0; return 0;

View File

@ -276,7 +276,7 @@ struct apimsg {
*/ */
/* For debugging only. */ /* 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 */ /* Messages sent by client */
extern struct msg *new_msg_register_opaque_type(uint32_t seqnum, uint8_t ltype, extern struct msg *new_msg_register_opaque_type(uint32_t seqnum, uint8_t ltype,

View File

@ -1156,6 +1156,7 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
struct msg_register_event *rmsg; struct msg_register_event *rmsg;
int rc; int rc;
uint32_t seqnum; uint32_t seqnum;
size_t size;
rmsg = (struct msg_register_event *)STREAM_DATA(msg->s); rmsg = (struct msg_register_event *)STREAM_DATA(msg->s);
@ -1165,13 +1166,16 @@ int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv,
/* Free existing filter in apiserv. */ /* Free existing filter in apiserv. */
XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter); XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter);
/* Alloc new space for filter. */ /* Alloc new space for filter. */
size = ntohs(msg->hdr.msglen);
if (size < OSPF_MAX_LSA_SIZE) {
apiserv->filter = apiserv->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, size);
XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen));
/* copy it over. */ /* copy it over. */
memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen)); memcpy(apiserv->filter, &rmsg->filter, size);
rc = OSPF_API_OK; rc = OSPF_API_OK;
} else
rc = OSPF_API_NOMEMORY;
/* Send a reply back to client with return code */ /* Send a reply back to client with return code */
rc = ospf_apiserver_send_reply(apiserv, seqnum, rc); rc = ospf_apiserver_send_reply(apiserv, seqnum, rc);

View File

@ -241,7 +241,7 @@ const char *ospf_timer_dump(struct thread *t, char *buf, size_t size)
static void ospf_packet_hello_dump(struct stream *s, uint16_t length) static void ospf_packet_hello_dump(struct stream *s, uint16_t length)
{ {
struct ospf_hello *hello; struct ospf_hello *hello;
int i; int i, len;
hello = (struct ospf_hello *)stream_pnt(s); hello = (struct ospf_hello *)stream_pnt(s);
@ -256,9 +256,9 @@ static void ospf_packet_hello_dump(struct stream *s, uint16_t length)
zlog_debug(" DRouter %pI4", &hello->d_router); zlog_debug(" DRouter %pI4", &hello->d_router);
zlog_debug(" BDRouter %pI4", &hello->bd_router); zlog_debug(" BDRouter %pI4", &hello->bd_router);
length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE; len = length - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE;
zlog_debug(" # Neighbors %d", length / 4); zlog_debug(" # Neighbors %d", len / 4);
for (i = 0; length > 0; i++, length -= sizeof(struct in_addr)) for (i = 0; len > 0; i++, len -= sizeof(struct in_addr))
zlog_debug(" Neighbor %pI4", &hello->neighbors[i]); zlog_debug(" Neighbor %pI4", &hello->neighbors[i]);
} }
@ -285,7 +285,8 @@ static void ospf_router_lsa_dump(struct stream *s, uint16_t length)
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
struct router_lsa *rl; struct router_lsa *rl;
int i, len; struct router_link *rlnk;
int i, len, sum;
rl = (struct router_lsa *)stream_pnt(s); rl = (struct router_lsa *)stream_pnt(s);
@ -294,16 +295,15 @@ static void ospf_router_lsa_dump(struct stream *s, uint16_t length)
ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ)); ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ));
zlog_debug(" # links %d", ntohs(rl->links)); zlog_debug(" # links %d", ntohs(rl->links));
len = ntohs(rl->header.length) - OSPF_LSA_HEADER_SIZE - 4; len = length - OSPF_LSA_HEADER_SIZE - 4;
for (i = 0; len > 0; i++) { rlnk = &rl->link[0];
zlog_debug(" Link ID %pI4", &rl->link[i].link_id); sum = 0;
zlog_debug(" Link Data %pI4", for (i = 0; sum < len && rlnk; sum += 12, rlnk = &rl->link[++i]) {
&rl->link[i].link_data); zlog_debug(" Link ID %pI4", &rlnk->link_id);
zlog_debug(" Type %d", (uint8_t)rl->link[i].type); zlog_debug(" Link Data %pI4", &rlnk->link_data);
zlog_debug(" TOS %d", (uint8_t)rl->link[i].tos); zlog_debug(" Type %d", (uint8_t)rlnk->type);
zlog_debug(" metric %d", ntohs(rl->link[i].metric)); zlog_debug(" TOS %d", (uint8_t)rlnk->tos);
zlog_debug(" metric %d", ntohs(rlnk->metric));
len -= 12;
} }
} }
@ -312,10 +312,11 @@ static void ospf_network_lsa_dump(struct stream *s, uint16_t length)
struct network_lsa *nl; struct network_lsa *nl;
int i, cnt; int i, cnt;
nl = (struct network_lsa *)stream_pnt(s);
cnt = (ntohs(nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
zlog_debug(" Network-LSA"); zlog_debug(" Network-LSA");
nl = (struct network_lsa *)stream_pnt(s);
cnt = (length - (OSPF_LSA_HEADER_SIZE + 4)) / 4;
/* /*
zlog_debug ("LSA total size %d", ntohs (nl->header.length)); zlog_debug ("LSA total size %d", ntohs (nl->header.length));
zlog_debug ("Network-LSA size %d", zlog_debug ("Network-LSA size %d",
@ -331,55 +332,53 @@ static void ospf_network_lsa_dump(struct stream *s, uint16_t length)
static void ospf_summary_lsa_dump(struct stream *s, uint16_t length) static void ospf_summary_lsa_dump(struct stream *s, uint16_t length)
{ {
struct summary_lsa *sl; struct summary_lsa *sl;
int size;
int i;
sl = (struct summary_lsa *)stream_pnt(s); sl = (struct summary_lsa *)stream_pnt(s);
zlog_debug(" Summary-LSA"); zlog_debug(" Summary-LSA");
zlog_debug(" Network Mask %pI4", &sl->mask); zlog_debug(" Network Mask %pI4", &sl->mask);
zlog_debug(" TOS=%d metric %d", sl->tos, GET_METRIC(sl->metric));
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));
} }
static void ospf_as_external_lsa_dump(struct stream *s, uint16_t length) static void ospf_as_external_lsa_dump(struct stream *s, uint16_t length)
{ {
struct as_external_lsa *al; struct as_external_lsa *al;
int size; struct as_route *asr;
int size, sum;
int i; int i;
al = (struct as_external_lsa *)stream_pnt(s); al = (struct as_external_lsa *)stream_pnt(s);
zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str); zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str);
zlog_debug(" Network Mask %pI4", &al->mask); zlog_debug(" Network Mask %pI4", &al->mask);
size = ntohs(al->header.length) - OSPF_LSA_HEADER_SIZE - 4; size = length - OSPF_LSA_HEADER_SIZE - 4;
for (i = 0; size > 0; size -= 12, i++) { 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", zlog_debug(" bit %s TOS=%d metric %d",
IS_EXTERNAL_METRIC(al->e[i].tos) ? "E" : "-", IS_EXTERNAL_METRIC(asr->tos) ? "E" : "-",
al->e[i].tos & 0x7f, GET_METRIC(al->e[i].metric)); asr->tos & 0x7f, GET_METRIC(asr->metric));
zlog_debug(" Forwarding address %pI4", zlog_debug(" Forwarding address %pI4", &asr->fwd_addr);
&al->e[i].fwd_addr);
zlog_debug(" External Route Tag %" ROUTE_TAG_PRI, 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) static void ospf_lsa_header_list_dump(struct stream *s, uint16_t length)
{ {
struct lsa_header *lsa; struct lsa_header *lsa;
int len;
zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE); zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE);
/* LSA Headers. */ /* LSA Headers. */
while (length > 0) { len = length;
while (len > 0) {
lsa = (struct lsa_header *)stream_pnt(s); lsa = (struct lsa_header *)stream_pnt(s);
ospf_lsa_header_dump(lsa); ospf_lsa_header_dump(lsa);
stream_forward_getp(s, OSPF_LSA_HEADER_SIZE); stream_forward_getp(s, OSPF_LSA_HEADER_SIZE);
length -= OSPF_LSA_HEADER_SIZE; len -= OSPF_LSA_HEADER_SIZE;
} }
} }
@ -417,6 +416,7 @@ static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length)
uint32_t ls_type; uint32_t ls_type;
struct in_addr ls_id; struct in_addr ls_id;
struct in_addr adv_router; struct in_addr adv_router;
int sum;
sp = stream_get_getp(s); sp = stream_get_getp(s);
@ -425,7 +425,8 @@ static void ospf_packet_ls_req_dump(struct stream *s, uint16_t length)
zlog_debug("Link State Request"); zlog_debug("Link State Request");
zlog_debug(" # Requests %d", length / 12); zlog_debug(" # Requests %d", length / 12);
for (; length > 0; length -= 12) { sum = 0;
for (; sum < length; sum += 12) {
ls_type = stream_getl(s); ls_type = stream_getl(s);
ls_id.s_addr = stream_get_ipv4(s); ls_id.s_addr = stream_get_ipv4(s);
adv_router.s_addr = stream_get_ipv4(s); adv_router.s_addr = stream_get_ipv4(s);
@ -442,23 +443,23 @@ static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length)
{ {
uint32_t sp; uint32_t sp;
struct lsa_header *lsa; struct lsa_header *lsa;
int lsa_len; int lsa_len, len;
uint32_t count; uint32_t count;
length -= OSPF_HEADER_SIZE; len = length - OSPF_HEADER_SIZE;
sp = stream_get_getp(s); sp = stream_get_getp(s);
count = stream_getl(s); count = stream_getl(s);
length -= 4; len -= 4;
zlog_debug("Link State Update"); zlog_debug("Link State Update");
zlog_debug(" # LSAs %d", count); zlog_debug(" # LSAs %d", count);
while (length > 0 && count > 0) { while (len > 0 && count > 0) {
if (length < OSPF_HEADER_SIZE || length % 4 != 0) { if ((uint16_t)len < OSPF_LSA_HEADER_SIZE || len % 4 != 0) {
zlog_debug(" Remaining %d bytes; Incorrect length.", zlog_debug(" Remaining %d bytes; Incorrect length.",
length); len);
break; break;
} }
@ -466,34 +467,39 @@ static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length)
lsa_len = ntohs(lsa->length); lsa_len = ntohs(lsa->length);
ospf_lsa_header_dump(lsa); 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) { switch (lsa->type) {
case OSPF_ROUTER_LSA: case OSPF_ROUTER_LSA:
ospf_router_lsa_dump(s, length); ospf_router_lsa_dump(s, lsa_len);
break; break;
case OSPF_NETWORK_LSA: case OSPF_NETWORK_LSA:
ospf_network_lsa_dump(s, length); ospf_network_lsa_dump(s, lsa_len);
break; break;
case OSPF_SUMMARY_LSA: case OSPF_SUMMARY_LSA:
case OSPF_ASBR_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA:
ospf_summary_lsa_dump(s, length); ospf_summary_lsa_dump(s, lsa_len);
break; break;
case OSPF_AS_EXTERNAL_LSA: case OSPF_AS_EXTERNAL_LSA:
ospf_as_external_lsa_dump(s, length); ospf_as_external_lsa_dump(s, lsa_len);
break; break;
case OSPF_AS_NSSA_LSA: case OSPF_AS_NSSA_LSA:
ospf_as_external_lsa_dump(s, length); ospf_as_external_lsa_dump(s, lsa_len);
break; break;
case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_LINK_LSA:
case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AREA_LSA:
case OSPF_OPAQUE_AS_LSA: case OSPF_OPAQUE_AS_LSA:
ospf_opaque_lsa_dump(s, length); ospf_opaque_lsa_dump(s, lsa_len);
break; break;
default: default:
break; break;
} }
stream_forward_getp(s, lsa_len); stream_forward_getp(s, lsa_len);
length -= lsa_len; len -= lsa_len;
count--; count--;
} }

View File

@ -1715,13 +1715,23 @@ static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op)
* ------------------------------------ * ------------------------------------
*/ */
#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 */ /* Cisco experimental SubTLV */
static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty, static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty,
struct tlv_header *tlvh) 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, vty_out(vty,
" Remote Interface Address Sub-TLV: Length %u\n Address: %pI4\n", " Remote Interface Address Sub-TLV: Length %u\n Address: %pI4\n",
@ -1736,6 +1746,8 @@ static uint16_t show_vty_ext_link_adj_sid(struct vty *vty,
{ {
struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh; 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, 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", " 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, ntohs(top->header.length), top->flags, top->mtid, top->weight,
@ -1755,6 +1767,8 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty,
struct ext_subtlv_lan_adj_sid *top = struct ext_subtlv_lan_adj_sid *top =
(struct ext_subtlv_lan_adj_sid *)tlvh; (struct ext_subtlv_lan_adj_sid *)tlvh;
check_tlv_size(EXT_SUBTLV_LAN_ADJ_SID_SIZE, "Lan-Adjacency SID");
vty_out(vty, 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", " 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, ntohs(top->header.length), top->flags, top->mtid, top->weight,
@ -1768,8 +1782,15 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty,
return TLV_SIZE(tlvh); 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", vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length)); ntohs(tlvh->type), ntohs(tlvh->length));
@ -1777,13 +1798,22 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
} }
/* Extended Link Sub TLVs */ /* 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 ext_tlv_link *top = (struct ext_tlv_link *)ext;
struct tlv_header *tlvh; 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; 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, vty_out(vty,
" Extended Link TLV: Length %u\n Link Type: 0x%x\n" " Extended Link TLV: Length %u\n Link Type: 0x%x\n"
" Link ID: %pI4\n", " Link ID: %pI4\n",
@ -1791,9 +1821,11 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext)
&top->link_id); &top->link_id);
vty_out(vty, " Link data: %pI4\n", &top->link_data); 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 tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
+ EXT_TLV_LINK_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)) { switch (ntohs(tlvh->type)) {
case EXT_SUBTLV_ADJ_SID: case EXT_SUBTLV_ADJ_SID:
sum += show_vty_ext_link_adj_sid(vty, tlvh); sum += show_vty_ext_link_adj_sid(vty, tlvh);
@ -1805,7 +1837,7 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext)
sum += show_vty_ext_link_rmt_itf_addr(vty, tlvh); sum += show_vty_ext_link_rmt_itf_addr(vty, tlvh);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break; break;
} }
} }
@ -1821,16 +1853,16 @@ static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t length = 0, sum = 0; uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */ /* 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)) { tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case EXT_TLV_LINK: case EXT_TLV_LINK:
sum += show_vty_link_info(vty, tlvh); sum += show_vty_link_info(vty, tlvh, length - sum);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break; break;
} }
} }
@ -1843,6 +1875,8 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty,
struct ext_subtlv_prefix_sid *top = struct ext_subtlv_prefix_sid *top =
(struct ext_subtlv_prefix_sid *)tlvh; (struct ext_subtlv_prefix_sid *)tlvh;
check_tlv_size(EXT_SUBTLV_PREFIX_SID_SIZE, "Prefix SID");
vty_out(vty, 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", " 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, ntohs(top->header.length), top->algorithm, top->flags,
@ -1857,28 +1891,39 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty,
} }
/* Extended Prefix SubTLVs */ /* 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 ext_tlv_prefix *top = (struct ext_tlv_prefix *)ext;
struct tlv_header *tlvh; 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; 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, vty_out(vty,
" Extended Prefix TLV: Length %u\n\tRoute Type: %u\n" " Extended Prefix TLV: Length %u\n\tRoute Type: %u\n"
"\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %pI4/%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, ntohs(top->header.length), top->route_type, top->af, top->flags,
&top->address, top->pref_length); &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 tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
+ EXT_TLV_PREFIX_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)) { switch (ntohs(tlvh->type)) {
case EXT_SUBTLV_PREFIX_SID: case EXT_SUBTLV_PREFIX_SID:
sum += show_vty_ext_pref_pref_sid(vty, tlvh); sum += show_vty_ext_pref_pref_sid(vty, tlvh);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break; break;
} }
} }
@ -1894,16 +1939,16 @@ static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t length = 0, sum = 0; uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */ /* 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)) { tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case EXT_TLV_PREFIX: case EXT_TLV_PREFIX:
sum += show_vty_pref_info(vty, tlvh); sum += show_vty_pref_info(vty, tlvh, length - sum);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break; break;
} }
} }

View File

@ -233,19 +233,17 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
lsah = (struct lsa_header *)lsa->data; lsah = (struct lsa_header *)lsa->data;
length = ntohs(lsah->length);
/* Check LSA len */ /* Check LSA len */
if (length <= OSPF_LSA_HEADER_SIZE) { if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
if (IS_DEBUG_OSPF_GR_HELPER) if (IS_DEBUG_OSPF_GR_HELPER)
zlog_debug("%s: Malformed packet: Invalid LSA len:%d", zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
__func__, length); __func__, length);
return OSPF_GR_FAILURE; 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)) { tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len against overall LSA */ /* Check TLV len against overall LSA */
@ -996,18 +994,16 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
lsah = (struct lsa_header *)lsa->data; lsah = (struct lsa_header *)lsa->data;
length = ntohs(lsah->length); if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
if (length <= OSPF_LSA_HEADER_SIZE) {
vty_out(vty, "%% Invalid LSA length: %d\n", length); vty_out(vty, "%% Invalid LSA length: %d\n", length);
return; return;
} }
length -= OSPF_LSA_HEADER_SIZE; length = lsa->size - OSPF_LSA_HEADER_SIZE;
vty_out(vty, " TLV info:\n"); 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)) { tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len */ /* Check TLV len */
if (sum + TLV_SIZE(tlvh) > length) { if (sum + TLV_SIZE(tlvh) > length) {

View File

@ -175,6 +175,7 @@ struct ospf_lsa *ospf_lsa_new_and_data(size_t size)
new = ospf_lsa_new(); new = ospf_lsa_new();
new->data = ospf_lsa_data_new(size); new->data = ospf_lsa_data_new(size);
new->size = size;
return new; return new;
} }
@ -3241,22 +3242,22 @@ int ospf_lsa_different(struct ospf_lsa *l1, struct ospf_lsa *l2)
if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1)) if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1))
return 1; return 1;
if (l1->data->length != l2->data->length) if (l1->size != l2->size)
return 1; return 1;
if (l1->data->length == 0) if (l1->size == 0)
return 1; return 1;
if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED)) if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED))
return 1; /* May be a stale LSA in the LSBD */ 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; p1 = (char *)l1->data;
p2 = (char *)l2->data; p2 = (char *)l2->data;
if (memcmp(p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE, 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) != 0)
return 1; return 1;

View File

@ -84,8 +84,9 @@ struct ospf_lsa {
#define OSPF_LSA_PREMATURE_AGE 0x40 #define OSPF_LSA_PREMATURE_AGE 0x40
#define OSPF_LSA_IN_MAXAGE 0x80 #define OSPF_LSA_IN_MAXAGE 0x80
/* LSA data. */ /* LSA data. and size */
struct lsa_header *data; struct lsa_header *data;
size_t size;
/* Received time stamp. */ /* Received time stamp. */
struct timeval tv_recv; struct timeval tv_recv;
@ -168,7 +169,7 @@ struct router_lsa {
uint8_t flags; uint8_t flags;
uint8_t zero; uint8_t zero;
uint16_t links; uint16_t links;
struct { struct router_link {
struct in_addr link_id; struct in_addr link_id;
struct in_addr link_data; struct in_addr link_data;
uint8_t type; uint8_t type;
@ -199,7 +200,7 @@ struct summary_lsa {
struct as_external_lsa { struct as_external_lsa {
struct lsa_header header; struct lsa_header header;
struct in_addr mask; struct in_addr mask;
struct { struct as_route {
uint8_t tos; uint8_t tos;
uint8_t metric[3]; uint8_t metric[3];
struct in_addr fwd_addr; struct in_addr fwd_addr;

View File

@ -1204,9 +1204,10 @@ void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa,
void ospf_opaque_lsa_dump(struct stream *s, uint16_t length) 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.data = (struct lsa_header *)stream_pnt(s);
lsa.size = length;
show_opaque_info_detail(NULL, &lsa, NULL); show_opaque_info_detail(NULL, &lsa, NULL);
return; return;
} }

View File

@ -79,6 +79,7 @@
#define VALID_OPAQUE_INFO_LEN(lsahdr) \ #define VALID_OPAQUE_INFO_LEN(lsahdr) \
((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \ ((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \
&& ((ntohs((lsahdr)->length) < OSPF_MAX_LSA_SIZE)) \
&& ((ntohs((lsahdr)->length) % sizeof(uint32_t)) == 0)) && ((ntohs((lsahdr)->length) % sizeof(uint32_t)) == 0))
/* /*

View File

@ -294,8 +294,8 @@ static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce)
pce->pce_header.header.type = htons(RI_TLV_PCE); pce->pce_header.header.type = htons(RI_TLV_PCE);
/* Set PCE Address */ /* Set PCE Address */
pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS); pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS);
pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4); pce->pce_address.header.length = htons(PCE_ADDRESS_IPV4_SIZE);
pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4); pce->pce_address.address.type = htons(PCE_ADDRESS_IPV4);
pce->pce_address.address.value = ipv4; pce->pce_address.address.value = ipv4;
return; return;
@ -323,7 +323,7 @@ static void set_pce_domain(uint16_t type, uint32_t domain,
sizeof(struct ri_pce_subtlv_domain)); sizeof(struct ri_pce_subtlv_domain));
new->header.type = htons(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->type = htons(type);
new->value = htonl(domain); new->value = htonl(domain);
@ -369,7 +369,7 @@ static void set_pce_neighbor(uint16_t type, uint32_t domain,
sizeof(struct ri_pce_subtlv_neighbor)); sizeof(struct ri_pce_subtlv_neighbor));
new->header.type = htons(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->type = htons(type);
new->value = htonl(domain); new->value = htonl(domain);
@ -1226,10 +1226,25 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
* Followings are vty session control functions. * 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) 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; struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh;
check_tlv_size(RI_TLV_CAPABILITIES_SIZE, "Router Capabilities");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Router Capabilities: 0x%x\n", vty_out(vty, " Router Capabilities: 0x%x\n",
ntohl(top->value)); ntohl(top->value));
@ -1245,21 +1260,30 @@ static uint16_t show_vty_pce_subtlv_address(struct vty *vty,
struct ri_pce_subtlv_address *top = struct ri_pce_subtlv_address *top =
(struct ri_pce_subtlv_address *)tlvh; (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) if (vty != NULL)
vty_out(vty, " PCE Address: %pI4\n", vty_out(vty, " PCE Address: %pI4\n",
&top->address.value); &top->address.value);
else else
zlog_debug(" PCE Address: %pI4", zlog_debug(" PCE Address: %pI4",
&top->address.value); &top->address.value);
} else { } else if (ntohs(top->address.type) == PCE_ADDRESS_IPV6) {
/* TODO: Add support to IPv6 with inet_ntop() */ /* TODO: Add support to IPv6 with inet_ntop() */
check_tlv_size(PCE_ADDRESS_IPV6_SIZE, "PCE Address");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Address: 0x%x\n", vty_out(vty, " PCE Address: 0x%x\n",
ntohl(top->address.value.s_addr)); ntohl(top->address.value.s_addr));
else else
zlog_debug(" PCE Address: 0x%x", zlog_debug(" PCE Address: 0x%x",
ntohl(top->address.value.s_addr)); 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); return TLV_SIZE(tlvh);
@ -1271,6 +1295,8 @@ static uint16_t show_vty_pce_subtlv_path_scope(struct vty *vty,
struct ri_pce_subtlv_path_scope *top = struct ri_pce_subtlv_path_scope *top =
(struct ri_pce_subtlv_path_scope *)tlvh; (struct ri_pce_subtlv_path_scope *)tlvh;
check_tlv_size(RI_PCE_SUBTLV_PATH_SCOPE_SIZE, "PCE Path Scope");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value)); vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value));
else else
@ -1285,19 +1311,29 @@ static uint16_t show_vty_pce_subtlv_domain(struct vty *vty,
struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh; struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh;
struct in_addr tmp; struct in_addr tmp;
check_tlv_size(RI_PCE_SUBTLV_DOMAIN_SIZE, "PCE Domain");
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value; tmp.s_addr = top->value;
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE domain Area: %pI4\n", &tmp); vty_out(vty, " PCE Domain Area: %pI4\n", &tmp);
else else
zlog_debug(" PCE domain Area: %pI4", &tmp); zlog_debug(" PCE Domain Area: %pI4", &tmp);
} else { } else if (ntohs(top->type) == PCE_DOMAIN_TYPE_AS) {
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE domain AS: %d\n", vty_out(vty, " PCE Domain AS: %d\n",
ntohl(top->value)); ntohl(top->value));
else 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); return TLV_SIZE(tlvh);
} }
@ -1309,21 +1345,30 @@ static uint16_t show_vty_pce_subtlv_neighbor(struct vty *vty,
(struct ri_pce_subtlv_neighbor *)tlvh; (struct ri_pce_subtlv_neighbor *)tlvh;
struct in_addr tmp; struct in_addr tmp;
check_tlv_size(RI_PCE_SUBTLV_NEIGHBOR_SIZE, "PCE Neighbor");
if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) {
tmp.s_addr = top->value; tmp.s_addr = top->value;
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE neighbor Area: %pI4\n", vty_out(vty, " PCE Neighbor Area: %pI4\n", &tmp);
&tmp);
else else
zlog_debug(" PCE neighbor Area: %pI4", &tmp); 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",
ntohl(top->value));
else
zlog_debug(" PCE Neighbor AS: %d",
ntohl(top->value));
} else { } else {
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE neighbor AS: %d\n", vty_out(vty, " Wrong PCE Neighbor type: %d\n",
ntohl(top->value)); ntohl(top->type));
else else
zlog_debug(" PCE neighbor AS: %d", zlog_debug(" Wrong PCE Neighbor type: %d",
ntohl(top->value)); ntohl(top->type));
} }
return TLV_SIZE(tlvh); return TLV_SIZE(tlvh);
} }
@ -1333,6 +1378,8 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
struct ri_pce_subtlv_cap_flag *top = struct ri_pce_subtlv_cap_flag *top =
(struct ri_pce_subtlv_cap_flag *)tlvh; (struct ri_pce_subtlv_cap_flag *)tlvh;
check_tlv_size(RI_PCE_SUBTLV_CAP_FLAG_SIZE, "PCE Capabilities");
if (vty != NULL) if (vty != NULL)
vty_out(vty, " PCE Capabilities Flag: 0x%x\n", vty_out(vty, " PCE Capabilities Flag: 0x%x\n",
ntohl(top->value)); ntohl(top->value));
@ -1343,8 +1390,21 @@ static uint16_t show_vty_pce_subtlv_cap_flag(struct vty *vty,
return TLV_SIZE(tlvh); 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) if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length)); ntohs(tlvh->type), ntohs(tlvh->length));
@ -1356,12 +1416,21 @@ static uint16_t show_vty_unknown_tlv(struct vty *vty, struct tlv_header *tlvh)
} }
static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri, 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; struct tlv_header *tlvh;
uint16_t length = ntohs(ri->length);
uint16_t sum = 0; 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)) { switch (ntohs(tlvh->type)) {
case RI_PCE_SUBTLV_ADDRESS: case RI_PCE_SUBTLV_ADDRESS:
sum += show_vty_pce_subtlv_address(vty, tlvh); sum += show_vty_pce_subtlv_address(vty, tlvh);
@ -1379,7 +1448,7 @@ static uint16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
sum += show_vty_pce_subtlv_cap_flag(vty, tlvh); sum += show_vty_pce_subtlv_cap_flag(vty, tlvh);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, length - sum);
break; break;
} }
} }
@ -1393,6 +1462,8 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
(struct ri_sr_tlv_sr_algorithm *)tlvh; (struct ri_sr_tlv_sr_algorithm *)tlvh;
int i; int i;
check_tlv_size(ALGORITHM_COUNT, "Segment Routing Algorithm");
if (vty != NULL) { if (vty != NULL) {
vty_out(vty, " Segment Routing Algorithm TLV:\n"); vty_out(vty, " Segment Routing Algorithm TLV:\n");
for (i = 0; i < ntohs(algo->header.length); i++) { for (i = 0; i < ntohs(algo->header.length); i++) {
@ -1411,9 +1482,7 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
break; break;
} }
} }
} } else {
else {
zlog_debug(" Segment Routing Algorithm TLV:"); zlog_debug(" Segment Routing Algorithm TLV:");
for (i = 0; i < ntohs(algo->header.length); i++) for (i = 0; i < ntohs(algo->header.length); i++)
switch (algo->value[i]) { switch (algo->value[i]) {
@ -1439,6 +1508,8 @@ static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
struct ri_sr_tlv_sid_label_range *range = struct ri_sr_tlv_sid_label_range *range =
(struct ri_sr_tlv_sid_label_range *)tlvh; (struct ri_sr_tlv_sid_label_range *)tlvh;
check_tlv_size(RI_SR_TLV_LABEL_RANGE_SIZE, "SR Label Range");
if (vty != NULL) { if (vty != NULL) {
vty_out(vty, vty_out(vty,
" Segment Routing %s Range TLV:\n" " Segment Routing %s Range TLV:\n"
@ -1467,6 +1538,8 @@ static uint16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
{ {
struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh; 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) { if (vty != NULL) {
vty_out(vty, vty_out(vty,
" Segment Routing MSD TLV:\n" " Segment Routing MSD TLV:\n"
@ -1488,9 +1561,9 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t length = 0, sum = 0; uint16_t length = 0, sum = 0;
/* Initialize TLV browsing */ /* 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)) { tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case RI_TLV_CAPABILITIES: case RI_TLV_CAPABILITIES:
@ -1513,7 +1586,7 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, length);
break; break;
} }
} }

View File

@ -75,7 +75,7 @@
/* RFC4970: Router Information Capabilities TLV */ /* Mandatory */ /* RFC4970: Router Information Capabilities TLV */ /* Mandatory */
#define RI_TLV_CAPABILITIES 1 #define RI_TLV_CAPABILITIES 1
#define RI_TLV_CAPABILITIES_SIZE 4
struct ri_tlv_router_cap { struct ri_tlv_router_cap {
struct tlv_header header; /* Value length is 4 bytes. */ struct tlv_header header; /* Value length is 4 bytes. */
uint32_t value; uint32_t value;
@ -105,12 +105,12 @@ struct ri_tlv_pce {
struct ri_pce_subtlv_address { struct ri_pce_subtlv_address {
/* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */ /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */
struct tlv_header header; struct tlv_header header;
#define PCE_ADDRESS_LENGTH_IPV4 8 #define PCE_ADDRESS_IPV4_SIZE 8
#define PCE_ADDRESS_LENGTH_IPV6 20 #define PCE_ADDRESS_IPV6_SIZE 20
struct { struct {
uint16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */ uint16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */
#define PCE_ADDRESS_TYPE_IPV4 1 #define PCE_ADDRESS_IPV4 1
#define PCE_ADDRESS_TYPE_IPV6 2 #define PCE_ADDRESS_IPV6 2
uint16_t reserved; uint16_t reserved;
struct in_addr value; /* PCE address */ struct in_addr value; /* PCE address */
} address; } address;
@ -118,6 +118,7 @@ struct ri_pce_subtlv_address {
/* PCE Path-Scope Sub-TLV */ /* Mandatory */ /* PCE Path-Scope Sub-TLV */ /* Mandatory */
#define RI_PCE_SUBTLV_PATH_SCOPE 2 #define RI_PCE_SUBTLV_PATH_SCOPE 2
#define RI_PCE_SUBTLV_PATH_SCOPE_SIZE 4
struct ri_pce_subtlv_path_scope { struct ri_pce_subtlv_path_scope {
struct tlv_header header; /* Type = 2; Length = 4 bytes. */ struct tlv_header header; /* Type = 2; Length = 4 bytes. */
/* /*
@ -128,11 +129,11 @@ struct ri_pce_subtlv_path_scope {
}; };
/* PCE Domain Sub-TLV */ /* Optional */ /* PCE Domain Sub-TLV */ /* Optional */
#define RI_PCE_SUBTLV_DOMAIN 3
#define PCE_DOMAIN_TYPE_AREA 1 #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 ri_pce_subtlv_domain {
struct tlv_header header; /* Type = 3; Length = 8 bytes. */ struct tlv_header header; /* Type = 3; Length = 8 bytes. */
uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
@ -142,6 +143,7 @@ struct ri_pce_subtlv_domain {
/* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */ /* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */
#define RI_PCE_SUBTLV_NEIGHBOR 4 #define RI_PCE_SUBTLV_NEIGHBOR 4
#define RI_PCE_SUBTLV_NEIGHBOR_SIZE 8
struct ri_pce_subtlv_neighbor { struct ri_pce_subtlv_neighbor {
struct tlv_header header; /* Type = 4; Length = 8 bytes. */ struct tlv_header header; /* Type = 4; Length = 8 bytes. */
uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ uint16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */
@ -151,6 +153,7 @@ struct ri_pce_subtlv_neighbor {
/* PCE Capabilities Flags Sub-TLV */ /* Optional */ /* PCE Capabilities Flags Sub-TLV */ /* Optional */
#define RI_PCE_SUBTLV_CAP_FLAG 5 #define RI_PCE_SUBTLV_CAP_FLAG 5
#define RI_PCE_SUBTLV_CAP_FLAG_SIZE 4
#define PCE_CAP_GMPLS_LINK 0x0001 #define PCE_CAP_GMPLS_LINK 0x0001
#define PCE_CAP_BIDIRECTIONAL 0x0002 #define PCE_CAP_BIDIRECTIONAL 0x0002

View File

@ -954,7 +954,7 @@ static inline void update_adj_sid(struct sr_nhlfe n1, struct sr_nhlfe n2)
*/ */
/* Extended Link SubTLVs Getter */ /* 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 sr_link *srl;
@ -966,13 +966,20 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
struct tlv_header *sub_tlvh; struct tlv_header *sub_tlvh;
uint16_t length = 0, sum = 0, i = 0; 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)); srl = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_link));
/* Initialize TLV browsing */ /* Initialize TLV browsing */
length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE; length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE;
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
+ EXT_TLV_LINK_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)) { switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_ADJ_SID: case EXT_SUBTLV_ADJ_SID:
adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh; adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
@ -1025,7 +1032,8 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh)
} }
/* Extended Prefix SubTLVs Getter */ /* 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 sr_prefix *srp;
@ -1035,13 +1043,20 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh)
struct tlv_header *sub_tlvh; struct tlv_header *sub_tlvh;
uint16_t length = 0, sum = 0; 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)); srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
/* Initialize TLV browsing */ /* Initialize TLV browsing */
length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE; length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE;
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
+ EXT_TLV_PREFIX_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)) { switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_PREFIX_SID: case EXT_SUBTLV_PREFIX_SID:
psid = (struct ext_subtlv_prefix_sid *)sub_tlvh; psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
@ -1353,7 +1368,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
/* Collect Router Information Sub TLVs */ /* Collect Router Information Sub TLVs */
/* Initialize TLV browsing */ /* Initialize TLV browsing */
length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; length = lsa->size - OSPF_LSA_HEADER_SIZE;
srgb.range_size = 0; srgb.range_size = 0;
srgb.lower_bound = 0; srgb.lower_bound = 0;
@ -1362,24 +1377,20 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case RI_SR_TLV_SR_ALGORITHM: case RI_SR_TLV_SR_ALGORITHM:
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh; algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
sum += TLV_SIZE(tlvh);
break; break;
case RI_SR_TLV_SRGB_LABEL_RANGE: case RI_SR_TLV_SRGB_LABEL_RANGE:
ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh; ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh;
sum += TLV_SIZE(tlvh);
break; break;
case RI_SR_TLV_SRLB_LABEL_RANGE: case RI_SR_TLV_SRLB_LABEL_RANGE:
ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh; ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh;
sum += TLV_SIZE(tlvh);
break; break;
case RI_SR_TLV_NODE_MSD: case RI_SR_TLV_NODE_MSD:
msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value; msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value;
sum += TLV_SIZE(tlvh);
break; break;
default: default:
sum += TLV_SIZE(tlvh);
break; break;
} }
sum += TLV_SIZE(tlvh);
} }
/* Check if Segment Routing Capabilities has been found */ /* Check if Segment Routing Capabilities has been found */
@ -1519,7 +1530,7 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa)
struct lsa_header *lsah = lsa->data; struct lsa_header *lsah = lsa->data;
struct sr_link *srl; struct sr_link *srl;
uint16_t length, sum; int length;
osr_debug("SR (%s): Process Extended Link LSA 8.0.0.%u from %pI4", osr_debug("SR (%s): Process Extended Link LSA 8.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)), __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
@ -1546,20 +1557,19 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa)
} }
/* Initialize TLV browsing */ /* Initialize TLV browsing */
length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; length = lsa->size - OSPF_LSA_HEADER_SIZE;
sum = 0; for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh;
for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
tlvh = TLV_HDR_NEXT(tlvh)) { tlvh = TLV_HDR_NEXT(tlvh)) {
if (ntohs(tlvh->type) == EXT_TLV_LINK) { if (ntohs(tlvh->type) == EXT_TLV_LINK) {
/* Got Extended Link information */ /* Got Extended Link information */
srl = get_ext_link_sid(tlvh); srl = get_ext_link_sid(tlvh, length);
/* Update SID if not null */ /* Update SID if not null */
if (srl != NULL) { if (srl != NULL) {
srl->instance = ntohl(lsah->id.s_addr); srl->instance = ntohl(lsah->id.s_addr);
update_ext_link_sid(srn, srl, lsa->flags); update_ext_link_sid(srn, srl, lsa->flags);
} }
} }
sum += TLV_SIZE(tlvh); length -= TLV_SIZE(tlvh);
} }
} }
@ -1753,7 +1763,7 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa)
struct lsa_header *lsah = (struct lsa_header *)lsa->data; struct lsa_header *lsah = (struct lsa_header *)lsa->data;
struct sr_prefix *srp; struct sr_prefix *srp;
uint16_t length, sum; int length;
osr_debug("SR (%s): Process Extended Prefix LSA 7.0.0.%u from %pI4", osr_debug("SR (%s): Process Extended Prefix LSA 7.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)), __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
@ -1780,20 +1790,19 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa)
} }
/* Initialize TLV browsing */ /* Initialize TLV browsing */
length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; length = lsa->size - OSPF_LSA_HEADER_SIZE;
sum = 0; for (tlvh = TLV_HDR_TOP(lsah); length > 0 && tlvh;
for (tlvh = TLV_HDR_TOP(lsah); sum < length;
tlvh = TLV_HDR_NEXT(tlvh)) { tlvh = TLV_HDR_NEXT(tlvh)) {
if (ntohs(tlvh->type) == EXT_TLV_LINK) { if (ntohs(tlvh->type) == EXT_TLV_LINK) {
/* Got Extended Link information */ /* Got Extended Link information */
srp = get_ext_prefix_sid(tlvh); srp = get_ext_prefix_sid(tlvh, length);
/* Update SID if not null */ /* Update SID if not null */
if (srp != NULL) { if (srp != NULL) {
srp->instance = ntohl(lsah->id.s_addr); srp->instance = ntohl(lsah->id.s_addr);
update_ext_prefix_sid(srn, srp); update_ext_prefix_sid(srn, srp);
} }
} }
sum += TLV_SIZE(tlvh); length -= TLV_SIZE(tlvh);
} }
} }

View File

@ -88,6 +88,7 @@ struct ri_sr_tlv_sr_algorithm {
/* RI SID/Label Range TLV used for SRGB & SRLB - section 3.2 & 3.3 */ /* 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_SRGB_LABEL_RANGE 9
#define RI_SR_TLV_SRLB_LABEL_RANGE 14 #define RI_SR_TLV_SRLB_LABEL_RANGE 14
#define RI_SR_TLV_LABEL_RANGE_SIZE 12
struct ri_sr_tlv_sid_label_range { struct ri_sr_tlv_sid_label_range {
struct tlv_header header; struct tlv_header header;
/* Only 24 upper most bits are significant */ /* Only 24 upper most bits are significant */
@ -99,6 +100,7 @@ struct ri_sr_tlv_sid_label_range {
/* RI Node/MSD TLV as per RFC 8476 */ /* RI Node/MSD TLV as per RFC 8476 */
#define RI_SR_TLV_NODE_MSD 12 #define RI_SR_TLV_NODE_MSD 12
#define RI_SR_TLV_NODE_MSD_SIZE 4
struct ri_sr_tlv_node_msd { struct ri_sr_tlv_node_msd {
struct tlv_header header; struct tlv_header header;
uint8_t subtype; /* always = 1 */ uint8_t subtype; /* always = 1 */

View File

@ -1882,7 +1882,7 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
struct ls_edge *edge; struct ls_edge *edge;
struct ls_subnet *subnet; struct ls_subnet *subnet;
struct listnode *node; struct listnode *node;
int len; int len, links;
/* Sanity Check */ /* Sanity Check */
if (!ted || !lsa || !lsa->data) if (!ted || !lsa || !lsa->data)
@ -1932,8 +1932,9 @@ static int ospf_te_parse_router_lsa(struct ls_ted *ted, struct ospf_lsa *lsa)
subnet->status = ORPHAN; subnet->status = ORPHAN;
/* Then, process Link Information */ /* Then, process Link Information */
len = ntohs(rl->header.length) - 4; len = lsa->size - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE;
for (int i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) { links = ntohs(rl->links);
for (int i = 0; i < links && len > 0; len -= 12, i++) {
struct prefix p; struct prefix p;
uint32_t metric; uint32_t metric;
@ -2152,20 +2153,20 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
/* Initialize TLV browsing */ /* Initialize TLV browsing */
tlvh = TLV_HDR_TOP(lsa->data); 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 only TLV we are done */ /* if TE Router-ID is alone, we are done ... */
if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR if (len == TE_LINK_SUBTLV_DEF_SIZE)
&& total_len == sizeof(struct te_tlv_router_addr))
return 0; return 0;
/* Skip TE Router-ID if present */ /* ... otherwise, skip it */
if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR) len -= TE_LINK_SUBTLV_DEF_SIZE + TLV_HDR_SIZE;
tlvh = TLV_HDR_NEXT(tlvh); tlvh = TLV_HDR_NEXT(tlvh);
}
/* Check if we have a TE Link TLV */ /* Check if we have a valid TE Link TLV */
len = TLV_BODY_SIZE(tlvh);
if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK)) if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
return 0; return 0;
@ -2467,8 +2468,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
&lsa->data->id, &node->router_id); &lsa->data->id, &node->router_id);
/* Initialize TLV browsing */ /* Initialize TLV browsing */
len = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; len = lsa->size - OSPF_LSA_HEADER_SIZE;
for (tlvh = TLV_HDR_TOP(lsah); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) { 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_sr_algorithm *algo;
struct ri_sr_tlv_sid_label_range *range; struct ri_sr_tlv_sid_label_range *range;
struct ri_sr_tlv_node_msd *msd; struct ri_sr_tlv_node_msd *msd;
@ -3152,11 +3154,25 @@ static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf)
/*------------------------------------------------------------------------* /*------------------------------------------------------------------------*
* Followings are vty session control functions. * 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) 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; 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) if (vty != NULL)
vty_out(vty, " Router-Address: %pI4\n", &top->value); vty_out(vty, " Router-Address: %pI4\n", &top->value);
else else
@ -3165,10 +3181,23 @@ static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *tlvh)
return TLV_SIZE(tlvh); 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; 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) if (vty != NULL)
vty_out(vty, " Link: %u octets of data\n", vty_out(vty, " Link: %u octets of data\n",
ntohs(top->header.length)); ntohs(top->header.length));
@ -3185,6 +3214,8 @@ static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
struct te_link_subtlv_link_type *top; struct te_link_subtlv_link_type *top;
const char *cp = "Unknown"; const char *cp = "Unknown";
check_tlv_size(TE_LINK_SUBTLV_TYPE_SIZE, "Link Type");
top = (struct te_link_subtlv_link_type *)tlvh; top = (struct te_link_subtlv_link_type *)tlvh;
switch (top->link_type.value) { switch (top->link_type.value) {
case LINK_TYPE_SUBTLV_VALUE_PTP: case LINK_TYPE_SUBTLV_VALUE_PTP:
@ -3211,6 +3242,8 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
{ {
struct te_link_subtlv_link_id *top; 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; top = (struct te_link_subtlv_link_id *)tlvh;
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Link-ID: %pI4\n", &top->value); vty_out(vty, " Link-ID: %pI4\n", &top->value);
@ -3221,11 +3254,24 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
} }
static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty, 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; struct te_link_subtlv_lclif_ipaddr *top;
int i, n; 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; top = (struct te_link_subtlv_lclif_ipaddr *)tlvh;
n = ntohs(tlvh->length) / sizeof(top->value[0]); n = ntohs(tlvh->length) / sizeof(top->value[0]);
@ -3244,11 +3290,24 @@ static uint16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty,
} }
static uint16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty, 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; struct te_link_subtlv_rmtif_ipaddr *top;
int i, n; 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; top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh;
n = ntohs(tlvh->length) / sizeof(top->value[0]); n = ntohs(tlvh->length) / sizeof(top->value[0]);
if (vty != NULL) if (vty != NULL)
@ -3270,6 +3329,8 @@ static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
{ {
struct te_link_subtlv_te_metric *top; 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; top = (struct te_link_subtlv_te_metric *)tlvh;
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Traffic Engineering Metric: %u\n", vty_out(vty, " Traffic Engineering Metric: %u\n",
@ -3287,6 +3348,8 @@ static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
struct te_link_subtlv_max_bw *top; struct te_link_subtlv_max_bw *top;
float fval; float fval;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Bandwidth");
top = (struct te_link_subtlv_max_bw *)tlvh; top = (struct te_link_subtlv_max_bw *)tlvh;
fval = ntohf(top->value); fval = ntohf(top->value);
@ -3304,6 +3367,8 @@ static uint16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty,
struct te_link_subtlv_max_rsv_bw *top; struct te_link_subtlv_max_rsv_bw *top;
float fval; float fval;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Maximum Reservable Bandwidth");
top = (struct te_link_subtlv_max_rsv_bw *)tlvh; top = (struct te_link_subtlv_max_rsv_bw *)tlvh;
fval = ntohf(top->value); fval = ntohf(top->value);
@ -3324,6 +3389,8 @@ static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
float fval1, fval2; float fval1, fval2;
int i; int i;
check_tlv_size(TE_LINK_SUBTLV_UNRSV_SIZE, "Unreserved Bandwidth");
top = (struct te_link_subtlv_unrsv_bw *)tlvh; top = (struct te_link_subtlv_unrsv_bw *)tlvh;
if (vty != NULL) if (vty != NULL)
vty_out(vty, vty_out(vty,
@ -3353,6 +3420,8 @@ static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty,
{ {
struct te_link_subtlv_rsc_clsclr *top; 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; top = (struct te_link_subtlv_rsc_clsclr *)tlvh;
if (vty != NULL) if (vty != NULL)
vty_out(vty, " Resource class/color: 0x%x\n", vty_out(vty, " Resource class/color: 0x%x\n",
@ -3369,6 +3438,8 @@ static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
{ {
struct te_link_subtlv_lrrid *top; 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; top = (struct te_link_subtlv_lrrid *)tlvh;
if (vty != NULL) { if (vty != NULL) {
@ -3391,6 +3462,8 @@ static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
{ {
struct te_link_subtlv_llri *top; 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; top = (struct te_link_subtlv_llri *)tlvh;
if (vty != NULL) { if (vty != NULL) {
@ -3413,6 +3486,8 @@ static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
{ {
struct te_link_subtlv_rip *top; struct te_link_subtlv_rip *top;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote ASBR Address");
top = (struct te_link_subtlv_rip *)tlvh; top = (struct te_link_subtlv_rip *)tlvh;
if (vty != NULL) if (vty != NULL)
@ -3430,6 +3505,8 @@ static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
{ {
struct te_link_subtlv_ras *top; struct te_link_subtlv_ras *top;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Remote AS number");
top = (struct te_link_subtlv_ras *)tlvh; top = (struct te_link_subtlv_ras *)tlvh;
if (vty != NULL) if (vty != NULL)
@ -3449,6 +3526,8 @@ static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
uint32_t delay; uint32_t delay;
uint32_t anomalous; uint32_t anomalous;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Average Link Delay");
top = (struct te_link_subtlv_av_delay *)tlvh; top = (struct te_link_subtlv_av_delay *)tlvh;
delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK; delay = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL; anomalous = (uint32_t)ntohl(top->value) & TE_EXT_ANORMAL;
@ -3470,6 +3549,8 @@ static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
uint32_t low, high; uint32_t low, high;
uint32_t anomalous; uint32_t anomalous;
check_tlv_size(TE_LINK_SUBTLV_MM_DELAY_SIZE, "Min/Max Link Delay");
top = (struct te_link_subtlv_mm_delay *)tlvh; top = (struct te_link_subtlv_mm_delay *)tlvh;
low = (uint32_t)ntohl(top->low) & TE_EXT_MASK; low = (uint32_t)ntohl(top->low) & TE_EXT_MASK;
anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL; anomalous = (uint32_t)ntohl(top->low) & TE_EXT_ANORMAL;
@ -3491,6 +3572,8 @@ static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
struct te_link_subtlv_delay_var *top; struct te_link_subtlv_delay_var *top;
uint32_t jitter; uint32_t jitter;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Delay Variation");
top = (struct te_link_subtlv_delay_var *)tlvh; top = (struct te_link_subtlv_delay_var *)tlvh;
jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK; jitter = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
@ -3510,6 +3593,8 @@ static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
uint32_t anomalous; uint32_t anomalous;
float fval; float fval;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Link Loss");
top = (struct te_link_subtlv_pkt_loss *)tlvh; top = (struct te_link_subtlv_pkt_loss *)tlvh;
loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK; loss = (uint32_t)ntohl(top->value) & TE_EXT_MASK;
fval = (float)(loss * LOSS_PRECISION); fval = (float)(loss * LOSS_PRECISION);
@ -3531,6 +3616,8 @@ static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
struct te_link_subtlv_res_bw *top; struct te_link_subtlv_res_bw *top;
float fval; float fval;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Residual Bandwidth");
top = (struct te_link_subtlv_res_bw *)tlvh; top = (struct te_link_subtlv_res_bw *)tlvh;
fval = ntohf(top->value); fval = ntohf(top->value);
@ -3552,6 +3639,8 @@ static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
struct te_link_subtlv_ava_bw *top; struct te_link_subtlv_ava_bw *top;
float fval; float fval;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Available Bandwidth");
top = (struct te_link_subtlv_ava_bw *)tlvh; top = (struct te_link_subtlv_ava_bw *)tlvh;
fval = ntohf(top->value); fval = ntohf(top->value);
@ -3573,6 +3662,8 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
struct te_link_subtlv_use_bw *top; struct te_link_subtlv_use_bw *top;
float fval; float fval;
check_tlv_size(TE_LINK_SUBTLV_DEF_SIZE, "Utilized Bandwidth");
top = (struct te_link_subtlv_use_bw *)tlvh; top = (struct te_link_subtlv_use_bw *)tlvh;
fval = ntohf(top->value); fval = ntohf(top->value);
@ -3588,8 +3679,21 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
return TLV_SIZE(tlvh); 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) if (vty != NULL)
vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n",
ntohs(tlvh->type), ntohs(tlvh->length)); ntohs(tlvh->type), ntohs(tlvh->length));
@ -3607,8 +3711,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
struct tlv_header *tlvh; struct tlv_header *tlvh;
uint16_t sum = subtotal; uint16_t sum = subtotal;
for (tlvh = tlvh0; sum < total; for (tlvh = tlvh0; sum < total; tlvh = TLV_HDR_NEXT(tlvh)) {
tlvh = TLV_HDR_NEXT(tlvh)) {
switch (ntohs(tlvh->type)) { switch (ntohs(tlvh->type)) {
case TE_LINK_SUBTLV_LINK_TYPE: case TE_LINK_SUBTLV_LINK_TYPE:
sum += show_vty_link_subtlv_link_type(vty, tlvh); sum += show_vty_link_subtlv_link_type(vty, tlvh);
@ -3617,10 +3720,12 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
sum += show_vty_link_subtlv_link_id(vty, tlvh); sum += show_vty_link_subtlv_link_id(vty, tlvh);
break; break;
case TE_LINK_SUBTLV_LCLIF_IPADDR: 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; break;
case TE_LINK_SUBTLV_RMTIF_IPADDR: 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; break;
case TE_LINK_SUBTLV_TE_METRIC: case TE_LINK_SUBTLV_TE_METRIC:
sum += show_vty_link_subtlv_te_metric(vty, tlvh); sum += show_vty_link_subtlv_te_metric(vty, tlvh);
@ -3671,7 +3776,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
sum += show_vty_link_subtlv_use_bw(vty, tlvh); sum += show_vty_link_subtlv_use_bw(vty, tlvh);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
break; break;
} }
} }
@ -3687,9 +3792,9 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
uint16_t subtotal, uint16_t total) = NULL; uint16_t subtotal, uint16_t total) = NULL;
sum = 0; 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))) { tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) {
if (subfunc != NULL) { if (subfunc != NULL) {
sum = (*subfunc)(vty, tlvh, sum, total); sum = (*subfunc)(vty, tlvh, sum, total);
@ -3704,12 +3809,12 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa)
sum += show_vty_router_addr(vty, tlvh); sum += show_vty_router_addr(vty, tlvh);
break; break;
case TE_TLV_LINK: 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; subfunc = ospf_mpls_te_show_link_subtlv;
next = TLV_DATA(tlvh); next = TLV_DATA(tlvh);
break; break;
default: default:
sum += show_vty_unknown_tlv(vty, tlvh); sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
break; break;
} }
} }
@ -4081,10 +4186,12 @@ static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp)
show_vty_link_subtlv_link_id(vty, &lp->link_id.header); show_vty_link_subtlv_link_id(vty, &lp->link_id.header);
if (TLV_TYPE(lp->lclif_ipaddr) != 0) if (TLV_TYPE(lp->lclif_ipaddr) != 0)
show_vty_link_subtlv_lclif_ipaddr( 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) if (TLV_TYPE(lp->rmtif_ipaddr) != 0)
show_vty_link_subtlv_rmtif_ipaddr( 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) if (TLV_TYPE(lp->rip) != 0)
show_vty_link_subtlv_rip(vty, &lp->rip.header); show_vty_link_subtlv_rip(vty, &lp->rip.header);
if (TLV_TYPE(lp->ras) != 0) if (TLV_TYPE(lp->ras) != 0)

View File

@ -6400,6 +6400,7 @@ static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
if (lsa != NULL) { if (lsa != NULL) {
struct network_lsa *nl = (struct network_lsa *)lsa->data; struct network_lsa *nl = (struct network_lsa *)lsa->data;
struct in_addr *addr;
show_ip_ospf_database_header(vty, lsa, json); show_ip_ospf_database_header(vty, lsa, json);
@ -6410,23 +6411,24 @@ static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa,
json_object_int_add(json, "networkMask", json_object_int_add(json, "networkMask",
ip_masklen(nl->mask)); ip_masklen(nl->mask));
length = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4; length = lsa->size - OSPF_LSA_HEADER_SIZE - 4;
addr = &nl->routers[0];
for (i = 0; length > 0; i++, length -= 4) for (i = 0; length > 0 && addr;
length -= 4, addr = &nl->routers[++i])
if (!json) { if (!json) {
vty_out(vty, " Attached Router: %pI4\n", vty_out(vty, " Attached Router: %pI4\n",
&nl->routers[i]); addr);
vty_out(vty, "\n"); vty_out(vty, "\n");
} else { } else {
json_router = json_object_new_object(); json_router = json_object_new_object();
json_object_string_add( json_object_string_add(
json_router, "attachedRouterId", json_router, "attachedRouterId",
inet_ntop(AF_INET, &nl->routers[i], inet_ntop(AF_INET, addr, buf,
buf, sizeof(buf))); sizeof(buf)));
json_object_object_add( json_object_object_add(json_attached_rt,
json_attached_rt, inet_ntop(AF_INET, addr,
inet_ntop(AF_INET, &(nl->routers[i]), buf,
buf, sizeof(buf)), sizeof(buf)),
json_router); json_router);
} }
} }