netfilter: bridge: add helpers for fetching physin/outdev
authorFlorian Westphal <fw@strlen.de>
Thu, 2 Apr 2015 12:31:41 +0000 (14:31 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 8 Apr 2015 14:49:08 +0000 (16:49 +0200)
right now we store this in the nf_bridge_info struct, accessible
via skb->nf_bridge.  This patch prepares removal of this pointer from skb:

Instead of using skb->nf_bridge->x, we use helpers to obtain the in/out
device (or ifindexes).

Followup patches to netfilter will then allow nf_bridge_info to be
obtained by a call into the br_netfilter core, rather than keeping a
pointer to it in sk_buff.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter_bridge.h
net/ipv4/netfilter/nf_reject_ipv4.c
net/ipv6/netfilter/nf_reject_ipv6.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/nf_log_common.c
net/netfilter/nf_queue.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue_core.c

index 2734977199cac6a587126202dff59827724af277..e1d96bc2767cf0f4da711075c885cdee7ac14baf 100644 (file)
@@ -2,7 +2,7 @@
 #define __LINUX_BRIDGE_NETFILTER_H
 
 #include <uapi/linux/netfilter_bridge.h>
-
+#include <linux/skbuff.h>
 
 enum nf_br_hook_priorities {
        NF_BR_PRI_FIRST = INT_MIN,
@@ -40,6 +40,27 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
                skb_dst_drop(skb);
 }
 
+static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
+{
+       return skb->nf_bridge ? skb->nf_bridge->physindev->ifindex : 0;
+}
+
+static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
+{
+       return skb->nf_bridge ? skb->nf_bridge->physoutdev->ifindex : 0;
+}
+
+static inline struct net_device *
+nf_bridge_get_physindev(const struct sk_buff *skb)
+{
+       return skb->nf_bridge ? skb->nf_bridge->physindev : NULL;
+}
+
+static inline struct net_device *
+nf_bridge_get_physoutdev(const struct sk_buff *skb)
+{
+       return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL;
+}
 #else
 #define br_drop_fake_rtable(skb)               do { } while (0)
 #endif /* CONFIG_BRIDGE_NETFILTER */
index c5b794da51a91fd8b2236379b532910cafc0568f..3262e41ff76f38a89db3fd7da8c771a51b273abf 100644 (file)
@@ -13,6 +13,7 @@
 #include <net/dst.h>
 #include <net/netfilter/ipv4/nf_reject.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_bridge.h>
 #include <net/netfilter/ipv4/nf_reject.h>
 
 const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
@@ -146,7 +147,8 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
         */
        if (oldskb->nf_bridge) {
                struct ethhdr *oeth = eth_hdr(oldskb);
-               nskb->dev = oldskb->nf_bridge->physindev;
+
+               nskb->dev = nf_bridge_get_physindev(oldskb);
                niph->tot_len = htons(nskb->len);
                ip_send_check(niph);
                if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
index 3afdce03d94e7c2dd27d19fabff9250c0f5aaddc..94b4c6dfb400c90b6c368acb7ecb83649309dce0 100644 (file)
@@ -13,6 +13,7 @@
 #include <net/ip6_checksum.h>
 #include <net/netfilter/ipv6/nf_reject.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_bridge.h>
 #include <net/netfilter/ipv6/nf_reject.h>
 
 const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
@@ -195,7 +196,8 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
         */
        if (oldskb->nf_bridge) {
                struct ethhdr *oeth = eth_hdr(oldskb);
-               nskb->dev = oldskb->nf_bridge->physindev;
+
+               nskb->dev = nf_bridge_get_physindev(oldskb);
                nskb->protocol = htons(ETH_P_IPV6);
                ip6h->payload_len = htons(sizeof(struct tcphdr));
                if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
index 758b002130d92f0e7fecf63627d426289cf03820..380ef5148ea11ef29b5e3ab8113b94905fbea389 100644 (file)
@@ -19,6 +19,7 @@
 #include <net/netlink.h>
 
 #include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter/ipset/pfxlen.h>
 #include <linux/netfilter/ipset/ip_set.h>
 #include <linux/netfilter/ipset/ip_set_hash.h>
@@ -211,6 +212,22 @@ hash_netiface4_data_next(struct hash_netiface4_elem *next,
 #define HKEY_DATALEN   sizeof(struct hash_netiface4_elem_hashed)
 #include "ip_set_hash_gen.h"
 
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+static const char *get_physindev_name(const struct sk_buff *skb)
+{
+       struct net_device *dev = nf_bridge_get_physindev(skb);
+
+       return dev ? dev->name : NULL;
+}
+
+static const char *get_phyoutdev_name(const struct sk_buff *skb)
+{
+       struct net_device *dev = nf_bridge_get_physoutdev(skb);
+
+       return dev ? dev->name : NULL;
+}
+#endif
+
 static int
 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
                    const struct xt_action_param *par,
@@ -234,16 +251,15 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
        e.ip &= ip_set_netmask(e.cidr);
 
 #define IFACE(dir)     (par->dir ? par->dir->name : NULL)
-#define PHYSDEV(dir)   (nf_bridge->dir ? nf_bridge->dir->name : NULL)
 #define SRCDIR         (opt->flags & IPSET_DIM_TWO_SRC)
 
        if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-               const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+               e.iface = SRCDIR ? get_physindev_name(skb) :
+                                  get_phyoutdev_name(skb);
 
-               if (!nf_bridge)
+               if (!e.iface)
                        return -EINVAL;
-               e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
                e.physdev = 1;
 #else
                e.iface = NULL;
@@ -476,11 +492,11 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
-               const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
-
-               if (!nf_bridge)
+               e.iface = SRCDIR ? get_physindev_name(skb) :
+                                  get_phyoutdev_name(skb);
+               if (!e.iface)
                        return -EINVAL;
-               e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
+
                e.physdev = 1;
 #else
                e.iface = NULL;
index 2631876ac55be96aeec77ab1d15f5db8c5a80c49..a5aa5967b8e17b894a798dbf29d07bf12063fc16 100644 (file)
@@ -17,6 +17,7 @@
 #include <net/route.h>
 
 #include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter/xt_LOG.h>
 #include <net/netfilter/nf_log.h>
 
@@ -163,10 +164,10 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
                const struct net_device *physindev;
                const struct net_device *physoutdev;
 
-               physindev = skb->nf_bridge->physindev;
+               physindev = nf_bridge_get_physindev(skb);
                if (physindev && in != physindev)
                        nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
-               physoutdev = skb->nf_bridge->physoutdev;
+               physoutdev = nf_bridge_get_physoutdev(skb);
                if (physoutdev && out != physoutdev)
                        nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
        }
index 4c8b68e5fa164fd71b6f613b66b36d52e6717bf4..fb045b4c29665c4243292343539e136c4a74ba3b 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/proc_fs.h>
 #include <linux/skbuff.h>
 #include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/seq_file.h>
 #include <linux/rcupdate.h>
 #include <net/protocol.h>
@@ -54,12 +55,14 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
                dev_put(entry->outdev);
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        if (entry->skb->nf_bridge) {
-               struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
+               struct net_device *physdev;
 
-               if (nf_bridge->physindev)
-                       dev_put(nf_bridge->physindev);
-               if (nf_bridge->physoutdev)
-                       dev_put(nf_bridge->physoutdev);
+               physdev = nf_bridge_get_physindev(entry->skb);
+               if (physdev)
+                       dev_put(physdev);
+               physdev = nf_bridge_get_physoutdev(entry->skb);
+               if (physdev)
+                       dev_put(physdev);
        }
 #endif
        /* Drop reference to owner of hook which queued us. */
@@ -79,13 +82,12 @@ bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
                dev_hold(entry->outdev);
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        if (entry->skb->nf_bridge) {
-               struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
                struct net_device *physdev;
 
-               physdev = nf_bridge->physindev;
+               physdev = nf_bridge_get_physindev(entry->skb);
                if (physdev)
                        dev_hold(physdev);
-               physdev = nf_bridge->physoutdev;
+               physdev = nf_bridge_get_physoutdev(entry->skb);
                if (physdev)
                        dev_hold(physdev);
        }
index 957b83a0223b8eef159b572a2b685095a2d3e0ab..51afea4b0af78a46c41099cd55ca9506f3636835 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
 #include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
 #include <net/netlink.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_log.h>
@@ -448,14 +449,18 @@ __build_packet_message(struct nfnl_log_net *log,
                                         htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
                                goto nla_put_failure;
                } else {
+                       struct net_device *physindev;
+
                        /* Case 2: indev is bridge group, we need to look for
                         * physical device (when called from ipv4) */
                        if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
                                         htonl(indev->ifindex)))
                                goto nla_put_failure;
-                       if (skb->nf_bridge && skb->nf_bridge->physindev &&
+
+                       physindev = nf_bridge_get_physindev(skb);
+                       if (physindev &&
                            nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-                                        htonl(skb->nf_bridge->physindev->ifindex)))
+                                        htonl(physindev->ifindex)))
                                goto nla_put_failure;
                }
 #endif
