Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/ax25/ax25_std_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) Alan Cox GW4PTS ([email protected])
8
* Copyright (C) Jonathan Naylor G4KLX ([email protected])
9
* Copyright (C) Joerg Reuter DL1BKE ([email protected])
10
* Copyright (C) Hans-Joachim Hetscher DD8NE ([email protected])
11
*
12
* Most of this code is based on the SDL diagrams published in the 7th ARRL
13
* Computer Networking Conference papers. The diagrams have mistakes in them,
14
* but are mostly correct. Before you modify the code could you read the SDL
15
* diagrams as the code is not obvious and probably very easy to break.
16
*/
17
#include <linux/errno.h>
18
#include <linux/types.h>
19
#include <linux/socket.h>
20
#include <linux/in.h>
21
#include <linux/kernel.h>
22
#include <linux/timer.h>
23
#include <linux/string.h>
24
#include <linux/sockios.h>
25
#include <linux/net.h>
26
#include <net/ax25.h>
27
#include <linux/inet.h>
28
#include <linux/netdevice.h>
29
#include <linux/skbuff.h>
30
#include <net/sock.h>
31
#include <net/tcp_states.h>
32
#include <asm/uaccess.h>
33
#include <asm/system.h>
34
#include <linux/fcntl.h>
35
#include <linux/mm.h>
36
#include <linux/interrupt.h>
37
38
/*
39
* State machine for state 1, Awaiting Connection State.
40
* The handling of the timer(s) is in file ax25_std_timer.c.
41
* Handling of state 0 and connection release is in ax25.c.
42
*/
43
static int ax25_std_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
44
{
45
switch (frametype) {
46
case AX25_SABM:
47
ax25->modulus = AX25_MODULUS;
48
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
49
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
50
break;
51
52
case AX25_SABME:
53
ax25->modulus = AX25_EMODULUS;
54
ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
55
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
56
break;
57
58
case AX25_DISC:
59
ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
60
break;
61
62
case AX25_UA:
63
if (pf) {
64
ax25_calculate_rtt(ax25);
65
ax25_stop_t1timer(ax25);
66
ax25_start_t3timer(ax25);
67
ax25_start_idletimer(ax25);
68
ax25->vs = 0;
69
ax25->va = 0;
70
ax25->vr = 0;
71
ax25->state = AX25_STATE_3;
72
ax25->n2count = 0;
73
if (ax25->sk != NULL) {
74
bh_lock_sock(ax25->sk);
75
ax25->sk->sk_state = TCP_ESTABLISHED;
76
/* For WAIT_SABM connections we will produce an accept ready socket here */
77
if (!sock_flag(ax25->sk, SOCK_DEAD))
78
ax25->sk->sk_state_change(ax25->sk);
79
bh_unlock_sock(ax25->sk);
80
}
81
}
82
break;
83
84
case AX25_DM:
85
if (pf) {
86
if (ax25->modulus == AX25_MODULUS) {
87
ax25_disconnect(ax25, ECONNREFUSED);
88
} else {
89
ax25->modulus = AX25_MODULUS;
90
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
91
}
92
}
93
break;
94
95
default:
96
break;
97
}
98
99
return 0;
100
}
101
102
/*
103
* State machine for state 2, Awaiting Release State.
104
* The handling of the timer(s) is in file ax25_std_timer.c
105
* Handling of state 0 and connection release is in ax25.c.
106
*/
107
static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
108
{
109
switch (frametype) {
110
case AX25_SABM:
111
case AX25_SABME:
112
ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
113
break;
114
115
case AX25_DISC:
116
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
117
ax25_disconnect(ax25, 0);
118
break;
119
120
case AX25_DM:
121
case AX25_UA:
122
if (pf)
123
ax25_disconnect(ax25, 0);
124
break;
125
126
case AX25_I:
127
case AX25_REJ:
128
case AX25_RNR:
129
case AX25_RR:
130
if (pf) ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
131
break;
132
133
default:
134
break;
135
}
136
137
return 0;
138
}
139
140
/*
141
* State machine for state 3, Connected State.
142
* The handling of the timer(s) is in file ax25_std_timer.c
143
* Handling of state 0 and connection release is in ax25.c.
144
*/
145
static int ax25_std_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
146
{
147
int queued = 0;
148
149
switch (frametype) {
150
case AX25_SABM:
151
case AX25_SABME:
152
if (frametype == AX25_SABM) {
153
ax25->modulus = AX25_MODULUS;
154
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
155
} else {
156
ax25->modulus = AX25_EMODULUS;
157
ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
158
}
159
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
160
ax25_stop_t1timer(ax25);
161
ax25_stop_t2timer(ax25);
162
ax25_start_t3timer(ax25);
163
ax25_start_idletimer(ax25);
164
ax25->condition = 0x00;
165
ax25->vs = 0;
166
ax25->va = 0;
167
ax25->vr = 0;
168
ax25_requeue_frames(ax25);
169
break;
170
171
case AX25_DISC:
172
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
173
ax25_disconnect(ax25, 0);
174
break;
175
176
case AX25_DM:
177
ax25_disconnect(ax25, ECONNRESET);
178
break;
179
180
case AX25_RR:
181
case AX25_RNR:
182
if (frametype == AX25_RR)
183
ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
184
else
185
ax25->condition |= AX25_COND_PEER_RX_BUSY;
186
if (type == AX25_COMMAND && pf)
187
ax25_std_enquiry_response(ax25);
188
if (ax25_validate_nr(ax25, nr)) {
189
ax25_check_iframes_acked(ax25, nr);
190
} else {
191
ax25_std_nr_error_recovery(ax25);
192
ax25->state = AX25_STATE_1;
193
}
194
break;
195
196
case AX25_REJ:
197
ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
198
if (type == AX25_COMMAND && pf)
199
ax25_std_enquiry_response(ax25);
200
if (ax25_validate_nr(ax25, nr)) {
201
ax25_frames_acked(ax25, nr);
202
ax25_calculate_rtt(ax25);
203
ax25_stop_t1timer(ax25);
204
ax25_start_t3timer(ax25);
205
ax25_requeue_frames(ax25);
206
} else {
207
ax25_std_nr_error_recovery(ax25);
208
ax25->state = AX25_STATE_1;
209
}
210
break;
211
212
case AX25_I:
213
if (!ax25_validate_nr(ax25, nr)) {
214
ax25_std_nr_error_recovery(ax25);
215
ax25->state = AX25_STATE_1;
216
break;
217
}
218
if (ax25->condition & AX25_COND_PEER_RX_BUSY) {
219
ax25_frames_acked(ax25, nr);
220
} else {
221
ax25_check_iframes_acked(ax25, nr);
222
}
223
if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
224
if (pf) ax25_std_enquiry_response(ax25);
225
break;
226
}
227
if (ns == ax25->vr) {
228
ax25->vr = (ax25->vr + 1) % ax25->modulus;
229
queued = ax25_rx_iframe(ax25, skb);
230
if (ax25->condition & AX25_COND_OWN_RX_BUSY)
231
ax25->vr = ns; /* ax25->vr - 1 */
232
ax25->condition &= ~AX25_COND_REJECT;
233
if (pf) {
234
ax25_std_enquiry_response(ax25);
235
} else {
236
if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
237
ax25->condition |= AX25_COND_ACK_PENDING;
238
ax25_start_t2timer(ax25);
239
}
240
}
241
} else {
242
if (ax25->condition & AX25_COND_REJECT) {
243
if (pf) ax25_std_enquiry_response(ax25);
244
} else {
245
ax25->condition |= AX25_COND_REJECT;
246
ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);
247
ax25->condition &= ~AX25_COND_ACK_PENDING;
248
}
249
}
250
break;
251
252
case AX25_FRMR:
253
case AX25_ILLEGAL:
254
ax25_std_establish_data_link(ax25);
255
ax25->state = AX25_STATE_1;
256
break;
257
258
default:
259
break;
260
}
261
262
return queued;
263
}
264
265
/*
266
* State machine for state 4, Timer Recovery State.
267
* The handling of the timer(s) is in file ax25_std_timer.c
268
* Handling of state 0 and connection release is in ax25.c.
269
*/
270
static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
271
{
272
int queued = 0;
273
274
switch (frametype) {
275
case AX25_SABM:
276
case AX25_SABME:
277
if (frametype == AX25_SABM) {
278
ax25->modulus = AX25_MODULUS;
279
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
280
} else {
281
ax25->modulus = AX25_EMODULUS;
282
ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
283
}
284
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
285
ax25_stop_t1timer(ax25);
286
ax25_stop_t2timer(ax25);
287
ax25_start_t3timer(ax25);
288
ax25_start_idletimer(ax25);
289
ax25->condition = 0x00;
290
ax25->vs = 0;
291
ax25->va = 0;
292
ax25->vr = 0;
293
ax25->state = AX25_STATE_3;
294
ax25->n2count = 0;
295
ax25_requeue_frames(ax25);
296
break;
297
298
case AX25_DISC:
299
ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
300
ax25_disconnect(ax25, 0);
301
break;
302
303
case AX25_DM:
304
ax25_disconnect(ax25, ECONNRESET);
305
break;
306
307
case AX25_RR:
308
case AX25_RNR:
309
if (frametype == AX25_RR)
310
ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
311
else
312
ax25->condition |= AX25_COND_PEER_RX_BUSY;
313
if (type == AX25_RESPONSE && pf) {
314
ax25_stop_t1timer(ax25);
315
ax25->n2count = 0;
316
if (ax25_validate_nr(ax25, nr)) {
317
ax25_frames_acked(ax25, nr);
318
if (ax25->vs == ax25->va) {
319
ax25_start_t3timer(ax25);
320
ax25->state = AX25_STATE_3;
321
} else {
322
ax25_requeue_frames(ax25);
323
}
324
} else {
325
ax25_std_nr_error_recovery(ax25);
326
ax25->state = AX25_STATE_1;
327
}
328
break;
329
}
330
if (type == AX25_COMMAND && pf)
331
ax25_std_enquiry_response(ax25);
332
if (ax25_validate_nr(ax25, nr)) {
333
ax25_frames_acked(ax25, nr);
334
} else {
335
ax25_std_nr_error_recovery(ax25);
336
ax25->state = AX25_STATE_1;
337
}
338
break;
339
340
case AX25_REJ:
341
ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
342
if (pf && type == AX25_RESPONSE) {
343
ax25_stop_t1timer(ax25);
344
ax25->n2count = 0;
345
if (ax25_validate_nr(ax25, nr)) {
346
ax25_frames_acked(ax25, nr);
347
if (ax25->vs == ax25->va) {
348
ax25_start_t3timer(ax25);
349
ax25->state = AX25_STATE_3;
350
} else {
351
ax25_requeue_frames(ax25);
352
}
353
} else {
354
ax25_std_nr_error_recovery(ax25);
355
ax25->state = AX25_STATE_1;
356
}
357
break;
358
}
359
if (type == AX25_COMMAND && pf)
360
ax25_std_enquiry_response(ax25);
361
if (ax25_validate_nr(ax25, nr)) {
362
ax25_frames_acked(ax25, nr);
363
ax25_requeue_frames(ax25);
364
} else {
365
ax25_std_nr_error_recovery(ax25);
366
ax25->state = AX25_STATE_1;
367
}
368
break;
369
370
case AX25_I:
371
if (!ax25_validate_nr(ax25, nr)) {
372
ax25_std_nr_error_recovery(ax25);
373
ax25->state = AX25_STATE_1;
374
break;
375
}
376
ax25_frames_acked(ax25, nr);
377
if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
378
if (pf)
379
ax25_std_enquiry_response(ax25);
380
break;
381
}
382
if (ns == ax25->vr) {
383
ax25->vr = (ax25->vr + 1) % ax25->modulus;
384
queued = ax25_rx_iframe(ax25, skb);
385
if (ax25->condition & AX25_COND_OWN_RX_BUSY)
386
ax25->vr = ns; /* ax25->vr - 1 */
387
ax25->condition &= ~AX25_COND_REJECT;
388
if (pf) {
389
ax25_std_enquiry_response(ax25);
390
} else {
391
if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
392
ax25->condition |= AX25_COND_ACK_PENDING;
393
ax25_start_t2timer(ax25);
394
}
395
}
396
} else {
397
if (ax25->condition & AX25_COND_REJECT) {
398
if (pf) ax25_std_enquiry_response(ax25);
399
} else {
400
ax25->condition |= AX25_COND_REJECT;
401
ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);
402
ax25->condition &= ~AX25_COND_ACK_PENDING;
403
}
404
}
405
break;
406
407
case AX25_FRMR:
408
case AX25_ILLEGAL:
409
ax25_std_establish_data_link(ax25);
410
ax25->state = AX25_STATE_1;
411
break;
412
413
default:
414
break;
415
}
416
417
return queued;
418
}
419
420
/*
421
* Higher level upcall for a LAPB frame
422
*/
423
int ax25_std_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
424
{
425
int queued = 0, frametype, ns, nr, pf;
426
427
frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);
428
429
switch (ax25->state) {
430
case AX25_STATE_1:
431
queued = ax25_std_state1_machine(ax25, skb, frametype, pf, type);
432
break;
433
case AX25_STATE_2:
434
queued = ax25_std_state2_machine(ax25, skb, frametype, pf, type);
435
break;
436
case AX25_STATE_3:
437
queued = ax25_std_state3_machine(ax25, skb, frametype, ns, nr, pf, type);
438
break;
439
case AX25_STATE_4:
440
queued = ax25_std_state4_machine(ax25, skb, frametype, ns, nr, pf, type);
441
break;
442
}
443
444
ax25_kick(ax25);
445
446
return queued;
447
}
448
449