diff options
| -rw-r--r-- | bgpd/bgp_filter.c | 6 | ||||
| -rw-r--r-- | ospfclient/ospf_apiclient.c | 18 | ||||
| -rw-r--r-- | ospfd/ospf_gr_helper.c | 137 | ||||
| -rw-r--r-- | ospfd/ospf_gr_helper.h | 6 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 45 | ||||
| -rw-r--r-- | pimd/pim_ifchannel.c | 45 | ||||
| -rw-r--r-- | pimd/pim_join.c | 21 |
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); |
