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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [x25/] [x25_in.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *      X.25 Packet Layer release 002
3
 *
4
 *      This is ALPHA test software. This code may break your machine,
5
 *      randomly fail to work with new releases, misbehave and/or generally
6
 *      screw up. It might even work.
7
 *
8
 *      This code REQUIRES 2.1.15 or higher
9
 *
10
 *      This module:
11
 *              This module is free software; you can redistribute it and/or
12
 *              modify it under the terms of the GNU General Public License
13
 *              as published by the Free Software Foundation; either version
14
 *              2 of the License, or (at your option) any later version.
15
 *
16
 *      History
17
 *      X.25 001        Jonathan Naylor   Started coding.
18
 *      X.25 002        Jonathan Naylor   Centralised disconnection code.
19
 *                                        New timer architecture.
20
 *      2000-03-20      Daniela Squassoni Disabling/enabling of facilities
21
 *                                        negotiation.
22
 *      2000-11-10      Henner Eisen      Check and reset for out-of-sequence
23
 *                                        i-frames.
24
 */
25
 
26
#include <linux/errno.h>
27
#include <linux/kernel.h>
28
#include <linux/string.h>
29
#include <linux/skbuff.h>
30
#include <net/sock.h>
31
#include <net/tcp_states.h>
32
#include <net/x25.h>
33
 
34
static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
35
{
36
        struct sk_buff *skbo, *skbn = skb;
37
        struct x25_sock *x25 = x25_sk(sk);
38
 
39
        if (more) {
40
                x25->fraglen += skb->len;
41
                skb_queue_tail(&x25->fragment_queue, skb);
42
                skb_set_owner_r(skb, sk);
43
                return 0;
44
        }
45
 
46
        if (!more && x25->fraglen > 0) { /* End of fragment */
47
                int len = x25->fraglen + skb->len;
48
 
49
                if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL){
50
                        kfree_skb(skb);
51
                        return 1;
52
                }
53
 
54
                skb_queue_tail(&x25->fragment_queue, skb);
55
 
56
                skb_reset_transport_header(skbn);
57
 
58
                skbo = skb_dequeue(&x25->fragment_queue);
59
                skb_copy_from_linear_data(skbo, skb_put(skbn, skbo->len),
60
                                          skbo->len);
61
                kfree_skb(skbo);
62
 
63
                while ((skbo =
64
                        skb_dequeue(&x25->fragment_queue)) != NULL) {
65
                        skb_pull(skbo, (x25->neighbour->extended) ?
66
                                        X25_EXT_MIN_LEN : X25_STD_MIN_LEN);
67
                        skb_copy_from_linear_data(skbo,
68
                                                  skb_put(skbn, skbo->len),
69
                                                  skbo->len);
70
                        kfree_skb(skbo);
71
                }
72
 
73
                x25->fraglen = 0;
74
        }
75
 
76
        skb_set_owner_r(skbn, sk);
77
        skb_queue_tail(&sk->sk_receive_queue, skbn);
78
        if (!sock_flag(sk, SOCK_DEAD))
79
                sk->sk_data_ready(sk, skbn->len);
80
 
81
        return 0;
82
}
83
 
84
/*
85
 * State machine for state 1, Awaiting Call Accepted State.
86
 * The handling of the timer(s) is in file x25_timer.c.
87
 * Handling of state 0 and connection release is in af_x25.c.
88
 */
89
static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
90
{
91
        struct x25_address source_addr, dest_addr;
92
 
93
        switch (frametype) {
94
                case X25_CALL_ACCEPTED: {
95
                        struct x25_sock *x25 = x25_sk(sk);
96
 
97
                        x25_stop_timer(sk);
98
                        x25->condition = 0x00;
99
                        x25->vs        = 0;
100
                        x25->va        = 0;
101
                        x25->vr        = 0;
102
                        x25->vl        = 0;
103
                        x25->state     = X25_STATE_3;
104
                        sk->sk_state   = TCP_ESTABLISHED;
105
                        /*
106
                         *      Parse the data in the frame.
107
                         */
108
                        skb_pull(skb, X25_STD_MIN_LEN);
109
                        skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
110
                        skb_pull(skb,
111
                                 x25_parse_facilities(skb, &x25->facilities,
112
                                                &x25->dte_facilities,
113
                                                &x25->vc_facil_mask));
114
                        /*
115
                         *      Copy any Call User Data.
116
                         */
117
                        if (skb->len >= 0) {
118
                                skb_copy_from_linear_data(skb,
119
                                              x25->calluserdata.cuddata,
120
                                              skb->len);
121
                                x25->calluserdata.cudlength = skb->len;
122
                        }
123
                        if (!sock_flag(sk, SOCK_DEAD))
124
                                sk->sk_state_change(sk);
125
                        break;
126
                }
127
                case X25_CLEAR_REQUEST:
128
                        x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
129
                        x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
130
                        break;
131
 
132
                default:
133
                        break;
134
        }
135
 
136
        return 0;
137
}
138
 
