diff options
| author | Florian Westphal <fw@strlen.de> | 2010-12-20 09:57:47 -0500 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2011-01-13 06:05:12 -0500 |
| commit | 6faee60a4e82075853a437831768cc9e2e563e4e (patch) | |
| tree | 2e5ae700342b8b24f027b7c7afa198f4bfe2e92f /net/bridge | |
| parent | 255d0dc34068a976550ce555e153c0bfcfec7cc6 (diff) | |
netfilter: ebt_ip6: allow matching on ipv6-icmp types/codes
To avoid adding a new match revision icmp type/code are stored
in the sport/dport area.
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Holger Eitzenberger <holger@eitzenberger.org>
Reviewed-by: Bart De Schuymer<bdschuym@pandora.be>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/bridge')
| -rw-r--r-- | net/bridge/netfilter/ebt_ip6.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c index 50a46afc2bcc..2ed0056a39a8 100644 --- a/net/bridge/netfilter/ebt_ip6.c +++ b/net/bridge/netfilter/ebt_ip6.c | |||
| @@ -22,9 +22,15 @@ | |||
| 22 | #include <linux/netfilter_bridge/ebtables.h> | 22 | #include <linux/netfilter_bridge/ebtables.h> |
| 23 | #include <linux/netfilter_bridge/ebt_ip6.h> | 23 | #include <linux/netfilter_bridge/ebt_ip6.h> |
| 24 | 24 | ||
| 25 | struct tcpudphdr { | 25 | union pkthdr { |
| 26 | __be16 src; | 26 | struct { |
| 27 | __be16 dst; | 27 | __be16 src; |
| 28 | __be16 dst; | ||
| 29 | } tcpudphdr; | ||
| 30 | struct { | ||
| 31 | u8 type; | ||
| 32 | u8 code; | ||
| 33 | } icmphdr; | ||
| 28 | }; | 34 | }; |
| 29 | 35 | ||
| 30 | static bool | 36 | static bool |
| @@ -33,8 +39,8 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 33 | const struct ebt_ip6_info *info = par->matchinfo; | 39 | const struct ebt_ip6_info *info = par->matchinfo; |
| 34 | const struct ipv6hdr *ih6; | 40 | const struct ipv6hdr *ih6; |
| 35 | struct ipv6hdr _ip6h; | 41 | struct ipv6hdr _ip6h; |
| 36 | const struct tcpudphdr *pptr; | 42 | const union pkthdr *pptr; |
| 37 | struct tcpudphdr _ports; | 43 | union pkthdr _pkthdr; |
| 38 | 44 | ||
| 39 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); | 45 | ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); |
| 40 | if (ih6 == NULL) | 46 | if (ih6 == NULL) |
| @@ -56,26 +62,34 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 56 | return false; | 62 | return false; |
| 57 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) | 63 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) |
| 58 | return false; | 64 | return false; |
| 59 | if (!(info->bitmask & EBT_IP6_DPORT) && | 65 | if (!(info->bitmask & ( EBT_IP6_DPORT | |
| 60 | !(info->bitmask & EBT_IP6_SPORT)) | 66 | EBT_IP6_SPORT | EBT_IP6_ICMP6))) |
| 61 | return true; | 67 | return true; |
| 62 | pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports), | 68 | |
| 63 | &_ports); | 69 | /* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */ |
| 70 | pptr = skb_header_pointer(skb, offset_ph, sizeof(_pkthdr), | ||
| 71 | &_pkthdr); | ||
| 64 | if (pptr == NULL) | 72 | if (pptr == NULL) |
| 65 | return false; | 73 | return false; |
| 66 | if (info->bitmask & EBT_IP6_DPORT) { | 74 | if (info->bitmask & EBT_IP6_DPORT) { |
| 67 | u32 dst = ntohs(pptr->dst); | 75 | u16 dst = ntohs(pptr->tcpudphdr.dst); |
| 68 | if (FWINV(dst < info->dport[0] || | 76 | if (FWINV(dst < info->dport[0] || |
| 69 | dst > info->dport[1], EBT_IP6_DPORT)) | 77 | dst > info->dport[1], EBT_IP6_DPORT)) |
| 70 | return false; | 78 | return false; |
| 71 | } | 79 | } |
| 72 | if (info->bitmask & EBT_IP6_SPORT) { | 80 | if (info->bitmask & EBT_IP6_SPORT) { |
| 73 | u32 src = ntohs(pptr->src); | 81 | u16 src = ntohs(pptr->tcpudphdr.src); |
| 74 | if (FWINV(src < info->sport[0] || | 82 | if (FWINV(src < info->sport[0] || |
| 75 | src > info->sport[1], EBT_IP6_SPORT)) | 83 | src > info->sport[1], EBT_IP6_SPORT)) |
| 76 | return false; | 84 | return false; |
| 77 | } | 85 | } |
| 78 | return true; | 86 | if ((info->bitmask & EBT_IP6_ICMP6) && |
| 87 | FWINV(pptr->icmphdr.type < info->icmpv6_type[0] || | ||
| 88 | pptr->icmphdr.type > info->icmpv6_type[1] || | ||
| 89 | pptr->icmphdr.code < info->icmpv6_code[0] || | ||
| 90 | pptr->icmphdr.code > info->icmpv6_code[1], | ||
| 91 | EBT_IP6_ICMP6)) | ||
| 92 | return false; | ||
| 79 | } | 93 | } |
| 80 | return true; | 94 | return true; |
| 81 | } | 95 | } |
| @@ -103,6 +117,14 @@ static int ebt_ip6_mt_check(const struct xt_mtchk_param *par) | |||
| 103 | return -EINVAL; | 117 | return -EINVAL; |
| 104 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) | 118 | if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1]) |
| 105 | return -EINVAL; | 119 | return -EINVAL; |
| 120 | if (info->bitmask & EBT_IP6_ICMP6) { | ||
| 121 | if ((info->invflags & EBT_IP6_PROTO) || | ||
| 122 | info->protocol != IPPROTO_ICMPV6) | ||
| 123 | return -EINVAL; | ||
| 124 | if (info->icmpv6_type[0] > info->icmpv6_type[1] || | ||
| 125 | info->icmpv6_code[0] > info->icmpv6_code[1]) | ||
| 126 | return -EINVAL; | ||
| 127 | } | ||
| 106 | return 0; | 128 | return 0; |
| 107 | } | 129 | } |
| 108 | 130 | ||
