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