summaryrefslogtreecommitdiff
path: root/ospfd/ospf_gr_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_gr_helper.c')
-rw-r--r--ospfd/ospf_gr_helper.c137
1 files changed, 126 insertions, 11 deletions
diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c
index a7b20d1f07..616013fb9e 100644
--- a/ospfd/ospf_gr_helper.c
+++ b/ospfd/ospf_gr_helper.c
@@ -50,26 +50,26 @@
#include "ospfd/ospf_ism.h"
#include "ospfd/ospf_gr_helper.h"
-const char *ospf_exit_reason_desc[] = {
+static const char * const ospf_exit_reason_desc[] = {
"Unknown reason",
"Helper inprogress",
"Topology Change",
- "Grace timer expairy",
+ "Grace timer expiry",
"Successful graceful restart",
};
-const char *ospf_restart_reason_desc[] = {
+static const char * const ospf_restart_reason_desc[] = {
"Unknown restart",
"Software restart",
"Software reload/upgrade",
"Switch to redundant control processor",
};
-const char *ospf_rejected_reason_desc[] = {
+static const char * const ospf_rejected_reason_desc[] = {
"Unknown reason",
"Helper support disabled",
"Neighbour is not in FULL state",
- "Supports only planned restart but received for unplanned",
+ "Supports only planned restart but received unplanned",
"Topo change due to change in lsa rxmt list",
"LSA age is more than Grace interval",
};
@@ -118,6 +118,39 @@ static void ospf_enable_rtr_hash_destroy(struct ospf *ospf)
}
/*
+ * GR exit reason strings
+ */
+const char *ospf_exit_reason2str(unsigned int reason)
+{
+ if (reason < array_size(ospf_exit_reason_desc))
+ return(ospf_exit_reason_desc[reason]);
+ else
+ return "Invalid reason";
+}
+
+/*
+ * GR restart reason strings
+ */
+const char *ospf_restart_reason2str(unsigned int reason)
+{
+ if (reason < array_size(ospf_restart_reason_desc))
+ return(ospf_restart_reason_desc[reason]);
+ else
+ return "Invalid reason";
+}
+
+/*
+ * GR rejected reason strings
+ */
+const char *ospf_rejected_reason2str(unsigned int reason)
+{
+ if (reason < array_size(ospf_rejected_reason_desc))
+ return(ospf_rejected_reason_desc[reason]);
+ else
+ return "Invalid reason";
+}
+
+/*
* Initialize GR helper config data structures.
*
* OSPF
@@ -200,12 +233,38 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
lsah = (struct lsa_header *)lsa->data;
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = ntohs(lsah->length);
+
+ /* Check LSA len */
+ if (length <= OSPF_LSA_HEADER_SIZE) {
+ if (IS_DEBUG_OSPF_GR_HELPER)
+ zlog_debug("%s: Malformed packet: Invalid LSA len:%d",
+ __func__, length);
+ return OSPF_GR_FAILURE;
+ }
+
+ length -= OSPF_LSA_HEADER_SIZE;
for (tlvh = TLV_HDR_TOP(lsah); sum < length;
tlvh = TLV_HDR_NEXT(tlvh)) {
+
+ /* Check TLV len against overall LSA */
+ if (sum + TLV_SIZE(tlvh) > length) {
+ if (IS_DEBUG_OSPF_GR_HELPER)
+ zlog_debug("%s: Malformed packet: Invalid TLV len:%zu",
+ __func__, TLV_SIZE(tlvh));
+ return OSPF_GR_FAILURE;
+ }
+
switch (ntohs(tlvh->type)) {
case GRACE_PERIOD_TYPE:
+ if (TLV_SIZE(tlvh) <
+ sizeof(struct grace_tlv_graceperiod)) {
+ zlog_debug("%s: Malformed packet: Invalid grace TLV len:%zu",
+ __func__, TLV_SIZE(tlvh));
+ return OSPF_GR_FAILURE;
+ }
+
grace_period = (struct grace_tlv_graceperiod *)tlvh;
*interval = ntohl(grace_period->interval);
sum += TLV_SIZE(tlvh);
@@ -216,6 +275,13 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
return OSPF_GR_FAILURE;
break;
case RESTART_REASON_TYPE:
+ if (TLV_SIZE(tlvh) <
+ sizeof(struct grace_tlv_restart_reason)) {
+ zlog_debug("%s: Malformed packet: Invalid reason TLV len:%zu",
+ __func__, TLV_SIZE(tlvh));
+ return OSPF_GR_FAILURE;
+ }
+
gr_reason = (struct grace_tlv_restart_reason *)tlvh;
*reason = gr_reason->reason;
sum += TLV_SIZE(tlvh);
@@ -224,6 +290,13 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
return OSPF_GR_FAILURE;
break;
case RESTARTER_IP_ADDR_TYPE:
+ if (TLV_SIZE(tlvh) <
+ sizeof(struct grace_tlv_restart_addr)) {
+ zlog_debug("%s: Malformed packet: Invalid addr TLV len:%zu",
+ __func__, TLV_SIZE(tlvh));
+ return OSPF_GR_FAILURE;
+ }
+
restart_addr = (struct grace_tlv_restart_addr *)tlvh;
addr->s_addr = restart_addr->addr.s_addr;
sum += TLV_SIZE(tlvh);
@@ -306,7 +379,8 @@ int ospf_process_grace_lsa(struct ospf *ospf, struct ospf_lsa *lsa,
zlog_debug(
"%s, Grace LSA received from %s, grace interval:%u, restartreason :%s",
__PRETTY_FUNCTION__, inet_ntoa(restart_addr),
- grace_interval, ospf_restart_reason_desc[restart_reason]);
+ grace_interval,
+ ospf_restart_reason2str(restart_reason));
/* Incase of broadcast links, if RESTARTER is DR_OTHER,
* grace LSA might be received from DR, so need to get
@@ -524,7 +598,7 @@ void ospf_helper_handle_topo_chg(struct ospf *ospf, struct ospf_lsa *lsa)
if (!ospf->active_restarter_cnt)
return;
- /* Topo change not required to be hanlded if strict
+ /* Topo change not required to be handled if strict
* LSA check is disbaled for this router.
*/
if (!ospf->strict_lsa_check)
@@ -598,7 +672,7 @@ void ospf_gr_helper_exit(struct ospf_neighbor *nbr,
if (IS_DEBUG_OSPF_GR_HELPER)
zlog_debug("%s, Exiting from HELPER support to %s, due to %s",
__PRETTY_FUNCTION__, inet_ntoa(nbr->src),
- ospf_exit_reason_desc[reason]);
+ ospf_exit_reason2str(reason));
/* Reset helper status*/
nbr->gr_helper_info.gr_helper_status = OSPF_GR_NOT_HELPER;
@@ -929,14 +1003,36 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
lsah = (struct lsa_header *)lsa->data;
- length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE;
+ length = ntohs(lsah->length);
+
+ if (length <= OSPF_LSA_HEADER_SIZE) {
+ vty_out(vty, "%% Invalid LSA length: %d\n", length);
+ return;
+ }
+
+ length -= OSPF_LSA_HEADER_SIZE;
vty_out(vty, " TLV info:\n");
for (tlvh = TLV_HDR_TOP(lsah); sum < length;
tlvh = TLV_HDR_NEXT(tlvh)) {
+ /* Check TLV len */
+ if (sum + TLV_SIZE(tlvh) > length) {
+ vty_out(vty, "%% Invalid TLV length: %zu\n",
+ TLV_SIZE(tlvh));
+ return;
+ }
+
switch (ntohs(tlvh->type)) {
case GRACE_PERIOD_TYPE:
+ if (TLV_SIZE(tlvh) <
+ sizeof(struct grace_tlv_graceperiod)) {
+ vty_out(vty,
+ "%% Invalid grace TLV length %zu\n",
+ TLV_SIZE(tlvh));
+ return;
+ }
+
gracePeriod = (struct grace_tlv_graceperiod *)tlvh;
sum += TLV_SIZE(tlvh);
@@ -944,13 +1040,29 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
ntohl(gracePeriod->interval));
break;
case RESTART_REASON_TYPE:
+ if (TLV_SIZE(tlvh) <
+ sizeof(struct grace_tlv_restart_reason)) {
+ vty_out(vty,
+ "%% Invalid reason TLV length %zu\n",
+ TLV_SIZE(tlvh));
+ return;
+ }
+
grReason = (struct grace_tlv_restart_reason *)tlvh;
sum += TLV_SIZE(tlvh);
vty_out(vty, " Restart reason:%s\n",
- ospf_restart_reason_desc[grReason->reason]);
+ ospf_restart_reason2str(grReason->reason));
break;
case RESTARTER_IP_ADDR_TYPE:
+ if (TLV_SIZE(tlvh) <
+ sizeof(struct grace_tlv_restart_addr)) {
+ vty_out(vty,
+ "%% Invalid addr TLV length %zu\n",
+ TLV_SIZE(tlvh));
+ return;
+ }
+
restartAddr = (struct grace_tlv_restart_addr *)tlvh;
sum += TLV_SIZE(tlvh);
@@ -958,6 +1070,9 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
inet_ntoa(restartAddr->addr));
break;
default:
+ vty_out(vty, " Unknown TLV type %d\n",
+ ntohs(tlvh->type));
+
break;
}
}