1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * |
4 | * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) |
5 | * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de) |
6 | */ |
7 | #include <linux/errno.h> |
8 | #include <linux/types.h> |
9 | #include <linux/socket.h> |
10 | #include <linux/in.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/timer.h> |
13 | #include <linux/string.h> |
14 | #include <linux/sockios.h> |
15 | #include <linux/net.h> |
16 | #include <net/ax25.h> |
17 | #include <linux/inet.h> |
18 | #include <linux/netdevice.h> |
19 | #include <linux/skbuff.h> |
20 | #include <net/sock.h> |
21 | #include <net/tcp_states.h> |
22 | #include <linux/uaccess.h> |
23 | #include <linux/fcntl.h> |
24 | #include <linux/mm.h> |
25 | #include <linux/interrupt.h> |
26 | |
27 | /* |
28 | * State machine for state 1, Awaiting Connection State. |
29 | * The handling of the timer(s) is in file ax25_ds_timer.c. |
30 | * Handling of state 0 and connection release is in ax25.c. |
31 | */ |
32 | static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type) |
33 | { |
34 | switch (frametype) { |
35 | case AX25_SABM: |
36 | ax25->modulus = AX25_MODULUS; |
37 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; |
38 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
39 | break; |
40 | |
41 | case AX25_SABME: |
42 | ax25->modulus = AX25_EMODULUS; |
43 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; |
44 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
45 | break; |
46 | |
47 | case AX25_DISC: |
48 | ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE); |
49 | break; |
50 | |
51 | case AX25_UA: |
52 | ax25_calculate_rtt(ax25); |
53 | ax25_stop_t1timer(ax25); |
54 | ax25_start_t3timer(ax25); |
55 | ax25_start_idletimer(ax25); |
56 | ax25->vs = 0; |
57 | ax25->va = 0; |
58 | ax25->vr = 0; |
59 | ax25->state = AX25_STATE_3; |
60 | ax25->n2count = 0; |
61 | if (ax25->sk != NULL) { |
62 | bh_lock_sock(ax25->sk); |
63 | ax25->sk->sk_state = TCP_ESTABLISHED; |
64 | /* |
65 | * For WAIT_SABM connections we will produce an accept |
66 | * ready socket here |
67 | */ |
68 | if (!sock_flag(sk: ax25->sk, flag: SOCK_DEAD)) |
69 | ax25->sk->sk_state_change(ax25->sk); |
70 | bh_unlock_sock(ax25->sk); |
71 | } |
72 | ax25_dama_on(ax25); |
73 | |
74 | /* according to DK4EG's spec we are required to |
75 | * send a RR RESPONSE FINAL NR=0. |
76 | */ |
77 | |
78 | ax25_std_enquiry_response(ax25); |
79 | break; |
80 | |
81 | case AX25_DM: |
82 | if (pf) |
83 | ax25_disconnect(ax25, ECONNREFUSED); |
84 | break; |
85 | |
86 | default: |
87 | if (pf) |
88 | ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND); |
89 | break; |
90 | } |
91 | |
92 | return 0; |
93 | } |
94 | |
95 | /* |
96 | * State machine for state 2, Awaiting Release State. |
97 | * The handling of the timer(s) is in file ax25_ds_timer.c |
98 | * Handling of state 0 and connection release is in ax25.c. |
99 | */ |
100 | static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type) |
101 | { |
102 | switch (frametype) { |
103 | case AX25_SABM: |
104 | case AX25_SABME: |
105 | ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); |
106 | ax25_dama_off(ax25); |
107 | break; |
108 | |
109 | case AX25_DISC: |
110 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
111 | ax25_dama_off(ax25); |
112 | ax25_disconnect(ax25, 0); |
113 | break; |
114 | |
115 | case AX25_DM: |
116 | case AX25_UA: |
117 | if (pf) { |
118 | ax25_dama_off(ax25); |
119 | ax25_disconnect(ax25, 0); |
120 | } |
121 | break; |
122 | |
123 | case AX25_I: |
124 | case AX25_REJ: |
125 | case AX25_RNR: |
126 | case AX25_RR: |
127 | if (pf) { |
128 | ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); |
129 | ax25_dama_off(ax25); |
130 | } |
131 | break; |
132 | |
133 | default: |
134 | break; |
135 | } |
136 | |
137 | return 0; |
138 | } |
139 | |
140 | /* |
141 | * State machine for state 3, Connected State. |
142 | * The handling of the timer(s) is in file ax25_timer.c |
143 | * Handling of state 0 and connection release is in ax25.c. |
144 | */ |
145 | static int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type) |
146 | { |
147 | int queued = 0; |
148 | |
149 | switch (frametype) { |
150 | case AX25_SABM: |
151 | case AX25_SABME: |
152 | if (frametype == AX25_SABM) { |
153 | ax25->modulus = AX25_MODULUS; |
154 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; |
155 | } else { |
156 | ax25->modulus = AX25_EMODULUS; |
157 | ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; |
158 | } |
159 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
160 | ax25_stop_t1timer(ax25); |
161 | ax25_start_t3timer(ax25); |
162 | ax25_start_idletimer(ax25); |
163 | ax25->condition = 0x00; |
164 | ax25->vs = 0; |
165 | ax25->va = 0; |
166 | ax25->vr = 0; |
167 | ax25_requeue_frames(ax25); |
168 | ax25_dama_on(ax25); |
169 | break; |
170 | |
171 | case AX25_DISC: |
172 | ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); |
173 | ax25_dama_off(ax25); |
174 | ax25_disconnect(ax25, 0); |
175 | break; |
176 | |
177 | case AX25_DM: |
178 | ax25_dama_off(ax25); |
179 | ax25_disconnect(ax25, ECONNRESET); |
180 | break; |
181 | |
182 | case AX25_RR: |
183 | case AX25_RNR: |
184 | if (frametype == AX25_RR) |
185 | ax25->condition &= ~AX25_COND_PEER_RX_BUSY; |
186 | else |
187 | ax25->condition |= AX25_COND_PEER_RX_BUSY; |
188 | |
189 | if (ax25_validate_nr(ax25, nr)) { |
190 | if (ax25_check_iframes_acked(ax25, nr)) |
191 | ax25->n2count=0; |
192 | if (type == AX25_COMMAND && pf) |
193 | ax25_ds_enquiry_response(ax25); |
194 | } else { |
195 | ax25_ds_nr_error_recovery(ax25); |
196 | ax25->state = AX25_STATE_1; |
197 | } |
198 | break; |
199 | |
200 | case AX25_REJ: |
201 | ax25->condition &= ~AX25_COND_PEER_RX_BUSY; |
202 | |
203 | if (ax25_validate_nr(ax25, nr)) { |
204 | if (ax25->va != nr) |
205 | ax25->n2count=0; |
206 | |
207 | ax25_frames_acked(ax25, nr); |
208 | ax25_calculate_rtt(ax25); |
209 | ax25_stop_t1timer(ax25); |
210 | ax25_start_t3timer(ax25); |
211 | ax25_requeue_frames(ax25); |
212 | |
213 | if (type == AX25_COMMAND && pf) |
214 | ax25_ds_enquiry_response(ax25); |
215 | } else { |
216 | ax25_ds_nr_error_recovery(ax25); |
217 | ax25->state = AX25_STATE_1; |
218 | } |
219 | break; |
220 | |
221 | case AX25_I: |
222 | if (!ax25_validate_nr(ax25, nr)) { |
223 | ax25_ds_nr_error_recovery(ax25); |
224 | ax25->state = AX25_STATE_1; |
225 | break; |
226 | } |
227 | if (ax25->condition & AX25_COND_PEER_RX_BUSY) { |
228 | ax25_frames_acked(ax25, nr); |
229 | ax25->n2count = 0; |
230 | } else { |
231 | if (ax25_check_iframes_acked(ax25, nr)) |
232 | ax25->n2count = 0; |
233 | } |
234 | if (ax25->condition & AX25_COND_OWN_RX_BUSY) { |
235 | if (pf) ax25_ds_enquiry_response(ax25); |
236 | break; |
237 | } |
238 | if (ns == ax25->vr) { |
239 | ax25->vr = (ax25->vr + 1) % ax25->modulus; |
240 | queued = ax25_rx_iframe(ax25, skb); |
241 | if (ax25->condition & AX25_COND_OWN_RX_BUSY) |
242 | ax25->vr = ns; /* ax25->vr - 1 */ |
243 | ax25->condition &= ~AX25_COND_REJECT; |
244 | if (pf) { |
245 | ax25_ds_enquiry_response(ax25); |
246 | } else { |
247 | if (!(ax25->condition & AX25_COND_ACK_PENDING)) { |
248 | ax25->condition |= AX25_COND_ACK_PENDING; |
249 | ax25_start_t2timer(ax25); |
250 | } |
251 | } |
252 | } else { |
253 | if (ax25->condition & AX25_COND_REJECT) { |
254 | if (pf) ax25_ds_enquiry_response(ax25); |
255 | } else { |
256 | ax25->condition |= AX25_COND_REJECT; |
257 | ax25_ds_enquiry_response(ax25); |
258 | ax25->condition &= ~AX25_COND_ACK_PENDING; |
259 | } |
260 | } |
261 | break; |
262 | |
263 | case AX25_FRMR: |
264 | case AX25_ILLEGAL: |
265 | ax25_ds_establish_data_link(ax25); |
266 | ax25->state = AX25_STATE_1; |
267 | break; |
268 | |
269 | default: |
270 | break; |
271 | } |
272 | |
273 | return queued; |
274 | } |
275 | |
276 | /* |
277 | * Higher level upcall for a LAPB frame |
278 | */ |
279 | int ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type) |
280 | { |
281 | int queued = 0, frametype, ns, nr, pf; |
282 | |
283 | frametype = ax25_decode(ax25, skb, &ns, &nr, &pf); |
284 | |
285 | switch (ax25->state) { |
286 | case AX25_STATE_1: |
287 | queued = ax25_ds_state1_machine(ax25, skb, frametype, pf, type); |
288 | break; |
289 | case AX25_STATE_2: |
290 | queued = ax25_ds_state2_machine(ax25, skb, frametype, pf, type); |
291 | break; |
292 | case AX25_STATE_3: |
293 | queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type); |
294 | break; |
295 | } |
296 | |
297 | return queued; |
298 | } |
299 | |