139
/*
140
 * State machine for state 2, Awaiting Clear Confirmation State.
141
 * The handling of the timer(s) is in file x25_timer.c
142
 * Handling of state 0 and connection release is in af_x25.c.
143
 */
144
static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
145
{
146
        switch (frametype) {
147
 
148
                case X25_CLEAR_REQUEST:
149
                        x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
150
                        x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
151
                        break;
152
 
153
                case X25_CLEAR_CONFIRMATION:
154
                        x25_disconnect(sk, 0, 0, 0);
155
                        break;
156
 
157
                default:
158
                        break;
159
        }
160
 
161
        return 0;
162
}
163
 
164
/*
165
 * State machine for state 3, Connected State.
166
 * The handling of the timer(s) is in file x25_timer.c
167
 * Handling of state 0 and connection release is in af_x25.c.
168
 */
169
static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
170
{
171
        int queued = 0;
172
        int modulus;
173
        struct x25_sock *x25 = x25_sk(sk);
174
 
175
        modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
176
 
177
        switch (frametype) {
178
 
179
                case X25_RESET_REQUEST:
180
                        x25_write_internal(sk, X25_RESET_CONFIRMATION);
181
                        x25_stop_timer(sk);
182
                        x25->condition = 0x00;
183
                        x25->vs        = 0;
184
                        x25->vr        = 0;
185
                        x25->va        = 0;
186
                        x25->vl        = 0;
187
                        x25_requeue_frames(sk);
188
                        break;
189
 
190
                case X25_CLEAR_REQUEST:
191
                        x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
192
                        x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
193
                        break;
194
 
195
                case X25_RR:
196
                case X25_RNR:
197
                        if (!x25_validate_nr(sk, nr)) {
198
                                x25_clear_queues(sk);
199
                                x25_write_internal(sk, X25_RESET_REQUEST);
200
                                x25_start_t22timer(sk);
201
                                x25->condition = 0x00;
202
                                x25->vs        = 0;
203
                                x25->vr        = 0;
204
                                x25->va        = 0;
205
                                x25->vl        = 0;
206
                                x25->state     = X25_STATE_4;
207
                        } else {
208
                                x25_frames_acked(sk, nr);
209
                                if (frametype == X25_RNR) {
210
                                        x25->condition |= X25_COND_PEER_RX_BUSY;
211
                                } else {
212
                                        x25->condition &= ~X25_COND_PEER_RX_BUSY;
213
                                }
214
                        }
215
                        break;
216
 
217
                case X25_DATA:  /* XXX */
218
                        x25->condition &= ~X25_COND_PEER_RX_BUSY;
219
                        if ((ns != x25->vr) || !x25_validate_nr(sk, nr)) {
220
                                x25_clear_queues(sk);
221
                                x25_write_internal(sk, X25_RESET_REQUEST);
222
                                x25_start_t22timer(sk);
223
                                x25->condition = 0x00;
224
                                x25->vs        = 0;
225
                                x25->vr        = 0;
226
                                x25->va        = 0;
227
                                x25->vl        = 0;
228
                                x25->state     = X25_STATE_4;
229
                                break;
230
                        }
231
                        x25_frames_acked(sk, nr);
232
                        if (ns == x25->vr) {
233
                                if (x25_queue_rx_frame(sk, skb, m) == 0) {
234
                                        x25->vr = (x25->vr + 1) % modulus;
235
                                        queued = 1;
236
                                } else {
237
                                        /* Should never happen */
238
                                        x25_clear_queues(sk);
239
                                        x25_write_internal(sk, X25_RESET_REQUEST);
240
                                        x25_start_t22timer(sk);
241
                                        x25->condition = 0x00;
242
                                        x25->vs        = 0;
243
                                        x25->vr        = 0;
244
                                        x25->va        = 0;
245
                                        x25->vl        = 0;
246
                                        x25->state     = X25_STATE_4;
247
                                        break;
248
                                }
249
                                if (atomic_read(&sk->sk_rmem_alloc) >
250
                                    (sk->sk_rcvbuf / 2))
251
                                        x25->condition |= X25_COND_OWN_RX_BUSY;
252
                        }
253
                        /*
254
                         *      If the window is full Ack it immediately, else
255
                         *      start the holdback timer.
256
                         */
257
                        if (((x25->vl + x25->facilities.winsize_in) % modulus) == x25->vr) {
258
                                x25->condition &= ~X25_COND_ACK_PENDING;
259
                                x25_stop_timer(sk);
260
                                x25_enquiry_response(sk);
261
                        } else {
262
                                x25->condition |= X25_COND_ACK_PENDING;
263
                                x25_start_t2timer(sk);
264
                        }
265
                        break;
266
 
267
                case X25_INTERRUPT_CONFIRMATION:
268
                        x25->intflag = 0;
269
                        break;
270
 
271
                case X25_INTERRUPT:
272
                        if (sock_flag(sk, SOCK_URGINLINE))
273
                                queued = !sock_queue_rcv_skb(sk, skb);
274
                        else {
275
                                skb_set_owner_r(skb, sk);
276
                                skb_queue_tail(&x25->interrupt_in_queue, skb);
277
                                queued = 1;
278
                        }
279
                        sk_send_sigurg(sk);
280
                        x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION);
281
                        break;
282
 
283
                default:
284
                        printk(KERN_WARNING "x25: unknown %02X in state 3\n", frametype);
285
                        break;
286
        }
