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 */ 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 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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