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 Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 8 * Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk) 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/sched.h> 16 #include <linux/timer.h> 17 #include <linux/string.h> 18 #include <linux/sockios.h> 19 #include <linux/net.h> 20 #include <net/ax25.h> 21 #include <linux/inet.h> 22 #include <linux/netdevice.h> 23 #include <linux/skbuff.h> 24 #include <net/sock.h> 25 #include <net/tcp.h> 26 #include <net/ip.h> /* For ip_rcv */ 27 #include <asm/uaccess.h> 28 #include <asm/system.h> 29 #include <linux/fcntl.h> 30 #include <linux/mm.h> 31 #include <linux/interrupt.h> 32 #include <net/netrom.h> 33 34 static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) 35 { 36 struct sk_buff *skbo, *skbn = skb; 37 struct nr_sock *nr = nr_sk(sk); 38 39 skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); 40 41 nr_start_idletimer(sk); 42 43 if (more) { 44 nr->fraglen += skb->len; 45 skb_queue_tail(&nr->frag_queue, skb); 46 return 0; 47 } 48 49 if (!more && nr->fraglen > 0) { /* End of fragment */ 50 nr->fraglen += skb->len; 51 skb_queue_tail(&nr->frag_queue, skb); 52 53 if ((skbn = alloc_skb(nr->fraglen, GFP_ATOMIC)) == NULL) 54 return 1; 55 56 skbn->h.raw = skbn->data; 57 58 while ((skbo = skb_dequeue(&nr->frag_queue)) != NULL) { 59 memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len); 60 kfree_skb(skbo); 61 } 62 63 nr->fraglen = 0; 64 } 65 66 return sock_queue_rcv_skb(sk, skbn); 67 } 68 69 /* 70 * State machine for state 1, Awaiting Connection State. 71 * The handling of the timer(s) is in file nr_timer.c. 72 * Handling of state 0 and connection release is in netrom.c. 73 */ 74 static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, 75 int frametype) 76 { 77 switch (frametype) { 78 case NR_CONNACK: { 79 struct nr_sock *nr = nr_sk(sk); 80 81 nr_stop_t1timer(sk); 82 nr_start_idletimer(sk); 83 nr->your_index = skb->data[17]; 84 nr->your_id = skb->data[18]; 85 nr->vs = 0; 86 nr->va = 0; 87 nr->vr = 0; 88 nr->vl = 0; 89 nr->state = NR_STATE_3; 90 nr->n2count = 0; 91 nr->window = skb->data[20]; 92 sk->sk_state = TCP_ESTABLISHED; 93 if (!sock_flag(sk, SOCK_DEAD)) 94 sk->sk_state_change(sk); 95 break; 96 } 97 98 case NR_CONNACK | NR_CHOKE_FLAG: 99 nr_disconnect(sk, ECONNREFUSED); 100 break; 101 102 default: 103 break; 104 } 105 return 0; 106 } 107 108 /* 109 * State machine for state 2, Awaiting Release State. 110 * The handling of the timer(s) is in file nr_timer.c 111 * Handling of state 0 and connection release is in netrom.c. 112 */ 113 static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, 114 int frametype) 115 { 116 switch (frametype) { 117 case NR_CONNACK | NR_CHOKE_FLAG: 118 nr_disconnect(sk, ECONNRESET); 119 break; 120 121 case NR_DISCREQ: 122 nr_write_internal(sk, NR_DISCACK); 123 124 case NR_DISCACK: 125 nr_disconnect(sk, 0); 126 break; 127 128 default: 129 break; 130 } 131 return 0; 132 } 133 134 /* 135 * State machine for state 3, Connected State. 136 * The handling of the timer(s) is in file nr_timer.c 137 * Handling of state 0 and connection release is in netrom.c. 138 */ 139 static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype) 140 { 141 struct nr_sock *nrom = nr_sk(sk); 142 struct sk_buff_head temp_queue; 143 struct sk_buff *skbn; 144 unsigned short save_vr; 145 unsigned short nr, ns; 146 int queued = 0; 147 148 nr = skb->data[18]; 149 ns = skb->data[17]; 150 151 switch (frametype) { 152 case NR_CONNREQ: 153 nr_write_internal(sk, NR_CONNACK); 154 break; 155 156 case NR_DISCREQ: 157 nr_write_internal(sk, NR_DISCACK); 158 nr_disconnect(sk, 0); 159 break; 160 161 case NR_CONNACK | NR_CHOKE_FLAG: 162 case NR_DISCACK: 163 nr_disconnect(sk, ECONNRESET); 164 break; 165 166 case NR_INFOACK: 167 case NR_INFOACK | NR_CHOKE_FLAG: 168 case NR_INFOACK | NR_NAK_FLAG: 169 case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG: 170 if (frametype & NR_CHOKE_FLAG) { 171 nrom->condition |= NR_COND_PEER_RX_BUSY; 172 nr_start_t4timer(sk); 173 } else { 174 nrom->condition &= ~NR_COND_PEER_RX_BUSY; 175 nr_stop_t4timer(sk); 176 } 177 if (!nr_validate_nr(sk, nr)) { 178 break; 179 } 180 if (frametype & NR_NAK_FLAG) { 181 nr_frames_acked(sk, nr); 182 nr_send_nak_frame(sk); 183 } else { 184 if (nrom->condition & NR_COND_PEER_RX_BUSY) { 185 nr_frames_acked(sk, nr); 186 } else { 187 nr_check_iframes_acked(sk, nr); 188 } 189 } 190 break; 191 192 case NR_INFO: 193 case NR_INFO | NR_NAK_FLAG: 194 case NR_INFO | NR_CHOKE_FLAG: 195 case NR_INFO | NR_MORE_FLAG: 196 case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG: 197 case NR_INFO | NR_CHOKE_FLAG | NR_MORE_FLAG: 198 case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG: 199 case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG: 200 if (frametype & NR_CHOKE_FLAG) { 201 nrom->condition |= NR_COND_PEER_RX_BUSY; 202 nr_start_t4timer(sk); 203 } else { 204 nrom->condition &= ~NR_COND_PEER_RX_BUSY; 205 nr_stop_t4timer(sk); 206 } 207 if (nr_validate_nr(sk, nr)) { 208 if (frametype & NR_NAK_FLAG) { 209 nr_frames_acked(sk, nr); 210 nr_send_nak_frame(sk); 211 } else { 212 if (nrom->condition & NR_COND_PEER_RX_BUSY) { 213 nr_frames_acked(sk, nr); 214 } else { 215 nr_check_iframes_acked(sk, nr); 216 } 217 } 218 } 219 queued = 1; 220 skb_queue_head(&nrom->reseq_queue, skb); 221 if (nrom->condition & NR_COND_OWN_RX_BUSY) 222 break; 223 skb_queue_head_init(&temp_queue); 224 do { 225 save_vr = nrom->vr; 226 while ((skbn = skb_dequeue(&nrom->reseq_queue)) != NULL) { 227 ns = skbn->data[17]; 228 if (ns == nrom->vr) { 229 if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) { 230 nrom->vr = (nrom->vr + 1) % NR_MODULUS; 231 } else { 232 nrom->condition |= NR_COND_OWN_RX_BUSY; 233 skb_queue_tail(&temp_queue, skbn); 234 } 235 } else if (nr_in_rx_window(sk, ns)) { 236 skb_queue_tail(&temp_queue, skbn); 237 } else { 238 kfree_skb(skbn); 239 } 240 } 241 while ((skbn = skb_dequeue(&temp_queue)) != NULL) { 242 skb_queue_tail(&nrom->reseq_queue, skbn); 243 } 244 } while (save_vr != nrom->vr); 245 /* 246 * Window is full, ack it immediately. 247 */ 248 if (((nrom->vl + nrom->window) % NR_MODULUS) == nrom->vr) { 249 nr_enquiry_response(sk); 250 } else { 251 if (!(nrom->condition & NR_COND_ACK_PENDING)) { 252 nrom->condition |= NR_COND_ACK_PENDING; 253 nr_start_t2timer(sk); 254 } 255 } 256 break; 257 258 default: 259 break; 260 } 261 return queued; 262 } 263 264 /* Higher level upcall for a LAPB frame - called with sk locked */ 265 int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb) 266 { 267 struct nr_sock *nr = nr_sk(sk); 268 int queued = 0, frametype; 269 270 if (nr->state == NR_STATE_0) 271 return 0; 272 273 frametype = skb->data[19]; 274 275 switch (nr->state) { 276 case NR_STATE_1: 277 queued = nr_state1_machine(sk, skb, frametype); 278 break; 279 case NR_STATE_2: 280 queued = nr_state2_machine(sk, skb, frametype); 281 break; 282 case NR_STATE_3: 283 queued = nr_state3_machine(sk, skb, frametype); 284 break; 285 } 286 287 nr_kick(sk); 288 289 return queued; 290 } 291