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 | ||