1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * llc_if.c - Defines LLC interface to upper layer 4 * 5 * Copyright (c) 1997 by Procom Technology, Inc. 6 * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7 */ 8 #include <linux/gfp.h> 9 #include <linux/module.h> 10 #include <linux/kernel.h> 11 #include <linux/netdevice.h> 12 #include <linux/errno.h> 13 #include <net/llc_if.h> 14 #include <net/llc_sap.h> 15 #include <net/llc_s_ev.h> 16 #include <net/llc_conn.h> 17 #include <net/sock.h> 18 #include <net/llc_c_ev.h> 19 #include <net/llc_c_ac.h> 20 #include <net/llc_c_st.h> 21 #include <net/tcp_states.h> 22 23 /** 24 * llc_build_and_send_pkt - Connection data sending for upper layers. 25 * @sk: connection 26 * @skb: packet to send 27 * 28 * This function is called when upper layer wants to send data using 29 * connection oriented communication mode. During sending data, connection 30 * will be locked and received frames and expired timers will be queued. 31 * Returns 0 for success, -ECONNABORTED when the connection already 32 * closed and -EBUSY when sending data is not permitted in this state or 33 * LLC has send an I pdu with p bit set to 1 and is waiting for it's 34 * response. 35 * 36 * This function always consumes a reference to the skb. 37 */ 38 int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) 39 { 40 struct llc_conn_state_ev *ev; 41 int rc = -ECONNABORTED; 42 struct llc_sock *llc = llc_sk(sk); 43 44 if (unlikely(llc->state == LLC_CONN_STATE_ADM)) 45 goto out_free; 46 rc = -EBUSY; 47 if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */ 48 llc->p_flag)) { 49 llc->failed_data_req = 1; 50 goto out_free; 51 } 52 ev = llc_conn_ev(skb); 53 ev->type = LLC_CONN_EV_TYPE_PRIM; 54 ev->prim = LLC_DATA_PRIM; 55 ev->prim_type = LLC_PRIM_TYPE_REQ; 56 skb->dev = llc->dev; 57 return llc_conn_state_process(sk, skb); 58 59 out_free: 60 kfree_skb(skb); 61 return rc; 62 } 63 64 /** 65 * llc_establish_connection - Called by upper layer to establish a conn 66 * @sk: connection 67 * @lmac: local mac address 68 * @dmac: destination mac address 69 * @dsap: destination sap 70 * 71 * Upper layer calls this to establish an LLC connection with a remote 72 * machine. This function packages a proper event and sends it connection 73 * component state machine. Success or failure of connection 74 * establishment will inform to upper layer via calling it's confirm 75 * function and passing proper information. 76 */ 77 int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac, u8 dsap) 78 { 79 int rc = -EISCONN; 80 struct llc_addr laddr, daddr; 81 struct sk_buff *skb; 82 struct llc_sock *llc = llc_sk(sk); 83 struct sock *existing; 84 85 laddr.lsap = llc->sap->laddr.lsap; 86 daddr.lsap = dsap; 87 memcpy(daddr.mac, dmac, sizeof(daddr.mac)); 88 memcpy(laddr.mac, lmac, sizeof(laddr.mac)); 89 existing = llc_lookup_established(llc->sap, &daddr, &laddr, sock_net(sk)); 90 if (existing) { 91 if (existing->sk_state == TCP_ESTABLISHED) { 92 sk = existing; 93 goto out_put; 94 } else 95 sock_put(existing); 96 } 97 sock_hold(sk); 98 rc = -ENOMEM; 99 skb = alloc_skb(0, GFP_ATOMIC); 100 if (skb) { 101 struct llc_conn_state_ev *ev = llc_conn_ev(skb); 102 103 ev->type = LLC_CONN_EV_TYPE_PRIM; 104 ev->prim = LLC_CONN_PRIM; 105 ev->prim_type = LLC_PRIM_TYPE_REQ; 106 skb_set_owner_w(skb, sk); 107 rc = llc_conn_state_process(sk, skb); 108 } 109 out_put: 110 sock_put(sk); 111 return rc; 112 } 113 114 /** 115 * llc_send_disc - Called by upper layer to close a connection 116 * @sk: connection to be closed 117 * 118 * Upper layer calls this when it wants to close an established LLC 119 * connection with a remote machine. This function packages a proper event 120 * and sends it to connection component state machine. Returns 0 for 121 * success, 1 otherwise. 122 */ 123 int llc_send_disc(struct sock *sk) 124 { 125 u16 rc = 1; 126 struct llc_conn_state_ev *ev; 127 struct sk_buff *skb; 128 129 sock_hold(sk); 130 if (sk->sk_type != SOCK_STREAM || sk->sk_state != TCP_ESTABLISHED || 131 llc_sk(sk)->state == LLC_CONN_STATE_ADM || 132 llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) 133 goto out; 134 /* 135 * Postpone unassigning the connection from its SAP and returning the 136 * connection until all ACTIONs have been completely executed 137 */ 138 skb = alloc_skb(0, GFP_ATOMIC); 139 if (!skb) 140 goto out; 141 skb_set_owner_w(skb, sk); 142 sk->sk_state = TCP_CLOSING; 143 ev = llc_conn_ev(skb); 144 ev->type = LLC_CONN_EV_TYPE_PRIM; 145 ev->prim = LLC_DISC_PRIM; 146 ev->prim_type = LLC_PRIM_TYPE_REQ; 147 rc = llc_conn_state_process(sk, skb); 148 out: 149 sock_put(sk); 150 return rc; 151 } 152