~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/ax25/ax25_std_in.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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 }
468 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.