@@ -479,14 +484,18 @@ __build_packet_message(struct nfnl_log_net *log,
                                         htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
                                goto nla_put_failure;
                } else {
+                       struct net_device *physoutdev;
+
                        /* Case 2: indev is a bridge group, we need to look
                         * for physical device (when called from ipv4) */
                        if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
                                         htonl(outdev->ifindex)))
                                goto nla_put_failure;
-                       if (skb->nf_bridge && skb->nf_bridge->physoutdev &&
+
+                       physoutdev = nf_bridge_get_physoutdev(skb);
+                       if (physoutdev &&
                            nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-                                        htonl(skb->nf_bridge->physoutdev->ifindex)))
+                                        htonl(physoutdev->ifindex)))
                                goto nla_put_failure;
                }
 #endif
index 86ee8b05adae3bb59f59da371c398fb3bb85d063..94e1aaf86070d096c3973bc005fc68ea7c4afcbf 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/proc_fs.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_queue.h>
 #include <linux/list.h>
@@ -396,14 +397,18 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                                         htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
                                goto nla_put_failure;
                } else {
+                       int physinif;
+
                        /* Case 2: indev is bridge group, we need to look for
                         * physical device (when called from ipv4) */
                        if (nla_put_be32(skb, NFQA_IFINDEX_INDEV,
                                         htonl(indev->ifindex)))
                                goto nla_put_failure;
-                       if (entskb->nf_bridge && entskb->nf_bridge->physindev &&
+
+                       physinif = nf_bridge_get_physinif(entskb);
+                       if (physinif &&
                            nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV,
-                                        htonl(entskb->nf_bridge->physindev->ifindex)))
+                                        htonl(physinif)))
                                goto nla_put_failure;
                }
 #endif
