summaryrefslogtreecommitdiff
path: root/ospfd/ospf_te.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_te.c')
-rw-r--r--ospfd/ospf_te.c167
1 files changed, 137 insertions, 30 deletions
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 1929e3dea4..0946e51077 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -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_subnet *subnet;
struct listnode *node;
- int len;
+ int len, links;
/* Sanity Check */
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;
/* 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;
@@ -2152,20 +2153,20 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
/* 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;
@@ -2467,8 +2468,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
&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;
@@ -3152,11 +3154,25 @@ static void ospf_te_init_ted(struct ls_ted *ted, struct ospf *ospf)
/*------------------------------------------------------------------------*
* 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
@@ -3165,10 +3181,23 @@ static uint16_t show_vty_router_addr(struct vty *vty, struct tlv_header *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;
+ 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));
@@ -3185,6 +3214,8 @@ static uint16_t show_vty_link_subtlv_link_type(struct vty *vty,
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:
@@ -3211,6 +3242,8 @@ static uint16_t show_vty_link_subtlv_link_id(struct vty *vty,
{
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);
@@ -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,
- 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]);
@@ -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,
- 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)
@@ -3270,6 +3329,8 @@ static uint16_t show_vty_link_subtlv_te_metric(struct vty *vty,
{
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",
@@ -3287,6 +3348,8 @@ static uint16_t show_vty_link_subtlv_max_bw(struct vty *vty,
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);
@@ -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;
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);
@@ -3324,6 +3389,8 @@ static uint16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty,
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,
@@ -3353,6 +3420,8 @@ static uint16_t show_vty_link_subtlv_rsc_clsclr(struct vty *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",
@@ -3369,6 +3438,8 @@ static uint16_t show_vty_link_subtlv_lrrid(struct vty *vty,
{
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) {
@@ -3391,6 +3462,8 @@ static uint16_t show_vty_link_subtlv_llri(struct vty *vty,
{
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) {
@@ -3413,6 +3486,8 @@ static uint16_t show_vty_link_subtlv_rip(struct vty *vty,
{
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)
@@ -3430,6 +3505,8 @@ static uint16_t show_vty_link_subtlv_ras(struct vty *vty,
{
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)
@@ -3449,6 +3526,8 @@ static uint16_t show_vty_link_subtlv_av_delay(struct vty *vty,
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;
@@ -3470,6 +3549,8 @@ static uint16_t show_vty_link_subtlv_mm_delay(struct vty *vty,
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;
@@ -3491,6 +3572,8 @@ static uint16_t show_vty_link_subtlv_delay_var(struct vty *vty,
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;
@@ -3510,6 +3593,8 @@ static uint16_t show_vty_link_subtlv_pkt_loss(struct vty *vty,
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);
@@ -3531,6 +3616,8 @@ static uint16_t show_vty_link_subtlv_res_bw(struct vty *vty,
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);
@@ -3552,6 +3639,8 @@ static uint16_t show_vty_link_subtlv_ava_bw(struct vty *vty,
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);
@@ -3573,6 +3662,8 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
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);
@@ -3588,8 +3679,21 @@ static uint16_t show_vty_link_subtlv_use_bw(struct vty *vty,
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));
@@ -3607,8 +3711,7 @@ static uint16_t ospf_mpls_te_show_link_subtlv(struct vty *vty,
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);
@@ -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);
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);
@@ -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);
break;
default:
- sum += show_vty_unknown_tlv(vty, tlvh);
+ sum += show_vty_unknown_tlv(vty, tlvh, total - sum);
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;
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);
@@ -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);
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;
}
}
@@ -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);
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)