From 5574999e598eee290c7e43a2b3a7aafd27be0ee0 Mon Sep 17 00:00:00 2001 From: Fritz Reichmann Date: Wed, 14 Sep 2011 19:31:51 +0400 Subject: isisd: fix crash on "no router isis" (BZ#536) The crash is due to threads accessing data that gets destroyed during the removal of the configuration. * isis_circuit.c: Destroy adjacencies to stop adjacency expiry thread. Stop PSNP threads. * isisd.c: Change state of circuit back to INIT and reassign the circuit structure to isis->init_circ_list rather than destroying the circuit data structure. Stop SPF threads. Stop LSP generation threads. * isisd.h: Add pointers to LSP threads into area structure in order to stop them in isisd.c * isis_lsp.c: Store pointer to LSP thread in area structure. * isis_pdu.c: Stop PDU generation for a circuit with a removed area. * isis_pfpacket.c: Stop processing received PDUs for a circuit with a removed area. --- isisd/isis_pdu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index a2ab0649..26330a4d 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1781,6 +1781,9 @@ isis_receive (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); + if (!circuit->area) + return ISIS_OK; + if (circuit->rcv_stream == NULL) circuit->rcv_stream = stream_new (ISO_MTU (circuit)); else @@ -2088,6 +2091,11 @@ send_lan_l2_hello (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); + + if (!circuit->area) { + return ISIS_OK; + } + circuit->u.bc.t_send_lan_hello[1] = NULL; if (circuit->u.bc.run_dr_elect[1]) -- cgit v1.2.1 From 89980759568ec5f5f50c225ef25a00938fc86c72 Mon Sep 17 00:00:00 2001 From: Fritz Reichmann Date: Wed, 14 Sep 2011 20:46:57 +0400 Subject: isisd: raise hello rate for DIS (BZ#539) * isis_pdu.c: Divide hello interval by three, depending if we are DIS or not. --- isisd/isis_pdu.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 26330a4d..4ea3ebd6 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1943,6 +1943,9 @@ send_hello (struct isis_circuit *circuit, int level) memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr)); interval = circuit->hello_multiplier[level - 1] * circuit->hello_interval[level - 1]; + /* If we are the DIS then hello interval is divided by three, as is the hold-timer */ + if (circuit->u.bc.is_dr[level - 1]) + interval=interval/3; if (interval > USHRT_MAX) interval = USHRT_MAX; hello_hdr.circuit_t = circuit->circuit_is_type; @@ -2065,9 +2068,21 @@ send_lan_l1_hello (struct thread *thread) { struct isis_circuit *circuit; int retval; + unsigned long next_hello; circuit = THREAD_ARG (thread); assert (circuit); + + if (!circuit->area) { + return ISIS_OK; + } + + /* Pseudonode sends hellos three times more than the other nodes */ + if (circuit->u.bc.is_dr[0]) + next_hello=circuit->hello_interval[0]/3+1; + else + next_hello=circuit->hello_interval[0]; + circuit->u.bc.t_send_lan_hello[0] = NULL; if (circuit->u.bc.run_dr_elect[0]) @@ -2078,7 +2093,7 @@ send_lan_l1_hello (struct thread *thread) /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0], send_lan_l1_hello, circuit, - isis_jitter (circuit->hello_interval[0], IIH_JITTER)); + isis_jitter (next_hello, IIH_JITTER)); return retval; } @@ -2088,6 +2103,7 @@ send_lan_l2_hello (struct thread *thread) { struct isis_circuit *circuit; int retval; + unsigned long next_hello; circuit = THREAD_ARG (thread); assert (circuit); @@ -2096,6 +2112,12 @@ send_lan_l2_hello (struct thread *thread) return ISIS_OK; } + /* Pseudonode sends hellos three times more than the other nodes */ + if (circuit->u.bc.is_dr[1]) + next_hello=circuit->hello_interval[1]/3+1; + else + next_hello=circuit->hello_interval[1]; + circuit->u.bc.t_send_lan_hello[1] = NULL; if (circuit->u.bc.run_dr_elect[1]) @@ -2106,7 +2128,7 @@ send_lan_l2_hello (struct thread *thread) /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1], send_lan_l2_hello, circuit, - isis_jitter (circuit->hello_interval[1], IIH_JITTER)); + isis_jitter (next_hello, IIH_JITTER)); return retval; } -- cgit v1.2.1 From 306ca83213aabe069f1645d1708bbc4f278e2a63 Mon Sep 17 00:00:00 2001 From: Peter Szilagyi Date: Tue, 13 Sep 2011 17:37:06 +0400 Subject: isisd: include hash.h, not hash.c --- isisd/isis_pdu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 4ea3ebd6..0896d540 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -29,7 +29,7 @@ #include "log.h" #include "stream.h" #include "vty.h" -#include "hash.c" +#include "hash.h" #include "prefix.h" #include "if.h" #include "checksum.h" -- cgit v1.2.1 From 7fd6cd819ff98f0580b745ba637990df9c20ef0f Mon Sep 17 00:00:00 2001 From: Peter Szilagyi Date: Sat, 1 Oct 2011 17:11:45 +0400 Subject: isisd: fix circuit state machine isisd has a so-called circuit state machine that takes care about the interface state changes, such as initializing, down, up. When an interface was brought down by a link failure, the interface information was deleted and set to NULL. When the link was restored later, the interface was looked up by the old pointer, but since it was cleared, it was never found again, resulting in an interface never entering the up state again. Also, the program regularly crashed because of a deleted pointer in the same context which was later accessed without any further checking. Signed-off-by: Fritz Reichmann --- isisd/isis_pdu.c | 129 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 69 insertions(+), 60 deletions(-) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 0896d540..4c602eea 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1916,6 +1916,9 @@ send_hello (struct isis_circuit *circuit, int level) unsigned long len_pointer, length; int retval; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + if (circuit->interface->mtu == 0) { zlog_warn ("circuit has zero MTU"); @@ -2222,6 +2225,9 @@ send_csnp (struct isis_circuit *circuit, int level) struct listnode *node; struct isis_lsp *lsp; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + memset (start, 0x00, ISIS_SYS_ID_LEN + 2); memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); @@ -2387,6 +2393,9 @@ send_psnp (int level, struct isis_circuit *circuit) struct list *list = NULL; struct listnode *node; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + if ((circuit->circ_type == CIRCUIT_T_BROADCAST && !circuit->u.bc.is_dr[level - 1]) || circuit->circ_type != CIRCUIT_T_BROADCAST) @@ -2493,85 +2502,85 @@ send_lsp (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); - if (circuit->state == C_STATE_UP) + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + + lsp = listgetdata ((node = listhead (circuit->lsp_queue))); + + /* + * Do not send if levels do not match + */ + if (!(lsp->level & circuit->circuit_is_type)) + goto dontsend; + + /* + * Do not send if we do not have adjacencies in state up on the circuit + */ + if (circuit->upadjcount[lsp->level - 1] == 0) + goto dontsend; + /* only send if it needs sending */ + if ((time (NULL) - lsp->last_sent) >= + circuit->area->lsp_gen_interval[lsp->level - 1]) { - lsp = listgetdata ((node = listhead (circuit->lsp_queue))); - /* - * Do not send if levels do not match - */ - if (!(lsp->level & circuit->circuit_is_type)) - goto dontsend; + if (isis->debugs & DEBUG_UPDATE_PACKETS) + { + zlog_debug + ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," + " lifetime %us on %s", circuit->area->area_tag, lsp->level, + rawlspid_print (lsp->lsp_header->lsp_id), + ntohl (lsp->lsp_header->seq_num), + ntohs (lsp->lsp_header->checksum), + ntohs (lsp->lsp_header->rem_lifetime), + circuit->interface->name); + } + /* copy our lsp to the send buffer */ + stream_copy (circuit->snd_stream, lsp->pdu); + + retval = circuit->tx (circuit, lsp->level); /* - * Do not send if we do not have adjacencies in state up on the circuit + * If the sending succeeded, we can del the lsp from circuits + * lsp_queue */ - if (circuit->upadjcount[lsp->level - 1] == 0) - goto dontsend; - /* only send if it needs sending */ - if ((time (NULL) - lsp->last_sent) >= - circuit->area->lsp_gen_interval[lsp->level - 1]) + if (retval == ISIS_OK) { - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug - ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," - " lifetime %us on %s", circuit->area->area_tag, lsp->level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - circuit->interface->name); - } - /* copy our lsp to the send buffer */ - stream_copy (circuit->snd_stream, lsp->pdu); - - retval = circuit->tx (circuit, lsp->level); + list_delete_node (circuit->lsp_queue, node); /* - * If the sending succeeded, we can del the lsp from circuits - * lsp_queue + * On broadcast circuits also the SRMflag can be cleared */ - if (retval == ISIS_OK) - { - list_delete_node (circuit->lsp_queue, node); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); + if (flags_any_set (lsp->SRMflags) == 0) + { /* - * On broadcast circuits also the SRMflag can be cleared + * need to remember when we were last sent */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - - if (flags_any_set (lsp->SRMflags) == 0) - { - /* - * need to remember when we were last sent - */ - lsp->last_sent = time (NULL); - } - } - else - { - zlog_debug ("sending of level %d link state failed", lsp->level); + lsp->last_sent = time (NULL); } } else { - /* my belief is that if it wasn't his time, the lsp can be removed - * from the queue - */ - dontsend: - list_delete_node (circuit->lsp_queue, node); + zlog_debug ("sending of level %d link state failed", lsp->level); } -#if 0 - /* - * If there are still LSPs send next one after lsp-interval (33 msecs) + } + else + { + /* my belief is that if it wasn't his time, the lsp can be removed + * from the queue */ - if (listcount (circuit->lsp_queue) > 0) - thread_add_timer (master, send_lsp, circuit, 1); -#endif + dontsend: + list_delete_node (circuit->lsp_queue, node); } +#if 0 + /* + * If there are still LSPs send next one after lsp-interval (33 msecs) + */ + if (listcount (circuit->lsp_queue) > 0) + thread_add_timer (master, send_lsp, circuit, 1); +#endif return retval; } -- cgit v1.2.1 From 907fd95e502e10334e5390c73cc57588b88b8171 Mon Sep 17 00:00:00 2001 From: Peter Szilagyi Date: Sat, 1 Oct 2011 17:15:46 +0400 Subject: isisd: send proper LSP after DIS election After an IS has been elected as the Designated IS for a LAN, it did not refresh the content of the pseudo-node after a new node has been connected to the same LAN. Instead, the periodically reoriginated pseudo-node LSP still contained only those IS neighbors that were already present when the DIS election process was commenced. The fix for the problem schedules an LSP regeneration rather than just reoriginating the same LSP with the old content. Signed-off-by: Fritz Reichmann --- isisd/isis_pdu.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 4c602eea..3d2629a8 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1187,6 +1187,7 @@ dontcheckadj: /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */ if ((!lsp || comp == LSP_NEWER)) { + int regenerate = (lsp == NULL); /* i */ if (lsp) { @@ -1232,6 +1233,9 @@ dontcheckadj: if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG (lsp->SSNflags, circuit); /* FIXME: v) */ + if (regenerate && circuit->u.bc.is_dr[level - 1]) { + lsp_l1_pseudo_generate (circuit); + } } /* 7.3.15.1 e) 2) LSP equal to the one in db */ else if (comp == LSP_EQUAL) -- cgit v1.2.1 From d034aa027ef44d0a74805c27ad2a4d8ea20395d1 Mon Sep 17 00:00:00 2001 From: Peter Szilagyi Date: Sat, 1 Oct 2011 17:22:51 +0400 Subject: isisd: fix wrong next-hops from SPF The forwarding table was filled with wrong next-hops, and which is even worse, it was done in a totally non-deterministic way. The next-hop set for an IP prefix by isisd was the neighbor IS from which the flooded LSP about the IP prefix was arrived. So, if an IS received all the LSPs through its, say, eth0 interface, all entries in the forwarding table contained the next IS reachable via eth0 as the next-hop. The solution is to propagate the correct next-hop further from node to node as the SPF algorithm traverses the graph and selects the next node to be added to the set of already covered nodes. Also, the construction of the tentative node list (the nodes where the shortest path is not known yet) was buggy: if a node was already a member of this list with a certain path cost, and an alternative path was found to it with a lower cost while processing a pseudo-node LSP, it was not added to the list. This way, the path selected by isisd for a certain prefix was the first one it encountered during the LSDB processing. Signed-off-by: Fritz Reichmann --- isisd/isis_pdu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 3d2629a8..e55d3365 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1222,7 +1222,6 @@ dontcheckadj: ntohs (hdr->pdu_len), lsp0, circuit->area); lsp->level = level; - lsp->adj = adj; lsp_insert (lsp, circuit->area->lspdb[level - 1]); /* ii */ ISIS_FLAGS_SET_ALL (lsp->SRMflags); @@ -1254,8 +1253,7 @@ dontcheckadj: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); } } - if (lsp) - lsp->adj = adj; + return retval; } -- cgit v1.2.1 From c25eaffdb2190149e768dc4ee4efc913c6d02992 Mon Sep 17 00:00:00 2001 From: Fritz Reichmann Date: Sat, 1 Oct 2011 17:43:12 +0400 Subject: isisd: unexpected kernel routing table (BZ#544) Fix bug 544: isisd produces an unexpected routing table for wide-metric. * isis_spf.c: Accept VTYPE_PSEUDO_TE_IS and VTYPE_NONPSEUDO_TE_IS vertex types for SPF calculation * isis_pdu.c: Change order of TLVs to match Cisco to make bitwise comparison easier for Wireshark * isis_tlv.c: EXTREME_TLV_DEBUG for TLV debugging instead of EXTREME_DEBUG --- isisd/isis_pdu.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index e55d3365..dfc613cf 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1992,29 +1992,18 @@ send_hello (struct isis_circuit *circuit, int level) if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, circuit->passwd.passwd, circuit->snd_stream)) return ISIS_WARNING; + + /* Protocols Supported TLV */ + if (circuit->nlpids.count > 0) + if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) + return ISIS_WARNING; + /* Area Addresses TLV */ assert (circuit->area); if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0) if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) return ISIS_WARNING; - /* LAN Neighbors TLV */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], - circuit->snd_stream)) - return ISIS_WARNING; - if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], - circuit->snd_stream)) - return ISIS_WARNING; - } - - /* Protocols Supported TLV */ - if (circuit->nlpids.count > 0) - if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) - return ISIS_WARNING; /* IP interface Address TLV */ if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0) if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream)) @@ -2028,6 +2017,22 @@ send_hello (struct isis_circuit *circuit, int level) return ISIS_WARNING; #endif /* HAVE_IPV6 */ + /* Restart signaling, vendor C sends it too */ + retval = add_tlv (211, 3, 0, circuit->snd_stream); + + /* LAN Neighbors TLV */ + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + { + if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0) + if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], + circuit->snd_stream)) + return ISIS_WARNING; + if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0) + if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], + circuit->snd_stream)) + return ISIS_WARNING; + } + if (circuit->u.bc.pad_hellos) if (tlv_add_padding (circuit->snd_stream)) return ISIS_WARNING; @@ -2284,9 +2289,7 @@ send_l1_csnp (struct thread *thread) circuit->t_send_csnp[0] = NULL; if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0]) - { send_csnp (circuit, 1); - } /* set next timer thread */ THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit, isis_jitter (circuit->csnp_interval[0], CSNP_JITTER)); @@ -2306,9 +2309,7 @@ send_l2_csnp (struct thread *thread) circuit->t_send_csnp[1] = NULL; if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1]) - { send_csnp (circuit, 2); - } /* set next timer thread */ THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit, isis_jitter (circuit->csnp_interval[1], CSNP_JITTER)); -- cgit v1.2.1 From e6b03b77766dce8009ad7b4a2392e14addf4ab0f Mon Sep 17 00:00:00 2001 From: Fritz Reichmann Date: Sat, 1 Oct 2011 17:49:48 +0400 Subject: isisd: implement MD5 circuit authentication * Replace command "isis passwd" with "isis passwd {clear|md5}" * Verify HMAC MD5 on ISIS Hello PDUs * Add HMAC MD5 authentication to md5.h/md5.c from RFC2104 --- isisd/isis_pdu.c | 66 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 15 deletions(-) (limited to 'isisd/isis_pdu.c') diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index dfc613cf..d67df31b 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -33,6 +33,7 @@ #include "prefix.h" #include "if.h" #include "checksum.h" +#include "md5.h" #include "isisd/dict.h" #include "isisd/include-netbsd/iso.h" @@ -168,26 +169,38 @@ accept_level (int level, int circuit_t) return retval; } + +/* + * Verify authentication information + * Support cleartext and HMAC MD5 authentication + */ int -authentication_check (struct isis_passwd *one, struct isis_passwd *theother) +authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit* c) { - if (one->type != theother->type) + unsigned char digest[ISIS_AUTH_MD5_SIZE]; + + if (c->passwd.type) { - zlog_warn ("Unsupported authentication type %d", theother->type); - return 1; /* Auth fail (different authentication types) */ - } - switch (one->type) + switch (c->passwd.type) { + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* HMAC MD5 (RFC 3567) */ + /* MD5 computation according to RFC 2104 */ + hmac_md5(c->rcv_stream->data, stream_get_endp(c->rcv_stream), (unsigned char *) &(local->passwd), c->passwd.len, (unsigned char *) &digest); + return memcmp (digest, remote->passwd, ISIS_AUTH_MD5_SIZE); + break; case ISIS_PASSWD_TYPE_CLEARTXT: - if (one->len != theother->len) + /* Cleartext (ISO 10589) */ + if (local->len != remote->len) return 1; /* Auth fail () - passwd len mismatch */ - return memcmp (one->passwd, theother->passwd, one->len); + return memcmp (local->passwd, remote->passwd, local->len); break; default: zlog_warn ("Unsupported authentication type"); break; } - return 0; /* Auth pass */ + } + return 0; /* Authentication pass when no authentication is configured */ } /* @@ -372,7 +385,7 @@ process_p2p_hello (struct isis_circuit *circuit) if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&circuit->passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, &circuit->passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "P2P hello authentication failure", @@ -744,10 +757,11 @@ process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa) goto out; } + /* Verify authentication, either cleartext of HMAC MD5 */ if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&circuit->passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, &circuit->passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "LAN hello authentication failure", @@ -1416,7 +1430,7 @@ process_snp (int snp_type, int level, struct isis_circuit *circuit, if (passwd->type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "SNP authentication" " failure", @@ -1913,9 +1927,10 @@ send_hello (struct isis_circuit *circuit, int level) struct isis_fixed_hdr fixed_hdr; struct isis_lan_hello_hdr hello_hdr; struct isis_p2p_hello_hdr p2p_hello_hdr; + char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; u_int32_t interval; - unsigned long len_pointer, length; + unsigned long len_pointer, length, auth_tlv; int retval; if (circuit->state != C_STATE_UP || circuit->interface == NULL) @@ -1987,12 +2002,25 @@ send_hello (struct isis_circuit *circuit, int level) /* * Then the variable length part */ + /* add circuit password */ - if (circuit->passwd.type) - if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, + /* Cleartext */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT) + if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, circuit->passwd.len, circuit->passwd.passwd, circuit->snd_stream)) return ISIS_WARNING; + /* or HMAC MD5 */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) + { + /* Remember where TLV is written so we can later overwrite the MD5 hash */ + auth_tlv = stream_get_endp (circuit->snd_stream); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, + hmac_md5_hash, circuit->snd_stream)) + return ISIS_WARNING; + } + /* Protocols Supported TLV */ if (circuit->nlpids.count > 0) if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) @@ -2041,6 +2069,14 @@ send_hello (struct isis_circuit *circuit, int level) /* Update PDU length */ stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length); + /* For HMAC MD5 we need to compute the md5 hash and store it */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) + { + hmac_md5(circuit->snd_stream->data, stream_get_endp(circuit->snd_stream), (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, (unsigned char *) &hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(circuit->snd_stream->data+auth_tlv+3,hmac_md5_hash,ISIS_AUTH_MD5_SIZE); + } + retval = circuit->tx (circuit, level); if (retval) zlog_warn ("sending of LAN Level %d Hello failed", level); -- cgit v1.2.1