diff options
Diffstat (limited to 'net/llc/llc_sap.c')
-rw-r--r-- | net/llc/llc_sap.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 008de1fc42ca..39760d013ce2 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c | |||
@@ -297,6 +297,17 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, | |||
297 | llc_sap_state_process(sap, skb); | 297 | llc_sap_state_process(sap, skb); |
298 | } | 298 | } |
299 | 299 | ||
300 | static inline bool llc_dgram_match(const struct llc_sap *sap, | ||
301 | const struct llc_addr *laddr, | ||
302 | const struct sock *sk) | ||
303 | { | ||
304 | struct llc_sock *llc = llc_sk(sk); | ||
305 | |||
306 | return sk->sk_type == SOCK_DGRAM && | ||
307 | llc->laddr.lsap == laddr->lsap && | ||
308 | llc_mac_match(llc->laddr.mac, laddr->mac); | ||
309 | } | ||
310 | |||
300 | /** | 311 | /** |
301 | * llc_lookup_dgram - Finds dgram socket for the local sap/mac | 312 | * llc_lookup_dgram - Finds dgram socket for the local sap/mac |
302 | * @sap: SAP | 313 | * @sap: SAP |
@@ -309,25 +320,41 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap, | |||
309 | const struct llc_addr *laddr) | 320 | const struct llc_addr *laddr) |
310 | { | 321 | { |
311 | struct sock *rc; | 322 | struct sock *rc; |
312 | struct hlist_node *node; | 323 | struct hlist_nulls_node *node; |
313 | 324 | ||
314 | read_lock_bh(&sap->sk_list.lock); | 325 | rcu_read_lock_bh(); |
315 | sk_for_each(rc, node, &sap->sk_list.list) { | 326 | again: |
316 | struct llc_sock *llc = llc_sk(rc); | 327 | sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { |
317 | 328 | if (llc_dgram_match(sap, laddr, rc)) { | |
318 | if (rc->sk_type == SOCK_DGRAM && | 329 | /* Extra checks required by SLAB_DESTROY_BY_RCU */ |
319 | llc->laddr.lsap == laddr->lsap && | 330 | if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) |
320 | llc_mac_match(llc->laddr.mac, laddr->mac)) { | 331 | goto again; |
321 | sock_hold(rc); | 332 | if (unlikely(llc_sk(rc)->sap != sap || |
333 | !llc_dgram_match(sap, laddr, rc))) { | ||
334 | sock_put(rc); | ||
335 | continue; | ||
336 | } | ||
322 | goto found; | 337 | goto found; |
323 | } | 338 | } |
324 | } | 339 | } |
325 | rc = NULL; | 340 | rc = NULL; |
326 | found: | 341 | found: |
327 | read_unlock_bh(&sap->sk_list.lock); | 342 | rcu_read_unlock_bh(); |
328 | return rc; | 343 | return rc; |
329 | } | 344 | } |
330 | 345 | ||
346 | static inline bool llc_mcast_match(const struct llc_sap *sap, | ||
347 | const struct llc_addr *laddr, | ||
348 | const struct sk_buff *skb, | ||
349 | const struct sock *sk) | ||
350 | { | ||
351 | struct llc_sock *llc = llc_sk(sk); | ||
352 | |||
353 | return sk->sk_type == SOCK_DGRAM && | ||
354 | llc->laddr.lsap == laddr->lsap && | ||
355 | llc->dev == skb->dev; | ||
356 | } | ||
357 | |||
331 | /** | 358 | /** |
332 | * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets. | 359 | * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets. |
333 | * @sap: SAP | 360 | * @sap: SAP |
@@ -341,20 +368,13 @@ static void llc_sap_mcast(struct llc_sap *sap, | |||
341 | struct sk_buff *skb) | 368 | struct sk_buff *skb) |
342 | { | 369 | { |
343 | struct sock *sk; | 370 | struct sock *sk; |
344 | struct hlist_node *node; | 371 | struct hlist_nulls_node *node; |
345 | 372 | ||
346 | read_lock_bh(&sap->sk_list.lock); | 373 | spin_lock_bh(&sap->sk_lock); |
347 | sk_for_each(sk, node, &sap->sk_list.list) { | 374 | sk_nulls_for_each_rcu(sk, node, &sap->sk_list) { |
348 | struct llc_sock *llc = llc_sk(sk); | ||
349 | struct sk_buff *skb1; | 375 | struct sk_buff *skb1; |
350 | 376 | ||
351 | if (sk->sk_type != SOCK_DGRAM) | 377 | if (!llc_mcast_match(sap, laddr, skb, sk)) |
352 | continue; | ||
353 | |||
354 | if (llc->laddr.lsap != laddr->lsap) | ||
355 | continue; | ||
356 | |||
357 | if (llc->dev != skb->dev) | ||
358 | continue; | 378 | continue; |
359 | 379 | ||
360 | skb1 = skb_clone(skb, GFP_ATOMIC); | 380 | skb1 = skb_clone(skb, GFP_ATOMIC); |
@@ -365,7 +385,7 @@ static void llc_sap_mcast(struct llc_sap *sap, | |||
365 | llc_sap_rcv(sap, skb1, sk); | 385 | llc_sap_rcv(sap, skb1, sk); |
366 | sock_put(sk); | 386 | sock_put(sk); |
367 | } | 387 | } |
368 | read_unlock_bh(&sap->sk_list.lock); | 388 | spin_unlock_bh(&sap->sk_lock); |
369 | } | 389 | } |
370 | 390 | ||
371 | 391 | ||