@@ -426,14 +431,18 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                                         htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
                                goto nla_put_failure;
                } else {
+                       int physoutif;
+
                        /* Case 2: outdev is bridge group, we need to look for
                         * physical output device (when called from ipv4) */
                        if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV,
                                         htonl(outdev->ifindex)))
                                goto nla_put_failure;
-                       if (entskb->nf_bridge && entskb->nf_bridge->physoutdev &&
+
+                       physoutif = nf_bridge_get_physoutif(entskb);
+                       if (physoutif &&
                            nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV,
-                                        htonl(entskb->nf_bridge->physoutdev->ifindex)))
+                                        htonl(physoutif)))
                                goto nla_put_failure;
                }
 #endif
@@ -765,11 +774,12 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
                        return 1;
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        if (entry->skb->nf_bridge) {
-               if (entry->skb->nf_bridge->physindev &&
-                   entry->skb->nf_bridge->physindev->ifindex == ifindex)
-                       return 1;
-               if (entry->skb->nf_bridge->physoutdev &&
-                   entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
+               int physinif, physoutif;
+
+               physinif = nf_bridge_get_physinif(entry->skb);
+               physoutif = nf_bridge_get_physoutif(entry->skb);
+
+               if (physinif == ifindex || physoutif == ifindex)
                        return 1;
        }
 #endif