diff options
Diffstat (limited to 'net/atm')
-rw-r--r-- | net/atm/addr.c | 6 | ||||
-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/signaling.c | 8 | ||||
-rw-r--r-- | net/atm/svc.c | 1 |
7 files changed, 79 insertions, 21 deletions
diff --git a/net/atm/addr.c b/net/atm/addr.c index 1c8867f7f54a..a30d0bf48063 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c | |||
@@ -50,8 +50,10 @@ void atm_reset_addr(struct atm_dev *dev) | |||
50 | struct atm_dev_addr *this, *p; | 50 | struct atm_dev_addr *this, *p; |
51 | 51 | ||
52 | spin_lock_irqsave(&dev->lock, flags); | 52 | spin_lock_irqsave(&dev->lock, flags); |
53 | list_for_each_entry_safe(this, p, &dev->local, entry) | 53 | list_for_each_entry_safe(this, p, &dev->local, entry) { |
54 | kfree(this); | 54 | list_del(&this->entry); |
55 | kfree(this); | ||
56 | } | ||
55 | spin_unlock_irqrestore(&dev->lock, flags); | 57 | spin_unlock_irqrestore(&dev->lock, flags); |
56 | notify_sigd(dev); | 58 | notify_sigd(dev); |
57 | } | 59 | } |
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/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); |