Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4f3db15 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: conntrack: add and use nf_l4proto_log_invalid



We currently pass down the l4 protocol to the conntrack ->packet()
function, but the only user of this is the debug info decision.

Same information can be derived from struct nf_conn.
As a first step, add and use a new log function for this, similar to
nf_ct_helper_log().

Add __cold annotation -- invalid packets should be infrequent so
gcc can consider all call paths that lead to such a function as
unlikely.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 2420770b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -152,8 +152,18 @@ extern const struct nla_policy nf_ct_port_nla_policy[];
#define LOG_INVALID(net, proto)				\
	((net)->ct.sysctl_log_invalid == (proto) ||	\
	 (net)->ct.sysctl_log_invalid == IPPROTO_RAW)

__printf(5, 6) __cold
void nf_l4proto_log_invalid(const struct sk_buff *skb,
			    struct net *net,
			    u16 pf, u8 protonum,
			    const char *fmt, ...);
#else
static inline int LOG_INVALID(struct net *net, int proto) { return 0; }

static inline __printf(5, 6) __cold
void nf_l4proto_log_invalid(const struct sk_buff *skb, struct net *net,
			    u16 pf, u8 protonum, const char *fmt, ...) {}
#endif /* CONFIG_SYSCTL */

#endif /*_NF_CONNTRACK_PROTOCOL_H*/
+9 −9
Original line number Diff line number Diff line
@@ -165,6 +165,12 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
	return NF_ACCEPT;
}

static void icmp_error_log(const struct sk_buff *skb, struct net *net,
			   u8 pf, const char *msg)
{
	nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMP, "%s", msg);
}

/* Small and modified version of icmp_rcv */
static int
icmp_error(struct net *net, struct nf_conn *tmpl,
@@ -177,18 +183,14 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
	/* Not enough header? */
	icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
	if (icmph == NULL) {
		if (LOG_INVALID(net, IPPROTO_ICMP))
			nf_log_packet(net, PF_INET, 0, skb, NULL, NULL,
				      NULL, "nf_ct_icmp: short packet ");
		icmp_error_log(skb, net, pf, "short packet");
		return -NF_ACCEPT;
	}

	/* See ip_conntrack_proto_tcp.c */
	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
	    nf_ip_checksum(skb, hooknum, dataoff, 0)) {
		if (LOG_INVALID(net, IPPROTO_ICMP))
			nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL,
				      "nf_ct_icmp: bad HW ICMP checksum ");
		icmp_error_log(skb, net, pf, "bad hw icmp checksum");
		return -NF_ACCEPT;
	}

@@ -199,9 +201,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl,
	 *		  discarded.
	 */
	if (icmph->type > NR_ICMP_TYPES) {
		if (LOG_INVALID(net, IPPROTO_ICMP))
			nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL,
				      "nf_ct_icmp: invalid ICMP type ");
		icmp_error_log(skb, net, pf, "invalid icmp type");
		return -NF_ACCEPT;
	}

+8 −6
Original line number Diff line number Diff line
@@ -176,6 +176,12 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
	return NF_ACCEPT;
}

static void icmpv6_error_log(const struct sk_buff *skb, struct net *net,
			     u8 pf, const char *msg)
{
	nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMPV6, "%s", msg);
}

static int
icmpv6_error(struct net *net, struct nf_conn *tmpl,
	     struct sk_buff *skb, unsigned int dataoff,
@@ -187,17 +193,13 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,

	icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
	if (icmp6h == NULL) {
		if (LOG_INVALID(net, IPPROTO_ICMPV6))
			nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
			      "nf_ct_icmpv6: short packet ");
		icmpv6_error_log(skb, net, pf, "short packet");
		return -NF_ACCEPT;
	}

	if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
	    nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
		if (LOG_INVALID(net, IPPROTO_ICMPV6))
			nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL,
				      "nf_ct_icmpv6: ICMPv6 checksum failed ");
		icmpv6_error_log(skb, net, pf, "ICMPv6 checksum failed");
		return -NF_ACCEPT;
	}

+24 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_log.h>

static struct nf_conntrack_l4proto __rcu **nf_ct_protos[NFPROTO_NUMPROTO] __read_mostly;
struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO] __read_mostly;
@@ -63,6 +64,29 @@ nf_ct_unregister_sysctl(struct ctl_table_header **header,
	*header = NULL;
	*table = NULL;
}

__printf(5, 6)
void nf_l4proto_log_invalid(const struct sk_buff *skb,
			    struct net *net,
			    u16 pf, u8 protonum,
			    const char *fmt, ...)
{
	struct va_format vaf;
	va_list args;

	if (net->ct.sysctl_log_invalid != protonum ||
	    net->ct.sysctl_log_invalid != IPPROTO_RAW)
		return;

	va_start(args, fmt);
	vaf.fmt = fmt;
	vaf.va = &args;

	nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
		      "nf_ct_proto_%d: %pV ", protonum, &vaf);
	va_end(args);
}
EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);
#endif

const struct nf_conntrack_l4proto *
+1 −2
Original line number Diff line number Diff line
@@ -604,8 +604,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
	return NF_ACCEPT;

out_invalid:
	if (LOG_INVALID(net, IPPROTO_DCCP))
		nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg);
	nf_l4proto_log_invalid(skb, net, pf, IPPROTO_DCCP, "%s", msg);
	return -NF_ACCEPT;
}

Loading