aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/feature-removal-schedule.txt16
-rw-r--r--include/linux/netfilter_bridge.h1
-rw-r--r--include/linux/netfilter_ipv4.h2
-rw-r--r--include/linux/netfilter_ipv6.h2
-rw-r--r--net/bridge/br_netfilter.c188
-rw-r--r--net/netfilter/xt_physdev.c12
6 files changed, 20 insertions, 201 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 040f437c421b..30f3c8c9c12a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -207,22 +207,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
207 207
208--------------------------- 208---------------------------
209 209
210What: Bridge netfilter deferred IPv4/IPv6 output hook calling
211When: January 2007
212Why: The deferred output hooks are a layering violation causing unusual
213 and broken behaviour on bridge devices. Examples of things they
214 break include QoS classifation using the MARK or CLASSIFY targets,
215 the IPsec policy match and connection tracking with VLANs on a
216 bridge. Their only use is to enable bridge output port filtering
217 within iptables with the physdev match, which can also be done by
218 combining iptables and ebtables using netfilter marks. Until it
219 will get removed the hook deferral is disabled by default and is
220 only enabled when needed.
221
222Who: Patrick McHardy <kaber@trash.net>
223
224---------------------------
225
226What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment 210What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
227When: October 2008 211When: October 2008
228Why: The stacking of class devices makes these values misleading and 212Why: The stacking of class devices makes these values misleading and
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 6c4613f8ad75..55689f39f77a 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -68,7 +68,6 @@ struct bridge_skb_cb {
68 } daddr; 68 } daddr;
69}; 69};
70 70
71extern int brnf_deferred_hooks;
72#else 71#else
73#define nf_bridge_maybe_copy_header(skb) (0) 72#define nf_bridge_maybe_copy_header(skb) (0)
74#define nf_bridge_pad(skb) (0) 73#define nf_bridge_pad(skb) (0)
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 5821eb5a0a3e..ceae87a4c891 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -57,10 +57,8 @@ enum nf_ip_hook_priorities {
57 NF_IP_PRI_RAW = -300, 57 NF_IP_PRI_RAW = -300,
58 NF_IP_PRI_SELINUX_FIRST = -225, 58 NF_IP_PRI_SELINUX_FIRST = -225,
59 NF_IP_PRI_CONNTRACK = -200, 59 NF_IP_PRI_CONNTRACK = -200,
60 NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
61 NF_IP_PRI_MANGLE = -150, 60 NF_IP_PRI_MANGLE = -150,
62 NF_IP_PRI_NAT_DST = -100, 61 NF_IP_PRI_NAT_DST = -100,
63 NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
64 NF_IP_PRI_FILTER = 0, 62 NF_IP_PRI_FILTER = 0,
65 NF_IP_PRI_NAT_SRC = 100, 63 NF_IP_PRI_NAT_SRC = 100,
66 NF_IP_PRI_SELINUX_LAST = 225, 64 NF_IP_PRI_SELINUX_LAST = 225,
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index ab81a6dc94ea..66ca8e3100dc 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -62,10 +62,8 @@ enum nf_ip6_hook_priorities {
62 NF_IP6_PRI_CONNTRACK_DEFRAG = -400, 62 NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
63 NF_IP6_PRI_SELINUX_FIRST = -225, 63 NF_IP6_PRI_SELINUX_FIRST = -225,
64 NF_IP6_PRI_CONNTRACK = -200, 64 NF_IP6_PRI_CONNTRACK = -200,
65 NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
66 NF_IP6_PRI_MANGLE = -150, 65 NF_IP6_PRI_MANGLE = -150,
67 NF_IP6_PRI_NAT_DST = -100, 66 NF_IP6_PRI_NAT_DST = -100,
68 NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
69 NF_IP6_PRI_FILTER = 0, 67 NF_IP6_PRI_FILTER = 0,
70 NF_IP6_PRI_NAT_SRC = 100, 68 NF_IP6_PRI_NAT_SRC = 100,
71 NF_IP6_PRI_SELINUX_LAST = 225, 69 NF_IP6_PRI_SELINUX_LAST = 225,
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index bd221ad52eaf..ea3337ad0edc 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -61,9 +61,6 @@ static int brnf_filter_vlan_tagged __read_mostly = 1;
61#define brnf_filter_vlan_tagged 1 61#define brnf_filter_vlan_tagged 1
62#endif 62#endif
63 63
64int brnf_deferred_hooks;
65EXPORT_SYMBOL_GPL(brnf_deferred_hooks);
66
67static __be16 inline vlan_proto(const struct sk_buff *skb) 64static __be16 inline vlan_proto(const struct sk_buff *skb)
68{ 65{
69 return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; 66 return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
@@ -685,110 +682,50 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
685 return NF_STOLEN; 682 return NF_STOLEN;
686} 683}
687 684
688/* PF_BRIDGE/LOCAL_OUT ***********************************************/ 685/* PF_BRIDGE/LOCAL_OUT ***********************************************
689static int br_nf_local_out_finish(struct sk_buff *skb) 686 *
690{ 687 * This function sees both locally originated IP packets and forwarded
691 if (skb->protocol == htons(ETH_P_8021Q)) {
692 skb_push(skb, VLAN_HLEN);
693 skb->nh.raw -= VLAN_HLEN;
694 }
695
696 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
697 br_forward_finish, NF_BR_PRI_FIRST + 1);
698
699 return 0;
700}
701
702/* This function sees both locally originated IP packets and forwarded
703 * IP packets (in both cases the destination device is a bridge 688 * IP packets (in both cases the destination device is a bridge
704 * device). It also sees bridged-and-DNAT'ed packets. 689 * device). It also sees bridged-and-DNAT'ed packets.
705 * To be able to filter on the physical bridge devices (with the physdev
706 * module), we steal packets destined to a bridge device away from the
707 * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
708 * when we have determined the real output device. This is done in here.
709 * 690 *
710 * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged 691 * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged
711 * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward() 692 * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
712 * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority 693 * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority
713 * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor 694 * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
714 * will be executed. 695 * will be executed.
715 * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched 696 */
716 * this packet before, and so the packet was locally originated. We fake
717 * the PF_INET/LOCAL_OUT hook.
718 * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
719 * so we fake the PF_INET/FORWARD hook. ip_sabotage_out() makes sure
720 * even routed packets that didn't arrive on a bridge interface have their
721 * nf_bridge->physindev set. */
722static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, 697static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
723 const struct net_device *in, 698 const struct net_device *in,
724 const struct net_device *out, 699 const struct net_device *out,
725 int (*okfn)(struct sk_buff *)) 700 int (*okfn)(struct sk_buff *))
726{ 701{
727 struct net_device *realindev, *realoutdev; 702 struct net_device *realindev;
728 struct sk_buff *skb = *pskb; 703 struct sk_buff *skb = *pskb;
729 struct nf_bridge_info *nf_bridge; 704 struct nf_bridge_info *nf_bridge;
730 int pf;
731 705
732 if (!skb->nf_bridge) 706 if (!skb->nf_bridge)
733 return NF_ACCEPT; 707 return NF_ACCEPT;
734 708
735 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
736 pf = PF_INET;
737 else
738 pf = PF_INET6;
739
740 nf_bridge = skb->nf_bridge; 709 nf_bridge = skb->nf_bridge;
741 nf_bridge->physoutdev = skb->dev; 710 if (!(nf_bridge->mask & BRNF_BRIDGED_DNAT))
742 realindev = nf_bridge->physindev; 711 return NF_ACCEPT;
743 712
744 /* Bridged, take PF_BRIDGE/FORWARD. 713 /* Bridged, take PF_BRIDGE/FORWARD.
745 * (see big note in front of br_nf_pre_routing_finish) */ 714 * (see big note in front of br_nf_pre_routing_finish) */
746 if (nf_bridge->mask & BRNF_BRIDGED_DNAT) { 715 nf_bridge->physoutdev = skb->dev;
747 if (nf_bridge->mask & BRNF_PKT_TYPE) { 716 realindev = nf_bridge->physindev;
748 skb->pkt_type = PACKET_OTHERHOST;
749 nf_bridge->mask ^= BRNF_PKT_TYPE;
750 }
751 if (skb->protocol == htons(ETH_P_8021Q)) {
752 skb_push(skb, VLAN_HLEN);
753 skb->nh.raw -= VLAN_HLEN;
754 }
755 717
756 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, 718 if (nf_bridge->mask & BRNF_PKT_TYPE) {
757 skb->dev, br_forward_finish); 719 skb->pkt_type = PACKET_OTHERHOST;
758 goto out; 720 nf_bridge->mask ^= BRNF_PKT_TYPE;
759 } 721 }
760 realoutdev = bridge_parent(skb->dev);
761 if (!realoutdev)
762 return NF_DROP;
763
764#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
765 /* iptables should match -o br0.x */
766 if (nf_bridge->netoutdev)
767 realoutdev = nf_bridge->netoutdev;
768#endif
769 if (skb->protocol == htons(ETH_P_8021Q)) { 722 if (skb->protocol == htons(ETH_P_8021Q)) {
770 skb_pull(skb, VLAN_HLEN); 723 skb_push(skb, VLAN_HLEN);
771 (*pskb)->nh.raw += VLAN_HLEN; 724 skb->nh.raw -= VLAN_HLEN;
772 }
773 /* IP forwarded traffic has a physindev, locally
774 * generated traffic hasn't. */
775 if (realindev != NULL) {
776 if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT)) {
777 struct net_device *parent = bridge_parent(realindev);
778 if (parent)
779 realindev = parent;
780 }
781
782 NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
783 realoutdev, br_nf_local_out_finish,
784 NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
785 } else {
786 NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
787 realoutdev, br_nf_local_out_finish,
788 NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
789 } 725 }
790 726
791out: 727 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
728 br_forward_finish);
792 return NF_STOLEN; 729 return NF_STOLEN;
793} 730}
794 731
@@ -894,69 +831,6 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
894 return NF_ACCEPT; 831 return NF_ACCEPT;
895} 832}
896 833
897/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT
898 * and PF_INET(6)/POST_ROUTING until we have done the forwarding
899 * decision in the bridge code and have determined nf_bridge->physoutdev. */
900static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
901 const struct net_device *in,
902 const struct net_device *out,
903 int (*okfn)(struct sk_buff *))
904{
905 struct sk_buff *skb = *pskb;
906
907 if ((out->hard_start_xmit == br_dev_xmit &&
908 okfn != br_nf_forward_finish &&
909 okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
910#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
911 || ((out->priv_flags & IFF_802_1Q_VLAN) &&
912 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
913#endif
914 ) {
915 struct nf_bridge_info *nf_bridge;
916
917 if (!skb->nf_bridge) {
918#ifdef CONFIG_SYSCTL
919 /* This code is executed while in the IP(v6) stack,
920 the version should be 4 or 6. We can't use
921 skb->protocol because that isn't set on
922 PF_INET(6)/LOCAL_OUT. */
923 struct iphdr *ip = skb->nh.iph;
924
925 if (ip->version == 4 && !brnf_call_iptables)
926 return NF_ACCEPT;
927 else if (ip->version == 6 && !brnf_call_ip6tables)
928 return NF_ACCEPT;
929 else if (!brnf_deferred_hooks)
930 return NF_ACCEPT;
931#endif
932 if (hook == NF_IP_POST_ROUTING)
933 return NF_ACCEPT;
934 if (!nf_bridge_alloc(skb))
935 return NF_DROP;
936 }
937
938 nf_bridge = skb->nf_bridge;
939
940 /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we
941 * will need the indev then. For a brouter, the real indev
942 * can be a bridge port, so we make sure br_nf_local_out()
943 * doesn't use the bridge parent of the indev by using
944 * the BRNF_DONT_TAKE_PARENT mask. */
945 if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
946 nf_bridge->mask |= BRNF_DONT_TAKE_PARENT;
947 nf_bridge->physindev = (struct net_device *)in;
948 }
949#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
950 /* the iptables outdev is br0.x, not br0 */
951 if (out->priv_flags & IFF_802_1Q_VLAN)
952 nf_bridge->netoutdev = (struct net_device *)out;
953#endif
954 return NF_STOP;
955 }
956
957 return NF_ACCEPT;
958}
959
960/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent 834/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
961 * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input. 835 * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
962 * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because 836 * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
@@ -1002,36 +876,6 @@ static struct nf_hook_ops br_nf_ops[] = {
1002 .pf = PF_INET6, 876 .pf = PF_INET6,
1003 .hooknum = NF_IP6_PRE_ROUTING, 877 .hooknum = NF_IP6_PRE_ROUTING,
1004 .priority = NF_IP6_PRI_FIRST, }, 878 .priority = NF_IP6_PRI_FIRST, },
1005 { .hook = ip_sabotage_out,
1006 .owner = THIS_MODULE,
1007 .pf = PF_INET,
1008 .hooknum = NF_IP_FORWARD,
1009 .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
1010 { .hook = ip_sabotage_out,
1011 .owner = THIS_MODULE,
1012 .pf = PF_INET6,
1013 .hooknum = NF_IP6_FORWARD,
1014 .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, },
1015 { .hook = ip_sabotage_out,
1016 .owner = THIS_MODULE,
1017 .pf = PF_INET,
1018 .hooknum = NF_IP_LOCAL_OUT,
1019 .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
1020 { .hook = ip_sabotage_out,
1021 .owner = THIS_MODULE,
1022 .pf = PF_INET6,
1023 .hooknum = NF_IP6_LOCAL_OUT,
1024 .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
1025 { .hook = ip_sabotage_out,
1026 .owner = THIS_MODULE,
1027 .pf = PF_INET,
1028 .hooknum = NF_IP_POST_ROUTING,
1029 .priority = NF_IP_PRI_FIRST, },
1030 { .hook = ip_sabotage_out,
1031 .owner = THIS_MODULE,
1032 .pf = PF_INET6,
1033 .hooknum = NF_IP6_POST_ROUTING,
1034 .priority = NF_IP6_PRI_FIRST, },
1035}; 879};
1036 880
1037#ifdef CONFIG_SYSCTL 881#ifdef CONFIG_SYSCTL
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index fd8f954cded5..b9b3ffc5451d 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -113,20 +113,16 @@ checkentry(const char *tablename,
113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || 113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
114 info->bitmask & ~XT_PHYSDEV_OP_MASK) 114 info->bitmask & ~XT_PHYSDEV_OP_MASK)
115 return 0; 115 return 0;
116 if (brnf_deferred_hooks == 0 && 116 if (info->bitmask & XT_PHYSDEV_OP_OUT &&
117 info->bitmask & XT_PHYSDEV_OP_OUT &&
118 (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || 117 (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
119 info->invert & XT_PHYSDEV_OP_BRIDGED) && 118 info->invert & XT_PHYSDEV_OP_BRIDGED) &&
120 hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | 119 hook_mask & ((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
121 (1 << NF_IP_POST_ROUTING))) { 120 (1 << NF_IP_POST_ROUTING))) {
122 printk(KERN_WARNING "physdev match: using --physdev-out in the " 121 printk(KERN_WARNING "physdev match: using --physdev-out in the "
123 "OUTPUT, FORWARD and POSTROUTING chains for non-bridged " 122 "OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
124 "traffic is deprecated and breaks other things, it will " 123 "traffic is not supported anymore.\n");
125 "be removed in January 2007. See Documentation/" 124 if (hook_mask & (1 << NF_IP_LOCAL_OUT))
126 "feature-removal-schedule.txt for details. This doesn't " 125 return 0;
127 "affect you in case you're using it for purely bridged "
128 "traffic.\n");
129 brnf_deferred_hooks = 1;
130 } 126 }
131 return 1; 127 return 1;
132} 128}