From patchwork Thu Oct 31 13:41:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 1187500 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wunner.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 473mxN1gLMz9sP6 for ; Fri, 1 Nov 2019 00:53:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727822AbfJaNxL (ORCPT ); Thu, 31 Oct 2019 09:53:11 -0400 Received: from mailout3.hostsharing.net ([176.9.242.54]:60621 "EHLO mailout3.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727719AbfJaNxL (ORCPT ); Thu, 31 Oct 2019 09:53:11 -0400 Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout3.hostsharing.net (Postfix) with ESMTPS id D84C1101E6B11; Thu, 31 Oct 2019 14:44:26 +0100 (CET) Received: from localhost (pd95be530.dip0.t-ipconnect.de [217.91.229.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 75857613C8DC; Thu, 31 Oct 2019 14:44:26 +0100 (CET) X-Mailbox-Line: From ba3cc38580d4cb43aa5599524ec5e5205d6dfa77 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Lukas Wunner Date: Thu, 31 Oct 2019 14:41:01 +0100 Subject: [PATCH nf-next,RFC 1/5] netfilter: Clean up unnecessary #ifdef To: "Pablo Neira Ayuso" , Jozsef Kadlecsik , Florian Westphal Cc: netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, Martin Mares , Daniel Borkmann Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org If CONFIG_NETFILTER_INGRESS is not enabled, nf_ingress() becomes a no-op because it solely contains an if-clause calling nf_hook_ingress_active(), for which an empty inline stub exists in . All the symbols used in the if-clause's body are still available even if CONFIG_NETFILTER_INGRESS is not enabled. The additional "#ifdef CONFIG_NETFILTER_INGRESS" in nf_ingress() is thus unnecessary, so drop it. Signed-off-by: Lukas Wunner Cc: Daniel Borkmann --- net/core/dev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 74f593986524..e555a8656c47 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5013,7 +5013,6 @@ static bool skb_pfmemalloc_protocol(struct sk_buff *skb) static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret, struct net_device *orig_dev) { -#ifdef CONFIG_NETFILTER_INGRESS if (nf_hook_ingress_active(skb)) { int ingress_retval; @@ -5027,7 +5026,6 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev, rcu_read_unlock(); return ingress_retval; } -#endif /* CONFIG_NETFILTER_INGRESS */ return 0; } From patchwork Thu Oct 31 13:41:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 1187501 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wunner.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 473mxP70z1z9s7T for ; Fri, 1 Nov 2019 00:53:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727816AbfJaNxL (ORCPT ); Thu, 31 Oct 2019 09:53:11 -0400 Received: from mailout3.hostsharing.net ([176.9.242.54]:32839 "EHLO mailout3.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727511AbfJaNxL (ORCPT ); Thu, 31 Oct 2019 09:53:11 -0400 X-Greylist: delayed 522 seconds by postgrey-1.27 at vger.kernel.org; Thu, 31 Oct 2019 09:53:10 EDT Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout3.hostsharing.net (Postfix) with ESMTPS id F3212101E6A30; Thu, 31 Oct 2019 14:47:57 +0100 (CET) Received: from localhost (pd95be530.dip0.t-ipconnect.de [217.91.229.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 8B0C2613C8DC; Thu, 31 Oct 2019 14:47:57 +0100 (CET) X-Mailbox-Line: From 442372563baf1a33ff48f8993be069960a7aea52 Mon Sep 17 00:00:00 2001 Message-Id: <442372563baf1a33ff48f8993be069960a7aea52.1572528496.git.lukas@wunner.de> In-Reply-To: References: From: Lukas Wunner Date: Thu, 31 Oct 2019 14:41:02 +0100 Subject: [PATCH nf-next,RFC 2/5] netfilter: Document ingress hook To: "Pablo Neira Ayuso" , Jozsef Kadlecsik , Florian Westphal Cc: netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, Martin Mares , Daniel Borkmann Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Amend kerneldoc of struct net_device to fix a "make htmldocs" warning: include/linux/netdevice.h:2045: warning: Function parameter or member 'nf_hooks_ingress' not described in 'net_device' Reported-by: kbuild test robot Signed-off-by: Lukas Wunner Cc: Daniel Borkmann --- include/linux/netdevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 3207e0b9ec4e..bc6914ea3faf 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1701,6 +1701,7 @@ enum netdev_priv_flags { * @miniq_ingress: ingress/clsact qdisc specific data for * ingress processing * @ingress_queue: XXX: need comments on this one + * @nf_hooks_ingress: netfilter hooks executed for ingress packets * @broadcast: hw bcast address * * @rx_cpu_rmap: CPU reverse-mapping for RX completion interrupts, From patchwork Thu Oct 31 13:41:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 1187512 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wunner.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 473n7T2hZ1z9sP3 for ; Fri, 1 Nov 2019 01:01:57 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727720AbfJaOB4 (ORCPT ); Thu, 31 Oct 2019 10:01:56 -0400 Received: from mailout1.hostsharing.net ([83.223.95.204]:59663 "EHLO mailout1.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727589AbfJaOB4 (ORCPT ); Thu, 31 Oct 2019 10:01:56 -0400 X-Greylist: delayed 508 seconds by postgrey-1.27 at vger.kernel.org; Thu, 31 Oct 2019 10:01:54 EDT Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout1.hostsharing.net (Postfix) with ESMTPS id 48833101933FD; Thu, 31 Oct 2019 14:53:25 +0100 (CET) Received: from localhost (pd95be530.dip0.t-ipconnect.de [217.91.229.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id EC858613C8DC; Thu, 31 Oct 2019 14:53:24 +0100 (CET) X-Mailbox-Line: From 06a0bd4f0b94d3078e1c3762f255a089835c8863 Mon Sep 17 00:00:00 2001 Message-Id: <06a0bd4f0b94d3078e1c3762f255a089835c8863.1572528497.git.lukas@wunner.de> In-Reply-To: References: From: Lukas Wunner Date: Thu, 31 Oct 2019 14:41:03 +0100 Subject: [PATCH nf-next, RFC 3/5] netfilter: Rename ingress hook include file To: "Pablo Neira Ayuso" , Jozsef Kadlecsik , Florian Westphal Cc: netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, Martin Mares , Daniel Borkmann Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Prepare for addition of a netfilter egress hook by renaming to . The egress hook also necessitates a refactoring of the include file, but that is done in a separate commit to ease reviewing. No functional change intended. Signed-off-by: Lukas Wunner Cc: Daniel Borkmann --- include/linux/{netfilter_ingress.h => netfilter_netdev.h} | 0 net/core/dev.c | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename include/linux/{netfilter_ingress.h => netfilter_netdev.h} (100%) diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_netdev.h similarity index 100% rename from include/linux/netfilter_ingress.h rename to include/linux/netfilter_netdev.h diff --git a/net/core/dev.c b/net/core/dev.c index e555a8656c47..c698a0fcfa02 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -135,7 +135,7 @@ #include #include #include -#include +#include #include #include #include From patchwork Thu Oct 31 13:41:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 1187507 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wunner.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 473n4J56wtz9sP6 for ; Fri, 1 Nov 2019 00:59:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727743AbfJaN7L (ORCPT ); Thu, 31 Oct 2019 09:59:11 -0400 Received: from mailout2.hostsharing.net ([83.223.78.233]:44937 "EHLO mailout2.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727567AbfJaN7K (ORCPT ); Thu, 31 Oct 2019 09:59:10 -0400 Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout2.hostsharing.net (Postfix) with ESMTPS id 8670F10189C8E; Thu, 31 Oct 2019 14:59:08 +0100 (CET) Received: from localhost (pd95be530.dip0.t-ipconnect.de [217.91.229.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id 37A36613C8DC; Thu, 31 Oct 2019 14:59:08 +0100 (CET) X-Mailbox-Line: From 9da2050c3bce81730e58eda7888e5f8eb4a96d56 Mon Sep 17 00:00:00 2001 Message-Id: <9da2050c3bce81730e58eda7888e5f8eb4a96d56.1572528497.git.lukas@wunner.de> In-Reply-To: References: From: Lukas Wunner Date: Thu, 31 Oct 2019 14:41:04 +0100 Subject: [PATCH nf-next,RFC 4/5] netfilter: Generalize ingress hook To: "Pablo Neira Ayuso" , Jozsef Kadlecsik , Florian Westphal Cc: netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, Martin Mares , Daniel Borkmann Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Prepare for addition of a netfilter egress hook by generalizing the ingress hook introduced by commit e687ad60af09 ("netfilter: add netfilter ingress hook after handle_ing() under unique static key"). In particular, rename and refactor the ingress hook's static inlines such that they can be reused for an egress hook. No functional change intended. Signed-off-by: Lukas Wunner Cc: Daniel Borkmann --- include/linux/netfilter_netdev.h | 45 ++++++++++++++++++++++---------- net/core/dev.c | 2 +- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/include/linux/netfilter_netdev.h b/include/linux/netfilter_netdev.h index a13774be2eb5..49e26479642e 100644 --- a/include/linux/netfilter_netdev.h +++ b/include/linux/netfilter_netdev.h @@ -1,34 +1,37 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _NETFILTER_INGRESS_H_ -#define _NETFILTER_INGRESS_H_ +#ifndef _NETFILTER_NETDEV_H_ +#define _NETFILTER_NETDEV_H_ #include #include -#ifdef CONFIG_NETFILTER_INGRESS -static inline bool nf_hook_ingress_active(const struct sk_buff *skb) +#ifdef CONFIG_NETFILTER +static __always_inline bool nf_hook_netdev_active(enum nf_dev_hooks hooknum, + struct nf_hook_entries __rcu *hooks) { #ifdef CONFIG_JUMP_LABEL - if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS])) + if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][hooknum])) return false; #endif - return rcu_access_pointer(skb->dev->nf_hooks_ingress); + return rcu_access_pointer(hooks); } /* caller must hold rcu_read_lock */ -static inline int nf_hook_ingress(struct sk_buff *skb) +static __always_inline int nf_hook_netdev(struct sk_buff *skb, + enum nf_dev_hooks hooknum, + struct nf_hook_entries __rcu *hooks) { - struct nf_hook_entries *e = rcu_dereference(skb->dev->nf_hooks_ingress); + struct nf_hook_entries *e = rcu_dereference(hooks); struct nf_hook_state state; int ret; - /* Must recheck the ingress hook head, in the event it became NULL - * after the check in nf_hook_ingress_active evaluated to true. + /* Must recheck the hook head, in the event it became NULL + * after the check in nf_hook_netdev_active evaluated to true. */ if (unlikely(!e)) return 0; - nf_hook_state_init(&state, NF_NETDEV_INGRESS, + nf_hook_state_init(&state, hooknum, NFPROTO_NETDEV, skb->dev, NULL, NULL, dev_net(skb->dev), NULL); ret = nf_hook_slow(skb, &state, e, 0); @@ -37,10 +40,26 @@ static inline int nf_hook_ingress(struct sk_buff *skb) return ret; } +#endif /* CONFIG_NETFILTER */ -static inline void nf_hook_ingress_init(struct net_device *dev) +static inline void nf_hook_netdev_init(struct net_device *dev) { +#ifdef CONFIG_NETFILTER_INGRESS RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL); +#endif +} + +#ifdef CONFIG_NETFILTER_INGRESS +static inline bool nf_hook_ingress_active(const struct sk_buff *skb) +{ + return nf_hook_netdev_active(NF_NETDEV_INGRESS, + skb->dev->nf_hooks_ingress); +} + +static inline int nf_hook_ingress(struct sk_buff *skb) +{ + return nf_hook_netdev(skb, NF_NETDEV_INGRESS, + skb->dev->nf_hooks_ingress); } #else /* CONFIG_NETFILTER_INGRESS */ static inline int nf_hook_ingress_active(struct sk_buff *skb) @@ -52,7 +71,5 @@ static inline int nf_hook_ingress(struct sk_buff *skb) { return 0; } - -static inline void nf_hook_ingress_init(struct net_device *dev) {} #endif /* CONFIG_NETFILTER_INGRESS */ #endif /* _NETFILTER_INGRESS_H_ */ diff --git a/net/core/dev.c b/net/core/dev.c index c698a0fcfa02..e4976f68f2dd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -9478,7 +9478,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, if (!dev->ethtool_ops) dev->ethtool_ops = &default_ethtool_ops; - nf_hook_ingress_init(dev); + nf_hook_netdev_init(dev); return dev; From patchwork Thu Oct 31 13:41:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 1187515 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wunner.de Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 473nDW6w3Vz9sP3 for ; Fri, 1 Nov 2019 01:06:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727830AbfJaOGT (ORCPT ); Thu, 31 Oct 2019 10:06:19 -0400 Received: from mailout1.hostsharing.net ([83.223.95.204]:60955 "EHLO mailout1.hostsharing.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727816AbfJaOGS (ORCPT ); Thu, 31 Oct 2019 10:06:18 -0400 Received: from h08.hostsharing.net (h08.hostsharing.net [IPv6:2a01:37:1000::53df:5f1c:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "*.hostsharing.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (not verified)) by mailout1.hostsharing.net (Postfix) with ESMTPS id 22DBC101933FD; Thu, 31 Oct 2019 15:06:16 +0100 (CET) Received: from localhost (pd95be530.dip0.t-ipconnect.de [217.91.229.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id D5548613C8DC; Thu, 31 Oct 2019 15:06:15 +0100 (CET) X-Mailbox-Line: From de461181e53bcec9a75a9630d0d998d555dc8bf5 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Lukas Wunner Date: Thu, 31 Oct 2019 14:41:05 +0100 Subject: [PATCH nf-next,RFC 5/5] netfilter: Introduce egress hook To: "Pablo Neira Ayuso" , Jozsef Kadlecsik , Florian Westphal Cc: netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, Martin Mares , Daniel Borkmann Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Commit e687ad60af09 ("netfilter: add netfilter ingress hook after handle_ing() under unique static key") introduced the ability to classify packets on ingress. Allow the same on egress. The need for this arose because I had to filter egress packets which do not match a specific ethertype. The most common solution appears to be to enslave the interface to a bridge and use ebtables, but that's cumbersome to configure and comes with a (small) performance penalty. An alternative approach is tc, but that doesn't afford equivalent matching options as netfilter. A bit of googling reveals that more people have expressed a desire for egress filtering in the past: https://www.spinics.net/lists/netfilter/msg50038.html https://unix.stackexchange.com/questions/512371 An egress hook therefore seems like an obvious addition. Signed-off-by: Lukas Wunner Cc: Daniel Borkmann --- include/linux/netdevice.h | 4 ++++ include/linux/netfilter_netdev.h | 27 +++++++++++++++++++++++++++ include/uapi/linux/netfilter.h | 1 + net/core/dev.c | 25 ++++++++++++++++++++----- net/netfilter/Kconfig | 8 ++++++++ net/netfilter/core.c | 24 ++++++++++++++++++++---- net/netfilter/nft_chain_filter.c | 4 +++- 7 files changed, 83 insertions(+), 10 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index bc6914ea3faf..111107aed50b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1720,6 +1720,7 @@ enum netdev_priv_flags { * @xps_maps: XXX: need comments on this one * @miniq_egress: clsact qdisc specific data for * egress processing + * @nf_hooks_egress: netfilter hooks executed for egress packets * @watchdog_timeo: Represents the timeout that is used by * the watchdog (see dev_watchdog()) * @watchdog_timer: List of timers @@ -1981,6 +1982,9 @@ struct net_device { #ifdef CONFIG_NET_CLS_ACT struct mini_Qdisc __rcu *miniq_egress; #endif +#ifdef CONFIG_NETFILTER_EGRESS + struct nf_hook_entries __rcu *nf_hooks_egress; +#endif /* These may be needed for future network-power-down code. */ struct timer_list watchdog_timer; diff --git a/include/linux/netfilter_netdev.h b/include/linux/netfilter_netdev.h index 49e26479642e..92d3611a782e 100644 --- a/include/linux/netfilter_netdev.h +++ b/include/linux/netfilter_netdev.h @@ -47,6 +47,9 @@ static inline void nf_hook_netdev_init(struct net_device *dev) #ifdef CONFIG_NETFILTER_INGRESS RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL); #endif +#ifdef CONFIG_NETFILTER_EGRESS + RCU_INIT_POINTER(dev->nf_hooks_egress, NULL); +#endif } #ifdef CONFIG_NETFILTER_INGRESS @@ -72,4 +75,28 @@ static inline int nf_hook_ingress(struct sk_buff *skb) return 0; } #endif /* CONFIG_NETFILTER_INGRESS */ + +#ifdef CONFIG_NETFILTER_EGRESS +static inline bool nf_hook_egress_active(const struct sk_buff *skb) +{ + return nf_hook_netdev_active(NF_NETDEV_EGRESS, + skb->dev->nf_hooks_egress); +} + +static inline int nf_hook_egress(struct sk_buff *skb) +{ + return nf_hook_netdev(skb, NF_NETDEV_EGRESS, + skb->dev->nf_hooks_egress); +} +#else /* CONFIG_NETFILTER_EGRESS */ +static inline int nf_hook_egress_active(struct sk_buff *skb) +{ + return 0; +} + +static inline int nf_hook_egress(struct sk_buff *skb) +{ + return 0; +} +#endif /* CONFIG_NETFILTER_EGRESS */ #endif /* _NETFILTER_INGRESS_H_ */ diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h index ca9e63d6e0e4..d1616574c54f 100644 --- a/include/uapi/linux/netfilter.h +++ b/include/uapi/linux/netfilter.h @@ -50,6 +50,7 @@ enum nf_inet_hooks { enum nf_dev_hooks { NF_NETDEV_INGRESS, + NF_NETDEV_EGRESS, NF_NETDEV_NUMHOOKS }; diff --git a/net/core/dev.c b/net/core/dev.c index e4976f68f2dd..d1e48fc4ae5c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3811,10 +3811,10 @@ int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(dev_loopback_xmit); -#ifdef CONFIG_NET_EGRESS static struct sk_buff * sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev) { +#ifdef CONFIG_NET_CLS_ACT struct mini_Qdisc *miniq = rcu_dereference_bh(dev->miniq_egress); struct tcf_result cl_res; @@ -3848,10 +3848,22 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev) default: break; } - +#endif /* CONFIG_NET_CLS_ACT */ return skb; } -#endif /* CONFIG_NET_EGRESS */ + +static int nf_egress(struct sk_buff *skb) +{ + if (nf_hook_egress_active(skb)) { + int ret; + + rcu_read_lock(); + ret = nf_hook_egress(skb); + rcu_read_unlock(); + return ret; + } + return 0; +} #ifdef CONFIG_XPS static int __get_xps_queue_idx(struct net_device *dev, struct sk_buff *skb, @@ -4039,13 +4051,16 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) qdisc_pkt_len_init(skb); #ifdef CONFIG_NET_CLS_ACT skb->tc_at_ingress = 0; -# ifdef CONFIG_NET_EGRESS +#endif +#ifdef CONFIG_NET_EGRESS if (static_branch_unlikely(&egress_needed_key)) { skb = sch_handle_egress(skb, &rc, dev); if (!skb) goto out; + + if (nf_egress(skb) < 0) + goto out; } -# endif #endif /* If device/qdisc don't need skb->dst, release it right now while * its hot in this cpu cache. diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 91efae88e8c2..a6ae141ec77e 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -10,6 +10,14 @@ config NETFILTER_INGRESS This allows you to classify packets from ingress using the Netfilter infrastructure. +config NETFILTER_EGRESS + bool "Netfilter egress support" + default y + select NET_EGRESS + help + This allows you to classify packets before transmission using the + Netfilter infrastructure. + config NETFILTER_NETLINK tristate diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 78f046ec506f..85e9c959aba7 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -306,6 +306,12 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum, if (dev && dev_net(dev) == net) return &dev->nf_hooks_ingress; } +#endif +#ifdef CONFIG_NETFILTER_EGRESS + if (hooknum == NF_NETDEV_EGRESS) { + if (dev && dev_net(dev) == net) + return &dev->nf_hooks_egress; + } #endif WARN_ON_ONCE(1); return NULL; @@ -318,11 +324,13 @@ static int __nf_register_net_hook(struct net *net, int pf, struct nf_hook_entries __rcu **pp; if (pf == NFPROTO_NETDEV) { -#ifndef CONFIG_NETFILTER_INGRESS - if (reg->hooknum == NF_NETDEV_INGRESS) + if ((!IS_ENABLED(CONFIG_NETFILTER_INGRESS) && + reg->hooknum == NF_NETDEV_INGRESS) || + (!IS_ENABLED(CONFIG_NETFILTER_EGRESS) && + reg->hooknum == NF_NETDEV_EGRESS)) return -EOPNOTSUPP; -#endif - if (reg->hooknum != NF_NETDEV_INGRESS || + if ((reg->hooknum != NF_NETDEV_INGRESS && + reg->hooknum != NF_NETDEV_EGRESS) || !reg->dev || dev_net(reg->dev) != net) return -EINVAL; } @@ -348,6 +356,10 @@ static int __nf_register_net_hook(struct net *net, int pf, if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) net_inc_ingress_queue(); #endif +#ifdef CONFIG_NETFILTER_EGRESS + if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_EGRESS) + net_inc_egress_queue(); +#endif #ifdef CONFIG_JUMP_LABEL static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]); #endif @@ -406,6 +418,10 @@ static void __nf_unregister_net_hook(struct net *net, int pf, if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) net_dec_ingress_queue(); #endif +#ifdef CONFIG_NETFILTER_EGRESS + if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_EGRESS) + net_dec_egress_queue(); +#endif #ifdef CONFIG_JUMP_LABEL static_key_slow_dec(&nf_hooks_needed[pf][reg->hooknum]); #endif diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c index c78d01bc02e9..67ce6dbb5496 100644 --- a/net/netfilter/nft_chain_filter.c +++ b/net/netfilter/nft_chain_filter.c @@ -277,9 +277,11 @@ static const struct nft_chain_type nft_chain_filter_netdev = { .name = "filter", .type = NFT_CHAIN_T_DEFAULT, .family = NFPROTO_NETDEV, - .hook_mask = (1 << NF_NETDEV_INGRESS), + .hook_mask = (1 << NF_NETDEV_INGRESS) | + (1 << NF_NETDEV_EGRESS), .hooks = { [NF_NETDEV_INGRESS] = nft_do_chain_netdev, + [NF_NETDEV_EGRESS] = nft_do_chain_netdev, }, };