aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet/af_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r--net/packet/af_packet.c57
1 files changed, 48 insertions, 9 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6dc01bdeb76b..8973ea78831e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -200,7 +200,8 @@ struct packet_sock {
200#endif 200#endif
201 struct packet_type prot_hook; 201 struct packet_type prot_hook;
202 spinlock_t bind_lock; 202 spinlock_t bind_lock;
203 char running; /* prot_hook is attached*/ 203 unsigned int running:1, /* prot_hook is attached*/
204 auxdata:1;
204 int ifindex; /* bound device */ 205 int ifindex; /* bound device */
205 __be16 num; 206 __be16 num;
206#ifdef CONFIG_PACKET_MULTICAST 207#ifdef CONFIG_PACKET_MULTICAST
@@ -214,6 +215,8 @@ struct packet_sock {
214#endif 215#endif
215}; 216};
216 217
218#define PACKET_SKB_CB(__skb) ((struct tpacket_auxdata *)((__skb)->cb))
219
217#ifdef CONFIG_PACKET_MMAP 220#ifdef CONFIG_PACKET_MMAP
218 221
219static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position) 222static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
@@ -462,6 +465,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
462 u8 * skb_head = skb->data; 465 u8 * skb_head = skb->data;
463 int skb_len = skb->len; 466 int skb_len = skb->len;
464 unsigned int snaplen, res; 467 unsigned int snaplen, res;
468 struct tpacket_auxdata *aux;
465 469
466 if (skb->pkt_type == PACKET_LOOPBACK) 470 if (skb->pkt_type == PACKET_LOOPBACK)
467 goto drop; 471 goto drop;
@@ -523,6 +527,15 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
523 if (dev->hard_header_parse) 527 if (dev->hard_header_parse)
524 sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr); 528 sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
525 529
530 aux = PACKET_SKB_CB(skb);
531 aux->tp_status = TP_STATUS_USER;
532 if (skb->ip_summed == CHECKSUM_PARTIAL)
533 aux->tp_status |= TP_STATUS_CSUMNOTREADY;
534 aux->tp_len = skb->len;
535 aux->tp_snaplen = snaplen;
536 aux->tp_mac = 0;
537 aux->tp_net = skb->nh.raw - skb->data;
538
526 if (pskb_trim(skb, snaplen)) 539 if (pskb_trim(skb, snaplen))
527 goto drop_n_acct; 540 goto drop_n_acct;
528 541
@@ -582,11 +595,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
582 else if (skb->pkt_type == PACKET_OUTGOING) { 595 else if (skb->pkt_type == PACKET_OUTGOING) {
583 /* Special case: outgoing packets have ll header at head */ 596 /* Special case: outgoing packets have ll header at head */
584 skb_pull(skb, skb->nh.raw - skb->data); 597 skb_pull(skb, skb->nh.raw - skb->data);
585 if (skb->ip_summed == CHECKSUM_PARTIAL)
586 status |= TP_STATUS_CSUMNOTREADY;
587 } 598 }
588 } 599 }
589 600
601 if (skb->ip_summed == CHECKSUM_PARTIAL)
602 status |= TP_STATUS_CSUMNOTREADY;
603
590 snaplen = skb->len; 604 snaplen = skb->len;
591 605
592 res = run_filter(skb, sk, snaplen); 606 res = run_filter(skb, sk, snaplen);
@@ -1119,6 +1133,11 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1119 if (msg->msg_name) 1133 if (msg->msg_name)
1120 memcpy(msg->msg_name, skb->cb, msg->msg_namelen); 1134 memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
1121 1135
1136 if (pkt_sk(sk)->auxdata) {
1137 struct tpacket_auxdata *aux = PACKET_SKB_CB(skb);
1138 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(*aux), aux);
1139 }
1140
1122 /* 1141 /*
1123 * Free or return the buffer as appropriate. Again this 1142 * Free or return the buffer as appropriate. Again this
1124 * hides all the races and re-entrancy issues from us. 1143 * hides all the races and re-entrancy issues from us.
@@ -1317,6 +1336,7 @@ static int
1317packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) 1336packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
1318{ 1337{
1319 struct sock *sk = sock->sk; 1338 struct sock *sk = sock->sk;
1339 struct packet_sock *po = pkt_sk(sk);
1320 int ret; 1340 int ret;
1321 1341
1322 if (level != SOL_PACKET) 1342 if (level != SOL_PACKET)
@@ -1369,6 +1389,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
1369 return 0; 1389 return 0;
1370 } 1390 }
1371#endif 1391#endif
1392 case PACKET_AUXDATA:
1393 {
1394 int val;
1395
1396 if (optlen < sizeof(val))
1397 return -EINVAL;
1398 if (copy_from_user(&val, optval, sizeof(val)))
1399 return -EFAULT;
1400
1401 po->auxdata = !!val;
1402 return 0;
1403 }
1372 default: 1404 default:
1373 return -ENOPROTOOPT; 1405 return -ENOPROTOOPT;
1374 } 1406 }
@@ -1378,8 +1410,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1378 char __user *optval, int __user *optlen) 1410 char __user *optval, int __user *optlen)
1379{ 1411{
1380 int len; 1412 int len;
1413 int val;
1381 struct sock *sk = sock->sk; 1414 struct sock *sk = sock->sk;
1382 struct packet_sock *po = pkt_sk(sk); 1415 struct packet_sock *po = pkt_sk(sk);
1416 void *data;
1417 struct tpacket_stats st;
1383 1418
1384 if (level != SOL_PACKET) 1419 if (level != SOL_PACKET)
1385 return -ENOPROTOOPT; 1420 return -ENOPROTOOPT;
@@ -1392,9 +1427,6 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1392 1427
1393 switch(optname) { 1428 switch(optname) {
1394 case PACKET_STATISTICS: 1429 case PACKET_STATISTICS:
1395 {
1396 struct tpacket_stats st;
1397
1398 if (len > sizeof(struct tpacket_stats)) 1430 if (len > sizeof(struct tpacket_stats))
1399 len = sizeof(struct tpacket_stats); 1431 len = sizeof(struct tpacket_stats);
1400 spin_lock_bh(&sk->sk_receive_queue.lock); 1432 spin_lock_bh(&sk->sk_receive_queue.lock);
@@ -1403,16 +1435,23 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1403 spin_unlock_bh(&sk->sk_receive_queue.lock); 1435 spin_unlock_bh(&sk->sk_receive_queue.lock);
1404 st.tp_packets += st.tp_drops; 1436 st.tp_packets += st.tp_drops;
1405 1437
1406 if (copy_to_user(optval, &st, len)) 1438 data = &st;
1407 return -EFAULT; 1439 break;
1440 case PACKET_AUXDATA:
1441 if (len > sizeof(int))
1442 len = sizeof(int);
1443 val = po->auxdata;
1444
1445 data = &val;
1408 break; 1446 break;
1409 }
1410 default: 1447 default:
1411 return -ENOPROTOOPT; 1448 return -ENOPROTOOPT;
1412 } 1449 }
1413 1450
1414 if (put_user(len, optlen)) 1451 if (put_user(len, optlen))
1415 return -EFAULT; 1452 return -EFAULT;
1453 if (copy_to_user(optval, data, len))
1454 return -EFAULT;
1416 return 0; 1455 return 0;
1417} 1456}
1418 1457