diff options
Diffstat (limited to 'net/atm')
| -rw-r--r-- | net/atm/addr.c | 55 | ||||
| -rw-r--r-- | net/atm/addr.h | 12 | ||||
| -rw-r--r-- | net/atm/atm_misc.c | 2 | ||||
| -rw-r--r-- | net/atm/br2684.c | 2 | ||||
| -rw-r--r-- | net/atm/clip.c | 2 | ||||
| -rw-r--r-- | net/atm/common.c | 6 | ||||
| -rw-r--r-- | net/atm/ioctl.c | 34 | ||||
| -rw-r--r-- | net/atm/lec.c | 43 | ||||
| -rw-r--r-- | net/atm/resources.c | 20 | ||||
| -rw-r--r-- | net/atm/signaling.c | 8 | ||||
| -rw-r--r-- | net/atm/svc.c | 1 |
11 files changed, 140 insertions, 45 deletions
diff --git a/net/atm/addr.c b/net/atm/addr.c index 1c8867f7f54a..3060fd0ba4b9 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c | |||
| @@ -44,29 +44,43 @@ static void notify_sigd(struct atm_dev *dev) | |||
| 44 | sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); | 44 | sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void atm_reset_addr(struct atm_dev *dev) | 47 | void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype) |
| 48 | { | 48 | { |
| 49 | unsigned long flags; | 49 | unsigned long flags; |
| 50 | struct atm_dev_addr *this, *p; | 50 | struct atm_dev_addr *this, *p; |
| 51 | struct list_head *head; | ||
| 51 | 52 | ||
| 52 | spin_lock_irqsave(&dev->lock, flags); | 53 | spin_lock_irqsave(&dev->lock, flags); |
| 53 | list_for_each_entry_safe(this, p, &dev->local, entry) | 54 | if (atype == ATM_ADDR_LECS) |
| 54 | kfree(this); | 55 | head = &dev->lecs; |
| 56 | else | ||
| 57 | head = &dev->local; | ||
| 58 | list_for_each_entry_safe(this, p, head, entry) { | ||
| 59 | list_del(&this->entry); | ||
| 60 | kfree(this); | ||
| 61 | } | ||
| 55 | spin_unlock_irqrestore(&dev->lock, flags); | 62 | spin_unlock_irqrestore(&dev->lock, flags); |
| 56 | notify_sigd(dev); | 63 | if (head == &dev->local) |
| 64 | notify_sigd(dev); | ||
| 57 | } | 65 | } |
| 58 | 66 | ||
| 59 | int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | 67 | int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
| 68 | enum atm_addr_type_t atype) | ||
| 60 | { | 69 | { |
| 61 | unsigned long flags; | 70 | unsigned long flags; |
| 62 | struct atm_dev_addr *this; | 71 | struct atm_dev_addr *this; |
| 72 | struct list_head *head; | ||
| 63 | int error; | 73 | int error; |
| 64 | 74 | ||
| 65 | error = check_addr(addr); | 75 | error = check_addr(addr); |
| 66 | if (error) | 76 | if (error) |
| 67 | return error; | 77 | return error; |
| 68 | spin_lock_irqsave(&dev->lock, flags); | 78 | spin_lock_irqsave(&dev->lock, flags); |
| 69 | list_for_each_entry(this, &dev->local, entry) { | 79 | if (atype == ATM_ADDR_LECS) |
| 80 | head = &dev->lecs; | ||
| 81 | else | ||
| 82 | head = &dev->local; | ||
| 83 | list_for_each_entry(this, head, entry) { | ||
| 70 | if (identical(&this->addr, addr)) { | 84 | if (identical(&this->addr, addr)) { |
| 71 | spin_unlock_irqrestore(&dev->lock, flags); | 85 | spin_unlock_irqrestore(&dev->lock, flags); |
| 72 | return -EEXIST; | 86 | return -EEXIST; |
| @@ -78,28 +92,36 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | |||
| 78 | return -ENOMEM; | 92 | return -ENOMEM; |
| 79 | } | 93 | } |
| 80 | this->addr = *addr; | 94 | this->addr = *addr; |
| 81 | list_add(&this->entry, &dev->local); | 95 | list_add(&this->entry, head); |
| 82 | spin_unlock_irqrestore(&dev->lock, flags); | 96 | spin_unlock_irqrestore(&dev->lock, flags); |
| 83 | notify_sigd(dev); | 97 | if (head == &dev->local) |
| 98 | notify_sigd(dev); | ||
| 84 | return 0; | 99 | return 0; |
| 85 | } | 100 | } |
| 86 | 101 | ||
| 87 | int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | 102 | int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
| 103 | enum atm_addr_type_t atype) | ||
| 88 | { | 104 | { |
| 89 | unsigned long flags; | 105 | unsigned long flags; |
| 90 | struct atm_dev_addr *this; | 106 | struct atm_dev_addr *this; |
| 107 | struct list_head *head; | ||
| 91 | int error; | 108 | int error; |
| 92 | 109 | ||
| 93 | error = check_addr(addr); | 110 | error = check_addr(addr); |
| 94 | if (error) | 111 | if (error) |
| 95 | return error; | 112 | return error; |
| 96 | spin_lock_irqsave(&dev->lock, flags); | 113 | spin_lock_irqsave(&dev->lock, flags); |
| 97 | list_for_each_entry(this, &dev->local, entry) { | 114 | if (atype == ATM_ADDR_LECS) |
| 115 | head = &dev->lecs; | ||
| 116 | else | ||
| 117 | head = &dev->local; | ||
| 118 | list_for_each_entry(this, head, entry) { | ||
| 98 | if (identical(&this->addr, addr)) { | 119 | if (identical(&this->addr, addr)) { |
| 99 | list_del(&this->entry); | 120 | list_del(&this->entry); |
| 100 | spin_unlock_irqrestore(&dev->lock, flags); | 121 | spin_unlock_irqrestore(&dev->lock, flags); |
| 101 | kfree(this); | 122 | kfree(this); |
| 102 | notify_sigd(dev); | 123 | if (head == &dev->local) |
| 124 | notify_sigd(dev); | ||
| 103 | return 0; | 125 | return 0; |
| 104 | } | 126 | } |
| 105 | } | 127 | } |
| @@ -108,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | |||
| 108 | } | 130 | } |
| 109 | 131 | ||
| 110 | int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, | 132 | int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, |
| 111 | size_t size) | 133 | size_t size, enum atm_addr_type_t atype) |
| 112 | { | 134 | { |
| 113 | unsigned long flags; | 135 | unsigned long flags; |
| 114 | struct atm_dev_addr *this; | 136 | struct atm_dev_addr *this; |
| 137 | struct list_head *head; | ||
| 115 | int total = 0, error; | 138 | int total = 0, error; |
| 116 | struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; | 139 | struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; |
| 117 | 140 | ||
| 118 | spin_lock_irqsave(&dev->lock, flags); | 141 | spin_lock_irqsave(&dev->lock, flags); |
| 119 | list_for_each_entry(this, &dev->local, entry) | 142 | if (atype == ATM_ADDR_LECS) |
| 143 | head = &dev->lecs; | ||
| 144 | else | ||
| 145 | head = &dev->local; | ||
| 146 | list_for_each_entry(this, head, entry) | ||
| 120 | total += sizeof(struct sockaddr_atmsvc); | 147 | total += sizeof(struct sockaddr_atmsvc); |
| 121 | tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); | 148 | tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); |
| 122 | if (!tmp_buf) { | 149 | if (!tmp_buf) { |
| 123 | spin_unlock_irqrestore(&dev->lock, flags); | 150 | spin_unlock_irqrestore(&dev->lock, flags); |
| 124 | return -ENOMEM; | 151 | return -ENOMEM; |
| 125 | } | 152 | } |
| 126 | list_for_each_entry(this, &dev->local, entry) | 153 | list_for_each_entry(this, head, entry) |
| 127 | memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); | 154 | memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); |
| 128 | spin_unlock_irqrestore(&dev->lock, flags); | 155 | spin_unlock_irqrestore(&dev->lock, flags); |
| 129 | error = total > size ? -E2BIG : total; | 156 | error = total > size ? -E2BIG : total; |
diff --git a/net/atm/addr.h b/net/atm/addr.h index 3099d21feeaa..f39433ad45da 100644 --- a/net/atm/addr.h +++ b/net/atm/addr.h | |||
| @@ -9,10 +9,12 @@ | |||
| 9 | #include <linux/atm.h> | 9 | #include <linux/atm.h> |
| 10 | #include <linux/atmdev.h> | 10 | #include <linux/atmdev.h> |
| 11 | 11 | ||
| 12 | 12 | void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type); | |
| 13 | void atm_reset_addr(struct atm_dev *dev); | 13 | int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
| 14 | int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); | 14 | enum atm_addr_type_t type); |
| 15 | int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); | 15 | int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
| 16 | int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); | 16 | enum atm_addr_type_t type); |
| 17 | int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf, | ||
| 18 | size_t size, enum atm_addr_type_t type); | ||
| 17 | 19 | ||
| 18 | #endif | 20 | #endif |
diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c index b2113c3454ae..223c7ad5bd0f 100644 --- a/net/atm/atm_misc.c +++ b/net/atm/atm_misc.c | |||
| @@ -25,7 +25,7 @@ int atm_charge(struct atm_vcc *vcc,int truesize) | |||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, | 27 | struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, |
| 28 | int gfp_flags) | 28 | gfp_t gfp_flags) |
| 29 | { | 29 | { |
| 30 | struct sock *sk = sk_atm(vcc); | 30 | struct sock *sk = sk_atm(vcc); |
| 31 | int guess = atm_guess_pdu2truesize(pdu_size); | 31 | int guess = atm_guess_pdu2truesize(pdu_size); |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 289956c4dd3e..72f3f7b8de80 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
| @@ -220,7 +220,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 220 | /* netif_stop_queue(dev); */ | 220 | /* netif_stop_queue(dev); */ |
| 221 | dev_kfree_skb(skb); | 221 | dev_kfree_skb(skb); |
| 222 | read_unlock(&devs_lock); | 222 | read_unlock(&devs_lock); |
| 223 | return -EUNATCH; | 223 | return 0; |
| 224 | } | 224 | } |
| 225 | if (!br2684_xmit_vcc(skb, brdev, brvcc)) { | 225 | if (!br2684_xmit_vcc(skb, brdev, brvcc)) { |
| 226 | /* | 226 | /* |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 28dab55a4387..4f54c9a5e84a 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
| @@ -310,7 +310,7 @@ static int clip_constructor(struct neighbour *neigh) | |||
| 310 | if (neigh->type != RTN_UNICAST) return -EINVAL; | 310 | if (neigh->type != RTN_UNICAST) return -EINVAL; |
| 311 | 311 | ||
| 312 | rcu_read_lock(); | 312 | rcu_read_lock(); |
| 313 | in_dev = rcu_dereference(__in_dev_get(dev)); | 313 | in_dev = __in_dev_get_rcu(dev); |
| 314 | if (!in_dev) { | 314 | if (!in_dev) { |
| 315 | rcu_read_unlock(); | 315 | rcu_read_unlock(); |
| 316 | return -EINVAL; | 316 | return -EINVAL; |
diff --git a/net/atm/common.c b/net/atm/common.c index e93e838069e8..63feea49fb13 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
| @@ -46,7 +46,7 @@ static void __vcc_insert_socket(struct sock *sk) | |||
| 46 | struct atm_vcc *vcc = atm_sk(sk); | 46 | struct atm_vcc *vcc = atm_sk(sk); |
| 47 | struct hlist_head *head = &vcc_hash[vcc->vci & | 47 | struct hlist_head *head = &vcc_hash[vcc->vci & |
| 48 | (VCC_HTABLE_SIZE - 1)]; | 48 | (VCC_HTABLE_SIZE - 1)]; |
| 49 | sk->sk_hashent = vcc->vci & (VCC_HTABLE_SIZE - 1); | 49 | sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1); |
| 50 | sk_add_node(sk, head); | 50 | sk_add_node(sk, head); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -178,8 +178,6 @@ static void vcc_destroy_socket(struct sock *sk) | |||
| 178 | if (vcc->push) | 178 | if (vcc->push) |
| 179 | vcc->push(vcc, NULL); /* atmarpd has no push */ | 179 | vcc->push(vcc, NULL); /* atmarpd has no push */ |
| 180 | 180 | ||
| 181 | vcc_remove_socket(sk); /* no more receive */ | ||
| 182 | |||
| 183 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { | 181 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { |
| 184 | atm_return(vcc,skb->truesize); | 182 | atm_return(vcc,skb->truesize); |
| 185 | kfree_skb(skb); | 183 | kfree_skb(skb); |
| @@ -188,6 +186,8 @@ static void vcc_destroy_socket(struct sock *sk) | |||
| 188 | module_put(vcc->dev->ops->owner); | 186 | module_put(vcc->dev->ops->owner); |
| 189 | atm_dev_put(vcc->dev); | 187 | atm_dev_put(vcc->dev); |
| 190 | } | 188 | } |
| 189 | |||
| 190 | vcc_remove_socket(sk); | ||
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | 193 | ||
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index d89056ec44d4..a150198b05a3 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c | |||
| @@ -105,17 +105,35 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 105 | if (!error) | 105 | if (!error) |
| 106 | sock->state = SS_CONNECTED; | 106 | sock->state = SS_CONNECTED; |
| 107 | goto done; | 107 | goto done; |
| 108 | default: | 108 | case ATM_SETBACKEND: |
| 109 | case ATM_NEWBACKENDIF: | ||
| 110 | { | ||
| 111 | atm_backend_t backend; | ||
| 112 | error = get_user(backend, (atm_backend_t __user *) argp); | ||
| 113 | if (error) | ||
| 114 | goto done; | ||
| 115 | switch (backend) { | ||
| 116 | case ATM_BACKEND_PPP: | ||
| 117 | request_module("pppoatm"); | ||
| 118 | break; | ||
| 119 | case ATM_BACKEND_BR2684: | ||
| 120 | request_module("br2684"); | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | break; | ||
| 125 | case ATMMPC_CTRL: | ||
| 126 | case ATMMPC_DATA: | ||
| 127 | request_module("mpoa"); | ||
| 128 | break; | ||
| 129 | case ATMARPD_CTRL: | ||
| 130 | request_module("clip"); | ||
| 131 | break; | ||
| 132 | case ATMLEC_CTRL: | ||
| 133 | request_module("lec"); | ||
| 109 | break; | 134 | break; |
| 110 | } | 135 | } |
| 111 | 136 | ||
| 112 | if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA) | ||
| 113 | request_module("mpoa"); | ||
| 114 | if (cmd == ATMARPD_CTRL) | ||
| 115 | request_module("clip"); | ||
| 116 | if (cmd == ATMLEC_CTRL) | ||
| 117 | request_module("lec"); | ||
| 118 | |||
| 119 | error = -ENOIOCTLCMD; | 137 | error = -ENOIOCTLCMD; |
| 120 | 138 | ||
| 121 | down(&ioctl_mutex); | 139 | down(&ioctl_mutex); |
diff --git a/net/atm/lec.c b/net/atm/lec.c index a0752487026d..ad840b9afba8 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
| @@ -686,9 +686,19 @@ static unsigned char lec_ctrl_magic[] = { | |||
| 686 | 0x01, | 686 | 0x01, |
| 687 | 0x01 }; | 687 | 0x01 }; |
| 688 | 688 | ||
| 689 | #define LEC_DATA_DIRECT_8023 2 | ||
| 690 | #define LEC_DATA_DIRECT_8025 3 | ||
| 691 | |||
| 692 | static int lec_is_data_direct(struct atm_vcc *vcc) | ||
| 693 | { | ||
| 694 | return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) || | ||
| 695 | (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025)); | ||
| 696 | } | ||
| 697 | |||
| 689 | static void | 698 | static void |
| 690 | lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | 699 | lec_push(struct atm_vcc *vcc, struct sk_buff *skb) |
| 691 | { | 700 | { |
| 701 | unsigned long flags; | ||
| 692 | struct net_device *dev = (struct net_device *)vcc->proto_data; | 702 | struct net_device *dev = (struct net_device *)vcc->proto_data; |
| 693 | struct lec_priv *priv = (struct lec_priv *)dev->priv; | 703 | struct lec_priv *priv = (struct lec_priv *)dev->priv; |
| 694 | 704 | ||
| @@ -728,7 +738,8 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 728 | skb_queue_tail(&sk->sk_receive_queue, skb); | 738 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 729 | sk->sk_data_ready(sk, skb->len); | 739 | sk->sk_data_ready(sk, skb->len); |
| 730 | } else { /* Data frame, queue to protocol handlers */ | 740 | } else { /* Data frame, queue to protocol handlers */ |
| 731 | unsigned char *dst; | 741 | struct lec_arp_table *entry; |
| 742 | unsigned char *src, *dst; | ||
| 732 | 743 | ||
| 733 | atm_return(vcc,skb->truesize); | 744 | atm_return(vcc,skb->truesize); |
| 734 | if (*(uint16_t *)skb->data == htons(priv->lecid) || | 745 | if (*(uint16_t *)skb->data == htons(priv->lecid) || |
| @@ -741,10 +752,30 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 741 | return; | 752 | return; |
| 742 | } | 753 | } |
| 743 | #ifdef CONFIG_TR | 754 | #ifdef CONFIG_TR |
| 744 | if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest; | 755 | if (priv->is_trdev) |
| 756 | dst = ((struct lecdatahdr_8025 *) skb->data)->h_dest; | ||
| 745 | else | 757 | else |
| 746 | #endif | 758 | #endif |
| 747 | dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest; | 759 | dst = ((struct lecdatahdr_8023 *) skb->data)->h_dest; |
| 760 | |||
| 761 | /* If this is a Data Direct VCC, and the VCC does not match | ||
| 762 | * the LE_ARP cache entry, delete the LE_ARP cache entry. | ||
| 763 | */ | ||
| 764 | spin_lock_irqsave(&priv->lec_arp_lock, flags); | ||
| 765 | if (lec_is_data_direct(vcc)) { | ||
| 766 | #ifdef CONFIG_TR | ||
| 767 | if (priv->is_trdev) | ||
| 768 | src = ((struct lecdatahdr_8025 *) skb->data)->h_source; | ||
| 769 | else | ||
| 770 | #endif | ||
| 771 | src = ((struct lecdatahdr_8023 *) skb->data)->h_source; | ||
| 772 | entry = lec_arp_find(priv, src); | ||
| 773 | if (entry && entry->vcc != vcc) { | ||
| 774 | lec_arp_remove(priv, entry); | ||
| 775 | kfree(entry); | ||
| 776 | } | ||
| 777 | } | ||
| 778 | spin_unlock_irqrestore(&priv->lec_arp_lock, flags); | ||
| 748 | 779 | ||
| 749 | if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ | 780 | if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ |
| 750 | !priv->is_proxy && /* Proxy wants all the packets */ | 781 | !priv->is_proxy && /* Proxy wants all the packets */ |
| @@ -1990,6 +2021,12 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, | |||
| 1990 | found = entry->vcc; | 2021 | found = entry->vcc; |
| 1991 | goto out; | 2022 | goto out; |
| 1992 | } | 2023 | } |
| 2024 | /* If the LE_ARP cache entry is still pending, reset count to 0 | ||
| 2025 | * so another LE_ARP request can be made for this frame. | ||
| 2026 | */ | ||
| 2027 | if (entry->status == ESI_ARP_PENDING) { | ||
| 2028 | entry->no_tries = 0; | ||
| 2029 | } | ||
| 1993 | /* Data direct VC not yet set up, check to see if the unknown | 2030 | /* Data direct VC not yet set up, check to see if the unknown |
| 1994 | frame count is greater than the limit. If the limit has | 2031 | frame count is greater than the limit. If the limit has |
| 1995 | not been reached, allow the caller to send packet to | 2032 | not been reached, allow the caller to send packet to |
diff --git a/net/atm/resources.c b/net/atm/resources.c index a57a9268bd24..415d2615d475 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c | |||
| @@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type) | |||
| 40 | dev->link_rate = ATM_OC3_PCR; | 40 | dev->link_rate = ATM_OC3_PCR; |
| 41 | spin_lock_init(&dev->lock); | 41 | spin_lock_init(&dev->lock); |
| 42 | INIT_LIST_HEAD(&dev->local); | 42 | INIT_LIST_HEAD(&dev->local); |
| 43 | INIT_LIST_HEAD(&dev->lecs); | ||
| 43 | 44 | ||
| 44 | return dev; | 45 | return dev; |
| 45 | } | 46 | } |
| @@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) | |||
| 320 | error = -EPERM; | 321 | error = -EPERM; |
| 321 | goto done; | 322 | goto done; |
| 322 | } | 323 | } |
| 323 | atm_reset_addr(dev); | 324 | atm_reset_addr(dev, ATM_ADDR_LOCAL); |
| 324 | break; | 325 | break; |
| 325 | case ATM_ADDADDR: | 326 | case ATM_ADDADDR: |
| 326 | case ATM_DELADDR: | 327 | case ATM_DELADDR: |
| 328 | case ATM_ADDLECSADDR: | ||
| 329 | case ATM_DELLECSADDR: | ||
| 327 | if (!capable(CAP_NET_ADMIN)) { | 330 | if (!capable(CAP_NET_ADMIN)) { |
| 328 | error = -EPERM; | 331 | error = -EPERM; |
| 329 | goto done; | 332 | goto done; |
| @@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) | |||
| 335 | error = -EFAULT; | 338 | error = -EFAULT; |
| 336 | goto done; | 339 | goto done; |
| 337 | } | 340 | } |
| 338 | if (cmd == ATM_ADDADDR) | 341 | if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) |
| 339 | error = atm_add_addr(dev, &addr); | 342 | error = atm_add_addr(dev, &addr, |
| 343 | (cmd == ATM_ADDADDR ? | ||
| 344 | ATM_ADDR_LOCAL : ATM_ADDR_LECS)); | ||
| 340 | else | 345 | else |
| 341 | error = atm_del_addr(dev, &addr); | 346 | error = atm_del_addr(dev, &addr, |
| 347 | (cmd == ATM_DELADDR ? | ||
| 348 | ATM_ADDR_LOCAL : ATM_ADDR_LECS)); | ||
| 342 | goto done; | 349 | goto done; |
| 343 | } | 350 | } |
| 344 | case ATM_GETADDR: | 351 | case ATM_GETADDR: |
| 345 | error = atm_get_addr(dev, buf, len); | 352 | case ATM_GETLECSADDR: |
| 353 | error = atm_get_addr(dev, buf, len, | ||
| 354 | (cmd == ATM_GETADDR ? | ||
| 355 | ATM_ADDR_LOCAL : ATM_ADDR_LECS)); | ||
| 346 | if (error < 0) | 356 | if (error < 0) |
| 347 | goto done; | 357 | goto done; |
| 348 | size = error; | 358 | size = error; |
diff --git a/net/atm/signaling.c b/net/atm/signaling.c index f7c449ac1800..e7211a7f382c 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c | |||
| @@ -217,8 +217,9 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, | |||
| 217 | static void purge_vcc(struct atm_vcc *vcc) | 217 | static void purge_vcc(struct atm_vcc *vcc) |
| 218 | { | 218 | { |
| 219 | if (sk_atm(vcc)->sk_family == PF_ATMSVC && | 219 | if (sk_atm(vcc)->sk_family == PF_ATMSVC && |
| 220 | !test_bit(ATM_VF_META,&vcc->flags)) { | 220 | !test_bit(ATM_VF_META, &vcc->flags)) { |
| 221 | set_bit(ATM_VF_RELEASED,&vcc->flags); | 221 | set_bit(ATM_VF_RELEASED, &vcc->flags); |
| 222 | clear_bit(ATM_VF_REGIS, &vcc->flags); | ||
| 222 | vcc_release_async(vcc, -EUNATCH); | 223 | vcc_release_async(vcc, -EUNATCH); |
| 223 | } | 224 | } |
| 224 | } | 225 | } |
| @@ -243,8 +244,7 @@ static void sigd_close(struct atm_vcc *vcc) | |||
| 243 | sk_for_each(s, node, head) { | 244 | sk_for_each(s, node, head) { |
| 244 | struct atm_vcc *vcc = atm_sk(s); | 245 | struct atm_vcc *vcc = atm_sk(s); |
| 245 | 246 | ||
| 246 | if (vcc->dev) | 247 | purge_vcc(vcc); |
| 247 | purge_vcc(vcc); | ||
| 248 | } | 248 | } |
| 249 | } | 249 | } |
| 250 | read_unlock(&vcc_sklist_lock); | 250 | read_unlock(&vcc_sklist_lock); |
diff --git a/net/atm/svc.c b/net/atm/svc.c index 08e46052a3e4..d7b266136bf6 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
| @@ -302,6 +302,7 @@ static int svc_listen(struct socket *sock,int backlog) | |||
| 302 | error = -EINVAL; | 302 | error = -EINVAL; |
| 303 | goto out; | 303 | goto out; |
| 304 | } | 304 | } |
| 305 | vcc_insert_socket(sk); | ||
| 305 | set_bit(ATM_VF_WAITING, &vcc->flags); | 306 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 306 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 307 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); |
| 307 | sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); | 308 | sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); |
