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