[kernel] revert 15922 - add back 2.6.29 kernel support
[openwrt.git] / target / linux / generic-2.6 / patches-2.6.29 / 240-packet_socket_type.patch
1 This patch allows the user to specify desired packet types (outgoing,
2 broadcast, unicast, etc.) on packet sockets via setsockopt.
3 This can reduce the load in situations where only a limited number
4 of packet types are necessary
5
6 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
7
8 --- a/include/linux/if_packet.h
9 +++ b/include/linux/if_packet.h
10 @@ -31,6 +31,8 @@ struct sockaddr_ll
11  /* These ones are invisible by user level */
12  #define PACKET_LOOPBACK                5               /* MC/BRD frame looped back */
13  #define PACKET_FASTROUTE       6               /* Fastrouted frame     */
14 +#define PACKET_MASK_ANY                0xffffffff      /* mask for packet type bits */
15 +
16  
17  /* Packet socket options */
18  
19 @@ -46,6 +48,7 @@ struct sockaddr_ll
20  #define PACKET_VERSION                 10
21  #define PACKET_HDRLEN                  11
22  #define PACKET_RESERVE                 12
23 +#define PACKET_RECV_TYPE               13
24  
25  struct tpacket_stats
26  {
27 --- a/net/packet/af_packet.c
28 +++ b/net/packet/af_packet.c
29 @@ -192,6 +192,7 @@ struct packet_sock {
30         unsigned int            tp_hdrlen;
31         unsigned int            tp_reserve;
32  #endif
33 +       unsigned int            pkt_type;
34  };
35  
36  struct packet_skb_cb {
37 @@ -282,6 +283,7 @@ static int packet_rcv_spkt(struct sk_buf
38  {
39         struct sock *sk;
40         struct sockaddr_pkt *spkt;
41 +       struct packet_sock *po;
42  
43         /*
44          *      When we registered the protocol we saved the socket in the data
45 @@ -289,6 +291,7 @@ static int packet_rcv_spkt(struct sk_buf
46          */
47  
48         sk = pt->af_packet_priv;
49 +       po = pkt_sk(sk);
50  
51         /*
52          *      Yank back the headers [hope the device set this
53 @@ -301,7 +304,7 @@ static int packet_rcv_spkt(struct sk_buf
54          *      so that this procedure is noop.
55          */
56  
57 -       if (skb->pkt_type == PACKET_LOOPBACK)
58 +       if (!(po->pkt_type & (1 << skb->pkt_type)))
59                 goto out;
60  
61         if (dev_net(dev) != sock_net(sk))
62 @@ -486,12 +489,12 @@ static int packet_rcv(struct sk_buff *sk
63         int skb_len = skb->len;
64         unsigned int snaplen, res;
65  
66 -       if (skb->pkt_type == PACKET_LOOPBACK)
67 -               goto drop;
68 -
69         sk = pt->af_packet_priv;
70         po = pkt_sk(sk);
71  
72 +       if (!(po->pkt_type & (1 << skb->pkt_type)))
73 +               goto drop;
74 +
75         if (dev_net(dev) != sock_net(sk))
76                 goto drop;
77  
78 @@ -608,12 +611,12 @@ static int tpacket_rcv(struct sk_buff *s
79         struct timeval tv;
80         struct timespec ts;
81  
82 -       if (skb->pkt_type == PACKET_LOOPBACK)
83 -               goto drop;
84 -
85         sk = pt->af_packet_priv;
86         po = pkt_sk(sk);
87  
88 +       if (!(po->pkt_type & (1 << skb->pkt_type)))
89 +               goto drop;
90 +
91         if (dev_net(dev) != sock_net(sk))
92                 goto drop;
93  
94 @@ -1073,6 +1076,7 @@ static int packet_create(struct net *net
95         spin_lock_init(&po->bind_lock);
96         mutex_init(&po->pg_vec_lock);
97         po->prot_hook.func = packet_rcv;
98 +       po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
99  
100         if (sock->type == SOCK_PACKET)
101                 po->prot_hook.func = packet_rcv_spkt;
102 @@ -1413,6 +1417,16 @@ packet_setsockopt(struct socket *sock, i
103                         ret = packet_mc_drop(sk, &mreq);
104                 return ret;
105         }
106 +       case PACKET_RECV_TYPE:
107 +       {
108 +               unsigned int val;
109 +               if (optlen != sizeof(val))
110 +                       return -EINVAL;
111 +               if (copy_from_user(&val, optval, sizeof(val)))
112 +                       return -EFAULT;
113 +               po->pkt_type = val & ~PACKET_LOOPBACK;
114 +               return 0;
115 +       }
116  
117  #ifdef CONFIG_PACKET_MMAP
118         case PACKET_RX_RING:
119 @@ -1544,6 +1558,13 @@ static int packet_getsockopt(struct sock
120  
121                 data = &val;
122                 break;
123 +       case PACKET_RECV_TYPE:
124 +               if (len > sizeof(unsigned int))
125 +                       len = sizeof(unsigned int);
126 +               val = po->pkt_type;
127 +
128 +               data = &val;
129 +               break;
130  #ifdef CONFIG_PACKET_MMAP
131         case PACKET_VERSION:
132                 if (len > sizeof(int))