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.c79
1 files changed, 66 insertions, 13 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6dc01bdeb76b..a6fa48788e8f 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -60,6 +60,7 @@
60#include <linux/netdevice.h> 60#include <linux/netdevice.h>
61#include <linux/if_packet.h> 61#include <linux/if_packet.h>
62#include <linux/wireless.h> 62#include <linux/wireless.h>
63#include <linux/kernel.h>
63#include <linux/kmod.h> 64#include <linux/kmod.h>
64#include <net/ip.h> 65#include <net/ip.h>
65#include <net/protocol.h> 66#include <net/protocol.h>
@@ -200,7 +201,8 @@ struct packet_sock {
200#endif 201#endif
201 struct packet_type prot_hook; 202 struct packet_type prot_hook;
202 spinlock_t bind_lock; 203 spinlock_t bind_lock;
203 char running; /* prot_hook is attached*/ 204 unsigned int running:1, /* prot_hook is attached*/
205 auxdata:1;
204 int ifindex; /* bound device */ 206 int ifindex; /* bound device */
205 __be16 num; 207 __be16 num;
206#ifdef CONFIG_PACKET_MULTICAST 208#ifdef CONFIG_PACKET_MULTICAST
@@ -214,6 +216,16 @@ struct packet_sock {
214#endif 216#endif
215}; 217};
216 218
219struct packet_skb_cb {
220 unsigned int origlen;
221 union {
222 struct sockaddr_pkt pkt;
223 struct sockaddr_ll ll;
224 } sa;
225};
226
227#define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb))
228
217#ifdef CONFIG_PACKET_MMAP 229#ifdef CONFIG_PACKET_MMAP
218 230
219static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position) 231static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
@@ -293,7 +305,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
293 /* drop conntrack reference */ 305 /* drop conntrack reference */
294 nf_reset(skb); 306 nf_reset(skb);
295 307
296 spkt = (struct sockaddr_pkt*)skb->cb; 308 spkt = &PACKET_SKB_CB(skb)->sa.pkt;
297 309
298 skb_push(skb, skb->data-skb->mac.raw); 310 skb_push(skb, skb->data-skb->mac.raw);
299 311
@@ -512,7 +524,10 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
512 skb = nskb; 524 skb = nskb;
513 } 525 }
514 526
515 sll = (struct sockaddr_ll*)skb->cb; 527 BUILD_BUG_ON(sizeof(*PACKET_SKB_CB(skb)) + MAX_ADDR_LEN - 8 >
528 sizeof(skb->cb));
529
530 sll = &PACKET_SKB_CB(skb)->sa.ll;
516 sll->sll_family = AF_PACKET; 531 sll->sll_family = AF_PACKET;
517 sll->sll_hatype = dev->type; 532 sll->sll_hatype = dev->type;
518 sll->sll_protocol = skb->protocol; 533 sll->sll_protocol = skb->protocol;
@@ -523,6 +538,8 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
523 if (dev->hard_header_parse) 538 if (dev->hard_header_parse)
524 sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr); 539 sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
525 540
541 PACKET_SKB_CB(skb)->origlen = skb->len;
542
526 if (pskb_trim(skb, snaplen)) 543 if (pskb_trim(skb, snaplen))
527 goto drop_n_acct; 544 goto drop_n_acct;
528 545
@@ -582,11 +599,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
582 else if (skb->pkt_type == PACKET_OUTGOING) { 599 else if (skb->pkt_type == PACKET_OUTGOING) {
583 /* Special case: outgoing packets have ll header at head */ 600 /* Special case: outgoing packets have ll header at head */
584 skb_pull(skb, skb->nh.raw - skb->data); 601 skb_pull(skb, skb->nh.raw - skb->data);
585 if (skb->ip_summed == CHECKSUM_PARTIAL)
586 status |= TP_STATUS_CSUMNOTREADY;
587 } 602 }
588 } 603 }
589 604
605 if (skb->ip_summed == CHECKSUM_PARTIAL)
606 status |= TP_STATUS_CSUMNOTREADY;
607
590 snaplen = skb->len; 608 snaplen = skb->len;
591 609
592 res = run_filter(skb, sk, snaplen); 610 res = run_filter(skb, sk, snaplen);
@@ -1092,7 +1110,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1092 * it in now. 1110 * it in now.
1093 */ 1111 */
1094 1112
1095 sll = (struct sockaddr_ll*)skb->cb; 1113 sll = &PACKET_SKB_CB(skb)->sa.ll;
1096 if (sock->type == SOCK_PACKET) 1114 if (sock->type == SOCK_PACKET)
1097 msg->msg_namelen = sizeof(struct sockaddr_pkt); 1115 msg->msg_namelen = sizeof(struct sockaddr_pkt);
1098 else 1116 else
@@ -1117,7 +1135,22 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1117 sock_recv_timestamp(msg, sk, skb); 1135 sock_recv_timestamp(msg, sk, skb);
1118 1136
1119 if (msg->msg_name) 1137 if (msg->msg_name)
1120 memcpy(msg->msg_name, skb->cb, msg->msg_namelen); 1138 memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
1139 msg->msg_namelen);
1140
1141 if (pkt_sk(sk)->auxdata) {
1142 struct tpacket_auxdata aux;
1143
1144 aux.tp_status = TP_STATUS_USER;
1145 if (skb->ip_summed == CHECKSUM_PARTIAL)
1146 aux.tp_status |= TP_STATUS_CSUMNOTREADY;
1147 aux.tp_len = PACKET_SKB_CB(skb)->origlen;
1148 aux.tp_snaplen = skb->len;
1149 aux.tp_mac = 0;
1150 aux.tp_net = skb->nh.raw - skb->data;
1151
1152 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
1153 }
1121 1154
1122 /* 1155 /*
1123 * Free or return the buffer as appropriate. Again this 1156 * Free or return the buffer as appropriate. Again this
@@ -1317,6 +1350,7 @@ static int
1317packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) 1350packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
1318{ 1351{
1319 struct sock *sk = sock->sk; 1352 struct sock *sk = sock->sk;
1353 struct packet_sock *po = pkt_sk(sk);
1320 int ret; 1354 int ret;
1321 1355
1322 if (level != SOL_PACKET) 1356 if (level != SOL_PACKET)
@@ -1369,6 +1403,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
1369 return 0; 1403 return 0;
1370 } 1404 }
1371#endif 1405#endif
1406 case PACKET_AUXDATA:
1407 {
1408 int val;
1409
1410 if (optlen < sizeof(val))
1411 return -EINVAL;
1412 if (copy_from_user(&val, optval, sizeof(val)))
1413 return -EFAULT;
1414
1415 po->auxdata = !!val;
1416 return 0;
1417 }
1372 default: 1418 default:
1373 return -ENOPROTOOPT; 1419 return -ENOPROTOOPT;
1374 } 1420 }
@@ -1378,8 +1424,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1378 char __user *optval, int __user *optlen) 1424 char __user *optval, int __user *optlen)
1379{ 1425{
1380 int len; 1426 int len;
1427 int val;
1381 struct sock *sk = sock->sk; 1428 struct sock *sk = sock->sk;
1382 struct packet_sock *po = pkt_sk(sk); 1429 struct packet_sock *po = pkt_sk(sk);
1430 void *data;
1431 struct tpacket_stats st;
1383 1432
1384 if (level != SOL_PACKET) 1433 if (level != SOL_PACKET)
1385 return -ENOPROTOOPT; 1434 return -ENOPROTOOPT;
@@ -1392,9 +1441,6 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1392 1441
1393 switch(optname) { 1442 switch(optname) {
1394 case PACKET_STATISTICS: 1443 case PACKET_STATISTICS:
1395 {
1396 struct tpacket_stats st;
1397
1398 if (len > sizeof(struct tpacket_stats)) 1444 if (len > sizeof(struct tpacket_stats))
1399 len = sizeof(struct tpacket_stats); 1445 len = sizeof(struct tpacket_stats);
1400 spin_lock_bh(&sk->sk_receive_queue.lock); 1446 spin_lock_bh(&sk->sk_receive_queue.lock);
@@ -1403,16 +1449,23 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1403 spin_unlock_bh(&sk->sk_receive_queue.lock); 1449 spin_unlock_bh(&sk->sk_receive_queue.lock);
1404 st.tp_packets += st.tp_drops; 1450 st.tp_packets += st.tp_drops;
1405 1451
1406 if (copy_to_user(optval, &st, len)) 1452 data = &st;
1407 return -EFAULT; 1453 break;
1454 case PACKET_AUXDATA:
1455 if (len > sizeof(int))
1456 len = sizeof(int);
1457 val = po->auxdata;
1458
1459 data = &val;
1408 break; 1460 break;
1409 }
1410 default: 1461 default:
1411 return -ENOPROTOOPT; 1462 return -ENOPROTOOPT;
1412 } 1463 }
1413 1464
1414 if (put_user(len, optlen)) 1465 if (put_user(len, optlen))
1415 return -EFAULT; 1466 return -EFAULT;
1467 if (copy_to_user(optval, data, len))
1468 return -EFAULT;
1416 return 0; 1469 return 0;
1417} 1470}
1418 1471