Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 111 additions & 11 deletions ospfd/ospf_sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
struct tlv_header *sub_tlvh;
uint32_t length = 0, sum = 0;
uint16_t i = 0;
bool error_p = false;

/* Check TLV size */
if ((ntohs(tlvh->length) > size)
Expand All @@ -1012,6 +1013,12 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)

switch (ntohs(sub_tlvh->type)) {
case EXT_SUBTLV_ADJ_SID:
/* Validate sub-TLV length */
if (TLV_BODY_SIZE(sub_tlvh) != EXT_SUBTLV_ADJ_SID_SIZE) {
error_p = true;
break;
}

adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
srl->type = ADJ_SID;
i = CHECK_FLAG(adj_sid->flags,
Expand All @@ -1027,6 +1034,12 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
IPV4_ADDR_COPY(&srl->nhlfe[i].nexthop, &link->link_id);
break;
case EXT_SUBTLV_LAN_ADJ_SID:
/* Validate sub-TLV length */
if (TLV_BODY_SIZE(sub_tlvh) != EXT_SUBTLV_LAN_ADJ_SID_SIZE) {
error_p = true;
break;
}

lan_sid = (struct ext_subtlv_lan_adj_sid *)sub_tlvh;
srl->type = LAN_ADJ_SID;
i = CHECK_FLAG(lan_sid->flags,
Expand All @@ -1043,18 +1056,37 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
&lan_sid->neighbor_id);
break;
case EXT_SUBTLV_RMT_ITF_ADDR:
/* Validate sub-TLV length */
if (TLV_BODY_SIZE(sub_tlvh) != EXT_SUBTLV_RMT_ITF_ADDR_SIZE) {
error_p = true;
break;
}

rmt_itf = (struct ext_subtlv_rmt_itf_addr *)sub_tlvh;
IPV4_ADDR_COPY(&srl->nhlfe[0].nexthop, &rmt_itf->value);
IPV4_ADDR_COPY(&srl->nhlfe[1].nexthop, &rmt_itf->value);
break;
default:
break;
}

if (error_p)
break;

sum += tlv_size;
if (sum < length)
sub_tlvh = TLV_HDR_NEXT(sub_tlvh);
if (sum >= length || ((length - sum) < TLV_HDR_SIZE))
break;

sub_tlvh = TLV_HDR_NEXT(sub_tlvh);
}

if (error_p) {
zlog_warn("Invalid Extended Link sub-TLV!");
XFREE(MTYPE_OSPF_SR_PARAMS, srl);
return NULL;
}


IPV4_ADDR_COPY(&srl->itf_addr, &link->link_data);

osr_debug(" |- Found primary %u and backup %u Adj/Lan Sid for %pI4",
Expand Down Expand Up @@ -1389,10 +1421,22 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
struct lsa_header *lsah = lsa->data;
struct ri_sr_tlv_sid_label_range *ri_srgb = NULL;
struct ri_sr_tlv_sid_label_range *ri_srlb = NULL;
struct ri_sr_tlv_sr_algorithm *algo = NULL;
struct sr_block srgb;
uint32_t length = 0, sum = 0;
uint8_t msd = 0;
bool error_p = false;
int i;
uint8_t *p;
/* Temp struct to copy flex-algo values from a TLV */
struct algo_s {
uint16_t length;
uint8_t value[ALGORITHM_COUNT];
} algo = {};

if (lsa->size <= OSPF_LSA_HEADER_SIZE) {
zlog_warn("Invalid SR Router-Information LSA");
return;
}

osr_debug("SR (%s): Process Router Information LSA 4.0.0.%u from %pI4",
__func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
Expand All @@ -1416,6 +1460,11 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
/* Collect Router Information Sub TLVs */
/* Initialize TLV browsing */
length = lsa->size - OSPF_LSA_HEADER_SIZE;
if (length <= TLV_HDR_SIZE) {
zlog_warn("Malformed Router-Information TLV");
return;
}

srgb.range_size = 0;
srgb.lower_bound = 0;

Expand All @@ -1425,28 +1474,80 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
if (tlv_size > length - sum) {
zlog_warn("Malformed RI TLV size %u (remaining %u)", tlv_size,
length - sum);
error_p = true;
break;
}

switch (ntohs(tlvh->type)) {
case RI_SR_TLV_SR_ALGORITHM:
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
/* Validate sub-TLV length: variable-length, in octets */
i = ntohs(tlvh->length);
if (i < 1 || i > ALGORITHM_COUNT) {
error_p = true;
break;
}

/* Must only use first TLV, if multiple are present */
if (algo.length > 0)
break;

/* Init algo octets */
for (i = 0; i < ALGORITHM_COUNT; i++)
algo.value[i] = SR_ALGORITHM_UNSET;

/* Copy octets from TLV to local buffer. Note that length is
* in host-order.
*/
p = TLV_DATA(tlvh);
algo.length = ntohs(tlvh->length);
for (i = 0; i < algo.length; i++)
algo.value[i] = *(p + i);

break;
case RI_SR_TLV_SRGB_LABEL_RANGE:
/* Validate sub-TLV length */
if (TLV_BODY_SIZE(tlvh) < RI_SR_TLV_LABEL_RANGE_SIZE) {
error_p = true;
break;
}

ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh;
break;
case RI_SR_TLV_SRLB_LABEL_RANGE:
/* Validate sub-TLV length */
if (TLV_BODY_SIZE(tlvh) < RI_SR_TLV_LABEL_RANGE_SIZE) {
error_p = true;
break;
}

ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh;
break;
case RI_SR_TLV_NODE_MSD:
/* Validate sub-TLV length */
if (TLV_BODY_SIZE(tlvh) < RI_SR_TLV_NODE_MSD_SIZE) {
error_p = true;
break;
}

msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value;
break;
default:
break;
}

if (error_p)
break;

sum += tlv_size;
if (sum < length)
tlvh = TLV_HDR_NEXT(tlvh);
if (sum >= length || ((length - sum) < TLV_HDR_SIZE))
break;

tlvh = TLV_HDR_NEXT(tlvh);
}

if (error_p) {
zlog_warn("Invalid RI sub-TLV");
return;
}

/* Check if Segment Routing Capabilities has been found */
Expand Down Expand Up @@ -1493,16 +1594,15 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
}

/* Update Algorithm, SRLB and MSD if present */
if (algo != NULL) {
int i;
for (i = 0;
i < ntohs(algo->header.length) && i < ALGORITHM_COUNT; i++)
srn->algo[i] = algo->value[0];
if (algo.length > 0) {
for (i = 0; i < algo.length && i < ALGORITHM_COUNT; i++)
srn->algo[i] = algo.value[i];
for (; i < ALGORITHM_COUNT; i++)
srn->algo[i] = SR_ALGORITHM_UNSET;
} else {
srn->algo[0] = SR_ALGORITHM_SPF;
}

srn->msd = msd;
if (ri_srlb != NULL) {
srn->srlb.range_size = GET_RANGE_SIZE(ntohl(ri_srlb->size));
Expand Down
Loading
Loading