提交 fc38582d 编写于 作者: P Patrick McHardy 提交者: David S. Miller

[NETFILTER]: bridge netfilter: consolidate header pushing/pulling code

Consolidate the common push/pull sequences into a few helper functions.
Signed-off-by: NPatrick McHardy <kaber@trash.net>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 cfd6c380
...@@ -55,18 +55,25 @@ static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) ...@@ -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) ...@@ -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_save_header(struct sk_buff *skb) 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)
{ {
int header_size = ETH_HLEN; unsigned int len = nf_bridge_encap_header_len(skb);
skb_pull(skb, len);
skb->network_header += len;
}
if (skb->protocol == htons(ETH_P_8021Q)) static inline void nf_bridge_pull_encap_header_rcsum(struct sk_buff *skb)
header_size += VLAN_HLEN; {
else if (skb->protocol == htons(ETH_P_PPP_SES)) unsigned int len = nf_bridge_encap_header_len(skb);
header_size += PPPOE_SES_HLEN;
skb_pull_rcsum(skb, len);
skb->network_header += len;
}
static inline void nf_bridge_save_header(struct sk_buff *skb)
{
int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) ...@@ -356,15 +354,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
* 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 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) ...@@ -380,13 +370,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
} }
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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册