diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index d209ae053c..cc1b2919c0 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2954,6 +2954,32 @@ static int ospf_maxage_lsa_remover(struct thread *thread) return 0; } +/* This function checks whether an LSA with initial sequence number should be + * originated after a wrap in sequence number + */ +void ospf_check_and_gen_init_seq_lsa(struct ospf_interface *oi, + struct ospf_lsa *recv_lsa) +{ + struct ospf_lsa *lsa = NULL; + struct ospf *ospf = oi->ospf; + + lsa = ospf_lsa_lookup_by_header(oi->area, recv_lsa->data); + + if ((lsa == NULL) || (!CHECK_FLAG(lsa->flags, OSPF_LSA_PREMATURE_AGE)) + || (lsa->retransmit_counter != 0)) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Do not generate LSA with initial seqence number."); + return; + } + + ospf_lsa_maxage_delete(ospf, lsa); + + lsa->data->ls_seqnum = lsa_seqnum_increment(lsa); + + ospf_lsa_refresh(ospf, lsa); +} + void ospf_lsa_maxage_delete(struct ospf *ospf, struct ospf_lsa *lsa) { struct route_node *rn; diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index d01dc720ba..5dcd072774 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -218,6 +218,8 @@ struct as_external_lsa { #define LS_AGE(x) (OSPF_LSA_MAXAGE < get_age(x) ? OSPF_LSA_MAXAGE : get_age(x)) #define IS_LSA_SELF(L) (CHECK_FLAG ((L)->flags, OSPF_LSA_SELF)) #define IS_LSA_MAXAGE(L) (LS_AGE ((L)) == OSPF_LSA_MAXAGE) +#define IS_LSA_MAX_SEQ(L) \ + ((L)->data->ls_seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)) #define OSPF_LSA_UPDATE_DELAY 2 @@ -347,6 +349,8 @@ extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, extern struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, struct ospf_lsa *type7, struct ospf_lsa *type5); +extern void ospf_check_and_gen_init_seq_lsa(struct ospf_interface *oi, + struct ospf_lsa *lsa); extern void ospf_flush_lsa_from_area(struct ospf *ospf, struct in_addr area_id, int type); #endif /* _ZEBRA_OSPF_LSA_H */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 9930b0bd49..000bbadc54 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2089,11 +2089,10 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, if (current == NULL || (ret = ospf_lsa_more_recent(current, lsa)) < 0) { /* CVE-2017-3224 */ - if (current && (lsa->data->ls_seqnum == - htonl(OSPF_MAX_SEQUENCE_NUMBER) - && !IS_LSA_MAXAGE(lsa))) { + if (current && (IS_LSA_MAX_SEQ(current)) + && (IS_LSA_MAX_SEQ(lsa)) && !IS_LSA_MAXAGE(lsa)) { zlog_debug( - "Link State Update[%s]: has Max Seq but not MaxAge. Dropping it", + "Link State Update[%s]: has Max Seq and higher checksum but not MaxAge. Dropping it", dump_lsa_key(lsa)); DISCARD_LSA(lsa, 4); @@ -2271,8 +2270,10 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, lsr = ospf_ls_retransmit_lookup(nbr, lsa); - if (lsr != NULL && ospf_lsa_more_recent(lsr, lsa) == 0) + if (lsr != NULL && ospf_lsa_more_recent(lsr, lsa) == 0) { ospf_ls_retransmit_delete(nbr, lsr); + ospf_check_and_gen_init_seq_lsa(oi, lsa); + } lsa->data = NULL; ospf_lsa_discard(lsa);