root/net/netrom/nr_in.c

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

DEFINITIONS

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

   1 /*
   2  *      NET/ROM release 003
   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  *      NET/ROM 003     Jonathan(G4KLX) Added NET/ROM fragment reception.
  24  *                      Darryl(G7LED)   Added missing INFO with NAK case, optimized
  25  *                                      INFOACK handling, removed reconnect on error.
  26  */
  27 
  28 #include <linux/config.h>
  29 #ifdef CONFIG_NETROM
  30 #include <linux/errno.h>
  31 #include <linux/types.h>
  32 #include <linux/socket.h>
  33 #include <linux/in.h>
  34 #include <linux/kernel.h>
  35 #include <linux/sched.h>
  36 #include <linux/timer.h>
  37 #include <linux/string.h>
  38 #include <linux/sockios.h>
  39 #include <linux/net.h>
  40 #include <net/ax25.h>
  41 #include <linux/inet.h>
  42 #include <linux/netdevice.h>
  43 #include <linux/skbuff.h>
  44 #include <net/sock.h>
  45 #include <net/ip.h>                     /* For ip_rcv */
  46 #include <asm/segment.h>
  47 #include <asm/system.h>
  48 #include <linux/fcntl.h>
  49 #include <linux/mm.h>
  50 #include <linux/interrupt.h>
  51 #include <net/netrom.h>
  52 
  53 static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55         struct sk_buff *skbo, *skbn = skb;
  56 
  57         if (more) {
  58                 sk->nr->fraglen += skb->len;
  59                 skb_queue_tail(&sk->nr->frag_queue, skb);
  60                 return 0;
  61         }
  62         
  63         if (!more && sk->nr->fraglen > 0) {     /* End of fragment */
  64                 sk->nr->fraglen += skb->len;
  65                 skb_queue_tail(&sk->nr->frag_queue, skb);
  66 
  67                 if ((skbn = alloc_skb(sk->nr->fraglen, GFP_ATOMIC)) == NULL)
  68                         return 1;
  69 
  70                 skbn->free = 1;
  71                 skbn->arp  = 1;
  72                 skbn->sk   = sk;
  73                 sk->rmem_alloc += skbn->truesize;
  74                 skbn->h.raw = skbn->data;
  75 
  76                 skbo = skb_dequeue(&sk->nr->frag_queue);
  77                 memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
  78                 kfree_skb(skbo, FREE_READ);
  79 
  80                 while ((skbo = skb_dequeue(&sk->nr->frag_queue)) != NULL) {
  81                         skb_pull(skbo, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
  82                         memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
  83                         kfree_skb(skbo, FREE_READ);
  84                 }
  85 
  86                 sk->nr->fraglen = 0;            
  87         }
  88 
  89         return sock_queue_rcv_skb(sk, skbn);
  90 }
  91 
  92 /*
  93  * State machine for state 1, Awaiting Connection State.
  94  * The handling of the timer(s) is in file nr_timer.c.
  95  * Handling of state 0 and connection release is in netrom.c.
  96  */
  97 static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         switch (frametype) {
 100 
 101                 case NR_CONNACK:
 102                         nr_calculate_rtt(sk);
 103                         sk->window         = skb->data[20];
 104                         sk->nr->your_index = skb->data[17];
 105                         sk->nr->your_id    = skb->data[18];
 106                         sk->nr->t1timer    = 0;
 107                         sk->nr->t2timer    = 0;
 108                         sk->nr->t4timer    = 0;
 109                         sk->nr->vs         = 0;
 110                         sk->nr->va         = 0;
 111                         sk->nr->vr         = 0;
 112                         sk->nr->vl         = 0;
 113                         sk->nr->state      = NR_STATE_3;
 114                         sk->state          = TCP_ESTABLISHED;
 115                         sk->nr->n2count    = 0;
 116                         /* For WAIT_SABM connections we will produce an accept ready socket here */
 117                         if (!sk->dead)
 118                                 sk->state_change(sk);
 119                         break;
 120 
 121                 case NR_CONNACK | NR_CHOKE_FLAG:
 122                         nr_clear_queues(sk);
 123                         sk->nr->state = NR_STATE_0;
 124                         sk->state     = TCP_CLOSE;
 125                         sk->err       = ECONNREFUSED;
 126                         if (!sk->dead)
 127                                 sk->state_change(sk);
 128                         sk->dead      = 1;
 129                         break;
 130 
 131                 default:
 132                         break;
 133         }
 134 
 135         return 0;
 136 }
 137 
 138 /*
 139  * State machine for state 2, Awaiting Release State.
 140  * The handling of the timer(s) is in file nr_timer.c
 141  * Handling of state 0 and connection release is in netrom.c.
 142  */
 143 static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145         switch (frametype) {
 146 
 147                 case NR_DISCREQ:
 148                         nr_write_internal(sk, NR_DISCACK);
 149 
 150                 case NR_DISCACK:
 151                         sk->nr->state = NR_STATE_0;
 152                         sk->state     = TCP_CLOSE;
 153                         sk->err       = 0;
 154                         if (!sk->dead)
 155                                 sk->state_change(sk);
 156                         sk->dead      = 1;
 157                         break;
 158 
 159                 default:
 160                         break;
 161         }
 162 
 163         return 0;
 164 }
 165 
 166 /*
 167  * State machine for state 3, Connected State.
 168  * The handling of the timer(s) is in file nr_timer.c
 169  * Handling of state 0 and connection release is in netrom.c.
 170  */
 171 static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         struct sk_buff_head temp_queue;
 174         struct sk_buff *skbn;
 175         unsigned short save_vr;
 176         unsigned short nr, ns;
 177         int queued = 0;
 178 
 179         nr = skb->data[18];
 180         ns = skb->data[17];
 181 
 182         switch (frametype) {
 183 
 184                 case NR_CONNREQ:
 185                         nr_write_internal(sk, NR_CONNACK);
 186                         break;
 187 
 188                 case NR_DISCREQ:
 189                         nr_clear_queues(sk);
 190                         nr_write_internal(sk, NR_DISCACK);
 191                         sk->nr->state = NR_STATE_0;
 192                         sk->state     = TCP_CLOSE;
 193                         sk->err       = 0;
 194                         if (!sk->dead)
 195                                 sk->state_change(sk);
 196                         sk->dead      = 1;
 197                         break;
 198 
 199                 case NR_DISCACK:
 200                         nr_clear_queues(sk);
 201                         sk->nr->state = NR_STATE_0;
 202                         sk->state     = TCP_CLOSE;
 203                         sk->err       = ECONNRESET;
 204                         if (!sk->dead)
 205                                 sk->state_change(sk);
 206                         sk->dead      = 1;
 207                         break;
 208 
 209                 case NR_INFOACK:
 210                 case NR_INFOACK | NR_CHOKE_FLAG:
 211                 case NR_INFOACK | NR_NAK_FLAG:
 212                 case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG:
 213                         if (frametype & NR_CHOKE_FLAG) {
 214                                 sk->nr->condition |= PEER_RX_BUSY_CONDITION;
 215                                 sk->nr->t4timer = nr_default.busy_delay;
 216                         } else {
 217                                 sk->nr->condition &= ~PEER_RX_BUSY_CONDITION;
 218                                 sk->nr->t4timer = 0;
 219                         }
 220                         if (!nr_validate_nr(sk, nr)) {
 221                                 break;
 222                         }
 223                         if (frametype & NR_NAK_FLAG) {
 224                                 nr_frames_acked(sk, nr);
 225                                 nr_send_nak_frame(sk);
 226                         } else {
 227                                 if (sk->nr->condition & PEER_RX_BUSY_CONDITION) {
 228                                         nr_frames_acked(sk, nr);
 229                                 } else {
 230                                         nr_check_iframes_acked(sk, nr);
 231                                 }
 232                         }
 233                         break;
 234                         
 235                 case NR_INFO:
 236                 case NR_INFO | NR_NAK_FLAG:
 237                 case NR_INFO | NR_CHOKE_FLAG:
 238                 case NR_INFO | NR_MORE_FLAG:
 239                 case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG:
 240                 case NR_INFO | NR_CHOKE_FLAG | NR_MORE_FLAG:
 241                 case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG:
 242                 case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG:
 243                         if (frametype & NR_CHOKE_FLAG) {
 244                                 sk->nr->condition |= PEER_RX_BUSY_CONDITION;
 245                                 sk->nr->t4timer = nr_default.busy_delay;
 246                         } else {
 247                                 sk->nr->condition &= ~PEER_RX_BUSY_CONDITION;
 248                                 sk->nr->t4timer = 0;
 249                         }
 250                         if (nr_validate_nr(sk, nr)) {
 251                                 if (frametype & NR_NAK_FLAG) {
 252                                         nr_frames_acked(sk, nr);
 253                                         nr_send_nak_frame(sk);
 254                                 } else {
 255                                         if (sk->nr->condition & PEER_RX_BUSY_CONDITION) {
 256                                                 nr_frames_acked(sk, nr);
 257                                         } else {
 258                                                 nr_check_iframes_acked(sk, nr);
 259                                         }
 260                                 }
 261                         }
 262                         queued = 1;
 263                         skb_queue_head(&sk->nr->reseq_queue, skb);
 264                         if (sk->nr->condition & OWN_RX_BUSY_CONDITION)
 265                                 break;
 266                         skb_queue_head_init(&temp_queue);
 267                         do {
 268                                 save_vr = sk->nr->vr;
 269                                 while ((skbn = skb_dequeue(&sk->nr->reseq_queue)) != NULL) {
 270                                         ns = skbn->data[17];
 271                                         if (ns == sk->nr->vr) {
 272                                                 if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) {
 273                                                         sk->nr->vr = (sk->nr->vr + 1) % NR_MODULUS;
 274                                                 } else {
 275                                                         sk->nr->condition |= OWN_RX_BUSY_CONDITION;
 276                                                         skb_queue_tail(&temp_queue, skbn);
 277                                                 }
 278                                         } else if (nr_in_rx_window(sk, ns)) {
 279                                                 skb_queue_tail(&temp_queue, skbn);
 280                                         } else {
 281                                                 skbn->free = 1;
 282                                                 kfree_skb(skbn, FREE_READ);
 283                                         }
 284                                 }
 285                                 while ((skbn = skb_dequeue(&temp_queue)) != NULL) {
 286                                         skb_queue_tail(&sk->nr->reseq_queue, skbn);
 287                                 }
 288                         } while (save_vr != sk->nr->vr);
 289                         /*
 290                          * Window is full, ack it immediately.
 291                          */
 292                         if (((sk->nr->vl + sk->window) % NR_MODULUS) == sk->nr->vr) {
 293                                 nr_enquiry_response(sk);
 294                         } else {
 295                                 if (!(sk->nr->condition & ACK_PENDING_CONDITION)) {
 296                                         sk->nr->t2timer = sk->nr->t2;
 297                                         sk->nr->condition |= ACK_PENDING_CONDITION;
 298                                 }
 299                         }
 300                         break;
 301 
 302                 default:
 303                         break;
 304         }
 305 
 306         return queued;
 307 }
 308 
 309 /* Higher level upcall for a LAPB frame */
 310 int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312         int queued = 0, frametype;
 313         
 314         if (sk->nr->state == NR_STATE_0 && sk->dead)
 315                 return queued;
 316 
 317         if (sk->nr->state != NR_STATE_1 && sk->nr->state != NR_STATE_2 &&
 318             sk->nr->state != NR_STATE_3) {
 319                 printk("nr_process_rx_frame: frame received - state: %d\n", sk->nr->state);
 320                 return queued;
 321         }
 322 
 323         del_timer(&sk->timer);
 324 
 325         frametype = skb->data[19];
 326 
 327         switch (sk->nr->state)
 328         {
 329                 case NR_STATE_1:
 330                         queued = nr_state1_machine(sk, skb, frametype);
 331                         break;
 332                 case NR_STATE_2:
 333                         queued = nr_state2_machine(sk, skb, frametype);
 334                         break;
 335                 case NR_STATE_3:
 336                         queued = nr_state3_machine(sk, skb, frametype);
 337                         break;
 338         }
 339 
 340         nr_set_timer(sk);
 341 
 342         return queued;
 343 }
 344 
 345 #endif

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