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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [ax25/] [ax25_in.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *      AX.25 release 035
3
 *
4
 *      This code REQUIRES 1.2.1 or higher/ NET3.029
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
 *                      Joerg(DL1BKE)   Fixed 2.0.x specific IP over AX.25 problem.
36
 */
37
 
38
#include <linux/config.h>
39
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
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/segment.h>
57
#include <asm/system.h>
58
#include <linux/fcntl.h>
59
#include <linux/mm.h>
60
#include <linux/interrupt.h>
61
 
62
static int ax25_rx_iframe(ax25_cb *, struct sk_buff *);
63
 
64
/*
65
 *      Given a fragment, queue it on the fragment queue and if the fragment
66
 *      is complete, send it back to ax25_rx_iframe.
67
 */
68
static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
69
{
70
        struct sk_buff *skbn, *skbo;
71
 
72
        if (ax25->fragno != 0) {
73
                if (!(*skb->data & AX25_SEG_FIRST)) {
74
                        if ((ax25->fragno - 1) == (*skb->data & AX25_SEG_REM)) {
75
                                /* Enqueue fragment */
76
                                ax25->fragno = *skb->data & AX25_SEG_REM;
77
                                skb_pull(skb, 1);       /* skip fragno */
78
                                ax25->fraglen += skb->len;
79
                                skb_queue_tail(&ax25->frag_queue, skb);
80
 
81
                                /* Last fragment received ? */
82
                                if (ax25->fragno == 0) {
83
                                        if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL) {
84
                                                while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
85
                                                        kfree_skb(skbo, FREE_READ);
86
                                                return 1;
87
                                        }
88
 
89
                                        skb_reserve(skbn, AX25_MAX_HEADER_LEN);
90
 
91
                                        skbn->free  = 1;
92
                                        skbn->dev   = ax25->device;
93
                                        skbn->h.raw = skbn->data;
94
 
95
                                        /* Copy data from the fragments */
96
                                        while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
97
                                                memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
98
                                                kfree_skb(skbo, FREE_READ);
99
                                        }
100
 
101
                                        ax25->fraglen = 0;
102
 
103
                                        if (ax25_rx_iframe(ax25, skbn) == 0)
104
                                                kfree_skb(skbn, FREE_READ);
105
                                }
106
 
107
                                return 1;
108
                        }
109
                }
110
        } else {
111
                /* First fragment received */
112
                if (*skb->data & AX25_SEG_FIRST) {
113
                        while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
114
                                kfree_skb(skbo, FREE_READ);
115
                        ax25->fragno = *skb->data & AX25_SEG_REM;
116
                        skb_pull(skb, 1);               /* skip fragno */
117
                        ax25->fraglen = skb->len;
118
                        skb_queue_tail(&ax25->frag_queue, skb);
119
                        return 1;
120
                }
121
        }
122
 
123
        return 0;
124
}
125
 
126
/*
127
 *      This is where all valid I frames are sent to, to be dispatched to
128
 *      whichever protocol requires them.
129
 */
130
static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
131
{
132
        int (*func)(struct sk_buff *, ax25_cb *);
133
        struct sk_buff *skbn;
134
        volatile int queued = 0;
135
        unsigned char pid;
136
 
137
        if (skb == NULL) return 0;
138
 
139
        ax25->idletimer = ax25->idle;
140
 
141
        pid = *skb->data;
142
 
143
#ifdef CONFIG_INET
144
        if (pid == AX25_P_IP) {
145
                if ((skbn = skb_copy(skb, GFP_ATOMIC)) != NULL) {
146
                        kfree_skb(skb, FREE_READ);
147
                        skb = skbn;
148
                }
149
                skb_pull(skb, 1);       /* Remove PID */
150
                skb->h.raw = skb->data;
151
                ip_rcv(skb, ax25->device, NULL);        /* Wrong ptype */
152
                return 1;
153
        }
154
#endif
155
        if (pid == AX25_P_SEGMENT) {
156
                skb_pull(skb, 1);       /* Remove PID */
157
                return ax25_rx_fragment(ax25, skb);
158
        }
159
 
160
        if ((func = ax25_protocol_function(pid)) != NULL) {
161
                skb_pull(skb, 1);       /* Remove PID */
162
                return (*func)(skb, ax25);
163
        }
164
 
165
        if (ax25->sk != NULL && ax25_dev_get_value(ax25->device, AX25_VALUES_CONMODE) == 2) {
166
                if ((!ax25->pidincl && ax25->sk->protocol == pid) || ax25->pidincl) {
167
                        if (sock_queue_rcv_skb(ax25->sk, skb) == 0)
168
                                queued = 1;
169
                        else
170
                                ax25->condition |= AX25_COND_OWN_RX_BUSY;
171
                }
172
        }
173
 
174
        return queued;
175
}
176
 
