diff options
Diffstat (limited to 'net/x25/x25_link.c')
-rw-r--r-- | net/x25/x25_link.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index fdae054b7dc1..57a81100c5da 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -58,11 +58,6 @@ static inline void x25_stop_t20timer(struct x25_neigh *nb) del_timer(&nb->t20timer); } -static inline int x25_t20timer_pending(struct x25_neigh *nb) -{ - return timer_pending(&nb->t20timer); -} - /* * This handles all restart and diagnostic frames. */ @@ -70,20 +65,45 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb, unsigned short frametype) { struct sk_buff *skbn; - int confirm; switch (frametype) { case X25_RESTART_REQUEST: - confirm = !x25_t20timer_pending(nb); - x25_stop_t20timer(nb); - nb->state = X25_LINK_STATE_3; - if (confirm) + switch (nb->state) { + case X25_LINK_STATE_0: + /* This can happen when the x25 module just gets loaded + * and doesn't know layer 2 has already connected + */ + nb->state = X25_LINK_STATE_3; x25_transmit_restart_confirmation(nb); + break; + case X25_LINK_STATE_2: + x25_stop_t20timer(nb); + nb->state = X25_LINK_STATE_3; + break; + case X25_LINK_STATE_3: + /* clear existing virtual calls */ + x25_kill_by_neigh(nb); + + x25_transmit_restart_confirmation(nb); + break; + } break; case X25_RESTART_CONFIRMATION: - x25_stop_t20timer(nb); - nb->state = X25_LINK_STATE_3; + switch (nb->state) { + case X25_LINK_STATE_2: + x25_stop_t20timer(nb); + nb->state = X25_LINK_STATE_3; + break; + case X25_LINK_STATE_3: + /* clear existing virtual calls */ + x25_kill_by_neigh(nb); + + x25_transmit_restart_request(nb); + nb->state = X25_LINK_STATE_2; + x25_start_t20timer(nb); + break; + } break; case X25_DIAGNOSTIC: @@ -214,8 +234,6 @@ void x25_link_established(struct x25_neigh *nb) { switch (nb->state) { case X25_LINK_STATE_0: - nb->state = X25_LINK_STATE_2; - break; case X25_LINK_STATE_1: x25_transmit_restart_request(nb); nb->state = X25_LINK_STATE_2; @@ -232,6 +250,9 @@ void x25_link_established(struct x25_neigh *nb) void x25_link_terminated(struct x25_neigh *nb) { nb->state = X25_LINK_STATE_0; + skb_queue_purge(&nb->queue); + x25_stop_t20timer(nb); + /* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */ x25_kill_by_neigh(nb); } @@ -277,9 +298,6 @@ void x25_link_device_up(struct net_device *dev) */ static void __x25_remove_neigh(struct x25_neigh *nb) { - skb_queue_purge(&nb->queue); - x25_stop_t20timer(nb); - if (nb->node.next) { list_del(&nb->node); x25_neigh_put(nb); |