Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/ax25/ax25_std_timer.c
15109 views
1
/*
2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
6
*
7
* Copyright (C) Alan Cox GW4PTS ([email protected])
8
* Copyright (C) Jonathan Naylor G4KLX ([email protected])
9
* Copyright (C) Joerg Reuter DL1BKE ([email protected])
10
* Copyright (C) Frederic Rible F1OAT ([email protected])
11
*/
12
#include <linux/errno.h>
13
#include <linux/types.h>
14
#include <linux/socket.h>
15
#include <linux/in.h>
16
#include <linux/kernel.h>
17
#include <linux/timer.h>
18
#include <linux/string.h>
19
#include <linux/sockios.h>
20
#include <linux/net.h>
21
#include <net/ax25.h>
22
#include <linux/inet.h>
23
#include <linux/netdevice.h>
24
#include <linux/skbuff.h>
25
#include <net/sock.h>
26
#include <net/tcp_states.h>
27
#include <asm/uaccess.h>
28
#include <asm/system.h>
29
#include <linux/fcntl.h>
30
#include <linux/mm.h>
31
#include <linux/interrupt.h>
32
33
void ax25_std_heartbeat_expiry(ax25_cb *ax25)
34
{
35
struct sock *sk = ax25->sk;
36
37
if (sk)
38
bh_lock_sock(sk);
39
40
switch (ax25->state) {
41
case AX25_STATE_0:
42
/* Magic here: If we listen() and a new link dies before it
43
is accepted() it isn't 'dead' so doesn't get removed. */
44
if (!sk || sock_flag(sk, SOCK_DESTROY) ||
45
(sk->sk_state == TCP_LISTEN &&
46
sock_flag(sk, SOCK_DEAD))) {
47
if (sk) {
48
sock_hold(sk);
49
ax25_destroy_socket(ax25);
50
bh_unlock_sock(sk);
51
sock_put(sk);
52
} else
53
ax25_destroy_socket(ax25);
54
return;
55
}
56
break;
57
58
case AX25_STATE_3:
59
case AX25_STATE_4:
60
/*
61
* Check the state of the receive buffer.
62
*/
63
if (sk != NULL) {
64
if (atomic_read(&sk->sk_rmem_alloc) <
65
(sk->sk_rcvbuf >> 1) &&
66
(ax25->condition & AX25_COND_OWN_RX_BUSY)) {
67
ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
68
ax25->condition &= ~AX25_COND_ACK_PENDING;
69
ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);
70
break;
71
}
72
}
73
}
74
75
if (sk)
76
bh_unlock_sock(sk);
77
78
ax25_start_heartbeat(ax25);
79
}
80
81
void ax25_std_t2timer_expiry(ax25_cb *ax25)
82
{
83
if (ax25->condition & AX25_COND_ACK_PENDING) {
84
ax25->condition &= ~AX25_COND_ACK_PENDING;
85
ax25_std_timeout_response(ax25);
86
}
87
}
88
89
void ax25_std_t3timer_expiry(ax25_cb *ax25)
90
{
91
ax25->n2count = 0;
92
ax25_std_transmit_enquiry(ax25);
93
ax25->state = AX25_STATE_4;
94
}
95
96
void ax25_std_idletimer_expiry(ax25_cb *ax25)
97
{
98
ax25_clear_queues(ax25);
99
100
ax25->n2count = 0;
101
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
102
ax25->state = AX25_STATE_2;
103
104
ax25_calculate_t1(ax25);
105
ax25_start_t1timer(ax25);
106
ax25_stop_t2timer(ax25);
107
ax25_stop_t3timer(ax25);
108
109
if (ax25->sk != NULL) {
110
bh_lock_sock(ax25->sk);
111
ax25->sk->sk_state = TCP_CLOSE;
112
ax25->sk->sk_err = 0;
113
ax25->sk->sk_shutdown |= SEND_SHUTDOWN;
114
if (!sock_flag(ax25->sk, SOCK_DEAD)) {
115
ax25->sk->sk_state_change(ax25->sk);
116
sock_set_flag(ax25->sk, SOCK_DEAD);
117
}
118
bh_unlock_sock(ax25->sk);
119
}
120
}
121
122
void ax25_std_t1timer_expiry(ax25_cb *ax25)
123
{
124
switch (ax25->state) {
125
case AX25_STATE_1:
126
if (ax25->n2count == ax25->n2) {
127
if (ax25->modulus == AX25_MODULUS) {
128
ax25_disconnect(ax25, ETIMEDOUT);
129
return;
130
} else {
131
ax25->modulus = AX25_MODULUS;
132
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
133
ax25->n2count = 0;
134
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
135
}
136
} else {
137
ax25->n2count++;
138
if (ax25->modulus == AX25_MODULUS)
139
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
140
else
141
ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
142
}
143
break;
144
145
case AX25_STATE_2:
146
if (ax25->n2count == ax25->n2) {
147
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
148
ax25_disconnect(ax25, ETIMEDOUT);
149
return;
150
} else {
151
ax25->n2count++;
152
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
153
}
154
break;
155
156
case AX25_STATE_3:
157
ax25->n2count = 1;
158
ax25_std_transmit_enquiry(ax25);
159
ax25->state = AX25_STATE_4;
160
break;
161
162
case AX25_STATE_4:
163
if (ax25->n2count == ax25->n2) {
164
ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
165
ax25_disconnect(ax25, ETIMEDOUT);
166
return;
167
} else {
168
ax25->n2count++;
169
ax25_std_transmit_enquiry(ax25);
170
}
171
break;
172
}
173
174
ax25_calculate_t1(ax25);
175
ax25_start_t1timer(ax25);
176
}
177
178