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 /* 26 * find_get_vcc - validate and get a reference to a vcc pointer 27 * @vcc: the vcc pointer to validate 28 * 29 * This function validates that @vcc points to a registered VCC in vcc_hash. 30 * If found, it increments the socket reference count and returns the vcc. 31 * The caller must call sock_put(sk_atm(vcc)) when done. 32 * 33 * Returns the vcc pointer if valid, NULL otherwise. 34 */ 35 static struct atm_vcc *find_get_vcc(struct atm_vcc *vcc) 36 { 37 int i; 38 39 read_lock(&vcc_sklist_lock); 40 for (i = 0; i < VCC_HTABLE_SIZE; i++) { 41 struct sock *s; 42 43 sk_for_each(s, &vcc_hash[i]) { 44 if (atm_sk(s) == vcc) { 45 sock_hold(s); 46 read_unlock(&vcc_sklist_lock); 47 return vcc; 48 } 49 } 50 } 51 read_unlock(&vcc_sklist_lock); 52 return NULL; 53 } 54 55 static void sigd_put_skb(struct sk_buff *skb) 56 { 57 if (!sigd) { 58 pr_debug("atmsvc: no signaling daemon\n"); 59 kfree_skb(skb); 60 return; 61 } 62 atm_force_charge(sigd, skb->truesize); 63 skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb); 64 sk_atm(sigd)->sk_data_ready(sk_atm(sigd)); 65 } 66 67 static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg) 68 { 69 struct sk_buff *skb; 70 71 if (test_bit(ATM_VF_RELEASED, &vcc->flags) || 72 !test_bit(ATM_VF_READY, &vcc->flags)) 73 return; 74 msg->type = as_error; 75 if (!vcc->dev->ops->change_qos) 76 msg->reply = -EOPNOTSUPP; 77 else { 78 /* should lock VCC */ 79 msg->reply = vcc->dev->ops->change_qos(vcc, &msg->qos, 80 msg->reply); 81 if (!msg->reply) 82 msg->type = as_okay; 83 } 84 /* 85 * Should probably just turn around the old skb. But then, the buffer 86 * space accounting needs to follow the change too. Maybe later. 87 */ 88 while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL))) 89 schedule(); 90 *(struct atmsvc_msg *)skb_put(skb, sizeof(struct atmsvc_msg)) = *msg; 91 sigd_put_skb(skb); 92 } 93 94 static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) 95 { 96 struct atmsvc_msg *msg; 97 struct atm_vcc *session_vcc; 98 struct sock *sk; 99 100 msg = (struct atmsvc_msg *) skb->data; 101 WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc)); 102 103 vcc = find_get_vcc(*(struct atm_vcc **)&msg->vcc); 104 if (!vcc) { 105 pr_debug("invalid vcc pointer in msg\n"); 106 dev_kfree_skb(skb); 107 return -EINVAL; 108 } 109 110 pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc); 111 sk = sk_atm(vcc); 112 113 switch (msg->type) { 114 case as_okay: 115 sk->sk_err = -msg->reply; 116 clear_bit(ATM_VF_WAITING, &vcc->flags); 117 if (!*vcc->local.sas_addr.prv && !*vcc->local.sas_addr.pub) { 118 vcc->local.sas_family = AF_ATMSVC; 119 memcpy(vcc->local.sas_addr.prv, 120 msg->local.sas_addr.prv, ATM_ESA_LEN); 121 memcpy(vcc->local.sas_addr.pub, 122 msg->local.sas_addr.pub, ATM_E164_LEN + 1); 123 } 124 session_vcc = vcc->session ? vcc->session : vcc; 125 if (session_vcc->vpi || session_vcc->vci) 126 break; 127 session_vcc->itf = msg->pvc.sap_addr.itf; 128 session_vcc->vpi = msg->pvc.sap_addr.vpi; 129 session_vcc->vci = msg->pvc.sap_addr.vci; 130 if (session_vcc->vpi || session_vcc->vci) 131 session_vcc->qos = msg->qos; 132 break; 133 case as_error: 134 clear_bit(ATM_VF_REGIS, &vcc->flags); 135 clear_bit(ATM_VF_READY, &vcc->flags); 136 sk->sk_err = -msg->reply; 137 clear_bit(ATM_VF_WAITING, &vcc->flags); 138 break; 139 case as_indicate: 140 /* Release the reference from msg->vcc, we'll use msg->listen_vcc instead */ 141 sock_put(sk); 142 143 vcc = find_get_vcc(*(struct atm_vcc **)&msg->listen_vcc); 144 if (!vcc) { 145 pr_debug("invalid listen_vcc pointer in msg\n"); 146 dev_kfree_skb(skb); 147 return -EINVAL; 148 } 149 150 sk = sk_atm(vcc); 151 pr_debug("as_indicate!!!\n"); 152 lock_sock(sk); 153 if (sk_acceptq_is_full(sk)) { 154 sigd_enq(NULL, as_reject, vcc, NULL, NULL); 155 dev_kfree_skb(skb); 156 goto as_indicate_complete; 157 } 158 sk_acceptq_added(sk); 159 skb_queue_tail(&sk->sk_receive_queue, skb); 160 pr_debug("waking sk_sleep(sk) 0x%p\n", sk_sleep(sk)); 161 sk->sk_state_change(sk); 162 as_indicate_complete: 163 release_sock(sk); 164 /* Paired with find_get_vcc(msg->listen_vcc) above */ 165 sock_put(sk); 166 return 0; 167 case as_close: 168 set_bit(ATM_VF_RELEASED, &vcc->flags); 169 vcc_release_async(vcc, msg->reply); 170 goto out; 171 case as_modify: 172 modify_qos(vcc, msg); 173 break; 174 case as_addparty: 175 case as_dropparty: 176 WRITE_ONCE(sk->sk_err_soft, -msg->reply); 177 /* < 0 failure, otherwise ep_ref */ 178 clear_bit(ATM_VF_WAITING, &vcc->flags); 179 break; 180 default: 181 pr_alert("bad message type %d\n", (int)msg->type); 182 /* Paired with find_get_vcc(msg->vcc) above */ 183 sock_put(sk); 184 return -EINVAL; 185 } 186 sk->sk_state_change(sk); 187 out: 188 dev_kfree_skb(skb); 189 /* Paired with find_get_vcc(msg->vcc) above */ 190 sock_put(sk); 191 return 0; 192 } 193 194 void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type, 195 struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc, 196 const struct sockaddr_atmsvc *svc, const struct atm_qos *qos, 197 int reply) 198 { 199 struct sk_buff *skb; 200 struct atmsvc_msg *msg; 201 static unsigned int session = 0; 202 203 pr_debug("%d (0x%p)\n", (int)type, vcc); 204 while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL))) 205 schedule(); 206 msg = skb_put_zero(skb, sizeof(struct atmsvc_msg)); 207 msg->type = type; 208 *(struct atm_vcc **) &msg->vcc = vcc; 209 *(struct atm_vcc **) &msg->listen_vcc = listen_vcc; 210 msg->reply = reply; 211 if (qos) 212 msg->qos = *qos; 213 if (vcc) 214 msg->sap = vcc->sap; 215 if (svc) 216 msg->svc = *svc; 217 if (vcc) 218 msg->local = vcc->local; 219 if (pvc) 220 msg->pvc = *pvc; 221 if (vcc) { 222 if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags)) 223 msg->session = ++session; 224 /* every new pmp connect gets the next session number */ 225 } 226 sigd_put_skb(skb); 227 if (vcc) 228 set_bit(ATM_VF_REGIS, &vcc->flags); 229 } 230 231 void sigd_enq(struct atm_vcc *vcc, enum atmsvc_msg_type type, 232 struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc, 233 const struct sockaddr_atmsvc *svc) 234 { 235 sigd_enq2(vcc, type, listen_vcc, pvc, svc, vcc ? &vcc->qos : NULL, 0); 236 /* other ISP applications may use "reply" */ 237 } 238 239 static void purge_vcc(struct atm_vcc *vcc) 240 { 241 if (sk_atm(vcc)->sk_family == PF_ATMSVC && 242 !test_bit(ATM_VF_META, &vcc->flags)) { 243 set_bit(ATM_VF_RELEASED, &vcc->flags); 244 clear_bit(ATM_VF_REGIS, &vcc->flags); 245 vcc_release_async(vcc, -EUNATCH); 246 } 247 } 248 249 static void sigd_close(struct atm_vcc *vcc) 250 { 251 struct sock *s; 252 int i; 253 254 pr_debug("\n"); 255 sigd = NULL; 256 if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) 257 pr_err("closing with requests pending\n"); 258 skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); 259 260 read_lock(&vcc_sklist_lock); 261 for (i = 0; i < VCC_HTABLE_SIZE; ++i) { 262 struct hlist_head *head = &vcc_hash[i]; 263 264 sk_for_each(s, head) { 265 vcc = atm_sk(s); 266 267 purge_vcc(vcc); 268 } 269 } 270 read_unlock(&vcc_sklist_lock); 271 } 272 273 static const struct atmdev_ops sigd_dev_ops = { 274 .close = sigd_close, 275 .send = sigd_send 276 }; 277 278 static struct atm_dev sigd_dev = { 279 .ops = &sigd_dev_ops, 280 .type = "sig", 281 .number = 999, 282 .lock = __SPIN_LOCK_UNLOCKED(sigd_dev.lock) 283 }; 284 285 int sigd_attach(struct atm_vcc *vcc) 286 { 287 if (sigd) 288 return -EADDRINUSE; 289 pr_debug("\n"); 290 sigd = vcc; 291 vcc->dev = &sigd_dev; 292 vcc_insert_socket(sk_atm(vcc)); 293 set_bit(ATM_VF_META, &vcc->flags); 294 set_bit(ATM_VF_READY, &vcc->flags); 295 return 0; 296 } 297