Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: x25: Fix handling of Restart Request and Restart Confirmation

1. When the x25 module gets loaded, layer 2 may already be running and
connected. In this case, although we are in X25_LINK_STATE_0, we still
need to handle the Restart Request received, rather than ignore it.

2. When we are in X25_LINK_STATE_2, we have already sent a Restart Request
and is waiting for the Restart Confirmation with t20timer. t20timer will
restart itself repeatedly forever so it will always be there, as long as we
are in State 2. So we don't need to check x25_t20timer_pending again.

Fixes: d023b2b9ccc2 ("net/x25: fix restart request/confirm handling")
Cc: Martin Schiller <ms@dev.tdt.de>
Signed-off-by: Xie He <xie.he.0141@gmail.com>
Acked-by: Martin Schiller <ms@dev.tdt.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Xie He and committed by
David S. Miller
6b21c0bb 0f86a5be

+9 -16
+9 -16
net/x25/x25_link.c
··· 58 58 del_timer(&nb->t20timer); 59 59 } 60 60 61 - static inline int x25_t20timer_pending(struct x25_neigh *nb) 62 - { 63 - return timer_pending(&nb->t20timer); 64 - } 65 - 66 61 /* 67 62 * This handles all restart and diagnostic frames. 68 63 */ ··· 65 70 unsigned short frametype) 66 71 { 67 72 struct sk_buff *skbn; 68 - int confirm; 69 73 70 74 switch (frametype) { 71 75 case X25_RESTART_REQUEST: 72 76 switch (nb->state) { 77 + case X25_LINK_STATE_0: 78 + /* This can happen when the x25 module just gets loaded 79 + * and doesn't know layer 2 has already connected 80 + */ 81 + nb->state = X25_LINK_STATE_3; 82 + x25_transmit_restart_confirmation(nb); 83 + break; 73 84 case X25_LINK_STATE_2: 74 - confirm = !x25_t20timer_pending(nb); 75 85 x25_stop_t20timer(nb); 76 86 nb->state = X25_LINK_STATE_3; 77 - if (confirm) 78 - x25_transmit_restart_confirmation(nb); 79 87 break; 80 88 case X25_LINK_STATE_3: 81 89 /* clear existing virtual calls */ ··· 92 94 case X25_RESTART_CONFIRMATION: 93 95 switch (nb->state) { 94 96 case X25_LINK_STATE_2: 95 - if (x25_t20timer_pending(nb)) { 96 - x25_stop_t20timer(nb); 97 - nb->state = X25_LINK_STATE_3; 98 - } else { 99 - x25_transmit_restart_request(nb); 100 - x25_start_t20timer(nb); 101 - } 97 + x25_stop_t20timer(nb); 98 + nb->state = X25_LINK_STATE_3; 102 99 break; 103 100 case X25_LINK_STATE_3: 104 101 /* clear existing virtual calls */