aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_packet.h1
-rw-r--r--net/packet/af_packet.c29
2 files changed, 27 insertions, 3 deletions
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index a630295b255f..18db0668065a 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -45,6 +45,7 @@ struct sockaddr_ll
45#define PACKET_ORIGDEV 9 45#define PACKET_ORIGDEV 9
46#define PACKET_VERSION 10 46#define PACKET_VERSION 10
47#define PACKET_HDRLEN 11 47#define PACKET_HDRLEN 11
48#define PACKET_RESERVE 12
48 49
49struct tpacket_stats 50struct tpacket_stats
50{ 51{
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index db792e02a37f..de73bcb5235a 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -188,6 +188,7 @@ struct packet_sock {
188 unsigned int pg_vec_len; 188 unsigned int pg_vec_len;
189 enum tpacket_versions tp_version; 189 enum tpacket_versions tp_version;
190 unsigned int tp_hdrlen; 190 unsigned int tp_hdrlen;
191 unsigned int tp_reserve;
191#endif 192#endif
192}; 193};
193 194
@@ -635,11 +636,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
635 snaplen = res; 636 snaplen = res;
636 637
637 if (sk->sk_type == SOCK_DGRAM) { 638 if (sk->sk_type == SOCK_DGRAM) {
638 macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16; 639 macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 +
640 po->tp_reserve;
639 } else { 641 } else {
640 unsigned maclen = skb_network_offset(skb); 642 unsigned maclen = skb_network_offset(skb);
641 netoff = TPACKET_ALIGN(po->tp_hdrlen + 643 netoff = TPACKET_ALIGN(po->tp_hdrlen +
642 (maclen < 16 ? 16 : maclen)); 644 (maclen < 16 ? 16 : maclen)) +
645 po->tp_reserve;
643 macoff = netoff - maclen; 646 macoff = netoff - maclen;
644 } 647 }
645 648
@@ -1448,6 +1451,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
1448 return -EINVAL; 1451 return -EINVAL;
1449 } 1452 }
1450 } 1453 }
1454 case PACKET_RESERVE:
1455 {
1456 unsigned int val;
1457
1458 if (optlen != sizeof(val))
1459 return -EINVAL;
1460 if (po->pg_vec)
1461 return -EBUSY;
1462 if (copy_from_user(&val, optval, sizeof(val)))
1463 return -EFAULT;
1464 po->tp_reserve = val;
1465 return 0;
1466 }
1451#endif 1467#endif
1452 case PACKET_AUXDATA: 1468 case PACKET_AUXDATA:
1453 { 1469 {
@@ -1547,6 +1563,12 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
1547 } 1563 }
1548 data = &val; 1564 data = &val;
1549 break; 1565 break;
1566 case PACKET_RESERVE:
1567 if (len > sizeof(unsigned int))
1568 len = sizeof(unsigned int);
1569 val = po->tp_reserve;
1570 data = &val;
1571 break;
1550#endif 1572#endif
1551 default: 1573 default:
1552 return -ENOPROTOOPT; 1574 return -ENOPROTOOPT;
@@ -1790,7 +1812,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
1790 return -EINVAL; 1812 return -EINVAL;
1791 if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) 1813 if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
1792 return -EINVAL; 1814 return -EINVAL;
1793 if (unlikely(req->tp_frame_size < po->tp_hdrlen)) 1815 if (unlikely(req->tp_frame_size < po->tp_hdrlen +
1816 po->tp_reserve))
1794 return -EINVAL; 1817 return -EINVAL;
1795 if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) 1818 if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
1796 return -EINVAL; 1819 return -EINVAL;