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 */
llc_sap_action_unitdata_ind(struct llc_sap * sap,struct sk_buff * skb)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
llc_prepare_and_xmit(struct sk_buff * skb)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 */
llc_sap_action_send_ui(struct llc_sap * sap,struct sk_buff * skb)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 */
llc_sap_action_send_xid_c(struct llc_sap * sap,struct sk_buff * skb)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 */
llc_sap_action_send_xid_r(struct llc_sap * sap,struct sk_buff * skb)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 */
llc_sap_action_send_test_c(struct llc_sap * sap,struct sk_buff * skb)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
llc_sap_action_send_test_r(struct llc_sap * sap,struct sk_buff * skb)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 */
llc_sap_action_report_status(struct llc_sap * sap,struct sk_buff * skb)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 */
llc_sap_action_xid_ind(struct llc_sap * sap,struct sk_buff * skb)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 */
llc_sap_action_test_ind(struct llc_sap * sap,struct sk_buff * skb)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