From 0250758d15469b160d9ead86805d0c108e85697d Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 10 Nov 2015 18:33:15 +0100 Subject: [PATCH] isisd: handle lsp confusion (ISO/IEC 10589:2002 7.3.16.2) Signed-off-by: Christian Franke Acked-by: Donald Sharp --- isisd/isis_lsp.c | 14 +++++++++++++- isisd/isis_pdu.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 291fa20ab6..3801eb737b 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -273,7 +273,19 @@ lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, return LSP_EQUAL; } - if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num)) + /* + * LSPs with identical checksums should only be treated as newer if: + * a) The current LSP has a remaining lifetime != 0 and the other LSP has a + * remaining lifetime == 0. In this case, we should participate in the purge + * and should not treat the current LSP with remaining lifetime == 0 as older. + * b) The LSP has an incorrect checksum. In this case, we need to react as given + * in 7.3.16.2. + */ + if (ntohl (seq_num) > ntohl (lsp->lsp_header->seq_num) + || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num) + && ( (lsp->lsp_header->rem_lifetime != 0 + && rem_lifetime == 0) + || lsp->lsp_header->checksum != checksum))) { if (isis->debugs & DEBUG_SNP_PACKETS) { diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 02d6fffc72..7f5a570799 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1281,6 +1281,7 @@ process_lsp (int level, struct isis_circuit *circuit, const u_char *ssnpa) u_char lspid[ISIS_SYS_ID_LEN + 2]; struct isis_passwd *passwd; uint16_t pdu_len; + int lsp_confusion; if (isis->debugs & DEBUG_UPDATE_PACKETS) { @@ -1455,6 +1456,21 @@ dontcheckadj: /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */ + /* 7.3.16.2 - If this is an LSP from another IS with identical seq_num but + * wrong checksum, initiate a purge. */ + if (lsp + && (lsp->lsp_header->seq_num == hdr->seq_num) + && (lsp->lsp_header->checksum != hdr->checksum)) + { + zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + ntohl(hdr->seq_num)); + hdr->rem_lifetime = 0; + lsp_confusion = 1; + } + else + lsp_confusion = 0; + /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ if (hdr->rem_lifetime == 0) { @@ -1477,14 +1493,20 @@ dontcheckadj: lsp_update (lsp, circuit->rcv_stream, circuit->area, level); /* ii */ lsp_set_all_srmflags (lsp); - /* iii */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); /* v */ ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */ - /* iv */ - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - ISIS_SET_FLAG (lsp->SSNflags, circuit); + /* For the case of lsp confusion, flood the purge back to its + * originator so that it can react. Otherwise, don't reflood + * through incoming circuit as usual */ + if (!lsp_confusion) + { + /* iii */ + ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); + /* iv */ + if (circuit->circ_type != CIRCUIT_T_BROADCAST) + ISIS_SET_FLAG (lsp->SSNflags, circuit); + } } /* 7.3.16.4 b) 2) */ else if (comp == LSP_EQUAL) {