root/net/atm/signaling.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sigd_put_skb
  2. modify_qos
  3. sigd_send
  4. sigd_enq2
  5. sigd_enq
  6. purge_vcc
  7. sigd_close
  8. sigd_attach

   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 the, 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->sk_ack_backlog++;
 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                 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 }

/* [<][>][^][v][top][bottom][index][help] */