diff options
Diffstat (limited to 'net/llc')
-rw-r--r-- | net/llc/af_llc.c | 11 | ||||
-rw-r--r-- | net/llc/llc_c_ac.c | 1 | ||||
-rw-r--r-- | net/llc/llc_conn.c | 28 | ||||
-rw-r--r-- | net/llc/llc_core.c | 34 | ||||
-rw-r--r-- | net/llc/llc_input.c | 9 |
5 files changed, 39 insertions, 44 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index ad9aad807aa8..a75b8f2aab19 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * See the GNU General Public License for more details. | 21 | * See the GNU General Public License for more details. |
22 | */ | 22 | */ |
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #include <linux/compiler.h> | ||
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
26 | #include <linux/rtnetlink.h> | 27 | #include <linux/rtnetlink.h> |
@@ -188,10 +189,6 @@ static int llc_ui_release(struct socket *sock) | |||
188 | if (!sock_flag(sk, SOCK_ZAPPED)) | 189 | if (!sock_flag(sk, SOCK_ZAPPED)) |
189 | llc_sap_remove_socket(llc->sap, sk); | 190 | llc_sap_remove_socket(llc->sap, sk); |
190 | release_sock(sk); | 191 | release_sock(sk); |
191 | if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) { | ||
192 | llc_release_sockets(llc->sap); | ||
193 | llc_sap_close(llc->sap); | ||
194 | } | ||
195 | if (llc->dev) | 192 | if (llc->dev) |
196 | dev_put(llc->dev); | 193 | dev_put(llc->dev); |
197 | sock_put(sk); | 194 | sock_put(sk); |
@@ -220,6 +217,7 @@ static int llc_ui_autoport(void) | |||
220 | llc_ui_sap_last_autoport = i + 2; | 217 | llc_ui_sap_last_autoport = i + 2; |
221 | goto out; | 218 | goto out; |
222 | } | 219 | } |
220 | llc_sap_put(sap); | ||
223 | } | 221 | } |
224 | llc_ui_sap_last_autoport = LLC_SAP_DYN_START; | 222 | llc_ui_sap_last_autoport = LLC_SAP_DYN_START; |
225 | tries++; | 223 | tries++; |
@@ -310,6 +308,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
310 | rc = -EBUSY; /* some other network layer is using the sap */ | 308 | rc = -EBUSY; /* some other network layer is using the sap */ |
311 | if (!sap) | 309 | if (!sap) |
312 | goto out; | 310 | goto out; |
311 | llc_sap_hold(sap); | ||
313 | } else { | 312 | } else { |
314 | struct llc_addr laddr, daddr; | 313 | struct llc_addr laddr, daddr; |
315 | struct sock *ask; | 314 | struct sock *ask; |
@@ -326,7 +325,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
326 | ask = llc_lookup_established(sap, &daddr, &laddr); | 325 | ask = llc_lookup_established(sap, &daddr, &laddr); |
327 | if (ask) { | 326 | if (ask) { |
328 | sock_put(ask); | 327 | sock_put(ask); |
329 | goto out; | 328 | goto out_put; |
330 | } | 329 | } |
331 | } | 330 | } |
332 | llc->laddr.lsap = addr->sllc_sap; | 331 | llc->laddr.lsap = addr->sllc_sap; |
@@ -336,6 +335,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) | |||
336 | llc_sap_add_socket(sap, sk); | 335 | llc_sap_add_socket(sap, sk); |
337 | sock_reset_flag(sk, SOCK_ZAPPED); | 336 | sock_reset_flag(sk, SOCK_ZAPPED); |
338 | rc = 0; | 337 | rc = 0; |
338 | out_put: | ||
339 | llc_sap_put(sap); | ||
339 | out: | 340 | out: |
340 | return rc; | 341 | return rc; |
341 | } | 342 | } |
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index c1e75103189a..05236c2cbb9e 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c | |||
@@ -75,6 +75,7 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) | |||
75 | llc->dev = skb->dev; | 75 | llc->dev = skb->dev; |
76 | ev->ind_prim = LLC_CONN_PRIM; | 76 | ev->ind_prim = LLC_CONN_PRIM; |
77 | rc = 0; | 77 | rc = 0; |
78 | llc_sap_put(sap); | ||
78 | } | 79 | } |
79 | return rc; | 80 | return rc; |
80 | } | 81 | } |
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 9f0e10e0978d..ab9e6d7e2875 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c | |||
@@ -633,6 +633,7 @@ static int llc_find_offset(int state, int ev_type) | |||
633 | */ | 633 | */ |
634 | void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) | 634 | void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) |
635 | { | 635 | { |
636 | llc_sap_hold(sap); | ||
636 | write_lock_bh(&sap->sk_list.lock); | 637 | write_lock_bh(&sap->sk_list.lock); |
637 | llc_sk(sk)->sap = sap; | 638 | llc_sk(sk)->sap = sap; |
638 | sk_add_node(sk, &sap->sk_list.list); | 639 | sk_add_node(sk, &sap->sk_list.list); |
@@ -652,6 +653,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) | |||
652 | write_lock_bh(&sap->sk_list.lock); | 653 | write_lock_bh(&sap->sk_list.lock); |
653 | sk_del_node_init(sk); | 654 | sk_del_node_init(sk); |
654 | write_unlock_bh(&sap->sk_list.lock); | 655 | write_unlock_bh(&sap->sk_list.lock); |
656 | llc_sap_put(sap); | ||
655 | } | 657 | } |
656 | 658 | ||
657 | /** | 659 | /** |
@@ -731,32 +733,6 @@ static atomic_t llc_sock_nr; | |||
731 | #endif | 733 | #endif |
732 | 734 | ||
733 | /** | 735 | /** |
734 | * llc_release_sockets - releases all sockets in a sap | ||
735 | * @sap: sap to release its sockets | ||
736 | * | ||
737 | * Releases all connections of a sap. Returns 0 if all actions complete | ||
738 | * successfully, nonzero otherwise | ||
739 | */ | ||
740 | int llc_release_sockets(struct llc_sap *sap) | ||
741 | { | ||
742 | int rc = 0; | ||
743 | struct sock *sk; | ||
744 | struct hlist_node *node; | ||
745 | |||
746 | write_lock_bh(&sap->sk_list.lock); | ||
747 | |||
748 | sk_for_each(sk, node, &sap->sk_list.list) { | ||
749 | llc_sk(sk)->state = LLC_CONN_STATE_TEMP; | ||
750 | |||
751 | if (llc_send_disc(sk)) | ||
752 | rc = 1; | ||
753 | } | ||
754 | |||
755 | write_unlock_bh(&sap->sk_list.lock); | ||
756 | return rc; | ||
757 | } | ||
758 | |||
759 | /** | ||
760 | * llc_backlog_rcv - Processes rx frames and expired timers. | 736 | * llc_backlog_rcv - Processes rx frames and expired timers. |
761 | * @sk: LLC sock (p8022 connection) | 737 | * @sk: LLC sock (p8022 connection) |
762 | * @skb: queued rx frame or event | 738 | * @skb: queued rx frame or event |
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 9727455bf0e7..9ccff1266b26 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c | |||
@@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void) | |||
40 | sap->state = LLC_SAP_STATE_ACTIVE; | 40 | sap->state = LLC_SAP_STATE_ACTIVE; |
41 | memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); | 41 | memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); |
42 | rwlock_init(&sap->sk_list.lock); | 42 | rwlock_init(&sap->sk_list.lock); |
43 | atomic_set(&sap->refcnt, 1); | ||
43 | } | 44 | } |
44 | return sap; | 45 | return sap; |
45 | } | 46 | } |
@@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void) | |||
52 | */ | 53 | */ |
53 | static void llc_add_sap(struct llc_sap *sap) | 54 | static void llc_add_sap(struct llc_sap *sap) |
54 | { | 55 | { |
55 | write_lock_bh(&llc_sap_list_lock); | ||
56 | list_add_tail(&sap->node, &llc_sap_list); | 56 | list_add_tail(&sap->node, &llc_sap_list); |
57 | write_unlock_bh(&llc_sap_list_lock); | ||
58 | } | 57 | } |
59 | 58 | ||
60 | /** | 59 | /** |
@@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap) | |||
70 | write_unlock_bh(&llc_sap_list_lock); | 69 | write_unlock_bh(&llc_sap_list_lock); |
71 | } | 70 | } |
72 | 71 | ||
72 | struct llc_sap *__llc_sap_find(unsigned char sap_value) | ||
73 | { | ||
74 | struct llc_sap* sap; | ||
75 | |||
76 | list_for_each_entry(sap, &llc_sap_list, node) | ||
77 | if (sap->laddr.lsap == sap_value) | ||
78 | goto out; | ||
79 | sap = NULL; | ||
80 | out: | ||
81 | return sap; | ||
82 | } | ||
83 | |||
73 | /** | 84 | /** |
74 | * llc_sap_find - searchs a SAP in station | 85 | * llc_sap_find - searchs a SAP in station |
75 | * @sap_value: sap to be found | 86 | * @sap_value: sap to be found |
76 | * | 87 | * |
77 | * Searchs for a sap in the sap list of the LLC's station upon the sap ID. | 88 | * Searchs for a sap in the sap list of the LLC's station upon the sap ID. |
89 | * If the sap is found it will be refcounted and the user will have to do | ||
90 | * a llc_sap_put after use. | ||
78 | * Returns the sap or %NULL if not found. | 91 | * Returns the sap or %NULL if not found. |
79 | */ | 92 | */ |
80 | struct llc_sap *llc_sap_find(unsigned char sap_value) | 93 | struct llc_sap *llc_sap_find(unsigned char sap_value) |
@@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) | |||
82 | struct llc_sap* sap; | 95 | struct llc_sap* sap; |
83 | 96 | ||
84 | read_lock_bh(&llc_sap_list_lock); | 97 | read_lock_bh(&llc_sap_list_lock); |
85 | list_for_each_entry(sap, &llc_sap_list, node) | 98 | sap = __llc_sap_find(sap_value); |
86 | if (sap->laddr.lsap == sap_value) | 99 | if (sap) |
87 | goto out; | 100 | llc_sap_hold(sap); |
88 | sap = NULL; | ||
89 | out: | ||
90 | read_unlock_bh(&llc_sap_list_lock); | 101 | read_unlock_bh(&llc_sap_list_lock); |
91 | return sap; | 102 | return sap; |
92 | } | 103 | } |
@@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap, | |||
106 | struct packet_type *pt, | 117 | struct packet_type *pt, |
107 | struct net_device *orig_dev)) | 118 | struct net_device *orig_dev)) |
108 | { | 119 | { |
109 | struct llc_sap *sap = llc_sap_find(lsap); | 120 | struct llc_sap *sap = NULL; |
110 | 121 | ||
111 | if (sap) { /* SAP already exists */ | 122 | write_lock_bh(&llc_sap_list_lock); |
112 | sap = NULL; | 123 | if (__llc_sap_find(lsap)) /* SAP already exists */ |
113 | goto out; | 124 | goto out; |
114 | } | ||
115 | sap = llc_sap_alloc(); | 125 | sap = llc_sap_alloc(); |
116 | if (!sap) | 126 | if (!sap) |
117 | goto out; | 127 | goto out; |
118 | sap->laddr.lsap = lsap; | 128 | sap->laddr.lsap = lsap; |
119 | sap->rcv_func = func; | 129 | sap->rcv_func = func; |
130 | llc_sap_hold(sap); | ||
120 | llc_add_sap(sap); | 131 | llc_add_sap(sap); |
121 | out: | 132 | out: |
133 | write_unlock_bh(&llc_sap_list_lock); | ||
122 | return sap; | 134 | return sap; |
123 | } | 135 | } |
124 | 136 | ||
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 60c1acac7c97..789eec426451 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c | |||
@@ -166,17 +166,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
166 | */ | 166 | */ |
167 | if (sap->rcv_func) { | 167 | if (sap->rcv_func) { |
168 | sap->rcv_func(skb, dev, pt, orig_dev); | 168 | sap->rcv_func(skb, dev, pt, orig_dev); |
169 | goto out; | 169 | goto out_put; |
170 | } | 170 | } |
171 | dest = llc_pdu_type(skb); | 171 | dest = llc_pdu_type(skb); |
172 | if (unlikely(!dest || !llc_type_handlers[dest - 1])) | 172 | if (unlikely(!dest || !llc_type_handlers[dest - 1])) |
173 | goto drop; | 173 | goto drop_put; |
174 | llc_type_handlers[dest - 1](sap, skb); | 174 | llc_type_handlers[dest - 1](sap, skb); |
175 | out_put: | ||
176 | llc_sap_put(sap); | ||
175 | out: | 177 | out: |
176 | return 0; | 178 | return 0; |
177 | drop: | 179 | drop: |
178 | kfree_skb(skb); | 180 | kfree_skb(skb); |
179 | goto out; | 181 | goto out; |
182 | drop_put: | ||
183 | kfree_skb(skb); | ||
184 | goto out_put; | ||
180 | handle_station: | 185 | handle_station: |
181 | if (!llc_station_handler) | 186 | if (!llc_station_handler) |
182 | goto drop; | 187 | goto drop; |