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