1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/netdevice.h>
17#include <asm/errno.h>
18#include <net/llc_if.h>
19#include <net/llc_sap.h>
20#include <net/llc_s_ev.h>
21#include <net/llc_conn.h>
22#include <net/sock.h>
23#include <net/llc_c_ev.h>
24#include <net/llc_c_ac.h>
25#include <net/llc_c_st.h>
26#include <net/tcp_states.h>
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
42{
43 struct llc_conn_state_ev *ev;
44 int rc = -ECONNABORTED;
45 struct llc_sock *llc = llc_sk(sk);
46
47 if (unlikely(llc->state == LLC_CONN_STATE_ADM))
48 goto out;
49 rc = -EBUSY;
50 if (unlikely(llc_data_accept_state(llc->state) ||
51 llc->p_flag)) {
52 llc->failed_data_req = 1;
53 goto out;
54 }
55 ev = llc_conn_ev(skb);
56 ev->type = LLC_CONN_EV_TYPE_PRIM;
57 ev->prim = LLC_DATA_PRIM;
58 ev->prim_type = LLC_PRIM_TYPE_REQ;
59 skb->dev = llc->dev;
60 rc = llc_conn_state_process(sk, skb);
61out:
62 return rc;
63}
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
79{
80 int rc = -EISCONN;
81 struct llc_addr laddr, daddr;
82 struct sk_buff *skb;
83 struct llc_sock *llc = llc_sk(sk);
84 struct sock *existing;
85
86 laddr.lsap = llc->sap->laddr.lsap;
87 daddr.lsap = dsap;
88 memcpy(daddr.mac, dmac, sizeof(daddr.mac));
89 memcpy(laddr.mac, lmac, sizeof(laddr.mac));
90 existing = llc_lookup_established(llc->sap, &daddr, &laddr);
91 if (existing) {
92 if (existing->sk_state == TCP_ESTABLISHED) {
93 sk = existing;
94 goto out_put;
95 } else
96 sock_put(existing);
97 }
98 sock_hold(sk);
99 rc = -ENOMEM;
100 skb = alloc_skb(0, GFP_ATOMIC);
101 if (skb) {
102 struct llc_conn_state_ev *ev = llc_conn_ev(skb);
103
104 ev->type = LLC_CONN_EV_TYPE_PRIM;
105 ev->prim = LLC_CONN_PRIM;
106 ev->prim_type = LLC_PRIM_TYPE_REQ;
107 skb_set_owner_w(skb, sk);
108 rc = llc_conn_state_process(sk, skb);
109 }
110out_put:
111 sock_put(sk);
112 return rc;
113}
114
115
116
117
118
119
120
121
122
123
124int llc_send_disc(struct sock *sk)
125{
126 u16 rc = 1;
127 struct llc_conn_state_ev *ev;
128 struct sk_buff *skb;
129
130 sock_hold(sk);
131 if (sk->sk_type != SOCK_STREAM || sk->sk_state != TCP_ESTABLISHED ||
132 llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
133 llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
134 goto out;
135
136
137
138
139 skb = alloc_skb(0, GFP_ATOMIC);
140 if (!skb)
141 goto out;
142 skb_set_owner_w(skb, sk);
143 sk->sk_state = TCP_CLOSING;
144 ev = llc_conn_ev(skb);
145 ev->type = LLC_CONN_EV_TYPE_PRIM;
146 ev->prim = LLC_DISC_PRIM;
147 ev->prim_type = LLC_PRIM_TYPE_REQ;
148 rc = llc_conn_state_process(sk, skb);
149out:
150 sock_put(sk);
151 return rc;
152}
153
154