root/net/netrom/nr_in.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nr_state1_machine
  2. nr_state2_machine
  3. nr_state3_machine
  4. nr_process_rx_frame

   1 /*
   2  *      NET/ROM release 002
   3  *
   4  *      This is ALPHA test software. This code may break your machine, randomly fail to work with new 
   5  *      releases, misbehave and/or generally screw up. It might even work. 
   6  *
   7  *      This code REQUIRES 1.2.1 or higher/ NET3.029
   8  *
   9  *      This module:
  10  *              This module is free software; you can redistribute it and/or
  11  *              modify it under the terms of the GNU General Public License
  12  *              as published by the Free Software Foundation; either version
  13  *              2 of the License, or (at your option) any later version.
  14  *
  15  *      Most of this code is based on the SDL diagrams published in the 7th
  16  *      ARRL Computer Networking Conference papers. The diagrams have mistakes
  17  *      in them, but are mostly correct. Before you modify the code could you
  18  *      read the SDL diagrams as the code is not obvious and probably very
  19  *      easy to break;
  20  *
  21  *      History
  22  *      NET/ROM 001     Jonathan(G4KLX) Cloned from ax25_in.c
  23  */
  24 
  25 #include <linux/config.h>
  26 #ifdef CONFIG_NETROM
  27 #include <linux/errno.h>
  28 #include <linux/types.h>
  29 #include <linux/socket.h>
  30 #include <linux/in.h>
  31 #include <linux/kernel.h>
  32 #include <linux/sched.h>
  33 #include <linux/timer.h>
  34 #include <linux/string.h>
  35 #include <linux/sockios.h>
  36 #include <linux/net.h>
  37 #include <net/ax25.h>
  38 #include <linux/inet.h>
  39 #include <linux/netdevice.h>
  40 #include <linux/skbuff.h>
  41 #include <net/sock.h>
  42 #include <net/ip.h>                     /* For ip_rcv */
  43 #include <asm/segment.h>
  44 #include <asm/system.h>
  45 #include <linux/fcntl.h>
  46 #include <linux/mm.h>
  47 #include <linux/interrupt.h>
  48 #include <net/netrom.h>
  49 
  50 /*
  51  * State machine for state 1, Awaiting Connection State.
  52  * The handling of the timer(s) is in file nr_timer.c.
  53  * Handling of state 0 and connection release is in netrom.c.
  54  */
  55 static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57         switch (frametype) {
  58 
  59                 case NR_CONNACK:
  60                         nr_calculate_rtt(sk);
  61                         sk->window         = skb->data[37];
  62                         sk->nr->your_index = skb->data[34];
  63                         sk->nr->your_id    = skb->data[35];
  64                         sk->nr->t1timer    = 0;
  65                         sk->nr->t2timer    = 0;
  66                         sk->nr->t4timer    = 0;
  67                         sk->nr->vs         = 0;
  68                         sk->nr->va         = 0;
  69                         sk->nr->vr         = 0;
  70                         sk->nr->vl         = 0;
  71                         sk->nr->state      = NR_STATE_3;
  72                         sk->state          = TCP_ESTABLISHED;
  73                         sk->nr->n2count    = 0;
  74                         /* For WAIT_SABM connections we will produce an accept ready socket here */
  75                         if (!sk->dead)
  76                                 sk->state_change(sk);
  77                         break;
  78 
  79                 case NR_CONNACK + NR_CHOKE_FLAG:
  80                         nr_clear_tx_queue(sk);
  81                         sk->nr->state = NR_STATE_0;
  82                         sk->state     = TCP_CLOSE;
  83                         sk->err       = ECONNREFUSED;
  84                         if (!sk->dead)
  85                                 sk->state_change(sk);
  86                         sk->dead      = 1;
  87                         break;
  88 
  89                 default:
  90                         break;
  91         }
  92 
  93         return 0;
  94 }
  95 
  96 /*
  97  * State machine for state 2, Awaiting Release State.
  98  * The handling of the timer(s) is in file nr_timer.c
  99  * Handling of state 0 and connection release is in netrom.c.
 100  */
 101 static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         switch (frametype) {
 104 
 105                 case NR_DISCREQ:
 106                         nr_write_internal(sk, NR_DISCACK);
 107                         break;
 108 
 109                 case NR_DISCACK:
 110                         sk->nr->state = NR_STATE_0;
 111                         sk->state     = TCP_CLOSE;
 112                         sk->err       = 0;
 113                         if (!sk->dead)
 114                                 sk->state_change(sk);
 115                         sk->dead      = 1;
 116                         break;
 117 
 118                 default:
 119                         break;
 120         }
 121 
 122         return 0;
 123 }
 124 
 125 /*
 126  * State machine for state 3, Connected State.
 127  * The handling of the timer(s) is in file nr_timer.c
 128  * Handling of state 0 and connection release is in netrom.c.
 129  */
 130 static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132         struct sk_buff_head temp_queue;
 133         struct sk_buff *skbn;
 134         unsigned short save_vr;
 135         unsigned short nr, ns;
 136         int queued = 0;
 137 
 138         nr = skb->data[35];
 139         ns = skb->data[34];
 140 
 141         switch (frametype) {
 142 
 143                 case NR_CONNREQ:
 144                         nr_write_internal(sk, NR_CONNACK);
 145                         sk->nr->condition = 0x00;
 146                         sk->nr->t1timer   = 0;
 147                         sk->nr->t2timer   = 0;
 148                         sk->nr->t4timer   = 0;
 149                         sk->nr->vs        = 0;
 150                         sk->nr->va        = 0;
 151                         sk->nr->vr        = 0;
 152                         sk->nr->vl        = 0;
 153                         break;
 154 
 155                 case NR_DISCREQ:
 156                         nr_clear_tx_queue(sk);
 157                         nr_write_internal(sk, NR_DISCACK);
 158                         sk->nr->state = NR_STATE_0;
 159                         sk->state     = TCP_CLOSE;
 160                         sk->err       = 0;
 161                         if (!sk->dead)
 162                                 sk->state_change(sk);
 163                         sk->dead      = 1;
 164                         break;
 165 
 166                 case NR_DISCACK:
 167                         nr_clear_tx_queue(sk);
 168                         sk->nr->state = NR_STATE_0;
 169                         sk->state     = TCP_CLOSE;
 170                         sk->err       = ECONNRESET;
 171                         if (!sk->dead)
 172                                 sk->state_change(sk);
 173                         sk->dead      = 1;
 174                         break;
 175 
 176                 case NR_INFOACK:
 177                 case NR_INFOACK + NR_CHOKE_FLAG:
 178                         if (frametype & NR_CHOKE_FLAG) {
 179                                 sk->nr->condition |= PEER_RX_BUSY_CONDITION;
 180                                 sk->nr->t4timer = nr_default.busy_delay;
 181                         } else {
 182                                 sk->nr->condition &= ~PEER_RX_BUSY_CONDITION;
 183                                 sk->nr->t4timer = 0;
 184                         }
 185                         if (!nr_validate_nr(sk, nr)) {
 186                                 nr_nr_error_recovery(sk);
 187                                 sk->nr->state = NR_STATE_1;
 188                                 break;
 189                         }
 190                         if (sk->nr->condition & PEER_RX_BUSY_CONDITION) {
 191                                 nr_frames_acked(sk, nr);
 192                         } else {
 193                                 nr_check_iframes_acked(sk, nr);
 194                         }
 195                         break;
 196                         
 197                 case NR_INFOACK + NR_NAK_FLAG:
 198                 case NR_INFOACK + NR_NAK_FLAG + NR_CHOKE_FLAG:
 199                         if (frametype & NR_CHOKE_FLAG) {
 200                                 sk->nr->condition |= PEER_RX_BUSY_CONDITION;
 201                                 sk->nr->t4timer = nr_default.busy_delay;
 202                         } else {
 203                                 sk->nr->condition &= ~PEER_RX_BUSY_CONDITION;
 204                                 sk->nr->t4timer = 0;
 205                         }
 206                         if (nr_validate_nr(sk, nr)) {
 207                                 nr_frames_acked(sk, nr);
 208                                 nr_send_nak_frame(sk);
 209                         } else {
 210                                 nr_nr_error_recovery(sk);
 211                                 sk->nr->state = NR_STATE_1;
 212                         }
 213                         break;
 214                         
 215                 case NR_INFO:
 216                 case NR_INFO + NR_CHOKE_FLAG:
 217                 case NR_INFO + NR_MORE_FLAG:
 218                 case NR_INFO + NR_CHOKE_FLAG + NR_MORE_FLAG:
 219                         if (frametype & NR_CHOKE_FLAG) {
 220                                 sk->nr->condition |= PEER_RX_BUSY_CONDITION;
 221                                 sk->nr->t4timer = nr_default.busy_delay;
 222                         } else {
 223                                 sk->nr->condition &= ~PEER_RX_BUSY_CONDITION;
 224                                 sk->nr->t4timer = 0;
 225                         }
 226                         if (!nr_validate_nr(sk, nr)) {
 227                                 nr_nr_error_recovery(sk);
 228                                 sk->nr->state = NR_STATE_1;
 229                                 break;
 230                         }
 231                         if (sk->nr->condition & PEER_RX_BUSY_CONDITION) {
 232                                 nr_frames_acked(sk, nr);
 233                         } else {
 234                                 nr_check_iframes_acked(sk, nr);
 235                         }
 236                         queued = 1;
 237                         skb_queue_head(&sk->nr->reseq_queue, skb);
 238                         if (sk->nr->condition & OWN_RX_BUSY_CONDITION)
 239                                 break;
 240                         skb_queue_head_init(&temp_queue);
 241                         do {
 242                                 save_vr = sk->nr->vr;
 243                                 while ((skbn = skb_dequeue(&sk->nr->reseq_queue)) != NULL) {
 244                                         ns = skbn->data[34];
 245                                         if (ns == sk->nr->vr) {
 246                                                 if (sock_queue_rcv_skb(sk, skbn) == 0) {
 247                                                         sk->nr->vr = (sk->nr->vr + 1) % NR_MODULUS;
 248                                                 } else {
 249                                                         sk->nr->condition |= OWN_RX_BUSY_CONDITION;
 250                                                         skb_queue_tail(&temp_queue, skbn);
 251                                                 }
 252                                         } else if (nr_in_rx_window(sk, ns)) {
 253                                                 skb_queue_tail(&temp_queue, skbn);
 254                                         } else {
 255                                                 skbn->free = 1;
 256                                                 kfree_skb(skbn, FREE_READ);
 257                                         }
 258                                 }
 259                                 while ((skbn = skb_dequeue(&temp_queue)) != NULL) {
 260                                         skb_queue_tail(&sk->nr->reseq_queue, skbn);
 261                                 }
 262                         } while (save_vr != sk->nr->vr);
 263                         /*
 264                          * Window is full, ack it immediately.
 265                          */
 266                         if (((sk->nr->vl + sk->window) % NR_MODULUS) == sk->nr->vr) {
 267                                 nr_enquiry_response(sk);
 268                         } else {
 269                                 if (!(sk->nr->condition & ACK_PENDING_CONDITION)) {
 270                                         sk->nr->t2timer = sk->nr->t2;
 271                                         sk->nr->condition |= ACK_PENDING_CONDITION;
 272                                 }
 273                         }
 274                         break;
 275 
 276                 default:
 277                         break;
 278         }
 279 
 280         return queued;
 281 }
 282 
 283 /* Higher level upcall for a LAPB frame */
 284 int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286         int queued = 0, frametype;
 287 
 288         del_timer(&sk->timer);
 289 
 290         frametype = skb->data[36];
 291 
 292         switch (sk->nr->state)
 293         {
 294                 case NR_STATE_1:
 295                         queued = nr_state1_machine(sk, skb, frametype);
 296                         break;
 297                 case NR_STATE_2:
 298                         queued = nr_state2_machine(sk, skb, frametype);
 299                         break;
 300                 case NR_STATE_3:
 301                         queued = nr_state3_machine(sk, skb, frametype);
 302                         break;
 303                 default:
 304                         printk("nr_process_rx_frame: frame received - state: %d\n", sk->nr->state);
 305                         break;
 306         }
 307 
 308         nr_set_timer(sk);
 309 
 310         return(queued);
 311 }
 312 
 313 #endif

/* [previous][next][first][last][top][bottom][index][help] */