af_packet: Introduce egress hook
Add egress hook for AF_PACKET sockets that have the PACKET_QDISC_BYPASS socket option set to on, which allows packets to escape without being filtered in the egress path. This patch only updates the AF_PACKET path, it does not update dev_direct_xmit() so the XDP infrastructure has a chance to bypass Netfilter. [lukas: acquire rcu_read_lock, fix typos, rebase] Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
42df6e1d22
commit
0d7308c0ff
@ -91,6 +91,7 @@
|
||||
#endif
|
||||
#include <linux/bpf.h>
|
||||
#include <net/compat.h>
|
||||
#include <linux/netfilter_netdev.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@ -241,8 +242,42 @@ struct packet_skb_cb {
|
||||
static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
|
||||
static void __fanout_link(struct sock *sk, struct packet_sock *po);
|
||||
|
||||
#ifdef CONFIG_NETFILTER_EGRESS
|
||||
static noinline struct sk_buff *nf_hook_direct_egress(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *next, *head = NULL, *tail;
|
||||
int rc;
|
||||
|
||||
rcu_read_lock();
|
||||
for (; skb != NULL; skb = next) {
|
||||
next = skb->next;
|
||||
skb_mark_not_on_list(skb);
|
||||
|
||||
if (!nf_hook_egress(skb, &rc, skb->dev))
|
||||
continue;
|
||||
|
||||
if (!head)
|
||||
head = skb;
|
||||
else
|
||||
tail->next = skb;
|
||||
|
||||
tail = skb;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return head;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int packet_direct_xmit(struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_NETFILTER_EGRESS
|
||||
if (nf_hook_egress_active()) {
|
||||
skb = nf_hook_direct_egress(skb);
|
||||
if (!skb)
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
#endif
|
||||
return dev_direct_xmit(skb, packet_pick_tx_queue(skb));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user