[NETFILTER]: bridge netfilter: consolidate header pushing/pulling code
Consolidate the common push/pull sequences into a few helper functions. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
cfd6c38096
commit
fc38582db9
@@ -55,18 +55,25 @@ static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
switch (skb->protocol) {
|
||||||
|
case __constant_htons(ETH_P_8021Q):
|
||||||
|
return VLAN_HLEN;
|
||||||
|
case __constant_htons(ETH_P_PPP_SES):
|
||||||
|
return PPPOE_SES_HLEN;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This is called by the IP fragmenting code and it ensures there is
|
/* This is called by the IP fragmenting code and it ensures there is
|
||||||
* enough room for the encapsulating header (if there is one). */
|
* enough room for the encapsulating header (if there is one). */
|
||||||
static inline int nf_bridge_pad(const struct sk_buff *skb)
|
static inline unsigned int nf_bridge_pad(const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int padding = 0;
|
if (skb->nf_bridge)
|
||||||
|
return nf_bridge_encap_header_len(skb);
|
||||||
if (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
|
return 0;
|
||||||
padding = VLAN_HLEN;
|
|
||||||
else if (skb->nf_bridge && skb->protocol == htons(ETH_P_PPP_SES))
|
|
||||||
padding = PPPOE_SES_HLEN;
|
|
||||||
|
|
||||||
return padding;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bridge_skb_cb {
|
struct bridge_skb_cb {
|
||||||
|
@@ -142,14 +142,33 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
|
|||||||
return skb->nf_bridge;
|
return skb->nf_bridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
unsigned int len = nf_bridge_encap_header_len(skb);
|
||||||
|
|
||||||
|
skb_push(skb, len);
|
||||||
|
skb->network_header -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nf_bridge_pull_encap_header(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
unsigned int len = nf_bridge_encap_header_len(skb);
|
||||||
|
|
||||||
|
skb_pull(skb, len);
|
||||||
|
skb->network_header += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nf_bridge_pull_encap_header_rcsum(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
unsigned int len = nf_bridge_encap_header_len(skb);
|
||||||
|
|
||||||
|
skb_pull_rcsum(skb, len);
|
||||||
|
skb->network_header += len;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void nf_bridge_save_header(struct sk_buff *skb)
|
static inline void nf_bridge_save_header(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int header_size = ETH_HLEN;
|
int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
|
||||||
|
|
||||||
if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
header_size += VLAN_HLEN;
|
|
||||||
else if (skb->protocol == htons(ETH_P_PPP_SES))
|
|
||||||
header_size += PPPOE_SES_HLEN;
|
|
||||||
|
|
||||||
skb_copy_from_linear_data_offset(skb, -header_size,
|
skb_copy_from_linear_data_offset(skb, -header_size,
|
||||||
skb->nf_bridge->data, header_size);
|
skb->nf_bridge->data, header_size);
|
||||||
@@ -162,12 +181,7 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
|
|||||||
int nf_bridge_copy_header(struct sk_buff *skb)
|
int nf_bridge_copy_header(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int header_size = ETH_HLEN;
|
int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
|
||||||
|
|
||||||
if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
header_size += VLAN_HLEN;
|
|
||||||
else if (skb->protocol == htons(ETH_P_PPP_SES))
|
|
||||||
header_size += PPPOE_SES_HLEN;
|
|
||||||
|
|
||||||
err = skb_cow(skb, header_size);
|
err = skb_cow(skb, header_size);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -175,11 +189,7 @@ int nf_bridge_copy_header(struct sk_buff *skb)
|
|||||||
|
|
||||||
skb_copy_to_linear_data_offset(skb, -header_size,
|
skb_copy_to_linear_data_offset(skb, -header_size,
|
||||||
skb->nf_bridge->data, header_size);
|
skb->nf_bridge->data, header_size);
|
||||||
|
__skb_push(skb, nf_bridge_encap_header_len(skb));
|
||||||
if (skb->protocol == htons(ETH_P_8021Q))
|
|
||||||
__skb_push(skb, VLAN_HLEN);
|
|
||||||
else if (skb->protocol == htons(ETH_P_PPP_SES))
|
|
||||||
__skb_push(skb, PPPOE_SES_HLEN);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,13 +210,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
|
|||||||
dst_hold(skb->dst);
|
dst_hold(skb->dst);
|
||||||
|
|
||||||
skb->dev = nf_bridge->physindev;
|
skb->dev = nf_bridge->physindev;
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_push_encap_header(skb);
|
||||||
skb_push(skb, VLAN_HLEN);
|
|
||||||
skb->network_header -= VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_push(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header -= PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
||||||
br_handle_frame_finish, 1);
|
br_handle_frame_finish, 1);
|
||||||
|
|
||||||
@@ -284,13 +288,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
|
|||||||
if (!skb->dev)
|
if (!skb->dev)
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
else {
|
else {
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_pull_encap_header(skb);
|
||||||
skb_pull(skb, VLAN_HLEN);
|
|
||||||
skb->network_header += VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_pull(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header += PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
skb->dst->output(skb);
|
skb->dst->output(skb);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -356,15 +354,7 @@ bridged_dnat:
|
|||||||
* bridged frame */
|
* bridged frame */
|
||||||
nf_bridge->mask |= BRNF_BRIDGED_DNAT;
|
nf_bridge->mask |= BRNF_BRIDGED_DNAT;
|
||||||
skb->dev = nf_bridge->physindev;
|
skb->dev = nf_bridge->physindev;
|
||||||
if (skb->protocol ==
|
nf_bridge_push_encap_header(skb);
|
||||||
htons(ETH_P_8021Q)) {
|
|
||||||
skb_push(skb, VLAN_HLEN);
|
|
||||||
skb->network_header -= VLAN_HLEN;
|
|
||||||
} else if(skb->protocol ==
|
|
||||||
htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_push(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header -= PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
|
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
|
||||||
skb, skb->dev, NULL,
|
skb, skb->dev, NULL,
|
||||||
br_nf_pre_routing_finish_bridge,
|
br_nf_pre_routing_finish_bridge,
|
||||||
@@ -380,13 +370,7 @@ bridged_dnat:
|
|||||||
}
|
}
|
||||||
|
|
||||||
skb->dev = nf_bridge->physindev;
|
skb->dev = nf_bridge->physindev;
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_push_encap_header(skb);
|
||||||
skb_push(skb, VLAN_HLEN);
|
|
||||||
skb->network_header -= VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_push(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header -= PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
||||||
br_handle_frame_finish, 1);
|
br_handle_frame_finish, 1);
|
||||||
|
|
||||||
@@ -536,14 +520,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
|
|||||||
#endif
|
#endif
|
||||||
if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
|
if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
nf_bridge_pull_encap_header_rcsum(skb);
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
|
||||||
skb_pull_rcsum(skb, VLAN_HLEN);
|
|
||||||
skb->network_header += VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_pull_rcsum(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header += PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
|
return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
@@ -557,14 +534,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
|
|||||||
|
|
||||||
if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
|
if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
nf_bridge_pull_encap_header_rcsum(skb);
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
|
||||||
skb_pull_rcsum(skb, VLAN_HLEN);
|
|
||||||
skb->network_header += VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_pull_rcsum(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header += PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
|
||||||
goto inhdr_error;
|
goto inhdr_error;
|
||||||
@@ -642,13 +612,7 @@ static int br_nf_forward_finish(struct sk_buff *skb)
|
|||||||
} else {
|
} else {
|
||||||
in = *((struct net_device **)(skb->cb));
|
in = *((struct net_device **)(skb->cb));
|
||||||
}
|
}
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_push_encap_header(skb);
|
||||||
skb_push(skb, VLAN_HLEN);
|
|
||||||
skb->network_header -= VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_push(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header -= PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
|
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
|
||||||
skb->dev, br_forward_finish, 1);
|
skb->dev, br_forward_finish, 1);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -682,13 +646,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
|
|||||||
else
|
else
|
||||||
pf = PF_INET6;
|
pf = PF_INET6;
|
||||||
|
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_pull_encap_header(*pskb);
|
||||||
skb_pull(*pskb, VLAN_HLEN);
|
|
||||||
(*pskb)->network_header += VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_pull(*pskb, PPPOE_SES_HLEN);
|
|
||||||
(*pskb)->network_header += PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
nf_bridge = skb->nf_bridge;
|
nf_bridge = skb->nf_bridge;
|
||||||
if (skb->pkt_type == PACKET_OTHERHOST) {
|
if (skb->pkt_type == PACKET_OTHERHOST) {
|
||||||
@@ -722,15 +680,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
|
|||||||
if (skb->protocol != htons(ETH_P_ARP)) {
|
if (skb->protocol != htons(ETH_P_ARP)) {
|
||||||
if (!IS_VLAN_ARP(skb))
|
if (!IS_VLAN_ARP(skb))
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
skb_pull(*pskb, VLAN_HLEN);
|
nf_bridge_pull_encap_header(*pskb);
|
||||||
(*pskb)->network_header += VLAN_HLEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arp_hdr(skb)->ar_pln != 4) {
|
if (arp_hdr(skb)->ar_pln != 4) {
|
||||||
if (IS_VLAN_ARP(skb)) {
|
if (IS_VLAN_ARP(skb))
|
||||||
skb_push(*pskb, VLAN_HLEN);
|
nf_bridge_push_encap_header(*pskb);
|
||||||
(*pskb)->network_header -= VLAN_HLEN;
|
|
||||||
}
|
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
*d = (struct net_device *)in;
|
*d = (struct net_device *)in;
|
||||||
@@ -777,13 +732,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
|
|||||||
skb->pkt_type = PACKET_OTHERHOST;
|
skb->pkt_type = PACKET_OTHERHOST;
|
||||||
nf_bridge->mask ^= BRNF_PKT_TYPE;
|
nf_bridge->mask ^= BRNF_PKT_TYPE;
|
||||||
}
|
}
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_push_encap_header(skb);
|
||||||
skb_push(skb, VLAN_HLEN);
|
|
||||||
skb->network_header -= VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_push(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header -= PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
|
NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
|
||||||
br_forward_finish);
|
br_forward_finish);
|
||||||
@@ -848,14 +797,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
|
|||||||
nf_bridge->mask |= BRNF_PKT_TYPE;
|
nf_bridge->mask |= BRNF_PKT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
nf_bridge_pull_encap_header(skb);
|
||||||
skb_pull(skb, VLAN_HLEN);
|
|
||||||
skb->network_header += VLAN_HLEN;
|
|
||||||
} else if (skb->protocol == htons(ETH_P_PPP_SES)) {
|
|
||||||
skb_pull(skb, PPPOE_SES_HLEN);
|
|
||||||
skb->network_header += PPPOE_SES_HLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
nf_bridge_save_header(skb);
|
nf_bridge_save_header(skb);
|
||||||
|
|
||||||
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
||||||
|
Reference in New Issue
Block a user