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