diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/llc/llc_c_ac.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'net/llc/llc_c_ac.c')
-rw-r--r-- | net/llc/llc_c_ac.c | 1514 |
1 files changed, 1514 insertions, 0 deletions
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c new file mode 100644 index 000000000000..b218be4c10ec --- /dev/null +++ b/net/llc/llc_c_ac.c | |||
@@ -0,0 +1,1514 @@ | |||
1 | /* | ||
2 | * llc_c_ac.c - actions performed during connection state transition. | ||
3 | * | ||
4 | * Description: | ||
5 | * Functions in this module are implementation of connection component actions | ||
6 | * Details of actions can be found in IEEE-802.2 standard document. | ||
7 | * All functions have one connection and one event as input argument. All of | ||
8 | * them return 0 On success and 1 otherwise. | ||
9 | * | ||
10 | * Copyright (c) 1997 by Procom Technology, Inc. | ||
11 | * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
12 | * | ||
13 | * This program can be redistributed or modified under the terms of the | ||
14 | * GNU General Public License as published by the Free Software Foundation. | ||
15 | * This program is distributed without any warranty or implied warranty | ||
16 | * of merchantability or fitness for a particular purpose. | ||
17 | * | ||
18 | * See the GNU General Public License for more details. | ||
19 | */ | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <net/llc_conn.h> | ||
22 | #include <net/llc_sap.h> | ||
23 | #include <net/sock.h> | ||
24 | #include <net/llc_c_ev.h> | ||
25 | #include <net/llc_c_ac.h> | ||
26 | #include <net/llc_c_st.h> | ||
27 | #include <net/llc_pdu.h> | ||
28 | #include <net/llc.h> | ||
29 | |||
30 | #include "llc_output.h" | ||
31 | |||
32 | static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb); | ||
33 | static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb); | ||
34 | static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *ev); | ||
35 | |||
36 | static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb); | ||
37 | |||
38 | static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, | ||
39 | struct sk_buff *skb); | ||
40 | |||
41 | static int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb); | ||
42 | |||
43 | #define INCORRECT 0 | ||
44 | |||
45 | int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb) | ||
46 | { | ||
47 | struct llc_sock *llc = llc_sk(sk); | ||
48 | |||
49 | if (llc->remote_busy_flag) { | ||
50 | u8 nr; | ||
51 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
52 | |||
53 | llc->remote_busy_flag = 0; | ||
54 | del_timer(&llc->busy_state_timer.timer); | ||
55 | nr = LLC_I_GET_NR(pdu); | ||
56 | llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); | ||
57 | } | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) | ||
62 | { | ||
63 | int rc = -ENOTCONN; | ||
64 | u8 dsap; | ||
65 | struct llc_sap *sap; | ||
66 | |||
67 | llc_pdu_decode_dsap(skb, &dsap); | ||
68 | sap = llc_sap_find(dsap); | ||
69 | if (sap) { | ||
70 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
71 | struct llc_sock *llc = llc_sk(sk); | ||
72 | |||
73 | llc_pdu_decode_sa(skb, llc->daddr.mac); | ||
74 | llc_pdu_decode_da(skb, llc->laddr.mac); | ||
75 | llc->dev = skb->dev; | ||
76 | ev->ind_prim = LLC_CONN_PRIM; | ||
77 | rc = 0; | ||
78 | } | ||
79 | return rc; | ||
80 | } | ||
81 | |||
82 | int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb) | ||
83 | { | ||
84 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
85 | |||
86 | ev->cfm_prim = LLC_CONN_PRIM; | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *skb) | ||
91 | { | ||
92 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
93 | |||
94 | ev->cfm_prim = LLC_DATA_PRIM; | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | int llc_conn_ac_data_ind(struct sock *sk, struct sk_buff *skb) | ||
99 | { | ||
100 | llc_conn_rtn_pdu(sk, skb); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) | ||
105 | { | ||
106 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
107 | u8 reason = 0; | ||
108 | int rc = 0; | ||
109 | |||
110 | if (ev->type == LLC_CONN_EV_TYPE_PDU) { | ||
111 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); | ||
112 | |||
113 | if (LLC_PDU_IS_RSP(pdu) && | ||
114 | LLC_PDU_TYPE_IS_U(pdu) && | ||
115 | LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM) | ||
116 | reason = LLC_DISC_REASON_RX_DM_RSP_PDU; | ||
117 | else if (LLC_PDU_IS_CMD(pdu) && | ||
118 | LLC_PDU_TYPE_IS_U(pdu) && | ||
119 | LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC) | ||
120 | reason = LLC_DISC_REASON_RX_DISC_CMD_PDU; | ||
121 | } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR) | ||
122 | reason = LLC_DISC_REASON_ACK_TMR_EXP; | ||
123 | else { | ||
124 | reason = 0; | ||
125 | rc = -EINVAL; | ||
126 | } | ||
127 | if (!rc) { | ||
128 | ev->reason = reason; | ||
129 | ev->ind_prim = LLC_DISC_PRIM; | ||
130 | } | ||
131 | return rc; | ||
132 | } | ||
133 | |||
134 | int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb) | ||
135 | { | ||
136 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
137 | |||
138 | ev->reason = ev->status; | ||
139 | ev->cfm_prim = LLC_DISC_PRIM; | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) | ||
144 | { | ||
145 | u8 reason = 0; | ||
146 | int rc = 1; | ||
147 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
148 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); | ||
149 | struct llc_sock *llc = llc_sk(sk); | ||
150 | |||
151 | switch (ev->type) { | ||
152 | case LLC_CONN_EV_TYPE_PDU: | ||
153 | if (LLC_PDU_IS_RSP(pdu) && | ||
154 | LLC_PDU_TYPE_IS_U(pdu) && | ||
155 | LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR) { | ||
156 | reason = LLC_RESET_REASON_LOCAL; | ||
157 | rc = 0; | ||
158 | } else if (LLC_PDU_IS_CMD(pdu) && | ||
159 | LLC_PDU_TYPE_IS_U(pdu) && | ||
160 | LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME) { | ||
161 | reason = LLC_RESET_REASON_REMOTE; | ||
162 | rc = 0; | ||
163 | } else { | ||
164 | reason = 0; | ||
165 | rc = 1; | ||
166 | } | ||
167 | break; | ||
168 | case LLC_CONN_EV_TYPE_ACK_TMR: | ||
169 | case LLC_CONN_EV_TYPE_P_TMR: | ||
170 | case LLC_CONN_EV_TYPE_REJ_TMR: | ||
171 | case LLC_CONN_EV_TYPE_BUSY_TMR: | ||
172 | if (llc->retry_count > llc->n2) { | ||
173 | reason = LLC_RESET_REASON_LOCAL; | ||
174 | rc = 0; | ||
175 | } else | ||
176 | rc = 1; | ||
177 | break; | ||
178 | } | ||
179 | if (!rc) { | ||
180 | ev->reason = reason; | ||
181 | ev->ind_prim = LLC_RESET_PRIM; | ||
182 | } | ||
183 | return rc; | ||
184 | } | ||
185 | |||
186 | int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb) | ||
187 | { | ||
188 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
189 | |||
190 | ev->reason = 0; | ||
191 | ev->cfm_prim = LLC_RESET_PRIM; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk, | ||
196 | struct sk_buff *skb) | ||
197 | { | ||
198 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
199 | |||
200 | if (LLC_PDU_IS_RSP(pdu) && | ||
201 | LLC_PDU_TYPE_IS_I(pdu) && | ||
202 | LLC_I_PF_IS_1(pdu) && llc_sk(sk)->ack_pf) | ||
203 | llc_conn_ac_clear_remote_busy(sk, skb); | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk, | ||
208 | struct sk_buff *skb) | ||
209 | { | ||
210 | struct llc_sock *llc = llc_sk(sk); | ||
211 | |||
212 | if (llc->data_flag == 2) | ||
213 | del_timer(&llc->rej_sent_timer.timer); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) | ||
218 | { | ||
219 | int rc = -ENOBUFS; | ||
220 | struct sk_buff *nskb = llc_alloc_frame(); | ||
221 | |||
222 | if (nskb) { | ||
223 | struct llc_sock *llc = llc_sk(sk); | ||
224 | struct llc_sap *sap = llc->sap; | ||
225 | |||
226 | nskb->dev = llc->dev; | ||
227 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
228 | llc->daddr.lsap, LLC_PDU_CMD); | ||
229 | llc_pdu_init_as_disc_cmd(nskb, 1); | ||
230 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
231 | if (rc) | ||
232 | goto free; | ||
233 | llc_conn_send_pdu(sk, nskb); | ||
234 | llc_conn_ac_set_p_flag_1(sk, skb); | ||
235 | } | ||
236 | out: | ||
237 | return rc; | ||
238 | free: | ||
239 | kfree_skb(nskb); | ||
240 | goto out; | ||
241 | } | ||
242 | |||
243 | int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) | ||
244 | { | ||
245 | int rc = -ENOBUFS; | ||
246 | struct sk_buff *nskb = llc_alloc_frame(); | ||
247 | |||
248 | if (nskb) { | ||
249 | struct llc_sock *llc = llc_sk(sk); | ||
250 | struct llc_sap *sap = llc->sap; | ||
251 | u8 f_bit; | ||
252 | |||
253 | nskb->dev = llc->dev; | ||
254 | llc_pdu_decode_pf_bit(skb, &f_bit); | ||
255 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
256 | llc->daddr.lsap, LLC_PDU_RSP); | ||
257 | llc_pdu_init_as_dm_rsp(nskb, f_bit); | ||
258 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
259 | if (rc) | ||
260 | goto free; | ||
261 | llc_conn_send_pdu(sk, nskb); | ||
262 | } | ||
263 | out: | ||
264 | return rc; | ||
265 | free: | ||
266 | kfree_skb(nskb); | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) | ||
271 | { | ||
272 | int rc = -ENOBUFS; | ||
273 | struct sk_buff *nskb = llc_alloc_frame(); | ||
274 | |||
275 | if (nskb) { | ||
276 | struct llc_sock *llc = llc_sk(sk); | ||
277 | struct llc_sap *sap = llc->sap; | ||
278 | u8 f_bit = 1; | ||
279 | |||
280 | nskb->dev = llc->dev; | ||
281 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
282 | llc->daddr.lsap, LLC_PDU_RSP); | ||
283 | llc_pdu_init_as_dm_rsp(nskb, f_bit); | ||
284 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
285 | if (rc) | ||
286 | goto free; | ||
287 | llc_conn_send_pdu(sk, nskb); | ||
288 | } | ||
289 | out: | ||
290 | return rc; | ||
291 | free: | ||
292 | kfree_skb(nskb); | ||
293 | goto out; | ||
294 | } | ||
295 | |||
296 | int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) | ||
297 | { | ||
298 | u8 f_bit; | ||
299 | int rc = -ENOBUFS; | ||
300 | struct sk_buff *nskb; | ||
301 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
302 | struct llc_sock *llc = llc_sk(sk); | ||
303 | |||
304 | llc->rx_pdu_hdr = *((u32 *)pdu); | ||
305 | if (LLC_PDU_IS_CMD(pdu)) | ||
306 | llc_pdu_decode_pf_bit(skb, &f_bit); | ||
307 | else | ||
308 | f_bit = 0; | ||
309 | nskb = llc_alloc_frame(); | ||
310 | if (nskb) { | ||
311 | struct llc_sap *sap = llc->sap; | ||
312 | |||
313 | nskb->dev = llc->dev; | ||
314 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
315 | llc->daddr.lsap, LLC_PDU_RSP); | ||
316 | llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, | ||
317 | llc->vR, INCORRECT); | ||
318 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
319 | if (rc) | ||
320 | goto free; | ||
321 | llc_conn_send_pdu(sk, nskb); | ||
322 | } | ||
323 | out: | ||
324 | return rc; | ||
325 | free: | ||
326 | kfree_skb(nskb); | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) | ||
331 | { | ||
332 | int rc = -ENOBUFS; | ||
333 | struct sk_buff *nskb = llc_alloc_frame(); | ||
334 | |||
335 | if (nskb) { | ||
336 | u8 f_bit = 0; | ||
337 | struct llc_sock *llc = llc_sk(sk); | ||
338 | struct llc_sap *sap = llc->sap; | ||
339 | struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr; | ||
340 | |||
341 | nskb->dev = llc->dev; | ||
342 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
343 | llc->daddr.lsap, LLC_PDU_RSP); | ||
344 | llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, | ||
345 | llc->vR, INCORRECT); | ||
346 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
347 | if (rc) | ||
348 | goto free; | ||
349 | llc_conn_send_pdu(sk, nskb); | ||
350 | } | ||
351 | out: | ||
352 | return rc; | ||
353 | free: | ||
354 | kfree_skb(nskb); | ||
355 | goto out; | ||
356 | } | ||
357 | |||
358 | int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) | ||
359 | { | ||
360 | u8 f_bit; | ||
361 | int rc = -ENOBUFS; | ||
362 | struct sk_buff *nskb; | ||
363 | |||
364 | llc_pdu_decode_pf_bit(skb, &f_bit); | ||
365 | nskb = llc_alloc_frame(); | ||
366 | if (nskb) { | ||
367 | struct llc_sock *llc = llc_sk(sk); | ||
368 | struct llc_sap *sap = llc->sap; | ||
369 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
370 | |||
371 | nskb->dev = llc->dev; | ||
372 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
373 | llc->daddr.lsap, LLC_PDU_RSP); | ||
374 | llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, | ||
375 | llc->vR, INCORRECT); | ||
376 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
377 | if (rc) | ||
378 | goto free; | ||
379 | llc_conn_send_pdu(sk, nskb); | ||
380 | } | ||
381 | out: | ||
382 | return rc; | ||
383 | free: | ||
384 | kfree_skb(nskb); | ||
385 | goto out; | ||
386 | } | ||
387 | |||
388 | int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) | ||
389 | { | ||
390 | int rc; | ||
391 | struct llc_sock *llc = llc_sk(sk); | ||
392 | struct llc_sap *sap = llc->sap; | ||
393 | |||
394 | llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, | ||
395 | llc->daddr.lsap, LLC_PDU_CMD); | ||
396 | llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR); | ||
397 | rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); | ||
398 | if (!rc) { | ||
399 | llc_conn_send_pdu(sk, skb); | ||
400 | llc_conn_ac_inc_vs_by_1(sk, skb); | ||
401 | } | ||
402 | return rc; | ||
403 | } | ||
404 | |||
405 | static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb) | ||
406 | { | ||
407 | int rc; | ||
408 | struct llc_sock *llc = llc_sk(sk); | ||
409 | struct llc_sap *sap = llc->sap; | ||
410 | |||
411 | llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, | ||
412 | llc->daddr.lsap, LLC_PDU_CMD); | ||
413 | llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); | ||
414 | rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); | ||
415 | if (!rc) { | ||
416 | llc_conn_send_pdu(sk, skb); | ||
417 | llc_conn_ac_inc_vs_by_1(sk, skb); | ||
418 | } | ||
419 | return rc; | ||
420 | } | ||
421 | |||
422 | int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
423 | { | ||
424 | int rc; | ||
425 | struct llc_sock *llc = llc_sk(sk); | ||
426 | struct llc_sap *sap = llc->sap; | ||
427 | |||
428 | llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, | ||
429 | llc->daddr.lsap, LLC_PDU_CMD); | ||
430 | llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); | ||
431 | rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); | ||
432 | if (!rc) { | ||
433 | llc_conn_send_pdu(sk, skb); | ||
434 | llc_conn_ac_inc_vs_by_1(sk, skb); | ||
435 | } | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
440 | { | ||
441 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
442 | u8 nr = LLC_I_GET_NR(pdu); | ||
443 | |||
444 | llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); | ||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, | ||
449 | struct sk_buff *skb) | ||
450 | { | ||
451 | u8 nr; | ||
452 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
453 | int rc = -ENOBUFS; | ||
454 | struct sk_buff *nskb = llc_alloc_frame(); | ||
455 | |||
456 | if (nskb) { | ||
457 | struct llc_sock *llc = llc_sk(sk); | ||
458 | struct llc_sap *sap = llc->sap; | ||
459 | |||
460 | nskb->dev = llc->dev; | ||
461 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
462 | llc->daddr.lsap, LLC_PDU_RSP); | ||
463 | llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); | ||
464 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
465 | if (!rc) | ||
466 | llc_conn_send_pdu(sk, nskb); | ||
467 | else | ||
468 | kfree_skb(skb); | ||
469 | } | ||
470 | if (rc) { | ||
471 | nr = LLC_I_GET_NR(pdu); | ||
472 | rc = 0; | ||
473 | llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); | ||
474 | } | ||
475 | return rc; | ||
476 | } | ||
477 | |||
478 | int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) | ||
479 | { | ||
480 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
481 | u8 nr = LLC_I_GET_NR(pdu); | ||
482 | |||
483 | llc_conn_resend_i_pdu_as_rsp(sk, nr, 1); | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) | ||
488 | { | ||
489 | int rc = -ENOBUFS; | ||
490 | struct sk_buff *nskb = llc_alloc_frame(); | ||
491 | |||
492 | if (nskb) { | ||
493 | struct llc_sock *llc = llc_sk(sk); | ||
494 | struct llc_sap *sap = llc->sap; | ||
495 | |||
496 | nskb->dev = llc->dev; | ||
497 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
498 | llc->daddr.lsap, LLC_PDU_CMD); | ||
499 | llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR); | ||
500 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
501 | if (rc) | ||
502 | goto free; | ||
503 | llc_conn_send_pdu(sk, nskb); | ||
504 | } | ||
505 | out: | ||
506 | return rc; | ||
507 | free: | ||
508 | kfree_skb(nskb); | ||
509 | goto out; | ||
510 | } | ||
511 | |||
512 | int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) | ||
513 | { | ||
514 | int rc = -ENOBUFS; | ||
515 | struct sk_buff *nskb = llc_alloc_frame(); | ||
516 | |||
517 | if (nskb) { | ||
518 | u8 f_bit = 1; | ||
519 | struct llc_sock *llc = llc_sk(sk); | ||
520 | struct llc_sap *sap = llc->sap; | ||
521 | |||
522 | nskb->dev = llc->dev; | ||
523 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
524 | llc->daddr.lsap, LLC_PDU_RSP); | ||
525 | llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); | ||
526 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
527 | if (rc) | ||
528 | goto free; | ||
529 | llc_conn_send_pdu(sk, nskb); | ||
530 | } | ||
531 | out: | ||
532 | return rc; | ||
533 | free: | ||
534 | kfree_skb(nskb); | ||
535 | goto out; | ||
536 | } | ||
537 | |||
538 | int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
539 | { | ||
540 | int rc = -ENOBUFS; | ||
541 | struct sk_buff *nskb = llc_alloc_frame(); | ||
542 | |||
543 | if (nskb) { | ||
544 | struct llc_sock *llc = llc_sk(sk); | ||
545 | struct llc_sap *sap = llc->sap; | ||
546 | u8 f_bit = 0; | ||
547 | |||
548 | nskb->dev = llc->dev; | ||
549 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
550 | llc->daddr.lsap, LLC_PDU_RSP); | ||
551 | llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); | ||
552 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
553 | if (rc) | ||
554 | goto free; | ||
555 | llc_conn_send_pdu(sk, nskb); | ||
556 | } | ||
557 | out: | ||
558 | return rc; | ||
559 | free: | ||
560 | kfree_skb(nskb); | ||
561 | goto out; | ||
562 | } | ||
563 | |||
564 | int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) | ||
565 | { | ||
566 | int rc = -ENOBUFS; | ||
567 | struct sk_buff *nskb = llc_alloc_frame(); | ||
568 | |||
569 | if (nskb) { | ||
570 | struct llc_sock *llc = llc_sk(sk); | ||
571 | struct llc_sap *sap = llc->sap; | ||
572 | |||
573 | nskb->dev = llc->dev; | ||
574 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
575 | llc->daddr.lsap, LLC_PDU_CMD); | ||
576 | llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR); | ||
577 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
578 | if (rc) | ||
579 | goto free; | ||
580 | llc_conn_send_pdu(sk, nskb); | ||
581 | } | ||
582 | out: | ||
583 | return rc; | ||
584 | free: | ||
585 | kfree_skb(nskb); | ||
586 | goto out; | ||
587 | } | ||
588 | |||
589 | int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) | ||
590 | { | ||
591 | int rc = -ENOBUFS; | ||
592 | struct sk_buff *nskb = llc_alloc_frame(); | ||
593 | |||
594 | if (nskb) { | ||
595 | struct llc_sock *llc = llc_sk(sk); | ||
596 | struct llc_sap *sap = llc->sap; | ||
597 | u8 f_bit = 1; | ||
598 | |||
599 | nskb->dev = llc->dev; | ||
600 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
601 | llc->daddr.lsap, LLC_PDU_RSP); | ||
602 | llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); | ||
603 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
604 | if (rc) | ||
605 | goto free; | ||
606 | llc_conn_send_pdu(sk, nskb); | ||
607 | } | ||
608 | out: | ||
609 | return rc; | ||
610 | free: | ||
611 | kfree_skb(nskb); | ||
612 | goto out; | ||
613 | } | ||
614 | |||
615 | int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
616 | { | ||
617 | int rc = -ENOBUFS; | ||
618 | struct sk_buff *nskb = llc_alloc_frame(); | ||
619 | |||
620 | if (nskb) { | ||
621 | u8 f_bit = 0; | ||
622 | struct llc_sock *llc = llc_sk(sk); | ||
623 | struct llc_sap *sap = llc->sap; | ||
624 | |||
625 | nskb->dev = llc->dev; | ||
626 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
627 | llc->daddr.lsap, LLC_PDU_RSP); | ||
628 | llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); | ||
629 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
630 | if (rc) | ||
631 | goto free; | ||
632 | llc_conn_send_pdu(sk, nskb); | ||
633 | } | ||
634 | out: | ||
635 | return rc; | ||
636 | free: | ||
637 | kfree_skb(nskb); | ||
638 | goto out; | ||
639 | } | ||
640 | |||
641 | int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb) | ||
642 | { | ||
643 | struct llc_sock *llc = llc_sk(sk); | ||
644 | |||
645 | if (!llc->remote_busy_flag) { | ||
646 | llc->remote_busy_flag = 1; | ||
647 | mod_timer(&llc->busy_state_timer.timer, | ||
648 | jiffies + llc->busy_state_timer.expire * HZ); | ||
649 | } | ||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
654 | { | ||
655 | int rc = -ENOBUFS; | ||
656 | struct sk_buff *nskb = llc_alloc_frame(); | ||
657 | |||
658 | if (nskb) { | ||
659 | struct llc_sock *llc = llc_sk(sk); | ||
660 | struct llc_sap *sap = llc->sap; | ||
661 | |||
662 | nskb->dev = llc->dev; | ||
663 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
664 | llc->daddr.lsap, LLC_PDU_RSP); | ||
665 | llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR); | ||
666 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
667 | if (rc) | ||
668 | goto free; | ||
669 | llc_conn_send_pdu(sk, nskb); | ||
670 | } | ||
671 | out: | ||
672 | return rc; | ||
673 | free: | ||
674 | kfree_skb(nskb); | ||
675 | goto out; | ||
676 | } | ||
677 | |||
678 | int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) | ||
679 | { | ||
680 | int rc = -ENOBUFS; | ||
681 | struct sk_buff *nskb = llc_alloc_frame(); | ||
682 | |||
683 | if (nskb) { | ||
684 | struct llc_sock *llc = llc_sk(sk); | ||
685 | struct llc_sap *sap = llc->sap; | ||
686 | |||
687 | nskb->dev = llc->dev; | ||
688 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
689 | llc->daddr.lsap, LLC_PDU_CMD); | ||
690 | llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR); | ||
691 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
692 | if (rc) | ||
693 | goto free; | ||
694 | llc_conn_send_pdu(sk, nskb); | ||
695 | } | ||
696 | out: | ||
697 | return rc; | ||
698 | free: | ||
699 | kfree_skb(nskb); | ||
700 | goto out; | ||
701 | } | ||
702 | |||
703 | int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) | ||
704 | { | ||
705 | int rc = -ENOBUFS; | ||
706 | struct sk_buff *nskb = llc_alloc_frame(); | ||
707 | |||
708 | if (nskb) { | ||
709 | struct llc_sock *llc = llc_sk(sk); | ||
710 | struct llc_sap *sap = llc->sap; | ||
711 | u8 f_bit = 1; | ||
712 | |||
713 | nskb->dev = llc->dev; | ||
714 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
715 | llc->daddr.lsap, LLC_PDU_RSP); | ||
716 | llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); | ||
717 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
718 | if (rc) | ||
719 | goto free; | ||
720 | llc_conn_send_pdu(sk, nskb); | ||
721 | } | ||
722 | out: | ||
723 | return rc; | ||
724 | free: | ||
725 | kfree_skb(nskb); | ||
726 | goto out; | ||
727 | } | ||
728 | |||
729 | int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) | ||
730 | { | ||
731 | int rc = -ENOBUFS; | ||
732 | struct sk_buff *nskb = llc_alloc_frame(); | ||
733 | |||
734 | if (nskb) { | ||
735 | struct llc_sock *llc = llc_sk(sk); | ||
736 | struct llc_sap *sap = llc->sap; | ||
737 | u8 f_bit = 1; | ||
738 | |||
739 | nskb->dev = llc->dev; | ||
740 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
741 | llc->daddr.lsap, LLC_PDU_RSP); | ||
742 | llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); | ||
743 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
744 | if (rc) | ||
745 | goto free; | ||
746 | llc_conn_send_pdu(sk, nskb); | ||
747 | } | ||
748 | out: | ||
749 | return rc; | ||
750 | free: | ||
751 | kfree_skb(nskb); | ||
752 | goto out; | ||
753 | } | ||
754 | |||
755 | int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
756 | { | ||
757 | int rc = -ENOBUFS; | ||
758 | struct sk_buff *nskb = llc_alloc_frame(); | ||
759 | |||
760 | if (nskb) { | ||
761 | struct llc_sock *llc = llc_sk(sk); | ||
762 | struct llc_sap *sap = llc->sap; | ||
763 | |||
764 | nskb->dev = llc->dev; | ||
765 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
766 | llc->daddr.lsap, LLC_PDU_RSP); | ||
767 | llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); | ||
768 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
769 | if (rc) | ||
770 | goto free; | ||
771 | llc_conn_send_pdu(sk, nskb); | ||
772 | } | ||
773 | out: | ||
774 | return rc; | ||
775 | free: | ||
776 | kfree_skb(nskb); | ||
777 | goto out; | ||
778 | } | ||
779 | |||
780 | int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) | ||
781 | { | ||
782 | int rc = -ENOBUFS; | ||
783 | struct sk_buff *nskb = llc_alloc_frame(); | ||
784 | |||
785 | if (nskb) { | ||
786 | struct llc_sock *llc = llc_sk(sk); | ||
787 | struct llc_sap *sap = llc->sap; | ||
788 | |||
789 | nskb->dev = llc->dev; | ||
790 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
791 | llc->daddr.lsap, LLC_PDU_RSP); | ||
792 | llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); | ||
793 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
794 | if (rc) | ||
795 | goto free; | ||
796 | llc_conn_send_pdu(sk, nskb); | ||
797 | } | ||
798 | out: | ||
799 | return rc; | ||
800 | free: | ||
801 | kfree_skb(nskb); | ||
802 | goto out; | ||
803 | } | ||
804 | |||
805 | void llc_conn_set_p_flag(struct sock *sk, u8 value) | ||
806 | { | ||
807 | int state_changed = llc_sk(sk)->p_flag && !value; | ||
808 | |||
809 | llc_sk(sk)->p_flag = value; | ||
810 | |||
811 | if (state_changed) | ||
812 | sk->sk_state_change(sk); | ||
813 | } | ||
814 | |||
815 | int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) | ||
816 | { | ||
817 | int rc = -ENOBUFS; | ||
818 | struct sk_buff *nskb = llc_alloc_frame(); | ||
819 | struct llc_sock *llc = llc_sk(sk); | ||
820 | |||
821 | if (nskb) { | ||
822 | struct llc_sap *sap = llc->sap; | ||
823 | u8 *dmac = llc->daddr.mac; | ||
824 | |||
825 | if (llc->dev->flags & IFF_LOOPBACK) | ||
826 | dmac = llc->dev->dev_addr; | ||
827 | nskb->dev = llc->dev; | ||
828 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
829 | llc->daddr.lsap, LLC_PDU_CMD); | ||
830 | llc_pdu_init_as_sabme_cmd(nskb, 1); | ||
831 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, dmac); | ||
832 | if (rc) | ||
833 | goto free; | ||
834 | llc_conn_send_pdu(sk, nskb); | ||
835 | llc_conn_set_p_flag(sk, 1); | ||
836 | } | ||
837 | out: | ||
838 | return rc; | ||
839 | free: | ||
840 | kfree_skb(nskb); | ||
841 | goto out; | ||
842 | } | ||
843 | |||
844 | int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) | ||
845 | { | ||
846 | u8 f_bit; | ||
847 | int rc = -ENOBUFS; | ||
848 | struct sk_buff *nskb = llc_alloc_frame(); | ||
849 | |||
850 | llc_pdu_decode_pf_bit(skb, &f_bit); | ||
851 | if (nskb) { | ||
852 | struct llc_sock *llc = llc_sk(sk); | ||
853 | struct llc_sap *sap = llc->sap; | ||
854 | |||
855 | nskb->dev = llc->dev; | ||
856 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, | ||
857 | llc->daddr.lsap, LLC_PDU_RSP); | ||
858 | llc_pdu_init_as_ua_rsp(nskb, f_bit); | ||
859 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
860 | if (rc) | ||
861 | goto free; | ||
862 | llc_conn_send_pdu(sk, nskb); | ||
863 | } | ||
864 | out: | ||
865 | return rc; | ||
866 | free: | ||
867 | kfree_skb(nskb); | ||
868 | goto out; | ||
869 | } | ||
870 | |||
871 | int llc_conn_ac_set_s_flag_0(struct sock *sk, struct sk_buff *skb) | ||
872 | { | ||
873 | llc_sk(sk)->s_flag = 0; | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | int llc_conn_ac_set_s_flag_1(struct sock *sk, struct sk_buff *skb) | ||
878 | { | ||
879 | llc_sk(sk)->s_flag = 1; | ||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb) | ||
884 | { | ||
885 | struct llc_sock *llc = llc_sk(sk); | ||
886 | |||
887 | llc_conn_set_p_flag(sk, 1); | ||
888 | mod_timer(&llc->pf_cycle_timer.timer, | ||
889 | jiffies + llc->pf_cycle_timer.expire * HZ); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | /** | ||
894 | * llc_conn_ac_send_ack_if_needed - check if ack is needed | ||
895 | * @sk: current connection structure | ||
896 | * @skb: current event | ||
897 | * | ||
898 | * Checks number of received PDUs which have not been acknowledged, yet, | ||
899 | * If number of them reaches to "npta"(Number of PDUs To Acknowledge) then | ||
900 | * sends an RR response as acknowledgement for them. Returns 0 for | ||
901 | * success, 1 otherwise. | ||
902 | */ | ||
903 | int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb) | ||
904 | { | ||
905 | u8 pf_bit; | ||
906 | struct llc_sock *llc = llc_sk(sk); | ||
907 | |||
908 | llc_pdu_decode_pf_bit(skb, &pf_bit); | ||
909 | llc->ack_pf |= pf_bit & 1; | ||
910 | if (!llc->ack_must_be_send) { | ||
911 | llc->first_pdu_Ns = llc->vR; | ||
912 | llc->ack_must_be_send = 1; | ||
913 | llc->ack_pf = pf_bit & 1; | ||
914 | } | ||
915 | if (((llc->vR - llc->first_pdu_Ns + 129) % 128) >= llc->npta) { | ||
916 | llc_conn_ac_send_rr_rsp_f_set_ackpf(sk, skb); | ||
917 | llc->ack_must_be_send = 0; | ||
918 | llc->ack_pf = 0; | ||
919 | llc_conn_ac_inc_npta_value(sk, skb); | ||
920 | } | ||
921 | return 0; | ||
922 | } | ||
923 | |||
924 | /** | ||
925 | * llc_conn_ac_rst_sendack_flag - resets ack_must_be_send flag | ||
926 | * @sk: current connection structure | ||
927 | * @skb: current event | ||
928 | * | ||
929 | * This action resets ack_must_be_send flag of given connection, this flag | ||
930 | * indicates if there is any PDU which has not been acknowledged yet. | ||
931 | * Returns 0 for success, 1 otherwise. | ||
932 | */ | ||
933 | int llc_conn_ac_rst_sendack_flag(struct sock *sk, struct sk_buff *skb) | ||
934 | { | ||
935 | llc_sk(sk)->ack_must_be_send = llc_sk(sk)->ack_pf = 0; | ||
936 | return 0; | ||
937 | } | ||
938 | |||
939 | /** | ||
940 | * llc_conn_ac_send_i_rsp_f_set_ackpf - acknowledge received PDUs | ||
941 | * @sk: current connection structure | ||
942 | * @skb: current event | ||
943 | * | ||
944 | * Sends an I response PDU with f-bit set to ack_pf flag as acknowledge to | ||
945 | * all received PDUs which have not been acknowledged, yet. ack_pf flag is | ||
946 | * set to one if one PDU with p-bit set to one is received. Returns 0 for | ||
947 | * success, 1 otherwise. | ||
948 | */ | ||
949 | static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, | ||
950 | struct sk_buff *skb) | ||
951 | { | ||
952 | int rc; | ||
953 | struct llc_sock *llc = llc_sk(sk); | ||
954 | struct llc_sap *sap = llc->sap; | ||
955 | |||
956 | llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap, | ||
957 | llc->daddr.lsap, LLC_PDU_RSP); | ||
958 | llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR); | ||
959 | rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); | ||
960 | if (!rc) { | ||
961 | llc_conn_send_pdu(sk, skb); | ||
962 | llc_conn_ac_inc_vs_by_1(sk, skb); | ||
963 | } | ||
964 | return rc; | ||
965 | } | ||
966 | |||
967 | /** | ||
968 | * llc_conn_ac_send_i_as_ack - sends an I-format PDU to acknowledge rx PDUs | ||
969 | * @sk: current connection structure. | ||
970 | * @skb: current event. | ||
971 | * | ||
972 | * This action sends an I-format PDU as acknowledge to received PDUs which | ||
973 | * have not been acknowledged, yet, if there is any. By using of this | ||
974 | * action number of acknowledgements decreases, this technic is called | ||
975 | * piggy backing. Returns 0 for success, 1 otherwise. | ||
976 | */ | ||
977 | int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb) | ||
978 | { | ||
979 | struct llc_sock *llc = llc_sk(sk); | ||
980 | |||
981 | if (llc->ack_must_be_send) { | ||
982 | llc_conn_ac_send_i_rsp_f_set_ackpf(sk, skb); | ||
983 | llc->ack_must_be_send = 0 ; | ||
984 | llc->ack_pf = 0; | ||
985 | } else | ||
986 | llc_conn_ac_send_i_cmd_p_set_0(sk, skb); | ||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | /** | ||
991 | * llc_conn_ac_send_rr_rsp_f_set_ackpf - ack all rx PDUs not yet acked | ||
992 | * @sk: current connection structure. | ||
993 | * @skb: current event. | ||
994 | * | ||
995 | * This action sends an RR response with f-bit set to ack_pf flag as | ||
996 | * acknowledge to all received PDUs which have not been acknowledged, yet, | ||
997 | * if there is any. ack_pf flag indicates if a PDU has been received with | ||
998 | * p-bit set to one. Returns 0 for success, 1 otherwise. | ||
999 | */ | ||
1000 | static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, | ||
1001 | struct sk_buff *skb) | ||
1002 | { | ||
1003 | int rc = -ENOBUFS; | ||
1004 | struct sk_buff *nskb = llc_alloc_frame(); | ||
1005 | |||
1006 | if (nskb) { | ||
1007 | struct llc_sock *llc = llc_sk(sk); | ||
1008 | struct llc_sap *sap = llc->sap; | ||
1009 | |||
1010 | nskb->dev = llc->dev; | ||
1011 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, | ||
1012 | llc->daddr.lsap, LLC_PDU_RSP); | ||
1013 | llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR); | ||
1014 | rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); | ||
1015 | if (rc) | ||
1016 | goto free; | ||
1017 | llc_conn_send_pdu(sk, nskb); | ||
1018 | } | ||
1019 | out: | ||
1020 | return rc; | ||
1021 | free: | ||
1022 | kfree_skb(nskb); | ||
1023 | goto out; | ||
1024 | } | ||
1025 | |||
1026 | /** | ||
1027 | * llc_conn_ac_inc_npta_value - tries to make value of npta greater | ||
1028 | * @sk: current connection structure. | ||
1029 | * @skb: current event. | ||
1030 | * | ||
1031 | * After "inc_cntr" times calling of this action, "npta" increase by one. | ||
1032 | * this action tries to make vale of "npta" greater as possible; number of | ||
1033 | * acknowledgements decreases by increasing of "npta". Returns 0 for | ||
1034 | * success, 1 otherwise. | ||
1035 | */ | ||
1036 | static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb) | ||
1037 | { | ||
1038 | struct llc_sock *llc = llc_sk(sk); | ||
1039 | |||
1040 | if (!llc->inc_cntr) { | ||
1041 | llc->dec_step = 0; | ||
1042 | llc->dec_cntr = llc->inc_cntr = 2; | ||
1043 | ++llc->npta; | ||
1044 | if (llc->npta > 127) | ||
1045 | llc->npta = 127 ; | ||
1046 | } else | ||
1047 | --llc->inc_cntr; | ||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | /** | ||
1052 | * llc_conn_ac_adjust_npta_by_rr - decreases "npta" by one | ||
1053 | * @sk: current connection structure. | ||
1054 | * @skb: current event. | ||
1055 | * | ||
1056 | * After receiving "dec_cntr" times RR command, this action decreases | ||
1057 | * "npta" by one. Returns 0 for success, 1 otherwise. | ||
1058 | */ | ||
1059 | int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb) | ||
1060 | { | ||
1061 | struct llc_sock *llc = llc_sk(sk); | ||
1062 | |||
1063 | if (!llc->connect_step && !llc->remote_busy_flag) { | ||
1064 | if (!llc->dec_step) { | ||
1065 | if (!llc->dec_cntr) { | ||
1066 | llc->inc_cntr = llc->dec_cntr = 2; | ||
1067 | if (llc->npta > 0) | ||
1068 | llc->npta = llc->npta - 1; | ||
1069 | } else | ||
1070 | llc->dec_cntr -=1; | ||
1071 | } | ||
1072 | } else | ||
1073 | llc->connect_step = 0 ; | ||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | /** | ||
1078 | * llc_conn_ac_adjust_npta_by_rnr - decreases "npta" by one | ||
1079 | * @sk: current connection structure. | ||
1080 | * @skb: current event. | ||
1081 | * | ||
1082 | * After receiving "dec_cntr" times RNR command, this action decreases | ||
1083 | * "npta" by one. Returns 0 for success, 1 otherwise. | ||
1084 | */ | ||
1085 | int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb) | ||
1086 | { | ||
1087 | struct llc_sock *llc = llc_sk(sk); | ||
1088 | |||
1089 | if (llc->remote_busy_flag) | ||
1090 | if (!llc->dec_step) { | ||
1091 | if (!llc->dec_cntr) { | ||
1092 | llc->inc_cntr = llc->dec_cntr = 2; | ||
1093 | if (llc->npta > 0) | ||
1094 | --llc->npta; | ||
1095 | } else | ||
1096 | --llc->dec_cntr; | ||
1097 | } | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1102 | * llc_conn_ac_dec_tx_win_size - decreases tx window size | ||
1103 | * @sk: current connection structure. | ||
1104 | * @skb: current event. | ||
1105 | * | ||
1106 | * After receiving of a REJ command or response, transmit window size is | ||
1107 | * decreased by number of PDUs which are outstanding yet. Returns 0 for | ||
1108 | * success, 1 otherwise. | ||
1109 | */ | ||
1110 | int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb) | ||
1111 | { | ||
1112 | struct llc_sock *llc = llc_sk(sk); | ||
1113 | u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q); | ||
1114 | |||
1115 | llc->k -= unacked_pdu; | ||
1116 | if (llc->k < 2) | ||
1117 | llc->k = 2; | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | /** | ||
1122 | * llc_conn_ac_inc_tx_win_size - tx window size is inc by 1 | ||
1123 | * @sk: current connection structure. | ||
1124 | * @skb: current event. | ||
1125 | * | ||
1126 | * After receiving an RR response with f-bit set to one, transmit window | ||
1127 | * size is increased by one. Returns 0 for success, 1 otherwise. | ||
1128 | */ | ||
1129 | int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb) | ||
1130 | { | ||
1131 | struct llc_sock *llc = llc_sk(sk); | ||
1132 | |||
1133 | llc->k += 1; | ||
1134 | if (llc->k > 128) | ||
1135 | llc->k = 128 ; | ||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb) | ||
1140 | { | ||
1141 | struct llc_sock *llc = llc_sk(sk); | ||
1142 | |||
1143 | del_timer(&llc->pf_cycle_timer.timer); | ||
1144 | del_timer(&llc->ack_timer.timer); | ||
1145 | del_timer(&llc->rej_sent_timer.timer); | ||
1146 | del_timer(&llc->busy_state_timer.timer); | ||
1147 | llc->ack_must_be_send = 0; | ||
1148 | llc->ack_pf = 0; | ||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb) | ||
1153 | { | ||
1154 | struct llc_sock *llc = llc_sk(sk); | ||
1155 | |||
1156 | del_timer(&llc->rej_sent_timer.timer); | ||
1157 | del_timer(&llc->pf_cycle_timer.timer); | ||
1158 | del_timer(&llc->busy_state_timer.timer); | ||
1159 | llc->ack_must_be_send = 0; | ||
1160 | llc->ack_pf = 0; | ||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1164 | int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb) | ||
1165 | { | ||
1166 | struct llc_sock *llc = llc_sk(sk); | ||
1167 | |||
1168 | mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ); | ||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb) | ||
1173 | { | ||
1174 | struct llc_sock *llc = llc_sk(sk); | ||
1175 | |||
1176 | mod_timer(&llc->rej_sent_timer.timer, | ||
1177 | jiffies + llc->rej_sent_timer.expire * HZ); | ||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk, | ||
1182 | struct sk_buff *skb) | ||
1183 | { | ||
1184 | struct llc_sock *llc = llc_sk(sk); | ||
1185 | |||
1186 | if (!timer_pending(&llc->ack_timer.timer)) | ||
1187 | mod_timer(&llc->ack_timer.timer, | ||
1188 | jiffies + llc->ack_timer.expire * HZ); | ||
1189 | return 0; | ||
1190 | } | ||
1191 | |||
1192 | int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb) | ||
1193 | { | ||
1194 | del_timer(&llc_sk(sk)->ack_timer.timer); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb) | ||
1199 | { | ||
1200 | struct llc_sock *llc = llc_sk(sk); | ||
1201 | |||
1202 | del_timer(&llc->pf_cycle_timer.timer); | ||
1203 | llc_conn_set_p_flag(sk, 0); | ||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
1207 | int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb) | ||
1208 | { | ||
1209 | del_timer(&llc_sk(sk)->rej_sent_timer.timer); | ||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb) | ||
1214 | { | ||
1215 | int acked; | ||
1216 | u16 unacked = 0; | ||
1217 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
1218 | struct llc_sock *llc = llc_sk(sk); | ||
1219 | |||
1220 | llc->last_nr = PDU_SUPV_GET_Nr(pdu); | ||
1221 | acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked); | ||
1222 | /* On loopback we don't queue I frames in unack_pdu_q queue. */ | ||
1223 | if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) { | ||
1224 | llc->retry_count = 0; | ||
1225 | del_timer(&llc->ack_timer.timer); | ||
1226 | if (llc->failed_data_req) { | ||
1227 | /* already, we did not accept data from upper layer | ||
1228 | * (tx_window full or unacceptable state). Now, we | ||
1229 | * can send data and must inform to upper layer. | ||
1230 | */ | ||
1231 | llc->failed_data_req = 0; | ||
1232 | llc_conn_ac_data_confirm(sk, skb); | ||
1233 | } | ||
1234 | if (unacked) | ||
1235 | mod_timer(&llc->ack_timer.timer, | ||
1236 | jiffies + llc->ack_timer.expire * HZ); | ||
1237 | } else if (llc->failed_data_req) { | ||
1238 | u8 f_bit; | ||
1239 | |||
1240 | llc_pdu_decode_pf_bit(skb, &f_bit); | ||
1241 | if (f_bit == 1) { | ||
1242 | llc->failed_data_req = 0; | ||
1243 | llc_conn_ac_data_confirm(sk, skb); | ||
1244 | } | ||
1245 | } | ||
1246 | return 0; | ||
1247 | } | ||
1248 | |||
1249 | int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb) | ||
1250 | { | ||
1251 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
1252 | |||
1253 | if (LLC_PDU_IS_RSP(pdu)) { | ||
1254 | u8 f_bit; | ||
1255 | |||
1256 | llc_pdu_decode_pf_bit(skb, &f_bit); | ||
1257 | if (f_bit) { | ||
1258 | llc_conn_set_p_flag(sk, 0); | ||
1259 | llc_conn_ac_stop_p_timer(sk, skb); | ||
1260 | } | ||
1261 | } | ||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | int llc_conn_ac_set_data_flag_2(struct sock *sk, struct sk_buff *skb) | ||
1266 | { | ||
1267 | llc_sk(sk)->data_flag = 2; | ||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | int llc_conn_ac_set_data_flag_0(struct sock *sk, struct sk_buff *skb) | ||
1272 | { | ||
1273 | llc_sk(sk)->data_flag = 0; | ||
1274 | return 0; | ||
1275 | } | ||
1276 | |||
1277 | int llc_conn_ac_set_data_flag_1(struct sock *sk, struct sk_buff *skb) | ||
1278 | { | ||
1279 | llc_sk(sk)->data_flag = 1; | ||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk, | ||
1284 | struct sk_buff *skb) | ||
1285 | { | ||
1286 | if (!llc_sk(sk)->data_flag) | ||
1287 | llc_sk(sk)->data_flag = 1; | ||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | int llc_conn_ac_set_p_flag_0(struct sock *sk, struct sk_buff *skb) | ||
1292 | { | ||
1293 | llc_conn_set_p_flag(sk, 0); | ||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | static int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb) | ||
1298 | { | ||
1299 | llc_conn_set_p_flag(sk, 1); | ||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct sk_buff *skb) | ||
1304 | { | ||
1305 | llc_sk(sk)->remote_busy_flag = 0; | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct sk_buff *skb) | ||
1310 | { | ||
1311 | llc_sk(sk)->cause_flag = 0; | ||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct sk_buff *skb) | ||
1316 | { | ||
1317 | llc_sk(sk)->cause_flag = 1; | ||
1318 | return 0; | ||
1319 | } | ||
1320 | |||
1321 | int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct sk_buff *skb) | ||
1322 | { | ||
1323 | llc_sk(sk)->retry_count = 0; | ||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk, struct sk_buff *skb) | ||
1328 | { | ||
1329 | llc_sk(sk)->retry_count++; | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | int llc_conn_ac_set_vr_0(struct sock *sk, struct sk_buff *skb) | ||
1334 | { | ||
1335 | llc_sk(sk)->vR = 0; | ||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct sk_buff *skb) | ||
1340 | { | ||
1341 | llc_sk(sk)->vR = PDU_GET_NEXT_Vr(llc_sk(sk)->vR); | ||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | int llc_conn_ac_set_vs_0(struct sock *sk, struct sk_buff *skb) | ||
1346 | { | ||
1347 | llc_sk(sk)->vS = 0; | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb) | ||
1352 | { | ||
1353 | llc_sk(sk)->vS = llc_sk(sk)->last_nr; | ||
1354 | return 0; | ||
1355 | } | ||
1356 | |||
1357 | int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) | ||
1358 | { | ||
1359 | llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128; | ||
1360 | return 0; | ||
1361 | } | ||
1362 | |||
1363 | void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) | ||
1364 | { | ||
1365 | struct sock *sk = (struct sock *)timeout_data; | ||
1366 | struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); | ||
1367 | |||
1368 | bh_lock_sock(sk); | ||
1369 | if (skb) { | ||
1370 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
1371 | |||
1372 | skb->sk = sk; | ||
1373 | ev->type = LLC_CONN_EV_TYPE_P_TMR; | ||
1374 | llc_process_tmr_ev(sk, skb); | ||
1375 | } | ||
1376 | bh_unlock_sock(sk); | ||
1377 | } | ||
1378 | |||
1379 | void llc_conn_busy_tmr_cb(unsigned long timeout_data) | ||
1380 | { | ||
1381 | struct sock *sk = (struct sock *)timeout_data; | ||
1382 | struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); | ||
1383 | |||
1384 | bh_lock_sock(sk); | ||
1385 | if (skb) { | ||
1386 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
1387 | |||
1388 | skb->sk = sk; | ||
1389 | ev->type = LLC_CONN_EV_TYPE_BUSY_TMR; | ||
1390 | llc_process_tmr_ev(sk, skb); | ||
1391 | } | ||
1392 | bh_unlock_sock(sk); | ||
1393 | } | ||
1394 | |||
1395 | void llc_conn_ack_tmr_cb(unsigned long timeout_data) | ||
1396 | { | ||
1397 | struct sock* sk = (struct sock *)timeout_data; | ||
1398 | struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); | ||
1399 | |||
1400 | bh_lock_sock(sk); | ||
1401 | if (skb) { | ||
1402 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
1403 | |||
1404 | skb->sk = sk; | ||
1405 | ev->type = LLC_CONN_EV_TYPE_ACK_TMR; | ||
1406 | llc_process_tmr_ev(sk, skb); | ||
1407 | } | ||
1408 | bh_unlock_sock(sk); | ||
1409 | } | ||
1410 | |||
1411 | void llc_conn_rej_tmr_cb(unsigned long timeout_data) | ||
1412 | { | ||
1413 | struct sock *sk = (struct sock *)timeout_data; | ||
1414 | struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); | ||
1415 | |||
1416 | bh_lock_sock(sk); | ||
1417 | if (skb) { | ||
1418 | struct llc_conn_state_ev *ev = llc_conn_ev(skb); | ||
1419 | |||
1420 | skb->sk = sk; | ||
1421 | ev->type = LLC_CONN_EV_TYPE_REJ_TMR; | ||
1422 | llc_process_tmr_ev(sk, skb); | ||
1423 | } | ||
1424 | bh_unlock_sock(sk); | ||
1425 | } | ||
1426 | |||
1427 | int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb) | ||
1428 | { | ||
1429 | llc_sk(sk)->X = llc_sk(sk)->vS; | ||
1430 | llc_conn_ac_set_vs_nr(sk, skb); | ||
1431 | return 0; | ||
1432 | } | ||
1433 | |||
1434 | int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb) | ||
1435 | { | ||
1436 | struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); | ||
1437 | u8 nr = PDU_SUPV_GET_Nr(pdu); | ||
1438 | |||
1439 | if (llc_circular_between(llc_sk(sk)->vS, nr, llc_sk(sk)->X)) | ||
1440 | llc_conn_ac_set_vs_nr(sk, skb); | ||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | /* | ||
1445 | * Non-standard actions; these not contained in IEEE specification; for | ||
1446 | * our own usage | ||
1447 | */ | ||
1448 | /** | ||
1449 | * llc_conn_disc - removes connection from SAP list and frees it | ||
1450 | * @sk: closed connection | ||
1451 | * @skb: occurred event | ||
1452 | */ | ||
1453 | int llc_conn_disc(struct sock *sk, struct sk_buff *skb) | ||
1454 | { | ||
1455 | /* FIXME: this thing seems to want to die */ | ||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | /** | ||
1460 | * llc_conn_reset - resets connection | ||
1461 | * @sk : reseting connection. | ||
1462 | * @skb: occurred event. | ||
1463 | * | ||
1464 | * Stop all timers, empty all queues and reset all flags. | ||
1465 | */ | ||
1466 | int llc_conn_reset(struct sock *sk, struct sk_buff *skb) | ||
1467 | { | ||
1468 | llc_sk_reset(sk); | ||
1469 | return 0; | ||
1470 | } | ||
1471 | |||
1472 | /** | ||
1473 | * llc_circular_between - designates that b is between a and c or not | ||
1474 | * @a: lower bound | ||
1475 | * @b: element to see if is between a and b | ||
1476 | * @c: upper bound | ||
1477 | * | ||
1478 | * This function designates that b is between a and c or not (for example, | ||
1479 | * 0 is between 127 and 1). Returns 1 if b is between a and c, 0 | ||
1480 | * otherwise. | ||
1481 | */ | ||
1482 | u8 llc_circular_between(u8 a, u8 b, u8 c) | ||
1483 | { | ||
1484 | b = b - a; | ||
1485 | c = c - a; | ||
1486 | return b <= c; | ||
1487 | } | ||
1488 | |||
1489 | /** | ||
1490 | * llc_process_tmr_ev - timer backend | ||
1491 | * @sk: active connection | ||
1492 | * @skb: occurred event | ||
1493 | * | ||
1494 | * This function is called from timer callback functions. When connection | ||
1495 | * is busy (during sending a data frame) timer expiration event must be | ||
1496 | * queued. Otherwise this event can be sent to connection state machine. | ||
1497 | * Queued events will process by llc_backlog_rcv function after sending | ||
1498 | * data frame. | ||
1499 | */ | ||
1500 | static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb) | ||
1501 | { | ||
1502 | if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) { | ||
1503 | printk(KERN_WARNING "%s: timer called on closed connection\n", | ||
1504 | __FUNCTION__); | ||
1505 | kfree_skb(skb); | ||
1506 | } else { | ||
1507 | if (!sock_owned_by_user(sk)) | ||
1508 | llc_conn_state_process(sk, skb); | ||
1509 | else { | ||
1510 | llc_set_backlog_type(skb, LLC_EVENT); | ||
1511 | sk_add_backlog(sk, skb); | ||
1512 | } | ||
1513 | } | ||
1514 | } | ||