287
 
288
        return queued;
289
}
290
 
291
/*
292
 * State machine for state 4, Awaiting Reset Confirmation State.
293
 * The handling of the timer(s) is in file x25_timer.c
294
 * Handling of state 0 and connection release is in af_x25.c.
295
 */
296
static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype)
297
{
298
        switch (frametype) {
299
 
300
                case X25_RESET_REQUEST:
301
                        x25_write_internal(sk, X25_RESET_CONFIRMATION);
302
                case X25_RESET_CONFIRMATION: {
303
                        struct x25_sock *x25 = x25_sk(sk);
304
 
305
                        x25_stop_timer(sk);
306
                        x25->condition = 0x00;
307
                        x25->va        = 0;
308
                        x25->vr        = 0;
309
                        x25->vs        = 0;
310
                        x25->vl        = 0;
311
                        x25->state     = X25_STATE_3;
312
                        x25_requeue_frames(sk);
313
                        break;
314
                }
315
                case X25_CLEAR_REQUEST:
316
                        x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
317
                        x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
318
                        break;
319
 
320
                default:
321
                        break;
322
        }
323
 
324
        return 0;
325
}
326
 
327
/* Higher level upcall for a LAPB frame */
328
int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
329
{
330
        struct x25_sock *x25 = x25_sk(sk);
331
        int queued = 0, frametype, ns, nr, q, d, m;
332
 
333
        if (x25->state == X25_STATE_0)
334
                return 0;
335
 
336
        frametype = x25_decode(sk, skb, &ns, &nr, &q, &d, &m);
337
 
338
        switch (x25->state) {
339
                case X25_STATE_1:
340
                        queued = x25_state1_machine(sk, skb, frametype);
341
                        break;
342
                case X25_STATE_2:
343
                        queued = x25_state2_machine(sk, skb, frametype);
344
                        break;
345
                case X25_STATE_3:
346
                        queued = x25_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
347
                        break;
348
                case X25_STATE_4:
349
                        queued = x25_state4_machine(sk, skb, frametype);
350
                        break;
351
        }
352
 
353
        x25_kick(sk);
354
 
355
        return queued;
356
}
357
 
358
int x25_backlog_rcv(struct sock *sk, struct sk_buff *skb)
359
{
360
        int queued = x25_process_rx_frame(sk, skb);
361
 
362
        if (!queued)
363
                kfree_skb(skb);
364
 
365
        return 0;
366
}

powered by: WebSVN 2.1.0

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