isisd: fix memory handling in isis_adj_process_threeway()

The adj_process_threeway() api may call the adj_state_change()
api, which may delete the adj struct being examined. Change the
signature so that callers pass a ptr-to-ptr so that they will
see that deletion.

Signed-off-by: Mark Stapp <mjs@cisco.com>
This commit is contained in:
Mark Stapp 2024-08-09 10:08:21 -04:00
parent e7fd713afc
commit 3eb7d16411
3 changed files with 13 additions and 13 deletions

View file

@ -231,11 +231,12 @@ static void isis_adj_route_switchover(struct isis_adjacency *adj)
} }
} }
void isis_adj_process_threeway(struct isis_adjacency *adj, void isis_adj_process_threeway(struct isis_adjacency **padj,
struct isis_threeway_adj *tw_adj, struct isis_threeway_adj *tw_adj,
enum isis_adj_usage adj_usage) enum isis_adj_usage adj_usage)
{ {
enum isis_threeway_state next_tw_state = ISIS_THREEWAY_DOWN; enum isis_threeway_state next_tw_state = ISIS_THREEWAY_DOWN;
struct isis_adjacency *adj = *padj;
if (tw_adj && !adj->circuit->disable_threeway_adj) { if (tw_adj && !adj->circuit->disable_threeway_adj) {
if (tw_adj->state == ISIS_THREEWAY_DOWN) { if (tw_adj->state == ISIS_THREEWAY_DOWN) {
@ -265,14 +266,13 @@ void isis_adj_process_threeway(struct isis_adjacency *adj,
fabricd_initial_sync_hello(adj->circuit); fabricd_initial_sync_hello(adj->circuit);
if (next_tw_state == ISIS_THREEWAY_DOWN) { if (next_tw_state == ISIS_THREEWAY_DOWN) {
isis_adj_state_change(&adj, ISIS_ADJ_DOWN, isis_adj_state_change(padj, ISIS_ADJ_DOWN, "Neighbor restarted");
"Neighbor restarted");
return; return;
} }
if (next_tw_state == ISIS_THREEWAY_UP) { if (next_tw_state == ISIS_THREEWAY_UP) {
if (adj->adj_state != ISIS_ADJ_UP) { if (adj->adj_state != ISIS_ADJ_UP) {
isis_adj_state_change(&adj, ISIS_ADJ_UP, NULL); isis_adj_state_change(padj, ISIS_ADJ_UP, NULL);
adj->adj_usage = adj_usage; adj->adj_usage = adj_usage;
} }
} }

View file

@ -111,7 +111,7 @@ struct isis_adjacency *isis_adj_find(const struct isis_area *area, int level,
struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa, struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
int level, struct isis_circuit *circuit); int level, struct isis_circuit *circuit);
void isis_delete_adj(void *adj); void isis_delete_adj(void *adj);
void isis_adj_process_threeway(struct isis_adjacency *adj, void isis_adj_process_threeway(struct isis_adjacency **padj,
struct isis_threeway_adj *tw_adj, struct isis_threeway_adj *tw_adj,
enum isis_adj_usage adj_usage); enum isis_adj_usage adj_usage);
DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj)); DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj));

View file

@ -281,14 +281,14 @@ static int process_p2p_hello(struct iih_info *iih)
if (iih->calculated_type == IS_LEVEL_1) { if (iih->calculated_type == IS_LEVEL_1) {
switch (iih->circ_type) { switch (iih->circ_type) {
case IS_LEVEL_1: case IS_LEVEL_1:
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
break; break;
case IS_LEVEL_1_AND_2: case IS_LEVEL_1_AND_2:
if ((adj->adj_state != ISIS_ADJ_UP) || if ((adj->adj_state != ISIS_ADJ_UP) ||
(adj->adj_usage == ISIS_ADJ_LEVEL1) || (adj->adj_usage == ISIS_ADJ_LEVEL1) ||
(adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) { (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) {
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
} }
break; break;
@ -301,7 +301,7 @@ static int process_p2p_hello(struct iih_info *iih)
case IS_LEVEL_1: case IS_LEVEL_1:
if (adj->adj_state != ISIS_ADJ_UP if (adj->adj_state != ISIS_ADJ_UP
|| adj->adj_usage == ISIS_ADJ_LEVEL1) { || adj->adj_usage == ISIS_ADJ_LEVEL1) {
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
} else if ((adj->adj_usage == ISIS_ADJ_LEVEL2) || } else if ((adj->adj_usage == ISIS_ADJ_LEVEL2) ||
(adj->adj_usage == (adj->adj_usage ==
@ -315,7 +315,7 @@ static int process_p2p_hello(struct iih_info *iih)
case IS_LEVEL_2: case IS_LEVEL_2:
if (adj->adj_state != ISIS_ADJ_UP if (adj->adj_state != ISIS_ADJ_UP
|| adj->adj_usage == ISIS_ADJ_LEVEL2) { || adj->adj_usage == ISIS_ADJ_LEVEL2) {
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
} else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
(adj->adj_usage == (adj->adj_usage ==
@ -329,7 +329,7 @@ static int process_p2p_hello(struct iih_info *iih)
case IS_LEVEL_1_AND_2: case IS_LEVEL_1_AND_2:
if (adj->adj_state != ISIS_ADJ_UP if (adj->adj_state != ISIS_ADJ_UP
|| adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { || adj->adj_usage == ISIS_ADJ_LEVEL1AND2) {
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
} else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
(adj->adj_usage == ISIS_ADJ_LEVEL2)) { (adj->adj_usage == ISIS_ADJ_LEVEL2)) {
@ -349,12 +349,12 @@ static int process_p2p_hello(struct iih_info *iih)
if (adj->adj_state != ISIS_ADJ_UP || if (adj->adj_state != ISIS_ADJ_UP ||
adj->adj_usage == ISIS_ADJ_LEVEL2 || adj->adj_usage == ISIS_ADJ_LEVEL2 ||
adj->adj_usage == ISIS_ADJ_LEVEL1AND2) { adj->adj_usage == ISIS_ADJ_LEVEL1AND2) {
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
} }
break; break;
case IS_LEVEL_2: case IS_LEVEL_2:
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
break; break;
} }
@ -401,7 +401,7 @@ static int process_p2p_hello(struct iih_info *iih)
case IS_LEVEL_2: case IS_LEVEL_2:
if (adj->adj_state != ISIS_ADJ_UP if (adj->adj_state != ISIS_ADJ_UP
|| adj->adj_usage == ISIS_ADJ_LEVEL2) { || adj->adj_usage == ISIS_ADJ_LEVEL2) {
isis_adj_process_threeway(adj, tw_adj, isis_adj_process_threeway(&adj, tw_adj,
iih->calculated_type); iih->calculated_type);
} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) {
/* (7) down - wrong system */ /* (7) down - wrong system */