linux/net/ax25/ax25_ds_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) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   8 * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
   9 */
  10#include <linux/errno.h>
  11#include <linux/types.h>
  12#include <linux/socket.h>
  13#include <linux/in.h>
  14#include <linux/kernel.h>
  15#include <linux/timer.h>
  16#include <linux/string.h>
  17#include <linux/sockios.h>
  18#include <linux/net.h>
  19#include <net/ax25.h>
  20#include <linux/inet.h>
  21#include <linux/netdevice.h>
  22#include <linux/skbuff.h>
  23#include <net/sock.h>
  24#include <net/tcp_states.h>
  25#include <asm/uaccess.h>
  26#include <asm/system.h>
  27#include <linux/fcntl.h>
  28#include <linux/mm.h>
  29#include <linux/interrupt.h>
  30
  31/*
  32 *      State machine for state 1, Awaiting Connection State.
  33 *      The handling of the timer(s) is in file ax25_ds_timer.c.
  34 *      Handling of state 0 and connection release is in ax25.c.
  35 */
  36static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
  37{
  38        switch (frametype) {
  39        case AX25_SABM:
  40                ax25->modulus = AX25_MODULUS;
  41                ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
  42                ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
  43                break;
  44
  45        case AX25_SABME:
  46                ax25->modulus = AX25_EMODULUS;
  47                ax25->window  =  ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
  48                ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
  49                break;
  50
  51        case AX25_DISC:
  52                ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
  53                break;
  54
  55        case AX25_UA:
  56                ax25_calculate_rtt(ax25);
  57                ax25_stop_t1timer(ax25);
  58                ax25_start_t3timer(ax25);
  59                ax25_start_idletimer(ax25);
  60                ax25->vs      = 0;
  61                ax25->va      = 0;
  62                ax25->vr      = 0;
  63                ax25->state   = AX25_STATE_3;
  64                ax25->n2count = 0;
  65                if (ax25->sk != NULL) {
  66                        bh_lock_sock(ax25->sk);
  67                        ax25->sk->sk_state = TCP_ESTABLISHED;
  68                        /*
  69                         * For WAIT_SABM connections we will produce an accept
  70                         * ready socket here
  71                         */
  72                        if (!sock_flag(ax25->sk, SOCK_DEAD))
  73                                ax25->sk->sk_state_change(ax25->sk);
  74                        bh_unlock_sock(ax25->sk);
  75                }
  76                ax25_dama_on(ax25);
  77
  78                /* according to DK4EG's spec we are required to
  79                 * send a RR RESPONSE FINAL NR=0.
  80                 */
  81
  82                ax25_std_enquiry_response(ax25);
  83                break;
  84
  85        case AX25_DM:
  86                if (pf)
  87                        ax25_disconnect(ax25, ECONNREFUSED);
  88                break;
  89
  90        default:
  91                if (pf)
  92                        ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
  93                break;
  94        }
  95
  96        return 0;
  97}
  98
  99/*
 100 *      State machine for state 2, Awaiting Release State.
 101 *      The handling of the timer(s) is in file ax25_ds_timer.c
 102 *      Handling of state 0 and connection release is in ax25.c.
 103 */
 104static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
 105{
 106        switch (frametype) {
 107        case AX25_SABM:
 108        case AX25_SABME:
 109                ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
 110                ax25_dama_off(ax25);
 111                break;
 112
 113        case AX25_DISC:
 114                ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
 115                ax25_dama_off(ax25);
 116                ax25_disconnect(ax25, 0);
 117                break;
 118
 119        case AX25_DM:
 120        case AX25_UA:
 121                if (pf) {
 122                        ax25_dama_off(ax25);
 123                        ax25_disconnect(ax25, 0);
 124                }
 125                break;
 126
 127        case AX25_I:
 128        case AX25_REJ:
 129        case AX25_RNR:
 130        case AX25_RR:
 131                if (pf) {
 132                        ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
 133                        ax25_dama_off(ax25);
 134                }
 135                break;
 136
 137        default:
 138                break;
 139        }
 140
 141        return 0;
 142}
 143
 144/*
 145 *      State machine for state 3, Connected State.
 146 *      The handling of the timer(s) is in file ax25_timer.c
 147 *      Handling of state 0 and connection release is in ax25.c.
 148 */
 149static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type)
 150{
 151        int queued = 0;
 152
 153        switch (frametype) {
 154        case AX25_SABM:
 155        case AX25_SABME:
 156                if (frametype == AX25_SABM) {
 157                        ax25->modulus   = AX25_MODULUS;
 158                        ax25->window    = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
 159                } else {
 160                        ax25->modulus   = AX25_EMODULUS;
 161                        ax25->window    = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
 162                }
 163                ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
 164                ax25_stop_t1timer(ax25);
 165                ax25_start_t3timer(ax25);
 166                ax25_start_idletimer(ax25);
 167                ax25->condition = 0x00;
 168                ax25->vs        = 0;
 169                ax25->va        = 0;
 170                ax25->vr        = 0;
 171                ax25_requeue_frames(ax25);
 172                ax25_dama_on(ax25);
 173                break;
 174
 175        case AX25_DISC:
 176                ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
 177                ax25_dama_off(ax25);
 178                ax25_disconnect(ax25, 0);
 179                break;
 180
 181        case AX25_DM:
 182                ax25_dama_off(ax25);
 183                ax25_disconnect(ax25, ECONNRESET);
 184                break;
 185
 186        case AX25_RR:
 187        case AX25_RNR:
 188                if (frametype == AX25_RR)
 189                        ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
 190                else
 191                        ax25->condition |= AX25_COND_PEER_RX_BUSY;
 192
 193                if (ax25_validate_nr(ax25, nr)) {
 194                        if (ax25_check_iframes_acked(ax25, nr))
 195                                ax25->n2count=0;
 196                        if (type == AX25_COMMAND && pf)
 197                                ax25_ds_enquiry_response(ax25);
 198                } else {
 199                        ax25_ds_nr_error_recovery(ax25);
 200                        ax25->state = AX25_STATE_1;
 201                }
 202                break;
 203
 204        case AX25_REJ:
 205                ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
 206
 207                if (ax25_validate_nr(ax25, nr)) {
 208                        if (ax25->va != nr)
 209                                ax25->n2count=0;
 210
 211                        ax25_frames_acked(ax25, nr);
 212                        ax25_calculate_rtt(ax25);
 213                        ax25_stop_t1timer(ax25);
 214                        ax25_start_t3timer(ax25);
 215                        ax25_requeue_frames(ax25);
 216
 217                        if (type == AX25_COMMAND && pf)
 218                                ax25_ds_enquiry_response(ax25);
 219                } else {
 220                        ax25_ds_nr_error_recovery(ax25);
 221                        ax25->state = AX25_STATE_1;
 222                }
 223                break;
 224
 225        case AX25_I:
 226                if (!ax25_validate_nr(ax25, nr)) {
 227                        ax25_ds_nr_error_recovery(ax25);
 228                        ax25->state = AX25_STATE_1;
 229                        break;
 230                }
 231                if (ax25->condition & AX25_COND_PEER_RX_BUSY) {
 232                        ax25_frames_acked(ax25, nr);
 233                        ax25->n2count = 0;
 234                } else {
 235                        if (ax25_check_iframes_acked(ax25, nr))
 236                                ax25->n2count = 0;
 237                }
 238                if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
 239                        if (pf) ax25_ds_enquiry_response(ax25);
 240                        break;
 241                }
 242                if (ns == ax25->vr) {
 243                        ax25->vr = (ax25->vr + 1) % ax25->modulus;
 244                        queued = ax25_rx_iframe(ax25, skb);
 245                        if (ax25->condition & AX25_COND_OWN_RX_BUSY)
 246                                ax25->vr = ns;  /* ax25->vr - 1 */
 247                        ax25->condition &= ~AX25_COND_REJECT;
 248                        if (pf) {
 249                                ax25_ds_enquiry_response(ax25);
 250                        } else {
 251                                if (!(ax25->condition & AX25_COND_ACK_PENDING)) {
 252                                        ax25->condition |= AX25_COND_ACK_PENDING;
 253                                        ax25_start_t2timer(ax25);
 254                                }
 255                        }
 256                } else {
 257                        if (ax25->condition & AX25_COND_REJECT) {
 258                                if (pf) ax25_ds_enquiry_response(ax25);
 259                        } else {
 260                                ax25->condition |= AX25_COND_REJECT;
 261                                ax25_ds_enquiry_response(ax25);
 262                                ax25->condition &= ~AX25_COND_ACK_PENDING;
 263                        }
 264                }
 265                break;
 266
 267        case AX25_FRMR:
 268        case AX25_ILLEGAL:
 269                ax25_ds_establish_data_link(ax25);
 270                ax25->state = AX25_STATE_1;
 271                break;
 272
 273        default:
 274                break;
 275        }
 276
 277        return queued;
 278}
 279
 280/*
 281 *      Higher level upcall for a LAPB frame
 282 */
 283int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type)
 284{
 285        int queued = 0, frametype, ns, nr, pf;
 286
 287        frametype = ax25_decode(ax25, skb, &ns, &nr, &pf);
 288
 289        switch (ax25->state) {
 290        case AX25_STATE_1:
 291                queued = ax25_ds_state1_machine(ax25, skb, frametype, pf, type);
 292                break;
 293        case AX25_STATE_2:
 294                queued = ax25_ds_state2_machine(ax25, skb, frametype, pf, type);
 295                break;
 296        case AX25_STATE_3:
 297                queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type);
 298                break;
 299        }
 300
 301        return queued;
 302}
 303
 304