Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/ax25/ax25_ds_in.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) Jonathan Naylor G4KLX ([email protected])
8
* Copyright (C) Joerg Reuter DL1BKE ([email protected])
9
*/
10
#include <linux/errno.h>
11
#include <linux/types.h>
12
#include <linux/socket.h>
13
#include <linux/in.h>
14
#include <linux/kernel.h>
15
#include <linux/timer.h>
16
#include <linux/string.h>
17
#include <linux/sockios.h>
18
#include <linux/net.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 <net/tcp_states.h>
25
#include <asm/uaccess.h>
26
#include <asm/system.h>
27
#include <linux/fcntl.h>
28
#include <linux/mm.h>
29
#include <linux/interrupt.h>
30
31
/*
32
* State machine for state 1, Awaiting Connection State.
33
* The handling of the timer(s) is in file ax25_ds_timer.c.
34
* Handling of state 0 and connection release is in ax25.c.
35
*/
36
static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
37
{
38
switch (frametype) {
39
case AX25_SABM:
40
ax25->modulus = AX25_MODULUS;
41
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
42
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
43
break;
44
45
case AX25_SABME:
46
ax25->modulus = AX25_EMODULUS;
47
ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
48
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
49
break;
50
51
case AX25_DISC:
52
ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
53
break;
54
55
case AX25_UA:
56
ax25_calculate_rtt(ax25);
57
ax25_stop_t1timer(ax25);
58
ax25_start_t3timer(ax25);
59
ax25_start_idletimer(ax25);
60
ax25->vs = 0;
61
ax25->va = 0;
62
ax25->vr = 0;
63
ax25->state = AX25_STATE_3;
64
ax25->n2count = 0;
65
if (ax25->sk != NULL) {
66
bh_lock_sock(ax25->sk);
67
ax25->sk->sk_state = TCP_ESTABLISHED;
68
/*
69
* For WAIT_SABM connections we will produce an accept
70
* ready socket here
71
*/
72
if (!sock_flag(ax25->sk, SOCK_DEAD))
73
ax25->sk->sk_state_change(ax25->sk);
74
bh_unlock_sock(ax25->sk);
75
}
76
ax25_dama_on(ax25);
77
78
/* according to DK4EG's spec we are required to
79
* send a RR RESPONSE FINAL NR=0.
80
*/
81
82
ax25_std_enquiry_response(ax25);
83
break;
84
85
case AX25_DM:
86
if (pf)
87
ax25_disconnect(ax25, ECONNREFUSED);
88
break;
89
90
default:
91
if (pf)
92
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
93
break;
94
}
95
96
return 0;
97
}
98
99
/*
100
* State machine for state 2, Awaiting Release State.
101
* The handling of the timer(s) is in file ax25_ds_timer.c
102
* Handling of state 0 and connection release is in ax25.c.
103
*/
104
static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
105
{
106
switch (frametype) {
107
case AX25_SABM:
108
case AX25_SABME:
109
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
110
ax25_dama_off(ax25);
111
break;
112
113
case AX25_DISC:
114
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
115
ax25_dama_off(ax25);
116
ax25_disconnect(ax25, 0);
117
break;
118
119
case AX25_DM:
120
case AX25_UA:
121
if (pf) {
122
ax25_dama_off(ax25);
123
ax25_disconnect(ax25, 0);
124
}
125
break;
126
127
case AX25_I:
128
case AX25_REJ:
129
case AX25_RNR:
130
case AX25_RR:
131
if (pf) {
132
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
133
ax25_dama_off(ax25);
134
}
135
break;
136
137
default:
138
break;
139
}
140
141
return 0;
142
}
143
144
/*
145
* State machine for state 3, Connected State.
146
* The handling of the timer(s) is in file ax25_timer.c
147
* Handling of state 0 and connection release is in ax25.c.
148
*/
149
static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
150
{
151
int queued = 0;
152
153
switch (frametype) {
154
case AX25_SABM:
155
case AX25_SABME:
156
if (frametype == AX25_SABM) {
157
ax25->modulus = AX25_MODULUS;
158
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
159
} else {
160
ax25->modulus = AX25_EMODULUS;
161
ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
162
}
163
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
164
ax25_stop_t1timer(ax25);
165
ax25_start_t3timer(ax25);
166
ax25_start_idletimer(ax25);
167
ax25->condition = 0x00;
168
ax25->vs = 0;
169
ax25->va = 0;
170
ax25->vr = 0;
171
ax25_requeue_frames(ax25);
172
ax25_dama_on(ax25);
173
break;
174
175
case AX25_DISC:
176
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
177
ax25_dama_off(ax25);
178
ax25_disconnect(ax25, 0);
179
break;
180
181
case AX25_DM:
182
ax25_dama_off(ax25);
183
ax25_disconnect(ax25, ECONNRESET);
184
break;
185
186
case AX25_RR:
187
case AX25_RNR:
188
if (frametype == AX25_RR)
189
ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
190
else
191
ax25->condition |= AX25_COND_PEER_RX_BUSY;
192
193
if (ax25_validate_nr(ax25, nr)) {
194
if (ax25_check_iframes_acked(ax25, nr))
195
ax25->n2count=0;
196
if (type == AX25_COMMAND && pf)
197
ax25_ds_enquiry_response(ax25);
198
} else {
199
ax25_ds_nr_error_recovery(ax25);
200
ax25->state = AX25_STATE_1;
201
}
202
break;
203
204
case AX25_REJ:
205
ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
206
207
if (ax25_validate_nr(ax25, nr)) {
208
if (ax25->va != nr)
209
ax25->n2count=0;
210
211
ax25_frames_acked(ax25, nr);
212
ax25_calculate_rtt(ax25);
213
ax25_stop_t1timer(ax25);
214
ax25_start_t3timer(ax25);
215
ax25_requeue_frames(ax25);
216
217
if (type == AX25_COMMAND && pf)
218
ax25_ds_enquiry_response(ax25);
219
} else {
220
ax25_ds_nr_error_recovery(ax25);
221
ax25->state = AX25_STATE_1;
222
}
223
break;
224
225
case AX25_I:
226
if (!ax25_validate_nr(ax25, nr)) {
227
ax25_ds_nr_error_recovery(ax25);
228
ax25->state = AX25_STATE_1;
229
break;
230
}
231
if (ax25->condition & AX25_COND_PEER_RX_BUSY) {
232
ax25_frames_acked(ax25, nr);
233
ax25->n2count = 0;
234
} else {
235
if (ax25_check_iframes_acked(ax25, nr))
236
ax25->n2count = 0;
237
}
238
if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
239
if (pf) ax25_ds_enquiry_response(ax25);
240
break;
241
}
242
if (ns == ax25->vr) {
243
ax25->vr = (ax25->vr + 1) % ax25->modulus;
244
queued = ax25_rx_iframe(ax25, skb);
245
if (ax25->condition & AX25_COND_OWN_RX_BUSY)
246
ax25->vr = ns; /* ax25->vr - 1 */
247
ax25->condition &= ~AX25_COND_REJECT;
248
if (pf) {
249
ax25_ds_enquiry_response(ax25);
250
} else {
251
if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
252
ax25->condition |= AX25_COND_ACK_PENDING;
253
ax25_start_t2timer(ax25);
254
}
255
}
256
} else {
257
if (ax25->condition & AX25_COND_REJECT) {
258
if (pf) ax25_ds_enquiry_response(ax25);
259
} else {
260
ax25->condition |= AX25_COND_REJECT;
261
ax25_ds_enquiry_response(ax25);
262
ax25->condition &= ~AX25_COND_ACK_PENDING;
263
}
264
}
265
break;
266
267
case AX25_FRMR:
268
case AX25_ILLEGAL:
269
ax25_ds_establish_data_link(ax25);
270
ax25->state = AX25_STATE_1;
271
break;
272
273
default:
274
break;
275
}
276
277
return queued;
278
}
279
280
/*
281
* Higher level upcall for a LAPB frame
282
*/
283
int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
284
{
285
int queued = 0, frametype, ns, nr, pf;
286
287
frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);
288
289
switch (ax25->state) {
290
case AX25_STATE_1:
291
queued = ax25_ds_state1_machine(ax25, skb, frametype, pf, type);
292
break;
293
case AX25_STATE_2:
294
queued = ax25_ds_state2_machine(ax25, skb, frametype, pf, type);
295
break;
296
case AX25_STATE_3:
297
queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type);
298
break;
299
}
300
301
return queued;
302
}
303
304
305