OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ax25/] [ax25_std_in.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.