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 out: 125 return rc; 126 } 127 128 /** 129 * llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ 130 * @sap: SAP 131 * @skb: the event to send 132 * 133 * Send a TEST command PDU to the MAC layer in response to a TEST REQUEST 134 * primitive from the network layer. Verify event is a primitive type 135 * event; verify the primitive is a TEST REQUEST. 136 */ 137 int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) 138 { 139 struct llc_sap_state_ev *ev = llc_sap_ev(skb); 140 141 llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap, 142 ev->daddr.lsap, LLC_PDU_CMD); 143 llc_pdu_init_as_test_cmd(skb); 144 145 return llc_prepare_and_xmit(skb); 146 } 147 148 int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) 149 { 150 u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap; 151 struct sk_buff *nskb; 152 int rc = 1; 153 u32 data_size; 154 155 if (skb->mac_len < ETH_HLEN) 156 return 1; 157 158 llc_pdu_decode_sa(skb, mac_da); 159 llc_pdu_decode_da(skb, mac_sa); 160 llc_pdu_decode_ssap(skb, &dsap); 161 162 /* The test request command is type U (llc_len = 3) */ 163 data_size = ntohs(eth_hdr(skb)->h_proto) - 3; 164 nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); 165 if (!nskb) 166 goto out; 167 llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, 168 LLC_PDU_RSP); 169 llc_pdu_init_as_test_rsp(nskb, skb); 170 rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); 171 if (likely(!rc)) 172 rc = dev_queue_xmit(nskb); 173 out: 174 return rc; 175 } 176 177 /** 178 * llc_sap_action_report_status - report data link status to layer mgmt 179 * @sap: SAP 180 * @skb: the event to send 181 * 182 * Report data link status to layer management. Verify our event is the 183 * kind we expect. 184 */ 185 int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb) 186 { 187 return 0; 188 } 189 190 /** 191 * llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND 192 * @sap: SAP 193 * @skb: the event to send 194 * 195 * Send a XID response PDU to the network layer via a XID INDICATION 196 * primitive. 197 */ 198 int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb) 199 { 200 llc_sap_rtn_pdu(sap, skb); 201 return 0; 202 } 203 204 /** 205 * llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND 206 * @sap: SAP 207 * @skb: the event to send 208 * 209 * Send a TEST response PDU to the network layer via a TEST INDICATION 210 * primitive. Verify our event is a PDU type event. 211 */ 212 int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb) 213 { 214 llc_sap_rtn_pdu(sap, skb); 215 return 0; 216 } 217