0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/gfp.h>
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/netdevice.h>
0018 #include <linux/errno.h>
0019 #include <net/llc_if.h>
0020 #include <net/llc_sap.h>
0021 #include <net/llc_s_ev.h>
0022 #include <net/llc_conn.h>
0023 #include <net/sock.h>
0024 #include <net/llc_c_ev.h>
0025 #include <net/llc_c_ac.h>
0026 #include <net/llc_c_st.h>
0027 #include <net/tcp_states.h>
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
0045 {
0046 struct llc_conn_state_ev *ev;
0047 int rc = -ECONNABORTED;
0048 struct llc_sock *llc = llc_sk(sk);
0049
0050 if (unlikely(llc->state == LLC_CONN_STATE_ADM))
0051 goto out_free;
0052 rc = -EBUSY;
0053 if (unlikely(llc_data_accept_state(llc->state) ||
0054 llc->p_flag)) {
0055 llc->failed_data_req = 1;
0056 goto out_free;
0057 }
0058 ev = llc_conn_ev(skb);
0059 ev->type = LLC_CONN_EV_TYPE_PRIM;
0060 ev->prim = LLC_DATA_PRIM;
0061 ev->prim_type = LLC_PRIM_TYPE_REQ;
0062 skb->dev = llc->dev;
0063 return llc_conn_state_process(sk, skb);
0064
0065 out_free:
0066 kfree_skb(skb);
0067 return rc;
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac, u8 dsap)
0084 {
0085 int rc = -EISCONN;
0086 struct llc_addr laddr, daddr;
0087 struct sk_buff *skb;
0088 struct llc_sock *llc = llc_sk(sk);
0089 struct sock *existing;
0090
0091 laddr.lsap = llc->sap->laddr.lsap;
0092 daddr.lsap = dsap;
0093 memcpy(daddr.mac, dmac, sizeof(daddr.mac));
0094 memcpy(laddr.mac, lmac, sizeof(laddr.mac));
0095 existing = llc_lookup_established(llc->sap, &daddr, &laddr);
0096 if (existing) {
0097 if (existing->sk_state == TCP_ESTABLISHED) {
0098 sk = existing;
0099 goto out_put;
0100 } else
0101 sock_put(existing);
0102 }
0103 sock_hold(sk);
0104 rc = -ENOMEM;
0105 skb = alloc_skb(0, GFP_ATOMIC);
0106 if (skb) {
0107 struct llc_conn_state_ev *ev = llc_conn_ev(skb);
0108
0109 ev->type = LLC_CONN_EV_TYPE_PRIM;
0110 ev->prim = LLC_CONN_PRIM;
0111 ev->prim_type = LLC_PRIM_TYPE_REQ;
0112 skb_set_owner_w(skb, sk);
0113 rc = llc_conn_state_process(sk, skb);
0114 }
0115 out_put:
0116 sock_put(sk);
0117 return rc;
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 int llc_send_disc(struct sock *sk)
0130 {
0131 u16 rc = 1;
0132 struct llc_conn_state_ev *ev;
0133 struct sk_buff *skb;
0134
0135 sock_hold(sk);
0136 if (sk->sk_type != SOCK_STREAM || sk->sk_state != TCP_ESTABLISHED ||
0137 llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
0138 llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
0139 goto out;
0140
0141
0142
0143
0144 skb = alloc_skb(0, GFP_ATOMIC);
0145 if (!skb)
0146 goto out;
0147 skb_set_owner_w(skb, sk);
0148 sk->sk_state = TCP_CLOSING;
0149 ev = llc_conn_ev(skb);
0150 ev->type = LLC_CONN_EV_TYPE_PRIM;
0151 ev->prim = LLC_DISC_PRIM;
0152 ev->prim_type = LLC_PRIM_TYPE_REQ;
0153 rc = llc_conn_state_process(sk, skb);
0154 out:
0155 sock_put(sk);
0156 return rc;
0157 }