Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/atm/signaling.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
/* net/atm/signaling.c - ATM signaling */
3
4
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
5
6
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
7
8
#include <linux/errno.h> /* error codes */
9
#include <linux/kernel.h> /* printk */
10
#include <linux/skbuff.h>
11
#include <linux/wait.h>
12
#include <linux/sched.h> /* jiffies and HZ */
13
#include <linux/atm.h> /* ATM stuff */
14
#include <linux/atmsap.h>
15
#include <linux/atmsvc.h>
16
#include <linux/atmdev.h>
17
#include <linux/bitops.h>
18
#include <linux/slab.h>
19
20
#include "resources.h"
21
#include "signaling.h"
22
23
struct atm_vcc *sigd = NULL;
24
25
static void sigd_put_skb(struct sk_buff *skb)
26
{
27
if (!sigd) {
28
pr_debug("atmsvc: no signaling daemon\n");
29
kfree_skb(skb);
30
return;
31
}
32
atm_force_charge(sigd, skb->truesize);
33
skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb);
34
sk_atm(sigd)->sk_data_ready(sk_atm(sigd));
35
}
36
37
static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg)
38
{
39
struct sk_buff *skb;
40
41
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
42
!test_bit(ATM_VF_READY, &vcc->flags))
43
return;
44
msg->type = as_error;
45
if (!vcc->dev->ops->change_qos)
46
msg->reply = -EOPNOTSUPP;
47
else {
48
/* should lock VCC */
49
msg->reply = vcc->dev->ops->change_qos(vcc, &msg->qos,
50
msg->reply);
51
if (!msg->reply)
52
msg->type = as_okay;
53
}
54
/*
55
* Should probably just turn around the old skb. But then, the buffer
56
* space accounting needs to follow the change too. Maybe later.
57
*/
58
while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
59
schedule();
60
*(struct atmsvc_msg *)skb_put(skb, sizeof(struct atmsvc_msg)) = *msg;
61
sigd_put_skb(skb);
62
}
63
64
static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb)
65
{
66
struct atmsvc_msg *msg;
67
struct atm_vcc *session_vcc;
68
struct sock *sk;
69
70
msg = (struct atmsvc_msg *) skb->data;
71
WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
72
vcc = *(struct atm_vcc **) &msg->vcc;
73
pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc);
74
sk = sk_atm(vcc);
75
76
switch (msg->type) {
77
case as_okay:
78
sk->sk_err = -msg->reply;
79
clear_bit(ATM_VF_WAITING, &vcc->flags);
80
if (!*vcc->local.sas_addr.prv && !*vcc->local.sas_addr.pub) {
81
vcc->local.sas_family = AF_ATMSVC;
82
memcpy(vcc->local.sas_addr.prv,
83
msg->local.sas_addr.prv, ATM_ESA_LEN);
84
memcpy(vcc->local.sas_addr.pub,
85
msg->local.sas_addr.pub, ATM_E164_LEN + 1);
86
}
87
session_vcc = vcc->session ? vcc->session : vcc;
88
if (session_vcc->vpi || session_vcc->vci)
89
break;
90
session_vcc->itf = msg->pvc.sap_addr.itf;
91
session_vcc->vpi = msg->pvc.sap_addr.vpi;
92
session_vcc->vci = msg->pvc.sap_addr.vci;
93
if (session_vcc->vpi || session_vcc->vci)
94
session_vcc->qos = msg->qos;
95
break;
96
case as_error:
97
clear_bit(ATM_VF_REGIS, &vcc->flags);
98
clear_bit(ATM_VF_READY, &vcc->flags);
99
sk->sk_err = -msg->reply;
100
clear_bit(ATM_VF_WAITING, &vcc->flags);
101
break;
102
case as_indicate:
103
vcc = *(struct atm_vcc **)&msg->listen_vcc;
104
sk = sk_atm(vcc);
105
pr_debug("as_indicate!!!\n");
106
lock_sock(sk);
107
if (sk_acceptq_is_full(sk)) {
108
sigd_enq(NULL, as_reject, vcc, NULL, NULL);
109
dev_kfree_skb(skb);
110
goto as_indicate_complete;
111
}
112
sk_acceptq_added(sk);
113
skb_queue_tail(&sk->sk_receive_queue, skb);
114
pr_debug("waking sk_sleep(sk) 0x%p\n", sk_sleep(sk));
115
sk->sk_state_change(sk);
116
as_indicate_complete:
117
release_sock(sk);
118
return 0;
119
case as_close:
120
set_bit(ATM_VF_RELEASED, &vcc->flags);
121
vcc_release_async(vcc, msg->reply);
122
goto out;
123
case as_modify:
124
modify_qos(vcc, msg);
125
break;
126
case as_addparty:
127
case as_dropparty:
128
WRITE_ONCE(sk->sk_err_soft, -msg->reply);
129
/* < 0 failure, otherwise ep_ref */
130
clear_bit(ATM_VF_WAITING, &vcc->flags);
131
break;
132
default:
133
pr_alert("bad message type %d\n", (int)msg->type);
134
return -EINVAL;
135
}
136
sk->sk_state_change(sk);
137
out:
138
dev_kfree_skb(skb);
139
return 0;
140
}
141
142
void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type,
143
struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc,
144
const struct sockaddr_atmsvc *svc, const struct atm_qos *qos,
145
int reply)
146
{
147
struct sk_buff *skb;
148
struct atmsvc_msg *msg;
149
static unsigned int session = 0;
150
151
pr_debug("%d (0x%p)\n", (int)type, vcc);
152
while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
153
schedule();
154
msg = skb_put_zero(skb, sizeof(struct atmsvc_msg));
155
msg->type = type;
156
*(struct atm_vcc **) &msg->vcc = vcc;
157
*(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
158
msg->reply = reply;
159
if (qos)
160
msg->qos = *qos;
161
if (vcc)
162
msg->sap = vcc->sap;
163
if (svc)
164
msg->svc = *svc;
165
if (vcc)
166
msg->local = vcc->local;
167
if (pvc)
168
msg->pvc = *pvc;
169
if (vcc) {
170
if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags))
171
msg->session = ++session;
172
/* every new pmp connect gets the next session number */
173
}
174
sigd_put_skb(skb);
175
if (vcc)
176
set_bit(ATM_VF_REGIS, &vcc->flags);
177
}
178
179
void sigd_enq(struct atm_vcc *vcc, enum atmsvc_msg_type type,
180
struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc,
181
const struct sockaddr_atmsvc *svc)
182
{
183
sigd_enq2(vcc, type, listen_vcc, pvc, svc, vcc ? &vcc->qos : NULL, 0);
184
/* other ISP applications may use "reply" */
185
}
186
187
static void purge_vcc(struct atm_vcc *vcc)
188
{
189
if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
190
!test_bit(ATM_VF_META, &vcc->flags)) {
191
set_bit(ATM_VF_RELEASED, &vcc->flags);
192
clear_bit(ATM_VF_REGIS, &vcc->flags);
193
vcc_release_async(vcc, -EUNATCH);
194
}
195
}
196
197
static void sigd_close(struct atm_vcc *vcc)
198
{
199
struct sock *s;
200
int i;
201
202
pr_debug("\n");
203
sigd = NULL;
204
if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
205
pr_err("closing with requests pending\n");
206
skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
207
208
read_lock(&vcc_sklist_lock);
209
for (i = 0; i < VCC_HTABLE_SIZE; ++i) {
210
struct hlist_head *head = &vcc_hash[i];
211
212
sk_for_each(s, head) {
213
vcc = atm_sk(s);
214
215
purge_vcc(vcc);
216
}
217
}
218
read_unlock(&vcc_sklist_lock);
219
}
220
221
static const struct atmdev_ops sigd_dev_ops = {
222
.close = sigd_close,
223
.send = sigd_send
224
};
225
226
static struct atm_dev sigd_dev = {
227
.ops = &sigd_dev_ops,
228
.type = "sig",
229
.number = 999,
230
.lock = __SPIN_LOCK_UNLOCKED(sigd_dev.lock)
231
};
232
233
int sigd_attach(struct atm_vcc *vcc)
234
{
235
if (sigd)
236
return -EADDRINUSE;
237
pr_debug("\n");
238
sigd = vcc;
239
vcc->dev = &sigd_dev;
240
vcc_insert_socket(sk_atm(vcc));
241
set_bit(ATM_VF_META, &vcc->flags);
242
set_bit(ATM_VF_READY, &vcc->flags);
243
return 0;
244
}
245
246