aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet/af_packet.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-23 19:49:31 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-23 19:49:31 -0400
commita4c12d6c5dde48c69464baf7c703e425ee511433 (patch)
tree73c375e41a353e2da0461ff30d744bff73958b08 /net/packet/af_packet.c
parent73af07de3e32b9ac328c3d1417258bb98a9b0a9b (diff)
parent3b9f9a1c3903b64c38505f9fed3bb11e48dbc931 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (353 commits) [IPV6] ADDRCONF: Mobile IPv6 Home Address support. [IPV6] ADDRCONF: Allow non-DAD'able addresses. [IPV6] NDISC: Fix is_router flag setting. [IPV6] ADDRCONF: Convert addrconf_lock to RCU. [IPV6] NDISC: Add proxy_ndp sysctl. [IPV6] NDISC: Set per-entry is_router flag in Proxy NA. [IPV6] NDISC: Avoid updating neighbor cache for proxied address in receiving NA. [IPV6]: Don't forward packets to proxied link-local address. [IPV6] NDISC: Handle NDP messages to proxied addresses. [NETFILTER]: PPTP conntrack: fix another GRE keymap leak [NETFILTER]: PPTP conntrack: fix GRE keymap leak [NETFILTER]: PPTP conntrack: fix PPTP_IN_CALL message types [NETFILTER]: PPTP conntrack: check call ID before changing state [NETFILTER]: PPTP conntrack: clean up debugging cruft [NETFILTER]: PPTP conntrack: consolidate header parsing [NETFILTER]: PPTP conntrack: consolidate header size checks [NETFILTER]: PPTP conntrack: simplify expectation handling [NETFILTER]: PPTP conntrack: remove unnecessary cid/pcid header pointers [NETFILTER]: PPTP conntrack: fix header definitions [NETFILTER]: PPTP conntrack: remove more dead code ...
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r--net/packet/af_packet.c45
1 files changed, 19 insertions, 26 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 4172a5235916..f4ccb90e6739 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -427,21 +427,24 @@ out_unlock:
427} 427}
428#endif 428#endif
429 429
430static inline unsigned run_filter(struct sk_buff *skb, struct sock *sk, unsigned res) 430static inline int run_filter(struct sk_buff *skb, struct sock *sk,
431 unsigned *snaplen)
431{ 432{
432 struct sk_filter *filter; 433 struct sk_filter *filter;
434 int err = 0;
433 435
434 bh_lock_sock(sk); 436 rcu_read_lock_bh();
435 filter = sk->sk_filter; 437 filter = rcu_dereference(sk->sk_filter);
436 /* 438 if (filter != NULL) {
437 * Our caller already checked that filter != NULL but we need to 439 err = sk_run_filter(skb, filter->insns, filter->len);
438 * verify that under bh_lock_sock() to be safe 440 if (!err)
439 */ 441 err = -EPERM;
440 if (likely(filter != NULL)) 442 else if (*snaplen > err)
441 res = sk_run_filter(skb, filter->insns, filter->len); 443 *snaplen = err;
442 bh_unlock_sock(sk); 444 }
445 rcu_read_unlock_bh();
443 446
444 return res; 447 return err;
445} 448}
446 449
447/* 450/*
@@ -491,13 +494,8 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
491 494
492 snaplen = skb->len; 495 snaplen = skb->len;
493 496
494 if (sk->sk_filter) { 497 if (run_filter(skb, sk, &snaplen) < 0)
495 unsigned res = run_filter(skb, sk, snaplen); 498 goto drop_n_restore;
496 if (res == 0)
497 goto drop_n_restore;
498 if (snaplen > res)
499 snaplen = res;
500 }
501 499
502 if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= 500 if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
503 (unsigned)sk->sk_rcvbuf) 501 (unsigned)sk->sk_rcvbuf)
@@ -586,20 +584,15 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
586 else if (skb->pkt_type == PACKET_OUTGOING) { 584 else if (skb->pkt_type == PACKET_OUTGOING) {
587 /* Special case: outgoing packets have ll header at head */ 585 /* Special case: outgoing packets have ll header at head */
588 skb_pull(skb, skb->nh.raw - skb->data); 586 skb_pull(skb, skb->nh.raw - skb->data);
589 if (skb->ip_summed == CHECKSUM_HW) 587 if (skb->ip_summed == CHECKSUM_PARTIAL)
590 status |= TP_STATUS_CSUMNOTREADY; 588 status |= TP_STATUS_CSUMNOTREADY;
591 } 589 }
592 } 590 }
593 591
594 snaplen = skb->len; 592 snaplen = skb->len;
595 593
596 if (sk->sk_filter) { 594 if (run_filter(skb, sk, &snaplen) < 0)
597 unsigned res = run_filter(skb, sk, snaplen); 595 goto drop_n_restore;
598 if (res == 0)
599 goto drop_n_restore;
600 if (snaplen > res)
601 snaplen = res;
602 }
603 596
604 if (sk->sk_type == SOCK_DGRAM) { 597 if (sk->sk_type == SOCK_DGRAM) {
605 macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16; 598 macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;