You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/target/linux/generic/patches-2.6.30/240-packet_socket_type.patch

133 lines
3.3 KiB
Diff

This patch allows the user to specify desired packet types (outgoing,
broadcast, unicast, etc.) on packet sockets via setsockopt.
This can reduce the load in situations where only a limited number
of packet types are necessary
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -31,6 +31,8 @@ struct sockaddr_ll
/* These ones are invisible by user level */
#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
#define PACKET_FASTROUTE 6 /* Fastrouted frame */
+#define PACKET_MASK_ANY 0xffffffff /* mask for packet type bits */
+
/* Packet socket options */
@@ -46,6 +48,7 @@ struct sockaddr_ll
#define PACKET_VERSION 10
#define PACKET_HDRLEN 11
#define PACKET_RESERVE 12
+#define PACKET_RECV_TYPE 13
struct tpacket_stats
{
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -192,6 +192,7 @@ struct packet_sock {
unsigned int tp_hdrlen;
unsigned int tp_reserve;
#endif
+ unsigned int pkt_type;
};
struct packet_skb_cb {
@@ -282,6 +283,7 @@ static int packet_rcv_spkt(struct sk_buf
{
struct sock *sk;
struct sockaddr_pkt *spkt;
+ struct packet_sock *po;
/*
* When we registered the protocol we saved the socket in the data
@@ -289,6 +291,7 @@ static int packet_rcv_spkt(struct sk_buf
*/
sk = pt->af_packet_priv;
+ po = pkt_sk(sk);
/*
* Yank back the headers [hope the device set this
@@ -301,7 +304,7 @@ static int packet_rcv_spkt(struct sk_buf
* so that this procedure is noop.
*/
- if (skb->pkt_type == PACKET_LOOPBACK)
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
goto out;
if (dev_net(dev) != sock_net(sk))
@@ -486,12 +489,12 @@ static int packet_rcv(struct sk_buff *sk
int skb_len = skb->len;
unsigned int snaplen, res;
- if (skb->pkt_type == PACKET_LOOPBACK)
- goto drop;
-
sk = pt->af_packet_priv;
po = pkt_sk(sk);
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
+ goto drop;
+
if (dev_net(dev) != sock_net(sk))
goto drop;
@@ -608,12 +611,12 @@ static int tpacket_rcv(struct sk_buff *s
struct timeval tv;
struct timespec ts;
- if (skb->pkt_type == PACKET_LOOPBACK)
- goto drop;
-
sk = pt->af_packet_priv;
po = pkt_sk(sk);
+ if (!(po->pkt_type & (1 << skb->pkt_type)))
+ goto drop;
+
if (dev_net(dev) != sock_net(sk))
goto drop;
@@ -1072,6 +1075,7 @@ static int packet_create(struct net *net
spin_lock_init(&po->bind_lock);
mutex_init(&po->pg_vec_lock);
po->prot_hook.func = packet_rcv;
+ po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
if (sock->type == SOCK_PACKET)
po->prot_hook.func = packet_rcv_spkt;
@@ -1412,6 +1416,16 @@ packet_setsockopt(struct socket *sock, i
ret = packet_mc_drop(sk, &mreq);
return ret;
}
+ case PACKET_RECV_TYPE:
+ {
+ unsigned int val;
+ if (optlen != sizeof(val))
+ return -EINVAL;
+ if (copy_from_user(&val, optval, sizeof(val)))
+ return -EFAULT;
+ po->pkt_type = val & ~PACKET_LOOPBACK;
+ return 0;
+ }
#ifdef CONFIG_PACKET_MMAP
case PACKET_RX_RING:
@@ -1543,6 +1557,13 @@ static int packet_getsockopt(struct sock
data = &val;
break;
+ case PACKET_RECV_TYPE:
+ if (len > sizeof(unsigned int))
+ len = sizeof(unsigned int);
+ val = po->pkt_type;
+
+ data = &val;
+ break;
#ifdef CONFIG_PACKET_MMAP
case PACKET_VERSION:
if (len > sizeof(int))