History

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.

Florian Westphal committed 15 years ago

Commit 6faee601 parent 255d0dc2 files · +46 −15Browse files

Unified · Split

2 files
  1. include/linux/netfilter_bridge/ebt_ip6.h +12 −3
  2. net/bridge/netfilter/ebt_ip6.c +34 −12
include/linux/netfilter_bridge/ebt_ip6.h+12−3
@@ -18,8 +18,11 @@ · 17 unmodified lines
1818 #define EBT_IP6_PROTO 0x08
1919 #define EBT_IP6_SPORT 0x10
2020 #define EBT_IP6_DPORT 0x20
21+#define EBT_IP6_ICMP6 0x40
22+
2123 #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)
2326 #define EBT_IP6_MATCH "ip6"
2427
2528 /* the same values are used for the invflags */
@@ -32,8 +35,14 @@ struct ebt_ip6_info { · 6 unmodified lines
3235 uint8_t protocol;
3336 uint8_t bitmask;
3437 uint8_t invflags;
35− uint16_t sport[2];
36− uint16_t dport[2];
38+ union {
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+ };
3746 };
3847
3948 #endif
net/bridge/netfilter/ebt_ip6.c+34−12
@@ -22,9 +22,15 @@ · 21 unmodified lines
2222 #include <linux/netfilter_bridge/ebtables.h>
2323 #include <linux/netfilter_bridge/ebt_ip6.h>
2424
25−struct tcpudphdr {
26− __be16 src;
27− __be16 dst;
25+union pkthdr {
26+ struct {
27+ __be16 src;
28+ __be16 dst;
29+ } tcpudphdr;
30+ struct {
31+ u8 type;
32+ u8 code;
33+ } icmphdr;
2834 };
2935
3036 static bool
@@ -33,8 +39,8 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) · 2 unmodified lines
3339 const struct ebt_ip6_info *info = par->matchinfo;
3440 const struct ipv6hdr *ih6;
3541 struct ipv6hdr _ip6h;
36− const struct tcpudphdr *pptr;
37− struct tcpudphdr _ports;
42+ const union pkthdr *pptr;
43+ union pkthdr _pkthdr;
3844
3945 ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h);
4046 if (ih6 == NULL)
@@ -56,26 +62,34 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) · 15 unmodified lines
5662 return false;
5763 if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
5864 return false;
59− if (!(info->bitmask & EBT_IP6_DPORT) &&
60− !(info->bitmask & EBT_IP6_SPORT))
65+ if (!(info->bitmask & ( EBT_IP6_DPORT |
66+ EBT_IP6_SPORT | EBT_IP6_ICMP6)))
6167 return true;
62− pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports),
63− &_ports);
68+
69+ /* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */
70+ pptr = skb_header_pointer(skb, offset_ph, sizeof(_pkthdr),
71+ &_pkthdr);
6472 if (pptr == NULL)
6573 return false;
6674 if (info->bitmask & EBT_IP6_DPORT) {
67− u32 dst = ntohs(pptr->dst);
75+ u16 dst = ntohs(pptr->tcpudphdr.dst);
6876 if (FWINV(dst < info->dport[0] ||
6977 dst > info->dport[1], EBT_IP6_DPORT))
7078 return false;
7179 }
7280 if (info->bitmask & EBT_IP6_SPORT) {
73− u32 src = ntohs(pptr->src);
81+ u16 src = ntohs(pptr->tcpudphdr.src);
7482 if (FWINV(src < info->sport[0] ||
7583 src > info->sport[1], EBT_IP6_SPORT))
7684 return false;
7785 }
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;
7993 }
8094 return true;
8195 }
@@ -103,6 +117,14 @@ static int ebt_ip6_mt_check(const struct xt_mtchk_param *par) · 21 unmodified lines
103117 return -EINVAL;
104118 if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1])
105119 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+ }
106128 return 0;
107129 }
108130