177
/*
178
 *      State machine for state 1, Awaiting Connection State.
179
 *      The handling of the timer(s) is in file ax25_timer.c.
180
 *      Handling of state 0 and connection release is in ax25.c.
181
 */
182
static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type, int dama)
183
{
184
        switch (frametype) {
185
                case AX25_SABM:
186
                        ax25->modulus = AX25_MODULUS;
187
                        ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
188
                        ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
189
                        break;
190
 
191
                case AX25_SABME:
192
                        ax25->modulus = AX25_EMODULUS;
193
                        ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
194
                        ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
195
                        break;
196
 
197
                case AX25_DISC:
198
                        ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
199
                        break;
200
 
201
                case AX25_UA:
202
                        if (pf || dama) {
203
                                if (dama) ax25_dama_on(ax25); /* bke */
204
                                ax25_calculate_rtt(ax25);
205
                                ax25->t1timer = 0;
206
                                ax25->t3timer = ax25->t3;
207
                                ax25->idletimer = ax25->idle;
208
                                ax25->vs      = 0;
209
                                ax25->va      = 0;
210
                                ax25->vr      = 0;
211
                                ax25->state   = AX25_STATE_3;
212
                                ax25->n2count = 0;
213
                                ax25->dama_slave = dama;        /* bke */
214
                                if (ax25->sk != NULL) {
215
                                        ax25->sk->state = TCP_ESTABLISHED;
216
                                        /* For WAIT_SABM connections we will produce an accept ready socket here */
217
                                        if (!ax25->sk->dead)
218
                                                ax25->sk->state_change(ax25->sk);
219
                                }
220
                        }
221
                        break;
222
 
223
                case AX25_DM:
224
                        if (pf) {
225
                                if (ax25->modulus == AX25_MODULUS) {
226
                                        ax25_disconnect(ax25, ECONNREFUSED);
227
                                } else {
228
                                        ax25->modulus = AX25_MODULUS;
229
                                        ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
230
                                }
231
                        }
232
                        break;
233
 
234
                default:
235
                        if (dama && pf)
236
                                ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
237
                        break;
238
        }
239
 
240
        return 0;
241
}
242
 
243
/*
244
 *      State machine for state 2, Awaiting Release State.
245
 *      The handling of the timer(s) is in file ax25_timer.c
246
 *      Handling of state 0 and connection release is in ax25.c.
247
 */
248
static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
249
{
250
        switch (frametype) {
251
                case AX25_SABM:
252
                case AX25_SABME:
253
                        ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
254
                        if (ax25->dama_slave)
255
                                ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
256
                        break;
257
 
258
                case AX25_DISC:
259
                        ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
260
                        if (ax25->dama_slave) ax25_disconnect(ax25, 0);
261
                        break;
262
 
263
                case AX25_DM:
264
                case AX25_UA:
265
                        if (pf) ax25_disconnect(ax25, 0);
266
                        break;
267
 
268
                case AX25_I:
269
                case AX25_REJ:
270
                case AX25_RNR:
271
                case AX25_RR:
272
                        if (pf) {
273
                                if (ax25->dama_slave)
274
                                        ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
275
                                else
276
                                        ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
277
                        }
278
                        break;
279
 
280
                default:
281
                        break;
282
        }
283
 
284
        return 0;
285
}
286
 
287
/*
288
 *      State machine for state 3, Connected State.
289
 *      The handling of the timer(s) is in file ax25_timer.c
290
 *      Handling of state 0 and connection release is in ax25.c.
291
 */
