| @@ -61,9 +61,6 @@ static int brnf_filter_vlan_tagged __read_mostly = 1; · 60 unmodified lines |
| 61 | #define brnf_filter_vlan_tagged 1 | 61 | #define brnf_filter_vlan_tagged 1 |
| 62 | #endif | 62 | #endif |
| 63 | | 63 | |
| 64 | int brnf_deferred_hooks; | | |
| 65 | EXPORT_SYMBOL_GPL(brnf_deferred_hooks); | | |
| 66 | | | |
| 67 | static __be16 inline vlan_proto(const struct sk_buff *skb) | 64 | static __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, · 615 unmodified lines |
| 685 | return NF_STOLEN; | 682 | return NF_STOLEN; |
| 686 | } | 683 | } |
| 687 | | 684 | |
| 688 | /* PF_BRIDGE/LOCAL_OUT ***********************************************/ | 685 | /* PF_BRIDGE/LOCAL_OUT *********************************************** |
| 689 | static 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. */ | | |
| 722 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | 697 | static 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 | |
| 791 | out: | 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, · 99 unmodified lines |
| 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. */ | | |
| 900 | static 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[] = { · 39 unmodified lines |
| 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 |