Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: bridge: split ipv6 code into separated file

Resolve compilation breakage when CONFIG_IPV6 is not set by moving the IPv6
code into a separated br_netfilter_ipv6.c file.

Fixes: efb6de9b4ba0 ("netfilter: bridge: forward IPv6 fragmented packets")
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+315 -239
+60
include/net/netfilter/br_netfilter.h
··· 1 1 #ifndef _BR_NETFILTER_H_ 2 2 #define _BR_NETFILTER_H_ 3 3 4 + #include "../../../net/bridge/br_private.h" 5 + 6 + static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) 7 + { 8 + skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); 9 + 10 + if (likely(skb->nf_bridge)) 11 + atomic_set(&(skb->nf_bridge->use), 1); 12 + 13 + return skb->nf_bridge; 14 + } 15 + 16 + void nf_bridge_update_protocol(struct sk_buff *skb); 17 + 18 + static inline struct nf_bridge_info * 19 + nf_bridge_info_get(const struct sk_buff *skb) 20 + { 21 + return skb->nf_bridge; 22 + } 23 + 24 + unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb); 25 + 26 + static inline void nf_bridge_push_encap_header(struct sk_buff *skb) 27 + { 28 + unsigned int len = nf_bridge_encap_header_len(skb); 29 + 30 + skb_push(skb, len); 31 + skb->network_header -= len; 32 + } 33 + 34 + int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb); 35 + 36 + static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) 37 + { 38 + struct net_bridge_port *port; 39 + 40 + port = br_port_get_rcu(dev); 41 + return port ? &port->br->fake_rtable : NULL; 42 + } 43 + 44 + struct net_device *setup_pre_routing(struct sk_buff *skb); 4 45 void br_netfilter_enable(void); 46 + 47 + #if IS_ENABLED(CONFIG_IPV6) 48 + int br_validate_ipv6(struct sk_buff *skb); 49 + unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, 50 + struct sk_buff *skb, 51 + const struct nf_hook_state *state); 52 + #else 53 + static inline int br_validate_ipv6(struct sk_buff *skb) 54 + { 55 + return -1; 56 + } 57 + 58 + static inline unsigned int 59 + br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, struct sk_buff *skb, 60 + const struct nf_hook_state *state) 61 + { 62 + return NF_DROP; 63 + } 64 + #endif 5 65 6 66 #endif /* _BR_NETFILTER_H_ */
+1
net/bridge/Makefile
··· 13 13 bridge-$(subst m,y,$(CONFIG_BRIDGE_NETFILTER)) += br_nf_core.o 14 14 15 15 br_netfilter-y := br_netfilter_hooks.o 16 + br_netfilter-$(subst m,y,$(CONFIG_IPV6)) += br_netfilter_ipv6.o 16 17 obj-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o 17 18 18 19 bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
+9 -239
net/bridge/br_netfilter_hooks.c
··· 123 123 static DEFINE_PER_CPU(struct brnf_frag_data, brnf_frag_data_storage); 124 124 #endif 125 125 126 - static struct nf_bridge_info *nf_bridge_info_get(const struct sk_buff *skb) 127 - { 128 - return skb->nf_bridge; 129 - } 130 - 131 126 static void nf_bridge_info_free(struct sk_buff *skb) 132 127 { 133 128 if (skb->nf_bridge) { ··· 131 136 } 132 137 } 133 138 134 - static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) 135 - { 136 - struct net_bridge_port *port; 137 - 138 - port = br_port_get_rcu(dev); 139 - return port ? &port->br->fake_rtable : NULL; 140 - } 141 - 142 139 static inline struct net_device *bridge_parent(const struct net_device *dev) 143 140 { 144 141 struct net_bridge_port *port; 145 142 146 143 port = br_port_get_rcu(dev); 147 144 return port ? port->br->dev : NULL; 148 - } 149 - 150 - static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) 151 - { 152 - skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); 153 - if (likely(skb->nf_bridge)) 154 - atomic_set(&(skb->nf_bridge->use), 1); 155 - 156 - return skb->nf_bridge; 157 145 } 158 146 159 147 static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb) ··· 156 178 return nf_bridge; 157 179 } 158 180 159 - static unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb) 181 + unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb) 160 182 { 161 183 switch (skb->protocol) { 162 184 case __cpu_to_be16(ETH_P_8021Q): ··· 166 188 default: 167 189 return 0; 168 190 } 169 - } 170 - 171 - static inline void nf_bridge_push_encap_header(struct sk_buff *skb) 172 - { 173 - unsigned int len = nf_bridge_encap_header_len(skb); 174 - 175 - skb_push(skb, len); 176 - skb->network_header -= len; 177 191 } 178 192 179 193 static inline void nf_bridge_pull_encap_header(struct sk_buff *skb) ··· 237 267 return -1; 238 268 } 239 269 240 - /* We only check the length. A bridge shouldn't do any hop-by-hop stuff 241 - * anyway 242 - */ 243 - static int check_hbh_len(struct sk_buff *skb) 244 - { 245 - unsigned char *raw = (u8 *)(ipv6_hdr(skb) + 1); 246 - u32 pkt_len; 247 - const unsigned char *nh = skb_network_header(skb); 248 - int off = raw - nh; 249 - int len = (raw[1] + 1) << 3; 250 - 251 - if ((raw + len) - skb->data > skb_headlen(skb)) 252 - goto bad; 253 - 254 - off += 2; 255 - len -= 2; 256 - 257 - while (len > 0) { 258 - int optlen = nh[off + 1] + 2; 259 - 260 - switch (nh[off]) { 261 - case IPV6_TLV_PAD1: 262 - optlen = 1; 263 - break; 264 - 265 - case IPV6_TLV_PADN: 266 - break; 267 - 268 - case IPV6_TLV_JUMBO: 269 - if (nh[off + 1] != 4 || (off & 3) != 2) 270 - goto bad; 271 - pkt_len = ntohl(*(__be32 *)(nh + off + 2)); 272 - if (pkt_len <= IPV6_MAXPLEN || 273 - ipv6_hdr(skb)->payload_len) 274 - goto bad; 275 - if (pkt_len > skb->len - sizeof(struct ipv6hdr)) 276 - goto bad; 277 - if (pskb_trim_rcsum(skb, 278 - pkt_len + sizeof(struct ipv6hdr))) 279 - goto bad; 280 - nh = skb_network_header(skb); 281 - break; 282 - default: 283 - if (optlen > len) 284 - goto bad; 285 - break; 286 - } 287 - off += optlen; 288 - len -= optlen; 289 - } 290 - if (len == 0) 291 - return 0; 292 - bad: 293 - return -1; 294 - } 295 - 296 - /* Equivalent to br_validate_ipv4 for IPv6 */ 297 - static int br_validate_ipv6(struct sk_buff *skb) 298 - { 299 - const struct ipv6hdr *hdr; 300 - struct net_device *dev = skb->dev; 301 - struct inet6_dev *idev = in6_dev_get(skb->dev); 302 - u32 pkt_len; 303 - u8 ip6h_len = sizeof(struct ipv6hdr); 304 - 305 - if (!pskb_may_pull(skb, ip6h_len)) 306 - goto inhdr_error; 307 - 308 - if (skb->len < ip6h_len) 309 - goto drop; 310 - 311 - hdr = ipv6_hdr(skb); 312 - 313 - if (hdr->version != 6) 314 - goto inhdr_error; 315 - 316 - pkt_len = ntohs(hdr->payload_len); 317 - 318 - if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { 319 - if (pkt_len + ip6h_len > skb->len) { 320 - IP6_INC_STATS_BH(dev_net(dev), idev, 321 - IPSTATS_MIB_INTRUNCATEDPKTS); 322 - goto drop; 323 - } 324 - if (pskb_trim_rcsum(skb, pkt_len + ip6h_len)) { 325 - IP6_INC_STATS_BH(dev_net(dev), idev, 326 - IPSTATS_MIB_INDISCARDS); 327 - goto drop; 328 - } 329 - } 330 - if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) 331 - goto drop; 332 - 333 - memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); 334 - /* No IP options in IPv6 header; however it should be 335 - * checked if some next headers need special treatment 336 - */ 337 - return 0; 338 - 339 - inhdr_error: 340 - IP6_INC_STATS_BH(dev_net(dev), idev, IPSTATS_MIB_INHDRERRORS); 341 - drop: 342 - return -1; 343 - } 344 - 345 - static void nf_bridge_update_protocol(struct sk_buff *skb) 270 + void nf_bridge_update_protocol(struct sk_buff *skb) 346 271 { 347 272 switch (skb->nf_bridge->orig_proto) { 348 273 case BRNF_PROTO_8021Q: ··· 256 391 * don't, we use the neighbour framework to find out. In both cases, we make 257 392 * sure that br_handle_frame_finish() is called afterwards. 258 393 */ 259 - static int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb) 394 + int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb) 260 395 { 261 396 struct neighbour *neigh; 262 397 struct dst_entry *dst; ··· 296 431 return 0; 297 432 } 298 433 299 - static bool daddr_was_changed(const struct sk_buff *skb, 300 - const struct nf_bridge_info *nf_bridge) 434 + static inline bool 435 + br_nf_ipv4_daddr_was_changed(const struct sk_buff *skb, 436 + const struct nf_bridge_info *nf_bridge) 301 437 { 302 - switch (skb->protocol) { 303 - case htons(ETH_P_IP): 304 - return ip_hdr(skb)->daddr != nf_bridge->ipv4_daddr; 305 - case htons(ETH_P_IPV6): 306 - return memcmp(&nf_bridge->ipv6_daddr, &ipv6_hdr(skb)->daddr, 307 - sizeof(ipv6_hdr(skb)->daddr)) != 0; 308 - default: 309 - return false; 310 - } 311 - } 312 - 313 - /* PF_BRIDGE/PRE_ROUTING: Undo the changes made for ip6tables 314 - * PREROUTING and continue the bridge PRE_ROUTING hook. See comment 315 - * for br_nf_pre_routing_finish(), same logic is used here but 316 - * equivalent IPv6 function ip6_route_input() called indirectly. 317 - */ 318 - static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) 319 - { 320 - struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); 321 - struct rtable *rt; 322 - struct net_device *dev = skb->dev; 323 - const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops(); 324 - 325 - nf_bridge->frag_max_size = IP6CB(skb)->frag_max_size; 326 - 327 - if (nf_bridge->pkt_otherhost) { 328 - skb->pkt_type = PACKET_OTHERHOST; 329 - nf_bridge->pkt_otherhost = false; 330 - } 331 - nf_bridge->mask &= ~BRNF_NF_BRIDGE_PREROUTING; 332 - if (daddr_was_changed(skb, nf_bridge)) { 333 - skb_dst_drop(skb); 334 - v6ops->route_input(skb); 335 - 336 - if (skb_dst(skb)->error) { 337 - kfree_skb(skb); 338 - return 0; 339 - } 340 - 341 - if (skb_dst(skb)->dev == dev) { 342 - skb->dev = nf_bridge->physindev; 343 - nf_bridge_update_protocol(skb); 344 - nf_bridge_push_encap_header(skb); 345 - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, 346 - sk, skb, skb->dev, NULL, 347 - br_nf_pre_routing_finish_bridge, 348 - 1); 349 - return 0; 350 - } 351 - ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr); 352 - skb->pkt_type = PACKET_HOST; 353 - } else { 354 - rt = bridge_parent_rtable(nf_bridge->physindev); 355 - if (!rt) { 356 - kfree_skb(skb); 357 - return 0; 358 - } 359 - skb_dst_set_noref(skb, &rt->dst); 360 - } 361 - 362 - skb->dev = nf_bridge->physindev; 363 - nf_bridge_update_protocol(skb); 364 - nf_bridge_push_encap_header(skb); 365 - NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, sk, skb, 366 - skb->dev, NULL, 367 - br_handle_frame_finish, 1); 368 - 369 - return 0; 438 + return ip_hdr(skb)->daddr != nf_bridge->ipv4_daddr; 370 439 } 371 440 372 441 /* This requires some explaining. If DNAT has taken place, ··· 357 558 nf_bridge->pkt_otherhost = false; 358 559 } 359 560 nf_bridge->mask &= ~BRNF_NF_BRIDGE_PREROUTING; 360 - if (daddr_was_changed(skb, nf_bridge)) { 561 + if (br_nf_ipv4_daddr_was_changed(skb, nf_bridge)) { 361 562 if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { 362 563 struct in_device *in_dev = __in_dev_get_rcu(dev); 363 564 ··· 435 636 } 436 637 437 638 /* Some common code for IPv4/IPv6 */ 438 - static struct net_device *setup_pre_routing(struct sk_buff *skb) 639 + struct net_device *setup_pre_routing(struct sk_buff *skb) 439 640 { 440 641 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); 441 642 ··· 456 657 /* Must drop socket now because of tproxy. */ 457 658 skb_orphan(skb); 458 659 return skb->dev; 459 - } 460 - 461 - /* Replicate the checks that IPv6 does on packet reception and pass the packet 462 - * to ip6tables. 463 - */ 464 - static unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, 465 - struct sk_buff *skb, 466 - const struct nf_hook_state *state) 467 - { 468 - struct nf_bridge_info *nf_bridge; 469 - 470 - if (br_validate_ipv6(skb)) 471 - return NF_DROP; 472 - 473 - nf_bridge_put(skb->nf_bridge); 474 - if (!nf_bridge_alloc(skb)) 475 - return NF_DROP; 476 - if (!setup_pre_routing(skb)) 477 - return NF_DROP; 478 - 479 - nf_bridge = nf_bridge_info_get(skb); 480 - nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; 481 - 482 - skb->protocol = htons(ETH_P_IPV6); 483 - NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->sk, skb, 484 - skb->dev, NULL, 485 - br_nf_pre_routing_finish_ipv6); 486 - 487 - return NF_STOLEN; 488 660 } 489 661 490 662 /* Direct IPv6 traffic to br_nf_pre_routing_ipv6.
+245
net/bridge/br_netfilter_ipv6.c
··· 1 + /* 2 + * Handle firewalling 3 + * Linux ethernet bridge 4 + * 5 + * Authors: 6 + * Lennert Buytenhek <buytenh@gnu.org> 7 + * Bart De Schuymer <bdschuym@pandora.be> 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License 11 + * as published by the Free Software Foundation; either version 12 + * 2 of the License, or (at your option) any later version. 13 + * 14 + * Lennert dedicates this file to Kerstin Wurdinger. 15 + */ 16 + 17 + #include <linux/module.h> 18 + #include <linux/kernel.h> 19 + #include <linux/slab.h> 20 + #include <linux/ip.h> 21 + #include <linux/netdevice.h> 22 + #include <linux/skbuff.h> 23 + #include <linux/if_arp.h> 24 + #include <linux/if_ether.h> 25 + #include <linux/if_vlan.h> 26 + #include <linux/if_pppox.h> 27 + #include <linux/ppp_defs.h> 28 + #include <linux/netfilter_bridge.h> 29 + #include <linux/netfilter_ipv4.h> 30 + #include <linux/netfilter_ipv6.h> 31 + #include <linux/netfilter_arp.h> 32 + #include <linux/in_route.h> 33 + #include <linux/inetdevice.h> 34 + 35 + #include <net/ip.h> 36 + #include <net/ipv6.h> 37 + #include <net/addrconf.h> 38 + #include <net/route.h> 39 + #include <net/netfilter/br_netfilter.h> 40 + 41 + #include <asm/uaccess.h> 42 + #include "br_private.h" 43 + #ifdef CONFIG_SYSCTL 44 + #include <linux/sysctl.h> 45 + #endif 46 + 47 + /* We only check the length. A bridge shouldn't do any hop-by-hop stuff 48 + * anyway 49 + */ 50 + static int br_nf_check_hbh_len(struct sk_buff *skb) 51 + { 52 + unsigned char *raw = (u8 *)(ipv6_hdr(skb) + 1); 53 + u32 pkt_len; 54 + const unsigned char *nh = skb_network_header(skb); 55 + int off = raw - nh; 56 + int len = (raw[1] + 1) << 3; 57 + 58 + if ((raw + len) - skb->data > skb_headlen(skb)) 59 + goto bad; 60 + 61 + off += 2; 62 + len -= 2; 63 + 64 + while (len > 0) { 65 + int optlen = nh[off + 1] + 2; 66 + 67 + switch (nh[off]) { 68 + case IPV6_TLV_PAD1: 69 + optlen = 1; 70 + break; 71 + 72 + case IPV6_TLV_PADN: 73 + break; 74 + 75 + case IPV6_TLV_JUMBO: 76 + if (nh[off + 1] != 4 || (off & 3) != 2) 77 + goto bad; 78 + pkt_len = ntohl(*(__be32 *)(nh + off + 2)); 79 + if (pkt_len <= IPV6_MAXPLEN || 80 + ipv6_hdr(skb)->payload_len) 81 + goto bad; 82 + if (pkt_len > skb->len - sizeof(struct ipv6hdr)) 83 + goto bad; 84 + if (pskb_trim_rcsum(skb, 85 + pkt_len + sizeof(struct ipv6hdr))) 86 + goto bad; 87 + nh = skb_network_header(skb); 88 + break; 89 + default: 90 + if (optlen > len) 91 + goto bad; 92 + break; 93 + } 94 + off += optlen; 95 + len -= optlen; 96 + } 97 + if (len == 0) 98 + return 0; 99 + bad: 100 + return -1; 101 + } 102 + 103 + int br_validate_ipv6(struct sk_buff *skb) 104 + { 105 + const struct ipv6hdr *hdr; 106 + struct net_device *dev = skb->dev; 107 + struct inet6_dev *idev = in6_dev_get(skb->dev); 108 + u32 pkt_len; 109 + u8 ip6h_len = sizeof(struct ipv6hdr); 110 + 111 + if (!pskb_may_pull(skb, ip6h_len)) 112 + goto inhdr_error; 113 + 114 + if (skb->len < ip6h_len) 115 + goto drop; 116 + 117 + hdr = ipv6_hdr(skb); 118 + 119 + if (hdr->version != 6) 120 + goto inhdr_error; 121 + 122 + pkt_len = ntohs(hdr->payload_len); 123 + 124 + if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { 125 + if (pkt_len + ip6h_len > skb->len) { 126 + IP6_INC_STATS_BH(dev_net(dev), idev, 127 + IPSTATS_MIB_INTRUNCATEDPKTS); 128 + goto drop; 129 + } 130 + if (pskb_trim_rcsum(skb, pkt_len + ip6h_len)) { 131 + IP6_INC_STATS_BH(dev_net(dev), idev, 132 + IPSTATS_MIB_INDISCARDS); 133 + goto drop; 134 + } 135 + } 136 + if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb)) 137 + goto drop; 138 + 139 + memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); 140 + /* No IP options in IPv6 header; however it should be 141 + * checked if some next headers need special treatment 142 + */ 143 + return 0; 144 + 145 + inhdr_error: 146 + IP6_INC_STATS_BH(dev_net(dev), idev, IPSTATS_MIB_INHDRERRORS); 147 + drop: 148 + return -1; 149 + } 150 + 151 + static inline bool 152 + br_nf_ipv6_daddr_was_changed(const struct sk_buff *skb, 153 + const struct nf_bridge_info *nf_bridge) 154 + { 155 + return memcmp(&nf_bridge->ipv6_daddr, &ipv6_hdr(skb)->daddr, 156 + sizeof(ipv6_hdr(skb)->daddr)) != 0; 157 + } 158 + 159 + /* PF_BRIDGE/PRE_ROUTING: Undo the changes made for ip6tables 160 + * PREROUTING and continue the bridge PRE_ROUTING hook. See comment 161 + * for br_nf_pre_routing_finish(), same logic is used here but 162 + * equivalent IPv6 function ip6_route_input() called indirectly. 163 + */ 164 + static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) 165 + { 166 + struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); 167 + struct rtable *rt; 168 + struct net_device *dev = skb->dev; 169 + const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops(); 170 + 171 + nf_bridge->frag_max_size = IP6CB(skb)->frag_max_size; 172 + 173 + if (nf_bridge->pkt_otherhost) { 174 + skb->pkt_type = PACKET_OTHERHOST; 175 + nf_bridge->pkt_otherhost = false; 176 + } 177 + nf_bridge->mask &= ~BRNF_NF_BRIDGE_PREROUTING; 178 + if (br_nf_ipv6_daddr_was_changed(skb, nf_bridge)) { 179 + skb_dst_drop(skb); 180 + v6ops->route_input(skb); 181 + 182 + if (skb_dst(skb)->error) { 183 + kfree_skb(skb); 184 + return 0; 185 + } 186 + 187 + if (skb_dst(skb)->dev == dev) { 188 + skb->dev = nf_bridge->physindev; 189 + nf_bridge_update_protocol(skb); 190 + nf_bridge_push_encap_header(skb); 191 + NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, 192 + sk, skb, skb->dev, NULL, 193 + br_nf_pre_routing_finish_bridge, 194 + 1); 195 + return 0; 196 + } 197 + ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr); 198 + skb->pkt_type = PACKET_HOST; 199 + } else { 200 + rt = bridge_parent_rtable(nf_bridge->physindev); 201 + if (!rt) { 202 + kfree_skb(skb); 203 + return 0; 204 + } 205 + skb_dst_set_noref(skb, &rt->dst); 206 + } 207 + 208 + skb->dev = nf_bridge->physindev; 209 + nf_bridge_update_protocol(skb); 210 + nf_bridge_push_encap_header(skb); 211 + NF_HOOK_THRESH(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, sk, skb, 212 + skb->dev, NULL, 213 + br_handle_frame_finish, 1); 214 + 215 + return 0; 216 + } 217 + 218 + /* Replicate the checks that IPv6 does on packet reception and pass the packet 219 + * to ip6tables. 220 + */ 221 + unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, 222 + struct sk_buff *skb, 223 + const struct nf_hook_state *state) 224 + { 225 + struct nf_bridge_info *nf_bridge; 226 + 227 + if (br_validate_ipv6(skb)) 228 + return NF_DROP; 229 + 230 + nf_bridge_put(skb->nf_bridge); 231 + if (!nf_bridge_alloc(skb)) 232 + return NF_DROP; 233 + if (!setup_pre_routing(skb)) 234 + return NF_DROP; 235 + 236 + nf_bridge = nf_bridge_info_get(skb); 237 + nf_bridge->ipv6_daddr = ipv6_hdr(skb)->daddr; 238 + 239 + skb->protocol = htons(ETH_P_IPV6); 240 + NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, state->sk, skb, 241 + skb->dev, NULL, 242 + br_nf_pre_routing_finish_ipv6); 243 + 244 + return NF_STOLEN; 245 + }