292
static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type, int dama)
293
{
294
        int queued = 0;
295
 
296
        switch (frametype) {
297
                case AX25_SABM:
298
                case AX25_SABME:
299
                        if (dama) ax25_dama_on(ax25);
300
                        if (frametype == AX25_SABM) {
301
                                ax25->modulus = AX25_MODULUS;
302
                                ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
303
                        } else {
304
                                ax25->modulus = AX25_EMODULUS;
305
                                ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
306
                        }
307
                        ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
308
                        ax25->condition = 0x00;
309
                        ax25->t1timer   = 0;
310
                        ax25->t3timer   = ax25->t3;
311
                        ax25->idletimer = ax25->idle;
312
                        ax25->vs        = 0;
313
                        ax25->va        = 0;
314
                        ax25->vr        = 0;
315
                        ax25->dama_slave = dama;
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 (!ax25->dama_slave && type == AX25_COMMAND && pf)
335
                                ax25_enquiry_response(ax25);
336
                        if (ax25_validate_nr(ax25, nr)) {
337
                                ax25_check_iframes_acked(ax25, nr);
338
                                if (ax25->dama_slave && type == AX25_COMMAND && pf)
339
                                        dama_enquiry_response(ax25);
340
                        } else {
341
                                ax25_nr_error_recovery(ax25);
342
                                ax25->state = AX25_STATE_1;
343
                        }
344
                        break;
345
 
346
                case AX25_REJ:
347
                        ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
348
                        if (!ax25->dama_slave && type == AX25_COMMAND && pf)
349
                                ax25_enquiry_response(ax25);
350
                        if (ax25_validate_nr(ax25, nr)) {
351
                                ax25_frames_acked(ax25, nr);
352
                                ax25_calculate_rtt(ax25);
353
                                ax25->t1timer = 0;
354
                                ax25->t3timer = ax25->t3;
355
                                ax25_requeue_frames(ax25);
356
                                if (ax25->dama_slave && type == AX25_COMMAND && pf)
357
                                        dama_enquiry_response(ax25);
358
                        } else {
359
                                ax25_nr_error_recovery(ax25);
360
                                ax25->state = AX25_STATE_1;
361
                        }
362
                        break;
363
 
364
                case AX25_I:
365
                        if (!ax25_validate_nr(ax25, nr)) {
366
                                ax25_nr_error_recovery(ax25);
367
                                ax25->state = AX25_STATE_1;
368
                                break;
369
                        }
370
                        if (ax25->condition & AX25_COND_PEER_RX_BUSY) {
371
                                ax25_frames_acked(ax25, nr);
372
                        } else {
373
                                ax25_check_iframes_acked(ax25, nr);
374
                        }
375
                        if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
376
                                if (pf) {
377
                                        if (ax25->dama_slave)
378
                                                dama_enquiry_response(ax25);
379
                                        else
380
                                                ax25_enquiry_response(ax25);
381
                                }
382
                                break;
383
                        }
384
                        if (ns == ax25->vr) {
385
                                ax25->vr = (ax25->vr + 1) % ax25->modulus;
386
                                queued = ax25_rx_iframe(ax25, skb);
387
                                if (ax25->condition & AX25_COND_OWN_RX_BUSY)
388
                                        ax25->vr = ns;  /* ax25->vr - 1 */
389
                                ax25->condition &= ~AX25_COND_REJECT;
390
                                if (pf) {
391
                                        if (ax25->dama_slave)
392
                                                dama_enquiry_response(ax25);
393
                                        else
394
                                                ax25_enquiry_response(ax25);
395
                                } else {
396
                                        if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
397
                                                ax25->t2timer    = ax25->t2;
398
                                                ax25->condition |= AX25_COND_ACK_PENDING;
399
                                        }
400
                                }
401
                        } else {
402
                                if (ax25->condition & AX25_COND_REJECT) {
403
                                        if (pf) {
404
                                                if (ax25->dama_slave)
405
                                                        dama_enquiry_response(ax25);
406
                                                else
407
                                                        ax25_enquiry_response(ax25);
408
                                        }
409
                                } else {
410
                                        ax25->condition |= AX25_COND_REJECT;
411
                                        if (ax25->dama_slave)
412
                                                dama_enquiry_response(ax25);
413
                                        else
414
                                                ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);
415
                                        ax25->condition &= ~AX25_COND_ACK_PENDING;
416
                                }
417
                        }
418
                        break;
419
 
