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 <fritz@reichmann.nl>
diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c
index 80d0c90..6cdde46 100644
--- a/isisd/isis_csm.c
+++ b/isisd/isis_csm.c
@@ -112,6 +112,7 @@
 	  isis_circuit_configure (circuit, (struct isis_area *) arg);
 	  isis_circuit_up (circuit);
 	  circuit->state = C_STATE_UP;
+	  circuit->connected = 1;
 	  isis_event_circuit_state_change (circuit, 1);
 	  listnode_delete (isis->init_circ_list, circuit);
 	  break;
@@ -136,9 +137,12 @@
 	  zlog_warn ("circuit already enabled");
 	  break;
 	case IF_UP_FROM_Z:
-	  isis_circuit_if_add (circuit, (struct interface *) arg);
-	  isis_circuit_up (circuit);
+	  if (!circuit->connected) {
+	    isis_circuit_if_add (circuit, (struct interface *) arg);
+	    isis_circuit_up (circuit);
+	  }
 	  circuit->state = C_STATE_UP;
+	  circuit->connected = 1;
 	  isis_event_circuit_state_change (circuit, 1);
 	  break;
 	case ISIS_DISABLE:
@@ -167,7 +171,6 @@
 	  isis_event_circuit_state_change (circuit, 0);
 	  break;
 	case IF_DOWN_FROM_Z:
-	  isis_circuit_if_del (circuit);
 	  circuit->state = C_STATE_CONF;
 	  isis_event_circuit_state_change (circuit, 0);
 	  break;