xref: /linux/net/llc/llc_pdu.c (revision 90e63d5354951d37fa2b3b91e6f17b95d2bf9bee)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * llc_pdu.c - access to PDU internals
4  *
5  * Copyright (c) 1997 by Procom Technology, Inc.
6  *		 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7  */
8 
9 #include <linux/netdevice.h>
10 #include <net/llc_pdu.h>
11 
12 static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
13 static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
14 
15 void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
16 {
17 	llc_pdu_un_hdr(skb)->ssap |= pdu_type;
18 }
19 
20 /**
21  *	llc_pdu_set_pf_bit - sets poll/final bit in LLC header
22  *	@skb: Frame to set bit in
23  *	@bit_value: poll/final bit (0 or 1).
24  *
25  *	This function sets poll/final bit in LLC header (based on type of PDU).
26  *	in I or S pdus, p/f bit is right bit of fourth byte in header. in U
27  *	pdus p/f bit is fifth bit of third byte.
28  */
29 void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
30 {
31 	u8 pdu_type;
32 	struct llc_pdu_sn *pdu;
33 
34 	llc_pdu_decode_pdu_type(skb, &pdu_type);
35 	pdu = llc_pdu_sn_hdr(skb);
36 
37 	switch (pdu_type) {
38 	case LLC_PDU_TYPE_I:
39 	case LLC_PDU_TYPE_S:
40 		pdu->ctrl_2 = (pdu->ctrl_2 & 0xFE) | bit_value;
41 		break;
42 	case LLC_PDU_TYPE_U:
43 		pdu->ctrl_1 |= (pdu->ctrl_1 & 0xEF) | (bit_value << 4);
44 		break;
45 	}
46 }
47 
48 /**
49  *	llc_pdu_decode_pf_bit - extracs poll/final bit from LLC header
50  *	@skb: input skb that p/f bit must be extracted from it
51  *	@pf_bit: poll/final bit (0 or 1)
52  *
53  *	This function extracts poll/final bit from LLC header (based on type of
54  *	PDU). In I or S pdus, p/f bit is right bit of fourth byte in header. In
55  *	U pdus p/f bit is fifth bit of third byte.
56  */
57 void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
58 {
59 	u8 pdu_type;
60 	struct llc_pdu_sn *pdu;
61 
62 	llc_pdu_decode_pdu_type(skb, &pdu_type);
63 	pdu = llc_pdu_sn_hdr(skb);
64 
65 	switch (pdu_type) {
66 	case LLC_PDU_TYPE_I:
67 	case LLC_PDU_TYPE_S:
68 		*pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
69 		break;
70 	case LLC_PDU_TYPE_U:
71 		*pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
72 		break;
73 	}
74 }
75 
76 /**
77  *	llc_pdu_init_as_disc_cmd - Builds DISC PDU
78  *	@skb: Address of the skb to build
79  *	@p_bit: The P bit to set in the PDU
80  *
81  *	Builds a pdu frame as a DISC command.
82  */
83 void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
84 {
85 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
86 
87 	pdu->ctrl_1  = LLC_PDU_TYPE_U;
88 	pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC;
89 	pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
90 }
91 
92 /**
93  *	llc_pdu_init_as_i_cmd - builds I pdu
94  *	@skb: Address of the skb to build
95  *	@p_bit: The P bit to set in the PDU
96  *	@ns: The sequence number of the data PDU
97  *	@nr: The seq. number of the expected I PDU from the remote
98  *
99  *	Builds a pdu frame as an I command.
100  */
101 void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
102 {
103 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
104 
105 	pdu->ctrl_1  = LLC_PDU_TYPE_I;
106 	pdu->ctrl_2  = 0;
107 	pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); /* p/f bit */
108 	pdu->ctrl_1 |= (ns << 1) & 0xFE;   /* set N(S) in bits 2..8 */
109 	pdu->ctrl_2 |= (nr << 1) & 0xFE;   /* set N(R) in bits 10..16 */
110 }
111 
112 /**
113  *	llc_pdu_init_as_rej_cmd - builds REJ PDU
114  *	@skb: Address of the skb to build
115  *	@p_bit: The P bit to set in the PDU
116  *	@nr: The seq. number of the expected I PDU from the remote
117  *
118  *	Builds a pdu frame as a REJ command.
119  */
120 void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
121 {
122 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
123 
124 	pdu->ctrl_1  = LLC_PDU_TYPE_S;
125 	pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ;
126 	pdu->ctrl_2  = 0;
127 	pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
128 	pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
129 	pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
130 }
131 
132 /**
133  *	llc_pdu_init_as_rnr_cmd - builds RNR pdu
134  *	@skb: Address of the skb to build
135  *	@p_bit: The P bit to set in the PDU
136  *	@nr: The seq. number of the expected I PDU from the remote
137  *
138  *	Builds a pdu frame as an RNR command.
139  */
140 void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
141 {
142 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
143 
144 	pdu->ctrl_1  = LLC_PDU_TYPE_S;
145 	pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR;
146 	pdu->ctrl_2  = 0;
147 	pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
148 	pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
149 	pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
150 }
151 
152 /**
153  *	llc_pdu_init_as_rr_cmd - Builds RR pdu
154  *	@skb: Address of the skb to build
155  *	@p_bit: The P bit to set in the PDU
156  *	@nr: The seq. number of the expected I PDU from the remote
157  *
158  *	Builds a pdu frame as an RR command.
159  */
160 void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
161 {
162 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
163 
164 	pdu->ctrl_1  = LLC_PDU_TYPE_S;
165 	pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
166 	pdu->ctrl_2  = p_bit & LLC_S_PF_BIT_MASK;
167 	pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
168 	pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
169 }
170 
171 /**
172  *	llc_pdu_init_as_sabme_cmd - builds SABME pdu
173  *	@skb: Address of the skb to build
174  *	@p_bit: The P bit to set in the PDU
175  *
176  *	Builds a pdu frame as an SABME command.
177  */
178 void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
179 {
180 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
181 
182 	pdu->ctrl_1  = LLC_PDU_TYPE_U;
183 	pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME;
184 	pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
185 }
186 
187 /**
188  *	llc_pdu_init_as_dm_rsp - builds DM response pdu
189  *	@skb: Address of the skb to build
190  *	@f_bit: The F bit to set in the PDU
191  *
192  *	Builds a pdu frame as a DM response.
193  */
194 void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
195 {
196 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
197 
198 	pdu->ctrl_1  = LLC_PDU_TYPE_U;
199 	pdu->ctrl_1 |= LLC_2_PDU_RSP_DM;
200 	pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
201 }
202 
203 /**
204  *	llc_pdu_init_as_frmr_rsp - builds FRMR response PDU
205  *	@skb: Address of the frame to build
206  *	@prev_pdu: The rejected PDU frame
207  *	@f_bit: The F bit to set in the PDU
208  *	@vs: tx state vari value for the data link conn at the rejecting LLC
209  *	@vr: rx state var value for the data link conn at the rejecting LLC
210  *	@vzyxw: completely described in the IEEE Std 802.2 document (Pg 55)
211  *
212  *	Builds a pdu frame as a FRMR response.
213  */
214 void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
215 			      u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
216 {
217 	struct llc_frmr_info *frmr_info;
218 	u8 prev_pf = 0;
219 	u8 *ctrl;
220 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
221 
222 	pdu->ctrl_1  = LLC_PDU_TYPE_U;
223 	pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR;
224 	pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
225 
226 	frmr_info = (struct llc_frmr_info *)&pdu->ctrl_2;
227 	ctrl = (u8 *)&prev_pdu->ctrl_1;
228 	FRMR_INFO_SET_REJ_CNTRL(frmr_info,ctrl);
229 	FRMR_INFO_SET_Vs(frmr_info, vs);
230 	FRMR_INFO_SET_Vr(frmr_info, vr);
231 	prev_pf = llc_pdu_get_pf_bit(prev_pdu);
232 	FRMR_INFO_SET_C_R_BIT(frmr_info, prev_pf);
233 	FRMR_INFO_SET_INVALID_PDU_CTRL_IND(frmr_info, vzyxw);
234 	FRMR_INFO_SET_INVALID_PDU_INFO_IND(frmr_info, vzyxw);
235 	FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw);
236 	FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw);
237 	FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw);
238 	skb_put(skb, sizeof(struct llc_frmr_info));
239 }
240 
241 /**
242  *	llc_pdu_init_as_rr_rsp - builds RR response pdu
243  *	@skb: Address of the skb to build
244  *	@f_bit: The F bit to set in the PDU
245  *	@nr: The seq. number of the expected data PDU from the remote
246  *
247  *	Builds a pdu frame as an RR response.
248  */
249 void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
250 {
251 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
252 
253 	pdu->ctrl_1  = LLC_PDU_TYPE_S;
254 	pdu->ctrl_1 |= LLC_2_PDU_RSP_RR;
255 	pdu->ctrl_2  = 0;
256 	pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
257 	pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
258 	pdu->ctrl_2 |= (nr << 1) & 0xFE;  /* set N(R) in bits 10..16 */
259 }
260 
261 /**
262  *	llc_pdu_init_as_rej_rsp - builds REJ response pdu
263  *	@skb: Address of the skb to build
264  *	@f_bit: The F bit to set in the PDU
265  *	@nr: The seq. number of the expected data PDU from the remote
266  *
267  *	Builds a pdu frame as a REJ response.
268  */
269 void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
270 {
271 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
272 
273 	pdu->ctrl_1  = LLC_PDU_TYPE_S;
274 	pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ;
275 	pdu->ctrl_2  = 0;
276 	pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
277 	pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
278 	pdu->ctrl_2 |= (nr << 1) & 0xFE;  /* set N(R) in bits 10..16 */
279 }
280 
281 /**
282  *	llc_pdu_init_as_rnr_rsp - builds RNR response pdu
283  *	@skb: Address of the frame to build
284  *	@f_bit: The F bit to set in the PDU
285  *	@nr: The seq. number of the expected data PDU from the remote
286  *
287  *	Builds a pdu frame as an RNR response.
288  */
289 void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
290 {
291 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
292 
293 	pdu->ctrl_1  = LLC_PDU_TYPE_S;
294 	pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
295 	pdu->ctrl_2  = 0;
296 	pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
297 	pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
298 	pdu->ctrl_2 |= (nr << 1) & 0xFE;  /* set N(R) in bits 10..16 */
299 }
300 
301 /**
302  *	llc_pdu_init_as_ua_rsp - builds UA response pdu
303  *	@skb: Address of the frame to build
304  *	@f_bit: The F bit to set in the PDU
305  *
306  *	Builds a pdu frame as a UA response.
307  */
308 void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
309 {
310 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
311 
312 	pdu->ctrl_1  = LLC_PDU_TYPE_U;
313 	pdu->ctrl_1 |= LLC_2_PDU_RSP_UA;
314 	pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
315 }
316 
317 /**
318  *	llc_pdu_decode_pdu_type - designates PDU type
319  *	@skb: input skb that type of it must be designated.
320  *	@type: type of PDU (output argument).
321  *
322  *	This function designates type of PDU (I, S or U).
323  */
324 static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
325 {
326 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
327 
328 	if (pdu->ctrl_1 & 1) {
329 		if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
330 			*type = LLC_PDU_TYPE_U;
331 		else
332 			*type = LLC_PDU_TYPE_S;
333 	} else
334 		*type = LLC_PDU_TYPE_I;
335 }
336 
337 /**
338  *	llc_pdu_get_pf_bit - extracts p/f bit of input PDU
339  *	@pdu: pointer to LLC header.
340  *
341  *	This function extracts p/f bit of input PDU. at first examines type of
342  *	PDU and then extracts p/f bit. Returns the p/f bit.
343  */
344 static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu)
345 {
346 	u8 pdu_type;
347 	u8 pf_bit = 0;
348 
349 	if (pdu->ctrl_1 & 1) {
350 		if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
351 			pdu_type = LLC_PDU_TYPE_U;
352 		else
353 			pdu_type = LLC_PDU_TYPE_S;
354 	} else
355 		pdu_type = LLC_PDU_TYPE_I;
356 	switch (pdu_type) {
357 	case LLC_PDU_TYPE_I:
358 	case LLC_PDU_TYPE_S:
359 		pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
360 		break;
361 	case LLC_PDU_TYPE_U:
362 		pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
363 		break;
364 	}
365 	return pf_bit;
366 }
367