diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bridge/br_netfilter.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 6fc9ecc4eb39..f29450b788be 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -113,6 +113,25 @@ static inline struct net_device *bridge_parent(const struct net_device *dev) | |||
| 113 | return port ? port->br->dev : NULL; | 113 | return port ? port->br->dev : NULL; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) | ||
| 117 | { | ||
| 118 | skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); | ||
| 119 | if (likely(skb->nf_bridge)) | ||
| 120 | atomic_set(&(skb->nf_bridge->use), 1); | ||
| 121 | |||
| 122 | return skb->nf_bridge; | ||
| 123 | } | ||
| 124 | |||
| 125 | static inline void nf_bridge_save_header(struct sk_buff *skb) | ||
| 126 | { | ||
| 127 | int header_size = 16; | ||
| 128 | |||
| 129 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
| 130 | header_size = 18; | ||
| 131 | |||
| 132 | memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); | ||
| 133 | } | ||
| 134 | |||
| 116 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ | 135 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ |
| 117 | /* Undo the changes made for ip6tables PREROUTING and continue the | 136 | /* Undo the changes made for ip6tables PREROUTING and continue the |
| 118 | * bridge PRE_ROUTING hook. */ | 137 | * bridge PRE_ROUTING hook. */ |
| @@ -371,7 +390,6 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | |||
| 371 | { | 390 | { |
| 372 | struct ipv6hdr *hdr; | 391 | struct ipv6hdr *hdr; |
| 373 | u32 pkt_len; | 392 | u32 pkt_len; |
| 374 | struct nf_bridge_info *nf_bridge; | ||
| 375 | 393 | ||
| 376 | if (skb->len < sizeof(struct ipv6hdr)) | 394 | if (skb->len < sizeof(struct ipv6hdr)) |
| 377 | goto inhdr_error; | 395 | goto inhdr_error; |
| @@ -400,7 +418,7 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | |||
| 400 | goto inhdr_error; | 418 | goto inhdr_error; |
| 401 | 419 | ||
| 402 | nf_bridge_put(skb->nf_bridge); | 420 | nf_bridge_put(skb->nf_bridge); |
| 403 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) | 421 | if (!nf_bridge_alloc(skb)) |
| 404 | return NF_DROP; | 422 | return NF_DROP; |
| 405 | if (!setup_pre_routing(skb)) | 423 | if (!setup_pre_routing(skb)) |
| 406 | return NF_DROP; | 424 | return NF_DROP; |
| @@ -428,7 +446,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 428 | struct iphdr *iph; | 446 | struct iphdr *iph; |
| 429 | __u32 len; | 447 | __u32 len; |
| 430 | struct sk_buff *skb = *pskb; | 448 | struct sk_buff *skb = *pskb; |
| 431 | struct nf_bridge_info *nf_bridge; | ||
| 432 | 449 | ||
| 433 | if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) { | 450 | if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) { |
| 434 | #ifdef CONFIG_SYSCTL | 451 | #ifdef CONFIG_SYSCTL |
| @@ -485,7 +502,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 485 | } | 502 | } |
| 486 | 503 | ||
| 487 | nf_bridge_put(skb->nf_bridge); | 504 | nf_bridge_put(skb->nf_bridge); |
| 488 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) | 505 | if (!nf_bridge_alloc(skb)) |
| 489 | return NF_DROP; | 506 | return NF_DROP; |
| 490 | if (!setup_pre_routing(skb)) | 507 | if (!setup_pre_routing(skb)) |
| 491 | return NF_DROP; | 508 | return NF_DROP; |
