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.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 94060edbbd70..e639645e8fec 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1881,7 +1881,35 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
1881 skb_reserve(skb, hlen); 1881 skb_reserve(skb, hlen);
1882 skb_reset_network_header(skb); 1882 skb_reset_network_header(skb);
1883 1883
1884 data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll); 1884 if (po->tp_tx_has_off) {
1885 int off_min, off_max, off;
1886 off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
1887 off_max = po->tx_ring.frame_size - tp_len;
1888 if (sock->type == SOCK_DGRAM) {
1889 switch (po->tp_version) {
1890 case TPACKET_V2:
1891 off = ph.h2->tp_net;
1892 break;
1893 default:
1894 off = ph.h1->tp_net;
1895 break;
1896 }
1897 } else {
1898 switch (po->tp_version) {
1899 case TPACKET_V2:
1900 off = ph.h2->tp_mac;
1901 break;
1902 default:
1903 off = ph.h1->tp_mac;
1904 break;
1905 }
1906 }
1907 if (unlikely((off < off_min) || (off_max < off)))
1908 return -EINVAL;
1909 data = ph.raw + off;
1910 } else {
1911 data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll);
1912 }
1885 to_write = tp_len; 1913 to_write = tp_len;
1886 1914
1887 if (sock->type == SOCK_DGRAM) { 1915 if (sock->type == SOCK_DGRAM) {
@@ -1907,7 +1935,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
1907 to_write -= dev->hard_header_len; 1935 to_write -= dev->hard_header_len;
1908 } 1936 }
1909 1937
1910 err = -EFAULT;
1911 offset = offset_in_page(data); 1938 offset = offset_in_page(data);
1912 len_max = PAGE_SIZE - offset; 1939 len_max = PAGE_SIZE - offset;
1913 len = ((to_write > len_max) ? len_max : to_write); 1940 len = ((to_write > len_max) ? len_max : to_write);
@@ -1957,7 +1984,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
1957 1984
1958 mutex_lock(&po->pg_vec_lock); 1985 mutex_lock(&po->pg_vec_lock);
1959 1986
1960 err = -EBUSY;
1961 if (saddr == NULL) { 1987 if (saddr == NULL) {
1962 dev = po->prot_hook.dev; 1988 dev = po->prot_hook.dev;
1963 proto = po->num; 1989 proto = po->num;
@@ -2478,7 +2504,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
2478 __be16 proto = (__force __be16)protocol; /* weird, but documented */ 2504 __be16 proto = (__force __be16)protocol; /* weird, but documented */
2479 int err; 2505 int err;
2480 2506
2481 if (!capable(CAP_NET_RAW)) 2507 if (!ns_capable(net->user_ns, CAP_NET_RAW))
2482 return -EPERM; 2508 return -EPERM;
2483 if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW && 2509 if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
2484 sock->type != SOCK_PACKET) 2510 sock->type != SOCK_PACKET)
@@ -3111,6 +3137,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
3111 3137
3112 return fanout_add(sk, val & 0xffff, val >> 16); 3138 return fanout_add(sk, val & 0xffff, val >> 16);
3113 } 3139 }
3140 case PACKET_TX_HAS_OFF:
3141 {
3142 unsigned int val;
3143
3144 if (optlen != sizeof(val))
3145 return -EINVAL;
3146 if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
3147 return -EBUSY;
3148 if (copy_from_user(&val, optval, sizeof(val)))
3149 return -EFAULT;
3150 po->tp_tx_has_off = !!val;
3151 return 0;
3152 }
3114 default: 3153 default:
3115 return -ENOPROTOOPT; 3154 return -ENOPROTOOPT;
3116 } 3155 }
@@ -3202,6 +3241,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
3202 ((u32)po->fanout->type << 16)) : 3241 ((u32)po->fanout->type << 16)) :
3203 0); 3242 0);
3204 break; 3243 break;
3244 case PACKET_TX_HAS_OFF:
3245 val = po->tp_tx_has_off;
3246 break;
3205 default: 3247 default:
3206 return -ENOPROTOOPT; 3248 return -ENOPROTOOPT;
3207 } 3249 }