summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_filter.c6
-rw-r--r--ospfclient/ospf_apiclient.c18
-rw-r--r--ospfd/ospf_gr_helper.c137
-rw-r--r--ospfd/ospf_gr_helper.h6
-rw-r--r--ospfd/ospf_vty.c45
-rw-r--r--pimd/pim_ifchannel.c45
-rw-r--r--pimd/pim_join.c21
7 files changed, 226 insertions, 52 deletions
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index 0308a30d54..3162579688 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -507,14 +507,16 @@ DEFUN(no_as_path, no_bgp_as_path_cmd,
/* Lookup asfilter. */
asfilter = as_filter_lookup(aslist, regstr, type);
- XFREE(MTYPE_TMP, regstr);
bgp_regex_free(regex);
if (asfilter == NULL) {
- vty_out(vty, "\n");
+ vty_out(vty, "Regex entered %s does not exist\n", regstr);
+ XFREE(MTYPE_TMP, regstr);
return CMD_WARNING_CONFIG_FAILED;
}
+ XFREE(MTYPE_TMP, regstr);
+
as_list_filter_delete(aslist, asfilter);
return CMD_SUCCESS;
diff --git a/ospfclient/ospf_apiclient.c b/ospfclient/ospf_apiclient.c
index fb8ad3e60a..d4f0dc953c 100644
--- a/ospfclient/ospf_apiclient.c
+++ b/ospfclient/ospf_apiclient.c
@@ -565,6 +565,7 @@ static void ospf_apiclient_handle_lsa_update(struct ospf_apiclient *oclient,
{
struct msg_lsa_change_notify *cn;
struct lsa_header *lsa;
+ void *p;
uint16_t lsalen;
cn = (struct msg_lsa_change_notify *)STREAM_DATA(msg->s);
@@ -578,9 +579,11 @@ static void ospf_apiclient_handle_lsa_update(struct ospf_apiclient *oclient,
__func__, lsalen, OSPF_MAX_LSA_SIZE);
return;
}
- lsa = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen);
- memcpy(lsa, &(cn->data), lsalen);
+ p = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen);
+
+ memcpy(p, &(cn->data), lsalen);
+ lsa = p;
/* Invoke registered update callback function */
if (oclient->update_notify) {
@@ -589,7 +592,7 @@ static void ospf_apiclient_handle_lsa_update(struct ospf_apiclient *oclient,
}
/* free memory allocated by ospf apiclient library */
- XFREE(MTYPE_OSPF_APICLIENT, lsa);
+ XFREE(MTYPE_OSPF_APICLIENT, p);
}
static void ospf_apiclient_handle_lsa_delete(struct ospf_apiclient *oclient,
@@ -597,6 +600,7 @@ static void ospf_apiclient_handle_lsa_delete(struct ospf_apiclient *oclient,
{
struct msg_lsa_change_notify *cn;
struct lsa_header *lsa;
+ void *p;
uint16_t lsalen;
cn = (struct msg_lsa_change_notify *)STREAM_DATA(msg->s);
@@ -610,9 +614,11 @@ static void ospf_apiclient_handle_lsa_delete(struct ospf_apiclient *oclient,
__func__, lsalen, OSPF_MAX_LSA_SIZE);
return;
}
- lsa = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen);
- memcpy(lsa, &(cn->data), lsalen);
+ p = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen);
+
+ memcpy(p, &(cn->data), lsalen);
+ lsa = p;
/* Invoke registered update callback function */
if (oclient->delete_notify) {
@@ -621,7 +627,7 @@ static void ospf_apiclient_handle_lsa_delete(struct ospf_apiclient *oclient,
}
/* free memory allocated by ospf apiclient library */
- XFREE(MTYPE_OSPF_APICLIENT, lsa);
+ XFREE(MTYPE_OSPF_APICLIENT, p);
}
static void ospf_apiclient_msghandle(struct ospf_apiclient *oclient,
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;
}
}
diff --git a/ospfd/ospf_gr_helper.h b/ospfd/ospf_gr_helper.h
index 4e83028fe6..c355bb4f3d 100644
--- a/ospfd/ospf_gr_helper.h
+++ b/ospfd/ospf_gr_helper.h
@@ -152,9 +152,9 @@ struct advRtr {
#define OSPF_GR_FAILURE 0
#define OSPF_GR_INVALID -1
-extern const char *ospf_exit_reason_desc[];
-extern const char *ospf_restart_reason_desc[];
-extern const char *ospf_rejected_reason_desc[];
+const char *ospf_exit_reason2str(unsigned int reason);
+const char *ospf_restart_reason2str(unsigned int reason);
+const char *ospf_rejected_reason2str(unsigned int reason);
extern void ospf_gr_helper_init(struct ospf *ospf);
extern void ospf_gr_helper_stop(struct ospf *ospf);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 87c1c91afb..5c82e11393 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -5132,9 +5132,8 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
" Graceful Restart grace period time: %d (seconds).\n",
nbr->gr_helper_info.recvd_grace_period);
vty_out(vty, " Graceful Restart reason: %s.\n",
- ospf_restart_reason_desc
- [nbr->gr_helper_info
- .gr_restart_reason]);
+ ospf_restart_reason2str(
+ nbr->gr_helper_info.gr_restart_reason));
} else {
vty_out(vty,
" Graceful Restart HELPER Status : None\n");
@@ -5143,15 +5142,14 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
if (nbr->gr_helper_info.rejected_reason
!= OSPF_HELPER_REJECTED_NONE)
vty_out(vty, " Helper rejected reason: %s.\n",
- ospf_rejected_reason_desc
- [nbr->gr_helper_info.rejected_reason]);
+ ospf_rejected_reason2str(
+ nbr->gr_helper_info.rejected_reason));
if (nbr->gr_helper_info.helper_exit_reason
!= OSPF_GR_HELPER_EXIT_NONE)
vty_out(vty, " Last helper exit reason: %s.\n\n",
- ospf_exit_reason_desc
- [nbr->gr_helper_info
- .helper_exit_reason]);
+ ospf_exit_reason2str(
+ nbr->gr_helper_info.helper_exit_reason));
else
vty_out(vty, "\n");
} else {
@@ -5165,25 +5163,24 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
nbr->gr_helper_info.recvd_grace_period);
json_object_string_add(
json_neigh, "grRestartReason",
- ospf_restart_reason_desc
- [nbr->gr_helper_info
- .gr_restart_reason]);
+ ospf_restart_reason2str(
+ nbr->gr_helper_info.gr_restart_reason));
}
if (nbr->gr_helper_info.rejected_reason
!= OSPF_HELPER_REJECTED_NONE)
json_object_string_add(
json_neigh, "helperRejectReason",
- ospf_rejected_reason_desc
- [nbr->gr_helper_info.rejected_reason]);
+ ospf_rejected_reason2str(
+ nbr->gr_helper_info.rejected_reason));
if (nbr->gr_helper_info.helper_exit_reason
!= OSPF_GR_HELPER_EXIT_NONE)
json_object_string_add(
json_neigh, "helperExitReason",
- ospf_exit_reason_desc
- [nbr->gr_helper_info
- .helper_exit_reason]);
+ ospf_exit_reason2str(
+ nbr->gr_helper_info
+ .helper_exit_reason));
}
ospf_bfd_show_info(vty, nbr->bfd_info, json_neigh, use_json, 0);
@@ -9308,7 +9305,7 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
if (ospf->last_exit_reason != OSPF_GR_HELPER_EXIT_NONE) {
vty_out(vty, " Last Helper exit Reason :%s\n",
- ospf_exit_reason_desc[ospf->last_exit_reason]);
+ ospf_exit_reason2str(ospf->last_exit_reason));
}
if (ospf->active_restarter_cnt)
@@ -9337,7 +9334,7 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
if (ospf->last_exit_reason != OSPF_GR_HELPER_EXIT_NONE)
json_object_string_add(
json_vrf, "LastExitReason",
- ospf_exit_reason_desc[ospf->last_exit_reason]);
+ ospf_exit_reason2str(ospf->last_exit_reason));
if (ospf->active_restarter_cnt)
json_object_int_add(json_vrf, "activeRestarterCnt",
@@ -9402,9 +9399,9 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
.t_grace_timer));
vty_out(vty,
" Graceful Restart reason: %s.\n\n",
- ospf_restart_reason_desc
- [nbr->gr_helper_info
- .gr_restart_reason]);
+ ospf_restart_reason2str(
+ nbr->gr_helper_info
+ .gr_restart_reason));
cnt++;
} else {
json_neigh = json_object_new_object();
@@ -9432,9 +9429,9 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
.t_grace_timer));
json_object_string_add(
json_neigh, "restartReason",
- ospf_restart_reason_desc
- [nbr->gr_helper_info
- .gr_restart_reason]);
+ ospf_restart_reason2str(
+ nbr->gr_helper_info
+ .gr_restart_reason));
json_object_object_add(
json_neighbors,
inet_ntoa(nbr->src),
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 212c77c039..b2971e5f1f 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -950,14 +950,44 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
pim_ifchannel_ifjoin_handler(ch, pim_ifp);
break;
case PIM_IFJOIN_PRUNE_PENDING:
+ /*
+ * Transitions from Prune-Pending State (Receive Join)
+ * RFC 7761 Sec 4.5.2:
+ * The (S,G) downstream state machine on interface I
+ * transitions to the Join state. The Prune-Pending Timer is
+ * canceled (without triggering an expiry event). The
+ * Expiry Timer (ET) is restarted and is then set to the
+ * maximum of its current value and the HoldTime from the
+ * triggering Join/Prune message.
+ */
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
- if (source_flags & PIM_ENCODE_RPT_BIT) {
+
+ /* Check if SGRpt join Received */
+ if ((source_flags & PIM_ENCODE_RPT_BIT)
+ && (sg->src.s_addr != INADDR_ANY)) {
+ /*
+ * Transitions from Prune-Pending State (Rcv SGRpt Join)
+ * RFC 7761 Sec 4.5.3:
+ * The (S,G,rpt) downstream state machine on interface
+ * I transitions to the NoInfo state.The ET and PPT are
+ * cancelled.
+ */
THREAD_OFF(ch->t_ifjoin_expiry_timer);
pim_ifchannel_ifjoin_switch(__func__, ch,
PIM_IFJOIN_NOINFO);
- } else {
- pim_ifchannel_ifjoin_handler(ch, pim_ifp);
+ return;
}
+
+ pim_ifchannel_ifjoin_handler(ch, pim_ifp);
+
+ if (ch->t_ifjoin_expiry_timer) {
+ unsigned long remain = thread_timer_remain_second(
+ ch->t_ifjoin_expiry_timer);
+
+ if (remain > holdtime)
+ return;
+ }
+
break;
case PIM_IFJOIN_PRUNE_TMP:
break;
@@ -1034,7 +1064,14 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
/* nothing to do */
break;
case PIM_IFJOIN_JOIN:
- THREAD_OFF(ch->t_ifjoin_expiry_timer);
+ /*
+ * The (S,G) downstream state machine on interface I
+ * transitions to the Prune-Pending state. The
+ * Prune-Pending Timer is started. It is set to the
+ * J/P_Override_Interval(I) if the router has more than one
+ * neighbor on that interface; otherwise, it is set to zero,
+ * causing it to expire immediately.
+ */
pim_ifchannel_ifjoin_switch(__func__, ch,
PIM_IFJOIN_PRUNE_PENDING);
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index 3a88de2070..f54d5bf9bf 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -173,6 +173,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
uint8_t *pastend;
int remain;
int group;
+ struct pim_ifchannel *child = NULL;
+ struct listnode *ch_node, *nch_node;
buf = tlv_buf;
pastend = tlv_buf + tlv_buf_size;
@@ -337,9 +339,24 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
*/
sg_ch = pim_ifchannel_find(ifp, &sg);
+ if (!sg_ch)
+ continue;
+
+ /* (*,G) prune received */
+ for (ALL_LIST_ELEMENTS(sg_ch->sources, ch_node,
+ nch_node, child)) {
+ if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) {
+ if (child->ifjoin_state
+ == PIM_IFJOIN_PRUNE_PENDING_TMP)
+ THREAD_OFF(
+ child->t_ifjoin_prune_pending_timer);
+ PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
+ child->ifjoin_state = PIM_IFJOIN_NOINFO;
+ }
+ }
+
/* Received SG-RPT Prune delete oif from specific S,G */
- if (starg_ch && sg_ch
- && (msg_source_flags & PIM_RPT_BIT_MASK)
+ if (starg_ch && (msg_source_flags & PIM_RPT_BIT_MASK)
&& !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) {
struct pim_upstream *up = sg_ch->upstream;
PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags);