Skip to content

Commit

Permalink
netfilter: flowtable: Fix QinQ and pppoe support for inet table
Browse files Browse the repository at this point in the history
[ Upstream commit 0492d85 ]

nf_flow_offload_inet_hook() does not check for 802.1q and PPPoE.
Fetch inner ethertype from these encapsulation protocols.

Fixes: 72efd58 ("netfilter: flowtable: add pppoe support")
Fixes: 4cd91f7 ("netfilter: flowtable: add vlan support")
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
ummakynes authored and gregkh committed Apr 8, 2022
1 parent 02e8969 commit 0582475
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
18 changes: 18 additions & 0 deletions include/net/netfilter/nf_flow_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/flow_offload.h>
#include <net/dst.h>
#include <linux/if_pppox.h>
#include <linux/ppp_defs.h>

struct nf_flowtable;
struct nf_flow_rule;
Expand Down Expand Up @@ -317,4 +319,20 @@ int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow,
int nf_flow_table_offload_init(void);
void nf_flow_table_offload_exit(void);

static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
{
__be16 proto;

proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
sizeof(struct pppoe_hdr)));
switch (proto) {
case htons(PPP_IP):
return htons(ETH_P_IP);
case htons(PPP_IPV6):
return htons(ETH_P_IPV6);
}

return 0;
}

#endif /* _NF_FLOW_TABLE_H */
17 changes: 17 additions & 0 deletions net/netfilter/nf_flow_table_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,29 @@
#include <linux/rhashtable.h>
#include <net/netfilter/nf_flow_table.h>
#include <net/netfilter/nf_tables.h>
#include <linux/if_vlan.h>

static unsigned int
nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct vlan_ethhdr *veth;
__be16 proto;

switch (skb->protocol) {
case htons(ETH_P_8021Q):
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
proto = veth->h_vlan_encapsulated_proto;
break;
case htons(ETH_P_PPP_SES):
proto = nf_flow_pppoe_proto(skb);
break;
default:
proto = skb->protocol;
break;
}

switch (proto) {
case htons(ETH_P_IP):
return nf_flow_offload_ip_hook(priv, skb, state);
case htons(ETH_P_IPV6):
Expand Down
18 changes: 0 additions & 18 deletions net/netfilter/nf_flow_table_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#include <linux/ipv6.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_pppox.h>
#include <linux/ppp_defs.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
Expand Down Expand Up @@ -239,22 +237,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
return NF_STOLEN;
}

static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
{
__be16 proto;

proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
sizeof(struct pppoe_hdr)));
switch (proto) {
case htons(PPP_IP):
return htons(ETH_P_IP);
case htons(PPP_IPV6):
return htons(ETH_P_IPV6);
}

return 0;
}

static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
u32 *offset)
{
Expand Down

0 comments on commit 0582475

Please sign in to comment.