1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * |
4 | * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk) |
5 | * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) |
6 | * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de) |
7 | * Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de) |
8 | * |
9 | * Most of this code is based on the SDL diagrams published in the 7th ARRL |
10 | * Computer Networking Conference papers. The diagrams have mistakes in them, |
11 | * but are mostly correct. Before you modify the code could you read the SDL |
12 | * diagrams as the code is not obvious and probably very easy to break. |
13 | */ |
14 | #include <linux/errno.h> |
15 | #include <linux/types.h> |
16 | #include <linux/socket.h> |
17 | #include <linux/in.h> |
18 | #include <linux/kernel.h> |
19 | #include <linux/timer.h> |
20 | #include <linux/string.h> |
21 | #include <linux/sockios.h> |
22 | #include <linux/net.h> |
23 | #include <net/ax25.h> |
24 | #include <linux/inet.h> |
25 | #include <linux/netdevice.h> |
26 | #include <linux/skbuff.h> |
27 | #include <net/sock.h> |
28 | #include <net/tcp_states.h> |
29 | #include <linux/uaccess.h> |
30 | #include <linux/fcntl.h> |
31 | #include <linux/mm.h> |
32 | #include <linux/interrupt.h> |
33 | |
34 | /* |
35 | * State machine for state 1, Awaiting Connection State. |
36 | * The handling of the timer(s) is in file ax25_std_timer.c. |
37 | * Handling of state 0 and connection release is in ax25.c. |
38 | */ |
39 | static int ax25_std_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type) |
40 | { |
41 | switch (frametype) { |
42 | case AX25_SABM: |
43 | ax25->modulus = AX25_MODULUS; |
44 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; |
45 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
46 | break; |
47 | |
48 | case AX25_SABME: |
49 | ax25->modulus = AX25_EMODULUS; |
50 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; |
51 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
52 | break; |
53 | |
54 | case AX25_DISC: |
55 | ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE); |
56 | break; |
57 | |
58 | case AX25_UA: |
59 | if (pf) { |
60 | ax25_calculate_rtt(ax25); |
61 | ax25_stop_t1timer(ax25); |
62 | ax25_start_t3timer(ax25); |
63 | ax25_start_idletimer(ax25); |
64 | ax25->vs = 0; |
65 | ax25->va = 0; |
66 | ax25->vr = 0; |
67 | ax25->state = AX25_STATE_3; |
68 | ax25->n2count = 0; |
69 | if (ax25->sk != NULL) { |
70 | bh_lock_sock(ax25->sk); |
71 | ax25->sk->sk_state = TCP_ESTABLISHED; |
72 | /* For WAIT_SABM connections we will produce an accept ready socket here */ |
73 | if (!sock_flag(sk: ax25->sk, flag: SOCK_DEAD)) |
74 | ax25->sk->sk_state_change(ax25->sk); |
75 | bh_unlock_sock(ax25->sk); |
76 | } |
77 | } |
78 | break; |
79 | |
80 | case AX25_DM: |
81 | if (pf) { |
82 | if (ax25->modulus == AX25_MODULUS) { |
83 | ax25_disconnect(ax25, ECONNREFUSED); |
84 | } else { |
85 | ax25->modulus = AX25_MODULUS; |
86 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; |
87 | } |
88 | } |
89 | break; |
90 | |
91 | default: |
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_std_timer.c |
101 | * Handling of state 0 and connection release is in ax25.c. |
102 | */ |
103 | static int ax25_std_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_DM, pf, AX25_RESPONSE); |
109 | break; |
110 | |
111 | case AX25_DISC: |
112 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
113 | ax25_disconnect(ax25, 0); |
114 | break; |
115 | |
116 | case AX25_DM: |
117 | case AX25_UA: |
118 | if (pf) |
119 | ax25_disconnect(ax25, 0); |
120 | break; |
121 | |
122 | case AX25_I: |
123 | case AX25_REJ: |
124 | case AX25_RNR: |
125 | case AX25_RR: |
126 | if (pf) ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE); |
127 | break; |
128 | |
129 | default: |
130 | break; |
131 | } |
132 | |
133 | return 0; |
134 | } |
135 | |
136 | /* |
137 | * State machine for state 3, Connected State. |
138 | * The handling of the timer(s) is in file ax25_std_timer.c |
139 | * Handling of state 0 and connection release is in ax25.c. |
140 | */ |
141 | static int ax25_std_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type) |
142 | { |
143 | int queued = 0; |
144 | |
145 | switch (frametype) { |
146 | case AX25_SABM: |
147 | case AX25_SABME: |
148 | if (frametype == AX25_SABM) { |
149 | ax25->modulus = AX25_MODULUS; |
150 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; |
151 | } else { |
152 | ax25->modulus = AX25_EMODULUS; |
153 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; |
154 | } |
155 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
156 | ax25_stop_t1timer(ax25); |
157 | ax25_stop_t2timer(ax25); |
158 | ax25_start_t3timer(ax25); |
159 | ax25_start_idletimer(ax25); |
160 | ax25->condition = 0x00; |
161 | ax25->vs = 0; |
162 | ax25->va = 0; |
163 | ax25->vr = 0; |
164 | ax25_requeue_frames(ax25); |
165 | break; |
166 | |
167 | case AX25_DISC: |
168 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
169 | ax25_disconnect(ax25, 0); |
170 | break; |
171 | |
172 | case AX25_DM: |
173 | ax25_disconnect(ax25, ECONNRESET); |
174 | break; |
175 | |
176 | case AX25_RR: |
177 | case AX25_RNR: |
178 | if (frametype == AX25_RR) |
179 | ax25->condition &= ~AX25_COND_PEER_RX_BUSY; |
180 | else |
181 | ax25->condition |= AX25_COND_PEER_RX_BUSY; |
182 | if (type == AX25_COMMAND && pf) |
183 | ax25_std_enquiry_response(ax25); |
184 | if (ax25_validate_nr(ax25, nr)) { |
185 | ax25_check_iframes_acked(ax25, nr); |
186 | } else { |
187 | ax25_std_nr_error_recovery(ax25); |
188 | ax25->state = AX25_STATE_1; |
189 | } |
190 | break; |
191 | |
192 | case AX25_REJ: |
193 | ax25->condition &= ~AX25_COND_PEER_RX_BUSY; |
194 | if (type == AX25_COMMAND && pf) |
195 | ax25_std_enquiry_response(ax25); |
196 | if (ax25_validate_nr(ax25, nr)) { |
197 | ax25_frames_acked(ax25, nr); |
198 | ax25_calculate_rtt(ax25); |
199 | ax25_stop_t1timer(ax25); |
200 | ax25_start_t3timer(ax25); |
201 | ax25_requeue_frames(ax25); |
202 | } else { |
203 | ax25_std_nr_error_recovery(ax25); |
204 | ax25->state = AX25_STATE_1; |
205 | } |
206 | break; |
207 | |
208 | case AX25_I: |
209 | if (!ax25_validate_nr(ax25, nr)) { |
210 | ax25_std_nr_error_recovery(ax25); |
211 | ax25->state = AX25_STATE_1; |
212 | break; |
213 | } |
214 | if (ax25->condition & AX25_COND_PEER_RX_BUSY) { |
215 | ax25_frames_acked(ax25, nr); |
216 | } else { |
217 | ax25_check_iframes_acked(ax25, nr); |
218 | } |
219 | if (ax25->condition & AX25_COND_OWN_RX_BUSY) { |
220 | if (pf) ax25_std_enquiry_response(ax25); |
221 | break; |
222 | } |
223 | if (ns == ax25->vr) { |
224 | ax25->vr = (ax25->vr + 1) % ax25->modulus; |
225 | queued = ax25_rx_iframe(ax25, skb); |
226 | if (ax25->condition & AX25_COND_OWN_RX_BUSY) |
227 | ax25->vr = ns; /* ax25->vr - 1 */ |
228 | ax25->condition &= ~AX25_COND_REJECT; |
229 | if (pf) { |
230 | ax25_std_enquiry_response(ax25); |
231 | } else { |
232 | if (!(ax25->condition & AX25_COND_ACK_PENDING)) { |
233 | ax25->condition |= AX25_COND_ACK_PENDING; |
234 | ax25_start_t2timer(ax25); |
235 | } |
236 | } |
237 | } else { |
238 | if (ax25->condition & AX25_COND_REJECT) { |
239 | if (pf) ax25_std_enquiry_response(ax25); |
240 | } else { |
241 | ax25->condition |= AX25_COND_REJECT; |
242 | ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE); |
243 | ax25->condition &= ~AX25_COND_ACK_PENDING; |
244 | } |
245 | } |
246 | break; |
247 | |
248 | case AX25_FRMR: |
249 | case AX25_ILLEGAL: |
250 | ax25_std_establish_data_link(ax25); |
251 | ax25->state = AX25_STATE_1; |
252 | break; |
253 | |
254 | default: |
255 | break; |
256 | } |
257 | |
258 | return queued; |
259 | } |
260 | |
261 | /* |
262 | * State machine for state 4, Timer Recovery State. |
263 | * The handling of the timer(s) is in file ax25_std_timer.c |
264 | * Handling of state 0 and connection release is in ax25.c. |
265 | */ |
266 | static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type) |
267 | { |
268 | int queued = 0; |
269 | |
270 | switch (frametype) { |
271 | case AX25_SABM: |
272 | case AX25_SABME: |
273 | if (frametype == AX25_SABM) { |
274 | ax25->modulus = AX25_MODULUS; |
275 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; |
276 | } else { |
277 | ax25->modulus = AX25_EMODULUS; |
278 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; |
279 | } |
280 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
281 | ax25_stop_t1timer(ax25); |
282 | ax25_stop_t2timer(ax25); |
283 | ax25_start_t3timer(ax25); |
284 | ax25_start_idletimer(ax25); |
285 | ax25->condition = 0x00; |
286 | ax25->vs = 0; |
287 | ax25->va = 0; |
288 | ax25->vr = 0; |
289 | ax25->state = AX25_STATE_3; |
290 | ax25->n2count = 0; |
291 | ax25_requeue_frames(ax25); |
292 | break; |
293 | |
294 | case AX25_DISC: |
295 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
296 | ax25_disconnect(ax25, 0); |
297 | break; |
298 | |
299 | case AX25_DM: |
300 | ax25_disconnect(ax25, ECONNRESET); |
301 | break; |
302 | |
303 | case AX25_RR: |
304 | case AX25_RNR: |
305 | if (frametype == AX25_RR) |
306 | ax25->condition &= ~AX25_COND_PEER_RX_BUSY; |
307 | else |
308 | ax25->condition |= AX25_COND_PEER_RX_BUSY; |
309 | if (type == AX25_RESPONSE && pf) { |
310 | ax25_stop_t1timer(ax25); |
311 | ax25->n2count = 0; |
312 | if (ax25_validate_nr(ax25, nr)) { |
313 | ax25_frames_acked(ax25, nr); |
314 | if (ax25->vs == ax25->va) { |
315 | ax25_start_t3timer(ax25); |
316 | ax25->state = AX25_STATE_3; |
317 | } else { |
318 | ax25_requeue_frames(ax25); |
319 | } |
320 | } else { |
321 | ax25_std_nr_error_recovery(ax25); |
322 | ax25->state = AX25_STATE_1; |
323 | } |
324 | break; |
325 | } |
326 | if (type == AX25_COMMAND && pf) |
327 | ax25_std_enquiry_response(ax25); |
328 | if (ax25_validate_nr(ax25, nr)) { |
329 | ax25_frames_acked(ax25, nr); |
330 | } else { |
331 | ax25_std_nr_error_recovery(ax25); |
332 | ax25->state = AX25_STATE_1; |
333 | } |
334 | break; |
335 | |
336 | case AX25_REJ: |
337 | ax25->condition &= ~AX25_COND_PEER_RX_BUSY; |
338 | if (pf && type == AX25_RESPONSE) { |
339 | ax25_stop_t1timer(ax25); |
340 | ax25->n2count = 0; |
341 | if (ax25_validate_nr(ax25, nr)) { |
342 | ax25_frames_acked(ax25, nr); |
343 | if (ax25->vs == ax25->va) { |
344 | ax25_start_t3timer(ax25); |
345 | ax25->state = AX25_STATE_3; |
346 | } else { |
347 | ax25_requeue_frames(ax25); |
348 | } |
349 | } else { |
350 | ax25_std_nr_error_recovery(ax25); |
351 | ax25->state = AX25_STATE_1; |
352 | } |
353 | break; |
354 | } |
355 | if (type == AX25_COMMAND && pf) |
356 | ax25_std_enquiry_response(ax25); |
357 | if (ax25_validate_nr(ax25, nr)) { |
358 | ax25_frames_acked(ax25, nr); |
359 | ax25_requeue_frames(ax25); |
360 | } else { |
361 | ax25_std_nr_error_recovery(ax25); |
362 | ax25->state = AX25_STATE_1; |
363 | } |
364 | break; |
365 | |
366 | case AX25_I: |
367 | if (!ax25_validate_nr(ax25, nr)) { |
368 | ax25_std_nr_error_recovery(ax25); |
369 | ax25->state = AX25_STATE_1; |
370 | break; |
371 | } |
372 | ax25_frames_acked(ax25, nr); |
373 | if (ax25->condition & AX25_COND_OWN_RX_BUSY) { |
374 | if (pf) |
375 | ax25_std_enquiry_response(ax25); |
376 | break; |
377 | } |
378 | if (ns == ax25->vr) { |
379 | ax25->vr = (ax25->vr + 1) % ax25->modulus; |
380 | queued = ax25_rx_iframe(ax25, skb); |
381 | if (ax25->condition & AX25_COND_OWN_RX_BUSY) |
382 | ax25->vr = ns; /* ax25->vr - 1 */ |
383 | ax25->condition &= ~AX25_COND_REJECT; |
384 | if (pf) { |
385 | ax25_std_enquiry_response(ax25); |
386 | } else { |
387 | if (!(ax25->condition & AX25_COND_ACK_PENDING)) { |
388 | ax25->condition |= AX25_COND_ACK_PENDING; |
389 | ax25_start_t2timer(ax25); |
390 | } |
391 | } |
392 | } else { |
393 | if (ax25->condition & AX25_COND_REJECT) { |
394 | if (pf) ax25_std_enquiry_response(ax25); |
395 | } else { |
396 | ax25->condition |= AX25_COND_REJECT; |
397 | ax25_send_control(ax25, AX25_REJ, pf, AX25_RESPONSE); |
398 | ax25->condition &= ~AX25_COND_ACK_PENDING; |
399 | } |
400 | } |
401 | break; |
402 | |
403 | case AX25_FRMR: |
404 | case AX25_ILLEGAL: |
405 | ax25_std_establish_data_link(ax25); |
406 | ax25->state = AX25_STATE_1; |
407 | break; |
408 | |
409 | default: |
410 | break; |
411 | } |
412 | |
413 | return queued; |
414 | } |
415 | |
416 | /* |
417 | * Higher level upcall for a LAPB frame |
418 | */ |
419 | int ax25_std_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type) |
420 | { |
421 | int queued = 0, frametype, ns, nr, pf; |
422 | |
423 | frametype = ax25_decode(ax25, skb, &ns, &nr, &pf); |
424 | |
425 | switch (ax25->state) { |
426 | case AX25_STATE_1: |
427 | queued = ax25_std_state1_machine(ax25, skb, frametype, pf, type); |
428 | break; |
429 | case AX25_STATE_2: |
430 | queued = ax25_std_state2_machine(ax25, skb, frametype, pf, type); |
431 | break; |
432 | case AX25_STATE_3: |
433 | queued = ax25_std_state3_machine(ax25, skb, frametype, ns, nr, pf, type); |
434 | break; |
435 | case AX25_STATE_4: |
436 | queued = ax25_std_state4_machine(ax25, skb, frametype, ns, nr, pf, type); |
437 | break; |
438 | } |
439 | |
440 | ax25_kick(ax25); |
441 | |
442 | return queued; |
443 | } |
444 | |