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