vserver 1.9.5.x5
[linux-2.6.git] / net / atm / signaling.c
index 1788799..0ecb4a4 100644 (file)
@@ -136,6 +136,7 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
                        if (vcc->sk->sk_ack_backlog ==
                            vcc->sk->sk_max_ack_backlog) {
                                sigd_enq(NULL,as_reject,vcc,NULL,NULL);
+                               dev_kfree_skb(skb);
                                goto as_indicate_complete;
                        }
                        vcc->sk->sk_ack_backlog++;
@@ -147,19 +148,23 @@ as_indicate_complete:
                        return 0;
                case as_close:
                        set_bit(ATM_VF_RELEASED,&vcc->flags);
-                       clear_bit(ATM_VF_READY,&vcc->flags);
-                       vcc->sk->sk_err = -msg->reply;
-                       clear_bit(ATM_VF_WAITING, &vcc->flags);
-                       break;
+                       vcc_release_async(vcc, msg->reply);
+                       goto out;
                case as_modify:
                        modify_qos(vcc,msg);
                        break;
+               case as_addparty:
+               case as_dropparty:
+                       vcc->sk->sk_err_soft = msg->reply;      /* < 0 failure, otherwise ep_ref */
+                       clear_bit(ATM_VF_WAITING, &vcc->flags);
+                       break;
                default:
                        printk(KERN_ALERT "sigd_send: bad message type %d\n",
                            (int) msg->type);
                        return -EINVAL;
        }
        vcc->sk->sk_state_change(vcc->sk);
+out:
        dev_kfree_skb(skb);
        return 0;
 }
@@ -171,6 +176,7 @@ void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
 {
        struct sk_buff *skb;
        struct atmsvc_msg *msg;
+       static unsigned session = 0;
 
        DPRINTK("sigd_enq %d (0x%p)\n",(int) type,vcc);
        while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
@@ -186,6 +192,11 @@ void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
        if (svc) msg->svc = *svc;
        if (vcc) msg->local = vcc->local;
        if (pvc) msg->pvc = *pvc;
+       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);
        if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags);
 }
@@ -205,9 +216,7 @@ static void purge_vcc(struct atm_vcc *vcc)
        if (vcc->sk->sk_family == PF_ATMSVC &&
            !test_bit(ATM_VF_META,&vcc->flags)) {
                set_bit(ATM_VF_RELEASED,&vcc->flags);
-               vcc->sk->sk_err = EUNATCH;
-               clear_bit(ATM_VF_WAITING, &vcc->flags);
-               vcc->sk->sk_state_change(vcc->sk);
+               vcc_release_async(vcc, -EUNATCH);
        }
 }