|
@@ -1486,6 +1486,39 @@ resolve_normal_ct(struct nf_conn *tmpl,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * icmp packets need special treatment to handle error messages that are
|
|
|
+ * related to a connection.
|
|
|
+ *
|
|
|
+ * Callers need to check if skb has a conntrack assigned when this
|
|
|
+ * helper returns; in such case skb belongs to an already known connection.
|
|
|
+ */
|
|
|
+static unsigned int __cold
|
|
|
+nf_conntrack_handle_icmp(struct nf_conn *tmpl,
|
|
|
+ struct sk_buff *skb,
|
|
|
+ unsigned int dataoff,
|
|
|
+ u8 protonum,
|
|
|
+ const struct nf_hook_state *state)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (state->pf == NFPROTO_IPV4 && protonum == IPPROTO_ICMP)
|
|
|
+ ret = nf_conntrack_icmpv4_error(tmpl, skb, dataoff, state);
|
|
|
+#if IS_ENABLED(CONFIG_IPV6)
|
|
|
+ else if (state->pf == NFPROTO_IPV6 && protonum == IPPROTO_ICMPV6)
|
|
|
+ ret = nf_conntrack_icmpv6_error(tmpl, skb, dataoff, state);
|
|
|
+#endif
|
|
|
+ else
|
|
|
+ return NF_ACCEPT;
|
|
|
+
|
|
|
+ if (ret <= 0) {
|
|
|
+ NF_CT_STAT_INC_ATOMIC(state->net, error);
|
|
|
+ NF_CT_STAT_INC_ATOMIC(state->net, invalid);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
unsigned int
|
|
|
nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
|
|
|
{
|
|
@@ -1518,14 +1551,10 @@ nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
|
|
|
|
|
|
l4proto = __nf_ct_l4proto_find(state->pf, protonum);
|
|
|
|
|
|
- /* It may be an special packet, error, unclean...
|
|
|
- * inverse of the return code tells to the netfilter
|
|
|
- * core what to do with the packet. */
|
|
|
- if (l4proto->error != NULL) {
|
|
|
- ret = l4proto->error(tmpl, skb, dataoff, state);
|
|
|
+ if (protonum == IPPROTO_ICMP || protonum == IPPROTO_ICMPV6) {
|
|
|
+ ret = nf_conntrack_handle_icmp(tmpl, skb, dataoff,
|
|
|
+ protonum, state);
|
|
|
if (ret <= 0) {
|
|
|
- NF_CT_STAT_INC_ATOMIC(state->net, error);
|
|
|
- NF_CT_STAT_INC_ATOMIC(state->net, invalid);
|
|
|
ret = -ret;
|
|
|
goto out;
|
|
|
}
|