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

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

netfilter: conntrack: add and use nf_ct_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.
Add a wrapper for the previous patch that extracs the information
from nf_conn and passes it to nf_l4proto_log_invalid().

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent c4f3db15
Loading
Loading
Loading
Loading
+8 −6
Original line number Original line Diff line number Diff line
@@ -149,21 +149,23 @@ int nf_ct_port_nlattr_tuple_size(void);
extern const struct nla_policy nf_ct_port_nla_policy[];
extern const struct nla_policy nf_ct_port_nla_policy[];


#ifdef CONFIG_SYSCTL
#ifdef CONFIG_SYSCTL
#define LOG_INVALID(net, proto)				\
__printf(3, 4) __cold
	((net)->ct.sysctl_log_invalid == (proto) ||	\
void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
	 (net)->ct.sysctl_log_invalid == IPPROTO_RAW)
			       const struct nf_conn *ct,

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

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


#endif /*_NF_CONNTRACK_PROTOCOL_H*/
#endif /*_NF_CONNTRACK_PROTOCOL_H*/
+23 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,29 @@ void nf_l4proto_log_invalid(const struct sk_buff *skb,
	va_end(args);
	va_end(args);
}
}
EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);
EXPORT_SYMBOL_GPL(nf_l4proto_log_invalid);

__printf(3, 4)
void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
			       const struct nf_conn *ct,
			       const char *fmt, ...)
{
	struct va_format vaf;
	struct net *net;
	va_list args;

	net = nf_ct_net(ct);
	if (likely(net->ct.sysctl_log_invalid == 0))
		return;

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

	nf_l4proto_log_invalid(skb, net, nf_ct_l3num(ct),
			       nf_ct_protonum(ct), "%pV", &vaf);
	va_end(args);
}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_log_invalid);
#endif
#endif


const struct nf_conntrack_l4proto *
const struct nf_conntrack_l4proto *
+5 −12
Original line number Original line Diff line number Diff line
@@ -428,13 +428,13 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
	default:
	default:
		dn = dccp_pernet(net);
		dn = dccp_pernet(net);
		if (dn->dccp_loose == 0) {
		if (dn->dccp_loose == 0) {
			msg = "nf_ct_dccp: not picking up existing connection ";
			msg = "not picking up existing connection ";
			goto out_invalid;
			goto out_invalid;
		}
		}
	case CT_DCCP_REQUEST:
	case CT_DCCP_REQUEST:
		break;
		break;
	case CT_DCCP_INVALID:
	case CT_DCCP_INVALID:
		msg = "nf_ct_dccp: invalid state transition ";
		msg = "invalid state transition ";
		goto out_invalid;
		goto out_invalid;
	}
	}


@@ -447,9 +447,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
	return true;
	return true;


out_invalid:
out_invalid:
	if (LOG_INVALID(net, IPPROTO_DCCP))
	nf_ct_l4proto_log_invalid(skb, ct, "%s", msg);
		nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL,
			      NULL, "%s", msg);
	return false;
	return false;
}
}


@@ -472,7 +470,6 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
		       u_int8_t pf,
		       u_int8_t pf,
		       unsigned int *timeouts)
		       unsigned int *timeouts)
{
{
	struct net *net = nf_ct_net(ct);
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	struct dccp_hdr _dh, *dh;
	struct dccp_hdr _dh, *dh;
	u_int8_t type, old_state, new_state;
	u_int8_t type, old_state, new_state;
@@ -534,15 +531,11 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
		ct->proto.dccp.last_pkt = type;
		ct->proto.dccp.last_pkt = type;


		spin_unlock_bh(&ct->lock);
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_DCCP))
		nf_ct_l4proto_log_invalid(skb, ct, "%s", "invalid packet");
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
				      "nf_ct_dccp: invalid packet ignored ");
		return NF_ACCEPT;
		return NF_ACCEPT;
	case CT_DCCP_INVALID:
	case CT_DCCP_INVALID:
		spin_unlock_bh(&ct->lock);
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_DCCP))
		nf_ct_l4proto_log_invalid(skb, ct, "%s", "invalid state transition");
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
				      "nf_ct_dccp: invalid state transition ");
		return -NF_ACCEPT;
		return -NF_ACCEPT;
	}
	}


