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