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); |
