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