// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Handle firewalling
* Linux ethernet bridge
*
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
* Bart De Schuymer <bdschuym@pandora.be>
*
* Lennert dedicates this file to Kerstin Wurdinger.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/if_pppox.h>
#include <linux/ppp_defs.h>
#include <linux/netfilter_bridge.h>
#include <uapi/linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_arp.h>
#include <linux/in_route.h>
#include <linux/rculist.h>
#include <linux/inetdevice.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
#include <net/route.h>
#include <net/netfilter/br_netfilter.h>
#include <net/netns/generic.h>
#include <linux/uaccess.h>
#include "br_private.h"
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
static unsigned int brnf_net_id __read_mostly;
struct brnf_net {
bool enabled;
#ifdef CONFIG_SYSCTL
struct ctl_table_header *ctl_hdr;
#endif
/* default value is 1 */
int call_iptables;
int call_ip6tables;
int call_arptables;
/* default value is 0 */
int filter_vlan_tagged;
int filter_pppoe_tagged;
int pass_vlan_indev;
};
#define IS_IP(skb) \
(!skb_vlan_tag_present(skb) && skb->protocol == htons(ETH_P_IP))
#define IS_IPV6(skb) \
(!skb_vlan_tag_present(skb) && skb->protocol == htons(ETH_P_IPV6))
#define IS_ARP(skb) \
(!skb_vlan_tag_present(skb) && skb->protocol == htons(ETH_P_ARP))
static inline __be16 vlan_proto(const struct sk_buff *skb)
{
if (skb_vlan_tag_present(skb))
return skb->protocol;
else if (skb->protocol == htons(ETH_P_8021Q))
return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
else
return 0;
}
static inline bool is_vlan_ip(const struct sk_buff *skb, const struct net *net)
{
struct brnf_net *brnet = net_generic(net, brnf_net_id);
return vlan_proto(skb) == htons(ETH_P_IP) && brnet->filter_vlan_tagged;
}
static inline bool is_vlan_ipv6(const struct sk_buff *skb,
const struct net *net)
{
struct brnf_net *brnet = net_generic(net, brnf_net_id);
return vlan_proto(skb) == htons(ETH_P_IPV6) &&
brnet->filter_vlan_tagged;
}
static inline bool is_vlan_arp(const struct sk_buff *skb, const struct net *net)
{
struct brnf_net *brnet = net_generic(net, brnf_net_id);
return vlan_proto(skb) == htons(ETH_P_ARP) && brnet->filter_vlan_tagged;
}
static inline __be16 pppoe_proto(const struct sk_buff *skb)
{
return *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
sizeof(struct pppoe_hdr)));
}
static inline bool is_pppoe_ip(const struct sk_buff *skb, const struct net *net)
{
struct brnf_net *brnet = net_generic(net, brnf_net_id);
return skb->protocol == htons(ETH_P_PPP_SES) &&
pppoe_proto(skb) ==