linux/net/x25/x25_timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *      X.25 Packet Layer release 002
   4 *
   5 *      This is ALPHA test software. This code may break your machine,
   6 *      randomly fail to work with new releases, misbehave and/or generally
   7 *      screw up. It might even work.
   8 *
   9 *      This code REQUIRES 2.1.15 or higher
  10 *
  11 *      History
  12 *      X.25 001        Jonathan Naylor Started coding.
  13 *      X.25 002        Jonathan Naylor New timer architecture.
  14 *                                      Centralised disconnection processing.
  15 */
  16
  17#include <linux/errno.h>
  18#include <linux/jiffies.h>
  19#include <linux/timer.h>
  20#include <net/sock.h>
  21#include <net/tcp_states.h>
  22#include <net/x25.h>
  23
  24static void x25_heartbeat_expiry(struct timer_list *t);
  25static void x25_timer_expiry(struct timer_list *t);
  26
  27void x25_init_timers(struct sock *sk)
  28{
  29        struct x25_sock *x25 = x25_sk(sk);
  30
  31        timer_setup(&x25->timer, x25_timer_expiry, 0);
  32
  33        /* initialized by sock_init_data */
  34        sk->sk_timer.function = x25_heartbeat_expiry;
  35}
  36
  37void x25_start_heartbeat(struct sock *sk)
  38{
  39        mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
  40}
  41
  42void x25_stop_heartbeat(struct sock *sk)
  43{
  44        del_timer(&sk->sk_timer);
  45}
  46
  47void x25_start_t2timer(struct sock *sk)
  48{
  49        struct x25_sock *x25 = x25_sk(sk);
  50
  51        mod_timer(&x25->timer, jiffies + x25->t2);
  52}
  53
  54void x25_start_t21timer(struct sock *sk)
  55{
  56        struct x25_sock *x25 = x25_sk(sk);
  57
  58        mod_timer(&x25->timer, jiffies + x25->t21);
  59}
  60
  61void x25_start_t22timer(struct sock *sk)
  62{
  63        struct x25_sock *x25 = x25_sk(sk);
  64
  65        mod_timer(&x25->timer, jiffies + x25->t22);
  66}
  67
  68void x25_start_t23timer(struct sock *sk)
  69{
  70        struct x25_sock *x25 = x25_sk(sk);
  71
  72        mod_timer(&x25->timer, jiffies + x25->t23);
  73}
  74
  75void x25_stop_timer(struct sock *sk)
  76{
  77        del_timer(&x25_sk(sk)->timer);
  78}
  79
  80unsigned long x25_display_timer(struct sock *sk)
  81{
  82        struct x25_sock *x25 = x25_sk(sk);
  83
  84        if (!timer_pending(&x25->timer))
  85                return 0;
  86
  87        return x25->timer.expires - jiffies;
  88}
  89
  90static void x25_heartbeat_expiry(struct timer_list *t)
  91{
  92        struct sock *sk = from_timer(sk, t, sk_timer);
  93
  94        bh_lock_sock(sk);
  95        if (sock_owned_by_user(sk)) /* can currently only occur in state 3 */
  96                goto restart_heartbeat;
  97
  98        switch (x25_sk(sk)->state) {
  99
 100                case X25_STATE_0:
 101                        /*
 102                         * Magic here: If we listen() and a new link dies
 103                         * before it is accepted() it isn't 'dead' so doesn't
 104                         * get removed.
 105                         */
 106                        if (sock_flag(sk, SOCK_DESTROY) ||
 107                            (sk->sk_state == TCP_LISTEN &&
 108                             sock_flag(sk, SOCK_DEAD))) {
 109                                bh_unlock_sock(sk);
 110                                x25_destroy_socket_from_timer(sk);
 111                                return;
 112                        }
 113                        break;
 114
 115                case X25_STATE_3:
 116                        /*
 117                         * Check for the state of the receive buffer.
 118                         */
 119                        x25_check_rbuf(sk);
 120                        break;
 121        }
 122restart_heartbeat:
 123        x25_start_heartbeat(sk);
 124        bh_unlock_sock(sk);
 125}
 126
 127/*
 128 *      Timer has expired, it may have been T2, T21, T22, or T23. We can tell
 129 *      by the state machine state.
 130 */
 131static inline void x25_do_timer_expiry(struct sock * sk)
 132{
 133        struct x25_sock *x25 = x25_sk(sk);
 134
 135        switch (x25->state) {
 136
 137                case X25_STATE_3:       /* T2 */
 138                        if (x25->condition & X25_COND_ACK_PENDING) {
 139                                x25->condition &= ~X25_COND_ACK_PENDING;
 140                                x25_enquiry_response(sk);
 141                        }
 142                        break;
 143
 144                case X25_STATE_1:       /* T21 */
 145                case X25_STATE_4:       /* T22 */
 146                        x25_write_internal(sk, X25_CLEAR_REQUEST);
 147                        x25->state = X25_STATE_2;
 148                        x25_start_t23timer(sk);
 149                        break;
 150
 151                case X25_STATE_2:       /* T23 */
 152                        x25_disconnect(sk, ETIMEDOUT, 0, 0);
 153                        break;
 154        }
 155}
 156
 157static void x25_timer_expiry(struct timer_list *t)
 158{
 159        struct x25_sock *x25 = from_timer(x25, t, timer);
 160        struct sock *sk = &x25->sk;
 161
 162        bh_lock_sock(sk);
 163        if (sock_owned_by_user(sk)) { /* can currently only occur in state 3 */
 164                if (x25_sk(sk)->state == X25_STATE_3)
 165                        x25_start_t2timer(sk);
 166        } else
 167                x25_do_timer_expiry(sk);
 168        bh_unlock_sock(sk);
 169}
 170