1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * 4 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 5 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de) 6 */ 7 #include <linux/errno.h> 8 #include <linux/types.h> 9 #include <linux/socket.h> 10 #include <linux/spinlock.h> 11 #include <linux/in.h> 12 #include <linux/kernel.h> 13 #include <linux/jiffies.h> 14 #include <linux/timer.h> 15 #include <linux/string.h> 16 #include <linux/sockios.h> 17 #include <linux/net.h> 18 #include <net/tcp_states.h> 19 #include <net/ax25.h> 20 #include <linux/inet.h> 21 #include <linux/netdevice.h> 22 #include <linux/skbuff.h> 23 #include <net/sock.h> 24 #include <linux/uaccess.h> 25 #include <linux/fcntl.h> 26 #include <linux/mm.h> 27 #include <linux/interrupt.h> 28 29 static void ax25_ds_timeout(struct timer_list *); 30 31 /* 32 * Add DAMA slave timeout timer to timer list. 33 * Unlike the connection based timers the timeout function gets 34 * triggered every second. Please note that NET_AX25_DAMA_SLAVE_TIMEOUT 35 * (aka /proc/sys/net/ax25/{dev}/dama_slave_timeout) is still in 36 * 1/10th of a second. 37 */ 38 39 void ax25_ds_setup_timer(ax25_dev *ax25_dev) 40 { 41 timer_setup(&ax25_dev->dama.slave_timer, ax25_ds_timeout, 0); 42 } 43 44 void ax25_ds_del_timer(ax25_dev *ax25_dev) 45 { 46 if (ax25_dev) 47 del_timer(&ax25_dev->dama.slave_timer); 48 } 49 50 void ax25_ds_set_timer(ax25_dev *ax25_dev) 51 { 52 if (ax25_dev == NULL) /* paranoia */ 53 return; 54 55 ax25_dev->dama.slave_timeout = 56 msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10; 57 mod_timer(&ax25_dev->dama.slave_timer, jiffies + HZ); 58 } 59 60 /* 61 * DAMA Slave Timeout 62 * Silently discard all (slave) connections in case our master forgot us... 63 */ 64 65 static void ax25_ds_timeout(struct timer_list *t) 66 { 67 ax25_dev *ax25_dev = from_timer(ax25_dev, t, dama.slave_timer); 68 ax25_cb *ax25; 69 70 if (ax25_dev == NULL || !ax25_dev->dama.slave) 71 return; /* Yikes! */ 72 73 if (!ax25_dev->dama.slave_timeout || --ax25_dev->dama.slave_timeout) { 74 ax25_ds_set_timer(ax25_dev); 75 return; 76 } 77 78 spin_lock(&ax25_list_lock); 79 ax25_for_each(ax25, &ax25_list) { 80 if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE)) 81 continue; 82 83 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); 84 ax25_disconnect(ax25, ETIMEDOUT); 85 } 86 spin_unlock(&ax25_list_lock); 87 88 ax25_dev_dama_off(ax25_dev); 89 } 90 91 void ax25_ds_heartbeat_expiry(ax25_cb *ax25) 92 { 93 struct sock *sk=ax25->sk; 94 95 if (sk) 96 bh_lock_sock(sk); 97 98 switch (ax25->state) { 99 100 case AX25_STATE_0: 101 case AX25_STATE_2: 102 /* Magic here: If we listen() and a new link dies before it 103 is accepted() it isn't 'dead' so doesn't get removed. */ 104 if (!sk || sock_flag(sk, SOCK_DESTROY) || 105 (sk->sk_state == TCP_LISTEN && 106 sock_flag(sk, SOCK_DEAD))) { 107 if (sk) { 108 sock_hold(sk); 109 ax25_destroy_socket(ax25); 110 bh_unlock_sock(sk); 111 /* Ungrab socket and destroy it */ 112 sock_put(sk); 113 } else 114 ax25_destroy_socket(ax25); 115 return; 116 } 117 break; 118 119 case AX25_STATE_3: 120 /* 121 * Check the state of the receive buffer. 122 */ 123 if (sk != NULL) { 124 if (atomic_read(&sk->sk_rmem_alloc) < 125 (sk->sk_rcvbuf >> 1) && 126 (ax25->condition & AX25_COND_OWN_RX_BUSY)) { 127 ax25->condition &= ~AX25_COND_OWN_RX_BUSY; 128 ax25->condition &= ~AX25_COND_ACK_PENDING; 129 break; 130 } 131 } 132 break; 133 } 134 135 if (sk) 136 bh_unlock_sock(sk); 137 138 ax25_start_heartbeat(ax25); 139 } 140 141 /* dl1bke 960114: T3 works much like the IDLE timeout, but 142 * gets reloaded with every frame for this 143 * connection. 144 */ 145 void ax25_ds_t3timer_expiry(ax25_cb *ax25) 146 { 147 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); 148 ax25_dama_off(ax25); 149 ax25_disconnect(ax25, ETIMEDOUT); 150 } 151 152 /* dl1bke 960228: close the connection when IDLE expires. 153 * unlike T3 this timer gets reloaded only on 154 * I frames. 155 */ 156 void ax25_ds_idletimer_expiry(ax25_cb *ax25) 157 { 158 ax25_clear_queues(ax25); 159 160 ax25->n2count = 0; 161 ax25->state = AX25_STATE_2; 162 163 ax25_calculate_t1(ax25); 164 ax25_start_t1timer(ax25); 165 ax25_stop_t3timer(ax25); 166 167 if (ax25->sk != NULL) { 168 bh_lock_sock(ax25->sk); 169 ax25->sk->sk_state = TCP_CLOSE; 170 ax25->sk->sk_err = 0; 171 ax25->sk->sk_shutdown |= SEND_SHUTDOWN; 172 if (!sock_flag(ax25->sk, SOCK_DEAD)) { 173 ax25->sk->sk_state_change(ax25->sk); 174 sock_set_flag(ax25->sk, SOCK_DEAD); 175 } 176 bh_unlock_sock(ax25->sk); 177 } 178 } 179 180 /* dl1bke 960114: The DAMA protocol requires to send data and SABM/DISC 181 * within the poll of any connected channel. Remember 182 * that we are not allowed to send anything unless we 183 * get polled by the Master. 184 * 185 * Thus we'll have to do parts of our T1 handling in 186 * ax25_enquiry_response(). 187 */ 188 void ax25_ds_t1_timeout(ax25_cb *ax25) 189 { 190 switch (ax25->state) { 191 case AX25_STATE_1: 192 if (ax25->n2count == ax25->n2) { 193 if (ax25->modulus == AX25_MODULUS) { 194 ax25_disconnect(ax25, ETIMEDOUT); 195 return; 196 } else { 197 ax25->modulus = AX25_MODULUS; 198 ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; 199 ax25->n2count = 0; 200 ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND); 201 } 202 } else { 203 ax25->n2count++; 204 if (ax25->modulus == AX25_MODULUS) 205 ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND); 206 else 207 ax25_send_control(ax25, AX25_SABME, AX25_POLLOFF, AX25_COMMAND); 208 } 209 break; 210 211 case AX25_STATE_2: 212 if (ax25->n2count == ax25->n2) { 213 ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); 214 if (!sock_flag(ax25->sk, SOCK_DESTROY)) 215 ax25_disconnect(ax25, ETIMEDOUT); 216 return; 217 } else { 218 ax25->n2count++; 219 } 220 break; 221 222 case AX25_STATE_3: 223 if (ax25->n2count == ax25->n2) { 224 ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE); 225 ax25_disconnect(ax25, ETIMEDOUT); 226 return; 227 } else { 228 ax25->n2count++; 229 } 230 break; 231 } 232 233 ax25_calculate_t1(ax25); 234 ax25_start_t1timer(ax25); 235 } 236
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.