420
                case AX25_FRMR:
421
                case AX25_ILLEGAL:
422
                        ax25_establish_data_link(ax25);
423
                        ax25->state = AX25_STATE_1;
424
                        break;
425
 
426
                default:
427
                        break;
428
        }
429
 
430
        return queued;
431
}
432
 
433
/*
434
 *      State machine for state 4, Timer Recovery State.
435
 *      The handling of the timer(s) is in file ax25_timer.c
436
 *      Handling of state 0 and connection release is in ax25.c.
437
 */
438
static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type, int dama)
439
{
440
        int queued = 0;
441
 
442
        switch (frametype) {
443
                case AX25_SABM:
444
                case AX25_SABME:
445
                        if (dama) ax25_dama_on(ax25);
446
                        if (frametype == AX25_SABM) {
447
                                ax25->modulus = AX25_MODULUS;
448
                                ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_WINDOW);
449
                        } else {
450
                                ax25->modulus = AX25_EMODULUS;
451
                                ax25->window  = ax25_dev_get_value(ax25->device, AX25_VALUES_EWINDOW);
452
                        }
453
                        ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
454
                        ax25->condition = 0x00;
455
                        ax25->t1timer   = 0;
456
                        ax25->t3timer   = ax25->t3;
457
                        ax25->idletimer = ax25->idle;
458
                        ax25->vs        = 0;
459
                        ax25->va        = 0;
460
                        ax25->vr        = 0;
461
                        ax25->state     = AX25_STATE_3;
462
                        ax25->n2count   = 0;
463
                        ax25->dama_slave = dama;
464
                        ax25_requeue_frames(ax25);
465
                        break;
466
 
467
                case AX25_DISC:
468
                        ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
469
                        ax25_disconnect(ax25, 0);
470
                        break;
471
 
472
                case AX25_DM:
473
                        ax25_disconnect(ax25, ECONNRESET);
474
                        break;
475
 
476
                case AX25_RR:
477
                case AX25_RNR:
478
                        if (frametype == AX25_RR)
479
                                ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
480
                        else
481
                                ax25->condition |= AX25_COND_PEER_RX_BUSY;
482
                        if (type == AX25_RESPONSE && pf) {
483
                                ax25->t1timer = 0;
484
                                if (ax25_validate_nr(ax25, nr)) {
485
                                        ax25_frames_acked(ax25, nr);
486
                                        if (ax25->vs == ax25->va) {
487
                                                ax25->t3timer = ax25->t3;
488
                                                ax25->n2count = 0;
489
                                                ax25->state   = AX25_STATE_3;
490
                                        } else {
491
                                                ax25_requeue_frames(ax25);
492
                                        }
493
                                } else {
494
                                        ax25_nr_error_recovery(ax25);
495
                                        ax25->state = AX25_STATE_1;
496
                                }
497
                                break;
498
                        }
499
                        if (!ax25->dama_slave && type == AX25_COMMAND && pf)
500
                                ax25_enquiry_response(ax25);
501
                        if (ax25_validate_nr(ax25, nr)) {
502
                                ax25_frames_acked(ax25, nr);
503
                                if (ax25->dama_slave && type == AX25_COMMAND && pf)
504
                                        dama_enquiry_response(ax25);
505
                        } else {
506
                                ax25_nr_error_recovery(ax25);
507
                                ax25->state = AX25_STATE_1;
508
                        }
509
                        break;
510
 
511
                case AX25_REJ:
512
                        ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
513
                        if (pf && (type == AX25_RESPONSE || (ax25->dama_slave && type == AX25_COMMAND))) {
514
                                ax25->t1timer = 0;
515
                                if (ax25_validate_nr(ax25, nr)) {
516
                                        ax25_frames_acked(ax25, nr);
517
                                        if (ax25->vs == ax25->va) {
518
                                                ax25->t3timer = ax25->t3;
519
                                                ax25->n2count = 0;
520
                                                ax25->state   = AX25_STATE_3;
521
                                        } else {
522
                                                ax25_requeue_frames(ax25);
523
                                        }
524
                                        if (ax25->dama_slave && type == AX25_COMMAND && pf)
525
                                                dama_enquiry_response(ax25);
526
                                } else {
527
                                        ax25_nr_error_recovery(ax25);
528
                                        ax25->state = AX25_STATE_1;
529
                                }
530
                                break;
531
                        }
532
                        if (!ax25->dama_slave && type == AX25_COMMAND && pf)
533
                                ax25_enquiry_response(ax25);
534
                        if (ax25_validate_nr(ax25, nr)) {
535
                                ax25_frames_acked(ax25, nr);
536
                                ax25_requeue_frames(ax25);
537
                                if (ax25->dama_slave && type == AX25_COMMAND && pf)
538
                                        dama_enquiry_response(ax25);
539
                        } else {
540
                                ax25_nr_error_recovery(ax25);
541
                                ax25->state = AX25_STATE_1;
542
                        }
543
                        break;
544
 
545
                case AX25_I:
546
                        if (!ax25_validate_nr(ax25, nr)) {
547
                                ax25_nr_error_recovery(ax25);
548
                                ax25->state = AX25_STATE_1;
549
                                break;
550
                        }
551
                        ax25_frames_acked(ax25, nr);
552
                        if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
553
                                if (pf) {
554
                                        if (ax25->dama_slave)
555
                                                ax25_enquiry_response(ax25);
556
                                        else
557
                                                dama_enquiry_response(ax25);
558
                                }
559
                                break;
560
                        }
