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 | |
| 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>
| -rw-r--r-- | include/linux/netfilter_bridge/ebt_ip6.h | 15 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebt_ip6.c | 46 |
2 files changed, 46 insertions, 15 deletions
diff --git a/include/linux/netfilter_bridge/ebt_ip6.h b/include/linux/netfilter_bridge/ebt_ip6.h index e5de98701519..22af18a3c16b 100644 --- a/include/linux/netfilter_bridge/ebt_ip6.h +++ b/include/linux/netfilter_bridge/ebt_ip6.h | |||
| @@ -18,8 +18,11 @@ | |||
| 18 | #define EBT_IP6_PROTO 0x08 | 18 | #define EBT_IP6_PROTO 0x08 |
| 19 | #define EBT_IP6_SPORT 0x10 | 19 | #define EBT_IP6_SPORT 0x10 |
| 20 | #define EBT_IP6_DPORT 0x20 | 20 | #define EBT_IP6_DPORT 0x20 |
| 21 | #define EBT_IP6_ICMP6 0x40 | ||
| 22 | |||
| 21 | #define EBT_IP6_MASK (EBT_IP6_SOURCE | EBT_IP6_DEST | EBT_IP6_TCLASS |\ | 23 | #define EBT_IP6_MASK (EBT_IP6_SOURCE | EBT_IP6_DEST | EBT_IP6_TCLASS |\ |
| 22 | EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT) | 24 | EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT | \ |
| 25 | EBT_IP6_ICMP6) | ||
| 23 | #define EBT_IP6_MATCH "ip6" | 26 | #define EBT_IP6_MATCH "ip6" |
| 24 | 27 | ||
| 25 | /* the same values are used for the invflags */ | 28 | /* the same values are used for the invflags */ |
| @@ -32,8 +35,14 @@ struct ebt_ip6_info { | |||
| 32 | uint8_t protocol; | 35 | uint8_t protocol; |
| 33 | uint8_t bitmask; | 36 | uint8_t bitmask; |
| 34 | uint8_t invflags; | 37 | uint8_t invflags; |
| 35 | uint16_t sport[2]; | 38 | union { |
| 36 | uint16_t dport[2]; | 39 | uint16_t sport[2]; |
| 40 | uint8_t icmpv6_type[2]; | ||
| 41 | }; | ||
| 42 | union { | ||
| 43 | uint16_t dport[2]; | ||
| 44 | uint8_t icmpv6_code[2]; | ||
| 45 | }; | ||
| 37 | }; | 46 | }; |
| 38 | 47 | ||
| 39 | #endif | 48 | #endif |
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 | ||
