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_circuit.c | 12 ++++++++++++ isisd/isis_lsp.c | 4 ++-- isisd/isis_pdu.c | 8 ++++++++ isisd/isis_pfpacket.c | 4 ++++ isisd/isisd.c | 13 ++++++++++++- isisd/isisd.h | 2 ++ 6 files changed, 40 insertions(+), 3 deletions(-) (limited to 'isisd') diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index d2923b57..e34d491a 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -142,6 +142,11 @@ isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area) { + /* destroy adjacencies */ + if (circuit->u.bc.adjdb[0]) + isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]); + if (circuit->u.bc.adjdb[1]) + isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]); /* Remove circuit from area */ listnode_delete (area->circuit_list, circuit); /* Free the index of SRM and SSN flags */ @@ -602,6 +607,13 @@ isis_circuit_down (struct isis_circuit *circuit) { THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello); } + + if (circuit->t_send_psnp[0]) { + THREAD_TIMER_OFF (circuit->t_send_psnp[0]); + } + if (circuit->t_send_psnp[1]) { + THREAD_TIMER_OFF (circuit->t_send_psnp[1]); + } /* close the socket */ close (circuit->fd); diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 50289db3..e12e4ca8 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -1640,7 +1640,7 @@ lsp_regenerate_schedule (struct isis_area *area) if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[0] = 1; - thread_add_timer (master, lsp_l1_regenerate, area, + area->t_lsp_l1_regenerate=thread_add_timer (master, lsp_l1_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); goto L2; } @@ -1663,7 +1663,7 @@ L2: if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[1] = 1; - thread_add_timer (master, lsp_l2_regenerate, area, + area->t_lsp_l2_regenerate=thread_add_timer (master, lsp_l2_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); return ISIS_OK; } 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]) diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 9e4165e3..8a5c3ed0 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -232,6 +232,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) LLC_LEN, MSG_PEEK, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + if (!circuit->area) { + return ISIS_OK; + } + if (bytesread < 0) { zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", diff --git a/isisd/isisd.c b/isisd/isisd.c index 1e84a1ce..20a32809 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -52,6 +52,7 @@ #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" #include "isisd/isis_events.h" +#include "isisd/isis_csm.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -217,21 +218,31 @@ isis_area_destroy (struct vty *vty, const char *area_tag) for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit)) { /* The fact that it's in circuit_list means that it was configured */ + isis_csm_state_change (ISIS_DISABLE, circuit, area); + isis_circuit_down (circuit); isis_circuit_deconfigure (circuit, area); - isis_circuit_del (circuit); } list_delete (area->circuit_list); } listnode_delete (isis->area_list, area); + THREAD_TIMER_OFF (area->t_tick); if (area->t_remove_aged) thread_cancel (area->t_remove_aged); THREAD_TIMER_OFF (area->t_lsp_refresh[0]); THREAD_TIMER_OFF (area->t_lsp_refresh[1]); + THREAD_TIMER_OFF (area->spftree[0]->t_spf); + THREAD_TIMER_OFF (area->spftree[1]->t_spf); + + THREAD_TIMER_OFF (area->t_lsp_l1_regenerate); + THREAD_TIMER_OFF (area->t_lsp_l2_regenerate); + XFREE (MTYPE_ISIS_AREA, area); + isis->sysid_set=0; + return CMD_SUCCESS; } diff --git a/isisd/isisd.h b/isisd/isisd.h index 2277f27c..b17982e2 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -93,6 +93,8 @@ struct isis_area struct flags flags; struct thread *t_tick; /* LSP walker */ struct thread *t_remove_aged; + struct thread *t_lsp_l1_regenerate; + struct thread *t_lsp_l2_regenerate; int lsp_regenerate_pending[ISIS_LEVELS]; struct thread *t_lsp_refresh[ISIS_LEVELS]; -- cgit v1.2.1