|
@@ -53,6 +53,17 @@ static const u_int8_t invmap[] = {
|
|
|
[ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY +1
|
|
|
};
|
|
|
|
|
|
+static const u_int8_t noct_valid_new[] = {
|
|
|
+ [ICMPV6_MGM_QUERY - 130] = 1,
|
|
|
+ [ICMPV6_MGM_REPORT -130] = 1,
|
|
|
+ [ICMPV6_MGM_REDUCTION - 130] = 1,
|
|
|
+ [NDISC_ROUTER_SOLICITATION - 130] = 1,
|
|
|
+ [NDISC_ROUTER_ADVERTISEMENT - 130] = 1,
|
|
|
+ [NDISC_NEIGHBOUR_SOLICITATION - 130] = 1,
|
|
|
+ [NDISC_NEIGHBOUR_ADVERTISEMENT - 130] = 1,
|
|
|
+ [ICMPV6_MLD2_REPORT - 130] = 1
|
|
|
+};
|
|
|
+
|
|
|
static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
|
|
|
const struct nf_conntrack_tuple *orig)
|
|
|
{
|
|
@@ -178,6 +189,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
|
|
|
{
|
|
|
const struct icmp6hdr *icmp6h;
|
|
|
struct icmp6hdr _ih;
|
|
|
+ int type;
|
|
|
|
|
|
icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
|
|
|
if (icmp6h == NULL) {
|
|
@@ -194,6 +206,15 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
|
|
|
return -NF_ACCEPT;
|
|
|
}
|
|
|
|
|
|
+ type = icmp6h->icmp6_type - 130;
|
|
|
+ if (type >= 0 && type < sizeof(noct_valid_new) &&
|
|
|
+ noct_valid_new[type]) {
|
|
|
+ skb->nfct = &nf_conntrack_untracked.ct_general;
|
|
|
+ skb->nfctinfo = IP_CT_NEW;
|
|
|
+ nf_conntrack_get(skb->nfct);
|
|
|
+ return NF_ACCEPT;
|
|
|
+ }
|
|
|
+
|
|
|
/* is not error message ? */
|
|
|
if (icmp6h->icmp6_type >= 128)
|
|
|
return NF_ACCEPT;
|