1 /*
2  *	NET/ROM release 007
3  *
4  *	This code REQUIRES 2.1.15 or higher/ NET3.038
5  *
6  *	This module:
7  *		This module is free software; you can redistribute it and/or
8  *		modify it under the terms of the GNU General Public License
9  *		as published by the Free Software Foundation; either version
10  *		2 of the License, or (at your option) any later version.
11  *
12  *	Most of this code is based on the SDL diagrams published in the 7th
13  *	ARRL Computer Networking Conference papers. The diagrams have mistakes
14  *	in them, but are mostly correct. Before you modify the code could you
15  *	read the SDL diagrams as the code is not obvious and probably very
16  *	easy to break;
17  *
18  *	History
19  *	NET/ROM 001	Jonathan(G4KLX)	Cloned from ax25_in.c
20  *	NET/ROM 003	Jonathan(G4KLX)	Added NET/ROM fragment reception.
21  *			Darryl(G7LED)	Added missing INFO with NAK case, optimized
22  *					INFOACK handling, removed reconnect on error.
23  *	NET/ROM 006	Jonathan(G4KLX)	Hdrincl removal changes.
24  *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
25  */
26 
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/uaccess.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 
nr_queue_rx_frame(struct sock * sk,struct sk_buff * skb,int more)50 static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
51 {
52 	struct sk_buff *skbo, *skbn = skb;
53 
54 	skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
55 
56 	nr_start_idletimer(sk);
57 
58 	if (more) {
59 		sk->protinfo.nr->fraglen += skb->len;
60 		skb_queue_tail(&sk->protinfo.nr->frag_queue, skb);
61 		return 0;
62 	}
63 
64 	if (!more && sk->protinfo.nr->fraglen > 0) {	/* End of fragment */
65 		sk->protinfo.nr->fraglen += skb->len;
66 		skb_queue_tail(&sk->protinfo.nr->frag_queue, skb);
67 
68 		if ((skbn = alloc_skb(sk->protinfo.nr->fraglen, GFP_ATOMIC)) == NULL)
69 			return 1;
70 
71 		skbn->h.raw = skbn->data;
72 
73 		while ((skbo = skb_dequeue(&sk->protinfo.nr->frag_queue)) != NULL) {
74 			memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
75 			kfree_skb(skbo);
76 		}
77 
78 		sk->protinfo.nr->fraglen = 0;
79 	}
80 
81 	return sock_queue_rcv_skb(sk, skbn);
82 }
83 
84 /*
85  * State machine for state 1, Awaiting Connection State.
86  * The handling of the timer(s) is in file nr_timer.c.
87  * Handling of state 0 and connection release is in netrom.c.
88  */
nr_state1_machine(struct sock * sk,struct sk_buff * skb,int frametype)89 static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
90 {
91 	switch (frametype) {
92 
93 		case NR_CONNACK:
94 			nr_stop_t1timer(sk);
95 			nr_start_idletimer(sk);
96 			sk->protinfo.nr->your_index = skb->data[17];
97 			sk->protinfo.nr->your_id    = skb->data[18];
98 			sk->protinfo.nr->vs         = 0;
99 			sk->protinfo.nr->va         = 0;
100 			sk->protinfo.nr->vr         = 0;
101 			sk->protinfo.nr->vl	    = 0;
102 			sk->protinfo.nr->state      = NR_STATE_3;
103 			sk->protinfo.nr->n2count    = 0;
104 			sk->protinfo.nr->window     = skb->data[20];
105 			sk->state                   = TCP_ESTABLISHED;
106 			if (!sk->dead)
107 				sk->state_change(sk);
108 			break;
109 
110 		case NR_CONNACK | NR_CHOKE_FLAG:
111 			nr_disconnect(sk, ECONNREFUSED);
112 			break;
113 
114 		default:
115 			break;
116 	}
117 
118 	return 0;
119 }
120 
121 /*
122  * State machine for state 2, Awaiting Release State.
123  * The handling of the timer(s) is in file nr_timer.c
124  * Handling of state 0 and connection release is in netrom.c.
125  */
nr_state2_machine(struct sock * sk,struct sk_buff * skb,int frametype)126 static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
127 {
128 	switch (frametype) {
129 
130 		case NR_CONNACK | NR_CHOKE_FLAG:
131 			nr_disconnect(sk, ECONNRESET);
132 			break;
133 
134 		case NR_DISCREQ:
135 			nr_write_internal(sk, NR_DISCACK);
136 
137 		case NR_DISCACK:
138 			nr_disconnect(sk, 0);
139 			break;
140 
141 		default:
142 			break;
143 	}
144 
145 	return 0;
146 }
147 
148 /*
149  * State machine for state 3, Connected State.
150  * The handling of the timer(s) is in file nr_timer.c
151  * Handling of state 0 and connection release is in netrom.c.
152  */
nr_state3_machine(struct sock * sk,struct sk_buff * skb,int frametype)153 static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype)
154 {
155 	struct sk_buff_head temp_queue;
156 	struct sk_buff *skbn;
157 	unsigned short save_vr;
158 	unsigned short nr, ns;
159 	int queued = 0;
160 
161 	nr = skb->data[18];
162 	ns = skb->data[17];
163 
164 	switch (frametype) {
165 
166 		case NR_CONNREQ:
167 			nr_write_internal(sk, NR_CONNACK);
168 			break;
169 
170 		case NR_DISCREQ:
171 			nr_write_internal(sk, NR_DISCACK);
172 			nr_disconnect(sk, 0);
173 			break;
174 
175 		case NR_CONNACK | NR_CHOKE_FLAG:
176 		case NR_DISCACK:
177 			nr_disconnect(sk, ECONNRESET);
178 			break;
179 
180 		case NR_INFOACK:
181 		case NR_INFOACK | NR_CHOKE_FLAG:
182 		case NR_INFOACK | NR_NAK_FLAG:
183 		case NR_INFOACK | NR_NAK_FLAG | NR_CHOKE_FLAG:
184 			if (frametype & NR_CHOKE_FLAG) {
185 				sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY;
186 				nr_start_t4timer(sk);
187 			} else {
188 				sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
189 				nr_stop_t4timer(sk);
190 			}
191 			if (!nr_validate_nr(sk, nr)) {
192 				break;
193 			}
194 			if (frametype & NR_NAK_FLAG) {
195 				nr_frames_acked(sk, nr);
196 				nr_send_nak_frame(sk);
197 			} else {
198 				if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) {
199 					nr_frames_acked(sk, nr);
200 				} else {
201 					nr_check_iframes_acked(sk, nr);
202 				}
203 			}
204 			break;
205 
206 		case NR_INFO:
207 		case NR_INFO | NR_NAK_FLAG:
208 		case NR_INFO | NR_CHOKE_FLAG:
209 		case NR_INFO | NR_MORE_FLAG:
210 		case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG:
211 		case NR_INFO | NR_CHOKE_FLAG | NR_MORE_FLAG:
212 		case NR_INFO | NR_NAK_FLAG | NR_MORE_FLAG:
213 		case NR_INFO | NR_NAK_FLAG | NR_CHOKE_FLAG | NR_MORE_FLAG:
214 			if (frametype & NR_CHOKE_FLAG) {
215 				sk->protinfo.nr->condition |= NR_COND_PEER_RX_BUSY;
216 				nr_start_t4timer(sk);
217 			} else {
218 				sk->protinfo.nr->condition &= ~NR_COND_PEER_RX_BUSY;
219 				nr_stop_t4timer(sk);
220 			}
221 			if (nr_validate_nr(sk, nr)) {
222 				if (frametype & NR_NAK_FLAG) {
223 					nr_frames_acked(sk, nr);
224 					nr_send_nak_frame(sk);
225 				} else {
226 					if (sk->protinfo.nr->condition & NR_COND_PEER_RX_BUSY) {
227 						nr_frames_acked(sk, nr);
228 					} else {
229 						nr_check_iframes_acked(sk, nr);
230 					}
231 				}
232 			}
233 			queued = 1;
234 			skb_queue_head(&sk->protinfo.nr->reseq_queue, skb);
235 			if (sk->protinfo.nr->condition & NR_COND_OWN_RX_BUSY)
236 				break;
237 			skb_queue_head_init(&temp_queue);
238 			do {
239 				save_vr = sk->protinfo.nr->vr;
240 				while ((skbn = skb_dequeue(&sk->protinfo.nr->reseq_queue)) != NULL) {
241 					ns = skbn->data[17];
242 					if (ns == sk->protinfo.nr->vr) {
243 						if (nr_queue_rx_frame(sk, skbn, frametype & NR_MORE_FLAG) == 0) {
244 							sk->protinfo.nr->vr = (sk->protinfo.nr->vr + 1) % NR_MODULUS;
245 						} else {
246 							sk->protinfo.nr->condition |= NR_COND_OWN_RX_BUSY;
247 							skb_queue_tail(&temp_queue, skbn);
248 						}
249 					} else if (nr_in_rx_window(sk, ns)) {
250 						skb_queue_tail(&temp_queue, skbn);
251 					} else {
252 						kfree_skb(skbn);
253 					}
254 				}
255 				while ((skbn = skb_dequeue(&temp_queue)) != NULL) {
256 					skb_queue_tail(&sk->protinfo.nr->reseq_queue, skbn);
257 				}
258 			} while (save_vr != sk->protinfo.nr->vr);
259 			/*
260 			 * Window is full, ack it immediately.
261 			 */
262 			if (((sk->protinfo.nr->vl + sk->protinfo.nr->window) % NR_MODULUS) == sk->protinfo.nr->vr) {
263 				nr_enquiry_response(sk);
264 			} else {
265 				if (!(sk->protinfo.nr->condition & NR_COND_ACK_PENDING)) {
266 					sk->protinfo.nr->condition |= NR_COND_ACK_PENDING;
267 					nr_start_t2timer(sk);
268 				}
269 			}
270 			break;
271 
272 		default:
273 			break;
274 	}
275 
276 	return queued;
277 }
278 
279 /* Higher level upcall for a LAPB frame */
nr_process_rx_frame(struct sock * sk,struct sk_buff * skb)280 int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
281 {
282 	int queued = 0, frametype;
283 
284 	if (sk->protinfo.nr->state == NR_STATE_0)
285 		return 0;
286 
287 	frametype = skb->data[19];
288 
289 	switch (sk->protinfo.nr->state) {
290 		case NR_STATE_1:
291 			queued = nr_state1_machine(sk, skb, frametype);
292 			break;
293 		case NR_STATE_2:
294 			queued = nr_state2_machine(sk, skb, frametype);
295 			break;
296 		case NR_STATE_3:
297 			queued = nr_state3_machine(sk, skb, frametype);
298 			break;
299 	}
300 
301 	nr_kick(sk);
302 
303 	return queued;
304 }
305