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