Skip to content

Commit 6faee60

Browse files
Florian Westphalummakynes
authored andcommitted
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 <[email protected]> Reviewed-by: Holger Eitzenberger <[email protected]> Reviewed-by: Bart De Schuymer<[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 255d0dc commit 6faee60

2 files changed

Lines changed: 46 additions & 15 deletions

File tree

include/linux/netfilter_bridge/ebt_ip6.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
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 {
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

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@
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)
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)
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)
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

0 commit comments

Comments
 (0)