xref: /linux/net/llc/llc_s_ac.c (revision fbc988f236a60cf50a89da78fc6b7213daa9999c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * llc_s_ac.c - actions performed during sap state transition.
4  *
5  * Description :
6  *   Functions in this module are implementation of sap component actions.
7  *   Details of actions can be found in IEEE-802.2 standard document.
8  *   All functions have one sap and one event as input argument. All of
9  *   them return 0 On success and 1 otherwise.
10  *
11  * Copyright (c) 1997 by Procom Technology, Inc.
12  *		 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
13  */
14 
15 #include <linux/netdevice.h>
16 #include <net/llc.h>
17 #include <net/llc_pdu.h>
18 #include <net/llc_s_ac.h>
19 #include <net/llc_s_ev.h>
20 #include <net/llc_sap.h>
21 #include <net/sock.h>
22 
23 /**
24  *	llc_sap_action_unitdata_ind - forward UI PDU to network layer
25  *	@sap: SAP
26  *	@skb: the event to forward
27  *
28  *	Received a UI PDU from MAC layer; forward to network layer as a
29  *	UNITDATA INDICATION; verify our event is the kind we expect
30  */
31 int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb)
32 {
33 	llc_sap_rtn_pdu(sap, skb);
34 	return 0;
35 }
36 
37 static int llc_prepare_and_xmit(struct sk_buff *skb)
38 {
39 	struct llc_sap_state_ev *ev = llc_sap_ev(skb);
40 	struct sk_buff *nskb;
41 	int rc;
42 
43 	rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
44 	if (rc)
45 		return rc;
46 
47 	nskb = skb_clone(skb, GFP_ATOMIC);
48 	if (!nskb)
49 		return -ENOMEM;
50 
51 	if (skb->sk)
52 		skb_set_owner_w(nskb, skb->sk);
53 
54 	return dev_queue_xmit(nskb);
55 }
56 
57 /**
58  *	llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer
59  *	@sap: SAP
60  *	@skb: the event to send
61  *
62  *	Sends a UI PDU to the MAC layer in response to a UNITDATA REQUEST
63  *	primitive from the network layer. Verifies event is a primitive type of
64  *	event. Verify the primitive is a UNITDATA REQUEST.
65  */
66 int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
67 {
68 	struct llc_sap_state_ev *ev = llc_sap_ev(skb);
69 
70 	llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
71 			    ev->daddr.lsap, LLC_PDU_CMD);
72 	llc_pdu_init_as_ui_cmd(skb);
73 
74 	return llc_prepare_and_xmit(skb);
75 }
76 
77 /**
78  *	llc_sap_action_send_xid_c - send XID PDU as response to XID REQ
79  *	@sap: SAP
80  *	@skb: the event to send
81  *
82  *	Send a XID command PDU to MAC layer in response to a XID REQUEST
83  *	primitive from the network layer. Verify event is a primitive type
84  *	event. Verify the primitive is a XID REQUEST.
85  */
86 int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
87 {
88 	struct llc_sap_state_ev *ev = llc_sap_ev(skb);
89 
90 	llc_pdu_header_init(skb, LLC_PDU_TYPE_U_XID, ev->saddr.lsap,
91 			    ev->daddr.lsap, LLC_PDU_CMD);
92 	llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
93 
94 	return llc_prepare_and_xmit(skb);
95 }
96 
97 /**
98  *	llc_sap_action_send_xid_r - send XID PDU resp to MAC for received XID
99  *	@sap: SAP
100  *	@skb: the event to send
101  *
102  *	Send XID response PDU to MAC in response to an earlier received XID
103  *	command PDU. Verify event is a PDU type event
104  */
105 int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
106 {
107 	u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
108 	int rc = 1;
109 	struct sk_buff *nskb;
110 
111 	llc_pdu_decode_sa(skb, mac_da);
112 	llc_pdu_decode_da(skb, mac_sa);
113 	llc_pdu_decode_ssap(skb, &dsap);
114 	nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U,
115 			       sizeof(struct llc_xid_info));
116 	if (!nskb)
117 		goto out;
118 	llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
119 			    LLC_PDU_RSP);
120 	llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
121 	rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
122 	if (likely(!rc))
123 		rc = dev_queue_xmit(nskb);
124 	else
125 		kfree_skb(nskb);
126 out:
127 	return rc;
128 }
129 
130 /**
131  *	llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ
132  *	@sap: SAP
133  *	@skb: the event to send
134  *
135  *	Send a TEST command PDU to the MAC layer in response to a TEST REQUEST
136  *	primitive from the network layer. Verify event is a primitive type
137  *	event; verify the primitive is a TEST REQUEST.
138  */
139 int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
140 {
141 	struct llc_sap_state_ev *ev = llc_sap_ev(skb);
142 
143 	llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
144 			    ev->daddr.lsap, LLC_PDU_CMD);
145 	llc_pdu_init_as_test_cmd(skb);
146 
147 	return llc_prepare_and_xmit(skb);
148 }
149 
150 int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
151 {
152 	u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
153 	struct sk_buff *nskb;
154 	int rc = 1;
155 	u32 data_size;
156 
157 	if (skb->mac_len < ETH_HLEN)
158 		return 1;
159 
160 	llc_pdu_decode_sa(skb, mac_da);
161 	llc_pdu_decode_da(skb, mac_sa);
162 	llc_pdu_decode_ssap(skb, &dsap);
163 
164 	/* The test request command is type U (llc_len = 3) */
165 	data_size = ntohs(eth_hdr(skb)->h_proto) - 3;
166 	nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size);
167 	if (!nskb)
168 		goto out;
169 	llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
170 			    LLC_PDU_RSP);
171 	llc_pdu_init_as_test_rsp(nskb, skb);
172 	rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
173 	if (likely(!rc))
174 		rc = dev_queue_xmit(nskb);
175 	else
176 		kfree_skb(nskb);
177 out:
178 	return rc;
179 }
180 
181 /**
182  *	llc_sap_action_report_status - report data link status to layer mgmt
183  *	@sap: SAP
184  *	@skb: the event to send
185  *
186  *	Report data link status to layer management. Verify our event is the
187  *	kind we expect.
188  */
189 int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb)
190 {
191 	return 0;
192 }
193 
194 /**
195  *	llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND
196  *	@sap: SAP
197  *	@skb: the event to send
198  *
199  *	Send a XID response PDU to the network layer via a XID INDICATION
200  *	primitive.
201  */
202 int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb)
203 {
204 	llc_sap_rtn_pdu(sap, skb);
205 	return 0;
206 }
207 
208 /**
209  *	llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND
210  *	@sap: SAP
211  *	@skb: the event to send
212  *
213  *	Send a TEST response PDU to the network layer via a TEST INDICATION
214  *	primitive. Verify our event is a PDU type event.
215  */
216 int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb)
217 {
218 	llc_sap_rtn_pdu(sap, skb);
219 	return 0;
220 }
221