+9 −16
Original line number Original line Diff line number Diff line
@@ -702,9 +702,9 @@ static bool tcp_in_window(const struct nf_conn *ct,
		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
		    tn->tcp_be_liberal)
		    tn->tcp_be_liberal)
			res = true;
			res = true;
		if (!res && LOG_INVALID(net, IPPROTO_TCP))
		if (!res) {
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
			nf_ct_l4proto_log_invalid(skb, ct,
			"nf_ct_tcp: %s ",
			"%s",
			before(seq, sender->td_maxend + 1) ?
			before(seq, sender->td_maxend + 1) ?
			in_recv_win ?
			in_recv_win ?
			before(sack, receiver->td_end + 1) ?
			before(sack, receiver->td_end + 1) ?
@@ -714,6 +714,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
			: "SEQ is under the lower bound (already ACKed data retransmitted)"
			: "SEQ is under the lower bound (already ACKed data retransmitted)"
			: "SEQ is over the upper bound (over the window of the receiver)");
			: "SEQ is over the upper bound (over the window of the receiver)");
		}
		}
	}


	pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
	pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
		 "receiver end=%u maxend=%u maxwin=%u\n",
		 "receiver end=%u maxend=%u maxwin=%u\n",
@@ -937,9 +938,7 @@ static int tcp_packet(struct nf_conn *ct,
					IP_CT_EXP_CHALLENGE_ACK;
					IP_CT_EXP_CHALLENGE_ACK;
		}
		}
		spin_unlock_bh(&ct->lock);
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_TCP))
		nf_ct_l4proto_log_invalid(skb, ct, "invalid packet ignored in "
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
				  "nf_ct_tcp: invalid packet ignored in "
					  "state %s ", tcp_conntrack_names[old_state]);
					  "state %s ", tcp_conntrack_names[old_state]);
		return NF_ACCEPT;
		return NF_ACCEPT;
	case TCP_CONNTRACK_MAX:
	case TCP_CONNTRACK_MAX:
@@ -962,9 +961,7 @@ static int tcp_packet(struct nf_conn *ct,
		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
			 dir, get_conntrack_index(th), old_state);
			 dir, get_conntrack_index(th), old_state);
		spin_unlock_bh(&ct->lock);
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_TCP))
		nf_ct_l4proto_log_invalid(skb, ct, "invalid state");
			nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
				  "nf_ct_tcp: invalid state ");
		return -NF_ACCEPT;
		return -NF_ACCEPT;
	case TCP_CONNTRACK_TIME_WAIT:
	case TCP_CONNTRACK_TIME_WAIT:
		/* RFC5961 compliance cause stack to send "challenge-ACK"
		/* RFC5961 compliance cause stack to send "challenge-ACK"
@@ -979,9 +976,7 @@ static int tcp_packet(struct nf_conn *ct,
			/* Detected RFC5961 challenge ACK */
			/* Detected RFC5961 challenge ACK */
			ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK;
			ct->proto.tcp.last_flags &= ~IP_CT_EXP_CHALLENGE_ACK;
			spin_unlock_bh(&ct->lock);
			spin_unlock_bh(&ct->lock);
			if (LOG_INVALID(net, IPPROTO_TCP))
			nf_ct_l4proto_log_invalid(skb, ct, "challenge-ack ignored");
				nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
				      "nf_ct_tcp: challenge-ACK ignored ");
			return NF_ACCEPT; /* Don't change state */
			return NF_ACCEPT; /* Don't change state */
		}
		}
		break;
		break;
@@ -991,9 +986,7 @@ static int tcp_packet(struct nf_conn *ct,
		    && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) {
		    && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) {
			/* Invalid RST  */
			/* Invalid RST  */
			spin_unlock_bh(&ct->lock);
			spin_unlock_bh(&ct->lock);
			if (LOG_INVALID(net, IPPROTO_TCP))
			nf_ct_l4proto_log_invalid(skb, ct, "invalid rst");
				nf_log_packet(net, pf, 0, skb, NULL, NULL,
					      NULL, "nf_ct_tcp: invalid RST ");
			return -NF_ACCEPT;
			return -NF_ACCEPT;
		}
		}
		if (index == TCP_RST_SET
		if (index == TCP_RST_SET