cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ax25_ds_timer.c (5801B)


      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
     29static 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
     39void ax25_ds_setup_timer(ax25_dev *ax25_dev)
     40{
     41	timer_setup(&ax25_dev->dama.slave_timer, ax25_ds_timeout, 0);
     42}
     43
     44void ax25_ds_del_timer(ax25_dev *ax25_dev)
     45{
     46	if (ax25_dev)
     47		del_timer(&ax25_dev->dama.slave_timer);
     48}
     49
     50void 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
     65static 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
     91void 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 */
    145void 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 */
    156void 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 */
    188void 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}