Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 46936
b: refs/heads/master
c: 8dc4194
h: refs/heads/master
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Feb 8, 2007
1 parent 087e957 commit 6c908d6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8eb9086f21c73b38b5ca27558db4c91d62d0e70b
refs/heads/master: 8dc4194474159660d7f37c495e3fc3f10d0db8cc
10 changes: 10 additions & 0 deletions trunk/include/linux/if_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,23 @@ struct sockaddr_ll
#define PACKET_RX_RING 5
#define PACKET_STATISTICS 6
#define PACKET_COPY_THRESH 7
#define PACKET_AUXDATA 8

struct tpacket_stats
{
unsigned int tp_packets;
unsigned int tp_drops;
};

struct tpacket_auxdata
{
__u32 tp_status;
__u32 tp_len;
__u32 tp_snaplen;
__u16 tp_mac;
__u16 tp_net;
};

struct tpacket_hdr
{
unsigned long tp_status;
Expand Down
57 changes: 48 additions & 9 deletions trunk/net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ struct packet_sock {
#endif
struct packet_type prot_hook;
spinlock_t bind_lock;
char running; /* prot_hook is attached*/
unsigned int running:1, /* prot_hook is attached*/
auxdata:1;
int ifindex; /* bound device */
__be16 num;
#ifdef CONFIG_PACKET_MULTICAST
Expand All @@ -214,6 +215,8 @@ struct packet_sock {
#endif
};

#define PACKET_SKB_CB(__skb) ((struct tpacket_auxdata *)((__skb)->cb))

#ifdef CONFIG_PACKET_MMAP

static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
Expand Down Expand Up @@ -462,6 +465,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
u8 * skb_head = skb->data;
int skb_len = skb->len;
unsigned int snaplen, res;
struct tpacket_auxdata *aux;

if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;
Expand Down Expand Up @@ -523,6 +527,15 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);

aux = PACKET_SKB_CB(skb);
aux->tp_status = TP_STATUS_USER;
if (skb->ip_summed == CHECKSUM_PARTIAL)
aux->tp_status |= TP_STATUS_CSUMNOTREADY;
aux->tp_len = skb->len;
aux->tp_snaplen = snaplen;
aux->tp_mac = 0;
aux->tp_net = skb->nh.raw - skb->data;

if (pskb_trim(skb, snaplen))
goto drop_n_acct;

Expand Down Expand Up @@ -582,11 +595,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
else if (skb->pkt_type == PACKET_OUTGOING) {
/* Special case: outgoing packets have ll header at head */
skb_pull(skb, skb->nh.raw - skb->data);
if (skb->ip_summed == CHECKSUM_PARTIAL)
status |= TP_STATUS_CSUMNOTREADY;
}
}

if (skb->ip_summed == CHECKSUM_PARTIAL)
status |= TP_STATUS_CSUMNOTREADY;

snaplen = skb->len;

res = run_filter(skb, sk, snaplen);
Expand Down Expand Up @@ -1119,6 +1133,11 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
if (msg->msg_name)
memcpy(msg->msg_name, skb->cb, msg->msg_namelen);

if (pkt_sk(sk)->auxdata) {
struct tpacket_auxdata *aux = PACKET_SKB_CB(skb);
put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(*aux), aux);
}

/*
* Free or return the buffer as appropriate. Again this
* hides all the races and re-entrancy issues from us.
Expand Down Expand Up @@ -1317,6 +1336,7 @@ static int
packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
int ret;

if (level != SOL_PACKET)
Expand Down Expand Up @@ -1369,6 +1389,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return 0;
}
#endif
case PACKET_AUXDATA:
{
int val;

if (optlen < sizeof(val))
return -EINVAL;
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;

po->auxdata = !!val;
return 0;
}
default:
return -ENOPROTOOPT;
}
Expand All @@ -1378,8 +1410,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
int len;
int val;
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
void *data;
struct tpacket_stats st;

if (level != SOL_PACKET)
return -ENOPROTOOPT;
Expand All @@ -1392,9 +1427,6 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,

switch(optname) {
case PACKET_STATISTICS:
{
struct tpacket_stats st;

if (len > sizeof(struct tpacket_stats))
len = sizeof(struct tpacket_stats);
spin_lock_bh(&sk->sk_receive_queue.lock);
Expand All @@ -1403,16 +1435,23 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
spin_unlock_bh(&sk->sk_receive_queue.lock);
st.tp_packets += st.tp_drops;

if (copy_to_user(optval, &st, len))
return -EFAULT;
data = &st;
break;
case PACKET_AUXDATA:
if (len > sizeof(int))
len = sizeof(int);
val = po->auxdata;

data = &val;
break;
}
default:
return -ENOPROTOOPT;
}

if (put_user(len, optlen))
return -EFAULT;
if (copy_to_user(optval, data, len))
return -EFAULT;
return 0;
}

Expand Down

0 comments on commit 6c908d6

Please sign in to comment.