1/*
2 * llc_c_ev.c - Connection component state transition event qualifiers
3 *
4 * A 'state' consists of a number of possible event matching functions,
5 * the actions associated with each being executed when that event is
6 * matched; a 'state machine' accepts events in a serial fashion from an
7 * event queue. Each event is passed to each successive event matching
8 * function until a match is made (the event matching function returns
9 * success, or '0') or the list of event matching functions is exhausted.
10 * If a match is made, the actions associated with the event are executed
11 * and the state is changed to that event's transition state. Before some
12 * events are recognized, even after a match has been made, a certain
13 * number of 'event qualifier' functions must also be executed. If these
14 * all execute successfully, then the event is finally executed.
15 *
16 * These event functions must return 0 for success, to show a matched
17 * event, of 1 if the event does not match. Event qualifier functions
18 * must return a 0 for success or a non-zero for failure. Each function
19 * is simply responsible for verifying one single thing and returning
20 * either a success or failure.
21 *
22 * All of followed event functions are described in 802.2 LLC Protocol
23 * standard document except two functions that we added that will explain
24 * in their comments, at below.
25 *
26 * Copyright (c) 1997 by Procom Technology, Inc.
27 * 		 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
28 *
29 * This program can be redistributed or modified under the terms of the
30 * GNU General Public License as published by the Free Software Foundation.
31 * This program is distributed without any warranty or implied warranty
32 * of merchantability or fitness for a particular purpose.
33 *
34 * See the GNU General Public License for more details.
35 */
36#include <linux/netdevice.h>
37#include <net/llc_conn.h>
38#include <net/llc_sap.h>
39#include <net/sock.h>
40#include <net/llc_c_ac.h>
41#include <net/llc_c_ev.h>
42#include <net/llc_pdu.h>
43
44#define dprintk(args...) printk(KERN_DEBUG args)
45
46/**
47 *	llc_util_ns_inside_rx_window - check if sequence number is in rx window
48 *	@ns: sequence number of received pdu.
49 *	@vr: sequence number which receiver expects to receive.
50 *	@rw: receive window size of receiver.
51 *
52 *	Checks if sequence number of received PDU is in range of receive
53 *	window. Returns 0 for success, 1 otherwise
54 */
55static u16 llc_util_ns_inside_rx_window(u8 ns, u8 vr, u8 rw)
56{
57	return !llc_circular_between(vr, ns,
58				     (vr + rw - 1) % LLC_2_SEQ_NBR_MODULO);
59}
60
61/**
62 *	llc_util_nr_inside_tx_window - check if sequence number is in tx window
63 *	@sk: current connection.
64 *	@nr: N(R) of received PDU.
65 *
66 *	This routine checks if N(R) of received PDU is in range of transmit
67 *	window; on the other hand checks if received PDU acknowledges some
68 *	outstanding PDUs that are in transmit window. Returns 0 for success, 1
69 *	otherwise.
70 */
71static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
72{
73	u8 nr1, nr2;
74	struct sk_buff *skb;
75	struct llc_pdu_sn *pdu;
76	struct llc_sock *llc = llc_sk(sk);
77	int rc = 0;
78
79	if (llc->dev->flags & IFF_LOOPBACK)
80		goto out;
81	rc = 1;
82	if (skb_queue_empty(&llc->pdu_unack_q))
83		goto out;
84	skb = skb_peek(&llc->pdu_unack_q);
85	pdu = llc_pdu_sn_hdr(skb);
86	nr1 = LLC_I_GET_NS(pdu);
87	skb = skb_peek_tail(&llc->pdu_unack_q);
88	pdu = llc_pdu_sn_hdr(skb);
89	nr2 = LLC_I_GET_NS(pdu);
90	rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO);
91out:
92	return rc;
93}
94
95int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
96{
97	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
98
99	return ev->prim == LLC_CONN_PRIM &&
100	       ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
101}
102
103int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
104{
105	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
106
107	return ev->prim == LLC_DATA_PRIM &&
108	       ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
109}
110
111int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
112{
113	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
114
115	return ev->prim == LLC_DISC_PRIM &&
116	       ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
117}
118
119int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
120{
121	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
122
123	return ev->prim == LLC_RESET_PRIM &&
124	       ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
125}
126
127int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
128{
129	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
130
131	return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
132	       ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
133}
134
135int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
136{
137	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
138
139	return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
140	       ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
141}
142
143int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb)
144{
145	return 1;
146}
147
148int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
149{
150	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
151
152	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
153	       LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1;
154}
155
156int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
157{
158	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
159
160	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
161	       LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1;
162}
163
164int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
165{
166	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
167
168	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
169	       LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1;
170}
171
172int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
173{
174	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
175
176	return llc_conn_space(sk, skb) &&
177	       LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
178	       LLC_I_PF_IS_0(pdu) &&
179	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
180}
181
182int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
183{
184	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
185
186	return llc_conn_space(sk, skb) &&
187	       LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
188	       LLC_I_PF_IS_1(pdu) &&
189	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
190}
191
192int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
193					      struct sk_buff *skb)
194{
195	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
196	const u8 vr = llc_sk(sk)->vR;
197	const u8 ns = LLC_I_GET_NS(pdu);
198
199	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
200	       LLC_I_PF_IS_0(pdu) && ns != vr &&
201	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
202}
203
204int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
205					      struct sk_buff *skb)
206{
207	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
208	const u8 vr = llc_sk(sk)->vR;
209	const u8 ns = LLC_I_GET_NS(pdu);
210
211	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
212	       LLC_I_PF_IS_1(pdu) && ns != vr &&
213	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
214}
215
216int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
217					     struct sk_buff *skb)
218{
219	const struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb);
220	const u8 vr = llc_sk(sk)->vR;
221	const u8 ns = LLC_I_GET_NS(pdu);
222	const u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
223		ns != vr &&
224		 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
225	if (!rc)
226		dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
227			__FUNCTION__, llc_sk(sk)->state, ns, vr);
228	return rc;
229}
230
231int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
232{
233	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
234
235	return llc_conn_space(sk, skb) &&
236	       LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
237	       LLC_I_PF_IS_0(pdu) &&
238	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
239}
240
241int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
242{
243	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
244
245	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
246	       LLC_I_PF_IS_1(pdu) &&
247	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
248}
249
250int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
251{
252	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
253
254	return llc_conn_space(sk, skb) &&
255	       LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
256	       LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
257}
258
259int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
260					      struct sk_buff *skb)
261{
262	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
263	const u8 vr = llc_sk(sk)->vR;
264	const u8 ns = LLC_I_GET_NS(pdu);
265
266	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
267	       LLC_I_PF_IS_0(pdu) && ns != vr &&
268	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
269}
270
271int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
272					      struct sk_buff *skb)
273{
274	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
275	const u8 vr = llc_sk(sk)->vR;
276	const u8 ns = LLC_I_GET_NS(pdu);
277
278	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
279	       LLC_I_PF_IS_1(pdu) && ns != vr &&
280	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
281}
282
283int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
284					      struct sk_buff *skb)
285{
286	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
287	const u8 vr = llc_sk(sk)->vR;
288	const u8 ns = LLC_I_GET_NS(pdu);
289
290	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
291	       !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
292}
293
294int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
295					     struct sk_buff *skb)
296{
297	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
298	const u8 vr = llc_sk(sk)->vR;
299	const u8 ns = LLC_I_GET_NS(pdu);
300	const u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
301		ns != vr &&
302		 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
303	if (!rc)
304		dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
305			__FUNCTION__, llc_sk(sk)->state, ns, vr);
306	return rc;
307}
308
309int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
310{
311	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
312
313	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
314	       LLC_S_PF_IS_0(pdu) &&
315	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
316}
317
318int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
319{
320	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
321
322	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
323	       LLC_S_PF_IS_1(pdu) &&
324	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
325}
326
327int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
328{
329	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
330
331	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
332	       LLC_S_PF_IS_0(pdu) &&
333	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
334}
335
336int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
337{
338	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
339
340	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
341	       LLC_S_PF_IS_1(pdu) &&
342	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
343}
344
345int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
346{
347	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
348
349	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
350	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
351}
352
353int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
354{
355	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
356
357	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
358	       LLC_S_PF_IS_0(pdu) &&
359	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
360}
361
362int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
363{
364	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
365
366	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
367	       LLC_S_PF_IS_1(pdu) &&
368	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
369}
370
371int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
372{
373	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
374
375	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
376	       LLC_S_PF_IS_0(pdu) &&
377	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
378}
379
380int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
381{
382	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
383
384	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
385	       LLC_S_PF_IS_1(pdu) &&
386	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
387}
388
389int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
390{
391	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
392
393	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
394	       LLC_S_PF_IS_0(pdu) &&
395	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1;
396}
397
398int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
399{
400	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
401
402	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
403	       LLC_S_PF_IS_1(pdu) &&
404	       LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1;
405}
406
407int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
408{
409	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
410
411	return llc_conn_space(sk, skb) &&
412	       LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
413	       LLC_S_PF_IS_0(pdu) &&
414	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
415}
416
417int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
418{
419	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
420
421	return llc_conn_space(sk, skb) &&
422	       LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
423	       LLC_S_PF_IS_1(pdu) &&
424	       LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
425}
426
427int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
428{
429	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
430
431	return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
432	       LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1;
433}
434
435int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
436{
437	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
438
439	return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
440	       LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_UA ? 0 : 1;
441}
442
443int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
444{
445	u16 rc = 1;
446	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
447
448	if (LLC_PDU_IS_CMD(pdu)) {
449		if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
450			if (LLC_I_PF_IS_1(pdu))
451				rc = 0;
452		} else if (LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PF_IS_1(pdu))
453			rc = 0;
454	}
455	return rc;
456}
457
458int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
459{
460	u16 rc = 1;
461	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
462
463	if (LLC_PDU_IS_CMD(pdu)) {
464		if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
465			rc = 0;
466		else if (LLC_PDU_TYPE_IS_U(pdu))
467			switch (LLC_U_PDU_CMD(pdu)) {
468			case LLC_2_PDU_CMD_SABME:
469			case LLC_2_PDU_CMD_DISC:
470				rc = 0;
471				break;
472			}
473	}
474	return rc;
475}
476
477int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
478{
479	u16 rc = 1;
480	const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
481
482	if (LLC_PDU_IS_RSP(pdu)) {
483		if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
484			rc = 0;
485		else if (LLC_PDU_TYPE_IS_U(pdu))
486			switch (LLC_U_PDU_RSP(pdu)) {
487			case LLC_2_PDU_RSP_UA:
488			case LLC_2_PDU_RSP_DM:
489			case LLC_2_PDU_RSP_FRMR:
490				rc = 0;
491				break;
492			}
493	}
494
495	return rc;
496}
497
498int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
499					       struct sk_buff *skb)
500{
501	u16 rc = 1;
502	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
503	const u8 vs = llc_sk(sk)->vS;
504	const u8 nr = LLC_I_GET_NR(pdu);
505
506	if (LLC_PDU_IS_CMD(pdu) &&
507	    (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
508	    nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
509		dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
510			__FUNCTION__, llc_sk(sk)->state, vs, nr);
511		rc = 0;
512	}
513	return rc;
514}
515
516int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
517					       struct sk_buff *skb)
518{
519	u16 rc = 1;
520	const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
521	const u8 vs = llc_sk(sk)->vS;
522	const u8 nr = LLC_I_GET_NR(pdu);
523
524	if (LLC_PDU_IS_RSP(pdu) &&
525	    (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
526	    nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
527		rc = 0;
528		dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
529			__FUNCTION__, llc_sk(sk)->state, vs, nr);
530	}
531	return rc;
532}
533
534int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb)
535{
536	return 0;
537}
538
539int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb)
540{
541	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
542
543	return ev->type != LLC_CONN_EV_TYPE_P_TMR;
544}
545
546int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb)
547{
548	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
549
550	return ev->type != LLC_CONN_EV_TYPE_ACK_TMR;
551}
552
553int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb)
554{
555	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
556
557	return ev->type != LLC_CONN_EV_TYPE_REJ_TMR;
558}
559
560int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb)
561{
562	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
563
564	return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR;
565}
566
567int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb)
568{
569	return 1;
570}
571
572int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb)
573{
574	const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
575
576	return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
577	       ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1;
578}
579
580/* Event qualifier functions
581 *
582 * these functions simply verify the value of a state flag associated with
583 * the connection and return either a 0 for success or a non-zero value
584 * for not-success; verify the event is the type we expect
585 */
586int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, struct sk_buff *skb)
587{
588	return llc_sk(sk)->data_flag != 1;
589}
590
591int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, struct sk_buff *skb)
592{
593	return llc_sk(sk)->data_flag;
594}
595
596int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, struct sk_buff *skb)
597{
598	return llc_sk(sk)->data_flag != 2;
599}
600
601int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb)
602{
603	return llc_sk(sk)->p_flag != 1;
604}
605
606/**
607 *	conn_ev_qlfy_last_frame_eq_1 - checks if frame is last in tx window
608 *	@sk: current connection structure.
609 *	@skb: current event.
610 *
611 *	This function determines when frame which is sent, is last frame of
612 *	transmit window, if it is then this function return zero else return
613 *	one.  This function is used for sending last frame of transmit window
614 *	as I-format command with p-bit set to one. Returns 0 if frame is last
615 *	frame, 1 otherwise.
616 */
617int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, struct sk_buff *skb)
618{
619	return !(skb_queue_len(&llc_sk(sk)->pdu_unack_q) + 1 == llc_sk(sk)->k);
620}
621
622/**
623 *	conn_ev_qlfy_last_frame_eq_0 - checks if frame isn't last in tx window
624 *	@sk: current connection structure.
625 *	@skb: current event.
626 *
627 *	This function determines when frame which is sent, isn't last frame of
628 *	transmit window, if it isn't then this function return zero else return
629 *	one. Returns 0 if frame isn't last frame, 1 otherwise.
630 */
631int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, struct sk_buff *skb)
632{
633	return skb_queue_len(&llc_sk(sk)->pdu_unack_q) + 1 == llc_sk(sk)->k;
634}
635
636int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb)
637{
638	return llc_sk(sk)->p_flag;
639}
640
641int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb)
642{
643	u8 f_bit;
644
645	llc_pdu_decode_pf_bit(skb, &f_bit);
646	return llc_sk(sk)->p_flag == f_bit ? 0 : 1;
647}
648
649int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, struct sk_buff *skb)
650{
651	return llc_sk(sk)->remote_busy_flag;
652}
653
654int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, struct sk_buff *skb)
655{
656	return !llc_sk(sk)->remote_busy_flag;
657}
658
659int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, struct sk_buff *skb)
660{
661	return !(llc_sk(sk)->retry_count < llc_sk(sk)->n2);
662}
663
664int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, struct sk_buff *skb)
665{
666	return !(llc_sk(sk)->retry_count >= llc_sk(sk)->n2);
667}
668
669int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb)
670{
671	return !llc_sk(sk)->s_flag;
672}
673
674int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb)
675{
676	return llc_sk(sk)->s_flag;
677}
678
679int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, struct sk_buff *skb)
680{
681	return !llc_sk(sk)->cause_flag;
682}
683
684int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, struct sk_buff *skb)
685{
686	return llc_sk(sk)->cause_flag;
687}
688
689int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, struct sk_buff *skb)
690{
691	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
692
693	ev->status = LLC_STATUS_CONN;
694	return 0;
695}
696
697int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, struct sk_buff *skb)
698{
699	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
700
701	ev->status = LLC_STATUS_DISC;
702	return 0;
703}
704
705int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, struct sk_buff *skb)
706{
707	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
708
709	ev->status = LLC_STATUS_FAILED;
710	return 0;
711}
712
713int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
714					    struct sk_buff *skb)
715{
716	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
717
718	ev->status = LLC_STATUS_REMOTE_BUSY;
719	return 0;
720}
721
722int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, struct sk_buff *skb)
723{
724	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
725
726	ev->status = LLC_STATUS_REFUSE;
727	return 0;
728}
729
730int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, struct sk_buff *skb)
731{
732	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
733
734	ev->status = LLC_STATUS_CONFLICT;
735	return 0;
736}
737
738int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, struct sk_buff *skb)
739{
740	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
741
742	ev->status = LLC_STATUS_RESET_DONE;
743	return 0;
744}
745