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