]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - net/atm/signaling.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* net/atm/signaling.c - ATM signaling */
4 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
6 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
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>
20 #include "resources.h"
21 #include "signaling.h"
23 struct atm_vcc
*sigd
= NULL
;
25 static void sigd_put_skb(struct sk_buff
*skb
)
28 pr_debug("atmsvc: no signaling daemon\n");
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
));
37 static void modify_qos(struct atm_vcc
*vcc
, struct atmsvc_msg
*msg
)
41 if (test_bit(ATM_VF_RELEASED
, &vcc
->flags
) ||
42 !test_bit(ATM_VF_READY
, &vcc
->flags
))
45 if (!vcc
->dev
->ops
->change_qos
)
46 msg
->reply
= -EOPNOTSUPP
;
49 msg
->reply
= vcc
->dev
->ops
->change_qos(vcc
, &msg
->qos
,
55 * Should probably just turn around the old skb. But the, the buffer
56 * space accounting needs to follow the change too. Maybe later.
58 while (!(skb
= alloc_skb(sizeof(struct atmsvc_msg
), GFP_KERNEL
)))
60 *(struct atmsvc_msg
*)skb_put(skb
, sizeof(struct atmsvc_msg
)) = *msg
;
64 static int sigd_send(struct atm_vcc
*vcc
, struct sk_buff
*skb
)
66 struct atmsvc_msg
*msg
;
67 struct atm_vcc
*session_vcc
;
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
);
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);
87 session_vcc
= vcc
->session
? vcc
->session
: vcc
;
88 if (session_vcc
->vpi
|| session_vcc
->vci
)
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
;
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
);
103 vcc
= *(struct atm_vcc
**)&msg
->listen_vcc
;
105 pr_debug("as_indicate!!!\n");
107 if (sk_acceptq_is_full(sk
)) {
108 sigd_enq(NULL
, as_reject
, vcc
, NULL
, NULL
);
110 goto as_indicate_complete
;
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
:
120 set_bit(ATM_VF_RELEASED
, &vcc
->flags
);
121 vcc_release_async(vcc
, msg
->reply
);
124 modify_qos(vcc
, msg
);
128 sk
->sk_err_soft
= -msg
->reply
;
129 /* < 0 failure, otherwise ep_ref */
130 clear_bit(ATM_VF_WAITING
, &vcc
->flags
);
133 pr_alert("bad message type %d\n", (int)msg
->type
);
136 sk
->sk_state_change(sk
);
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
,
148 struct atmsvc_msg
*msg
;
149 static unsigned int session
= 0;
151 pr_debug("%d (0x%p)\n", (int)type
, vcc
);
152 while (!(skb
= alloc_skb(sizeof(struct atmsvc_msg
), GFP_KERNEL
)))
154 msg
= skb_put_zero(skb
, sizeof(struct atmsvc_msg
));
156 *(struct atm_vcc
**) &msg
->vcc
= vcc
;
157 *(struct atm_vcc
**) &msg
->listen_vcc
= listen_vcc
;
166 msg
->local
= vcc
->local
;
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 */
176 set_bit(ATM_VF_REGIS
, &vcc
->flags
);
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
)
183 sigd_enq2(vcc
, type
, listen_vcc
, pvc
, svc
, vcc
? &vcc
->qos
: NULL
, 0);
184 /* other ISP applications may use "reply" */
187 static void purge_vcc(struct atm_vcc
*vcc
)
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
);
197 static void sigd_close(struct atm_vcc
*vcc
)
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
);
208 read_lock(&vcc_sklist_lock
);
209 for (i
= 0; i
< VCC_HTABLE_SIZE
; ++i
) {
210 struct hlist_head
*head
= &vcc_hash
[i
];
212 sk_for_each(s
, head
) {
218 read_unlock(&vcc_sklist_lock
);
221 static const struct atmdev_ops sigd_dev_ops
= {
226 static struct atm_dev sigd_dev
= {
227 .ops
= &sigd_dev_ops
,
230 .lock
= __SPIN_LOCK_UNLOCKED(sigd_dev
.lock
)
233 int sigd_attach(struct atm_vcc
*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
);