561
                        if (ns == ax25->vr) {
562
                                ax25->vr = (ax25->vr + 1) % ax25->modulus;
563
                                queued = ax25_rx_iframe(ax25, skb);
564
                                if (ax25->condition & AX25_COND_OWN_RX_BUSY)
565
                                        ax25->vr = ns;  /* ax25->vr - 1 */
566
                                ax25->condition &= ~AX25_COND_REJECT;
567
                                if (pf) {
568
                                        if (ax25->dama_slave)
569
                                                dama_enquiry_response(ax25);
570
                                        else
571
                                                ax25_enquiry_response(ax25);
572
                                } else {
573
                                        if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
574
                                                ax25->t2timer    = ax25->t2;
575
                                                ax25->condition |= AX25_COND_ACK_PENDING;
576
                                        }
577
                                }
578
                        } else {
579
                                if (ax25->condition & AX25_COND_REJECT) {
580
                                        if (pf) {
581
                                                if (ax25->dama_slave)
582
                                                        dama_enquiry_response(ax25);
583
                                                else
584
                                                        ax25_enquiry_response(ax25);
585
                                        }
586
                                } else {
587
                                        ax25->condition |= AX25_COND_REJECT;
588
                                        if (ax25->dama_slave)
589
                                                dama_enquiry_response(ax25);
590
                                        else
591
                                                ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE);
592
                                        ax25->condition &= ~AX25_COND_ACK_PENDING;
593
                                }
594
                        }
595
                        break;
596
 
597
                case AX25_FRMR:
598
                case AX25_ILLEGAL:
599
                        ax25_establish_data_link(ax25);
600
                        ax25->state = AX25_STATE_1;
601
                        break;
602
 
603
                default:
604
                        break;
605
        }
606
 
607
        return queued;
608
}
609
 
610
/*
611
 *      Higher level upcall for a LAPB frame
612
 */
613
int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, int dama)
614
{
615
        int queued = 0, frametype, ns, nr, pf;
616
 
617
        if (ax25->state == AX25_STATE_0)
618
                return 0;
619
 
620
        del_timer(&ax25->timer);
621
 
622
        frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);
623
 
624
        switch (ax25->state) {
625
                case AX25_STATE_1:
626
                        queued = ax25_state1_machine(ax25, skb, frametype, pf, type, dama);
627
                        break;
628
                case AX25_STATE_2:
629
                        queued = ax25_state2_machine(ax25, skb, frametype, pf, type);
630
                        break;
631
                case AX25_STATE_3:
632
                        queued = ax25_state3_machine(ax25, skb, frametype, ns, nr, pf, type, dama);
633
                        break;
634
                case AX25_STATE_4:
635
                        queued = ax25_state4_machine(ax25, skb, frametype, ns, nr, pf, type, dama);
636
                        break;
637
        }
638
 
639
        ax25_set_timer(ax25);
640
 
641
        return queued;
642
}
643
 
644
#endif

powered by: WebSVN 2.1.0

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