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