linux/net/netfilter/nf_conntrack_proto_tcp.c

// SPDX-License-Identifier: GPL-2.0-only
/* (C) 1999-2001 Paul `Rusty' Russell
 * (C) 2002-2004 Netfilter Core Team <[email protected]>
 * (C) 2002-2013 Jozsef Kadlecsik <[email protected]>
 * (C) 2006-2012 Patrick McHardy <[email protected]>
 */

#include <linux/types.h>
#include <linux/timer.h>
#include <linux/module.h>
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
#include <linux/ipv6.h>
#include <net/ip6_checksum.h>
#include <asm/unaligned.h>

#include <net/tcp.h>

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_seqadj.h>
#include <net/netfilter/nf_conntrack_synproxy.h>
#include <net/netfilter/nf_conntrack_timeout.h>
#include <net/netfilter/nf_log.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>

  /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
     closely.  They're more complex. --RR */

static const char *const tcp_conntrack_names[] =;

enum nf_ct_tcp_action {};

#define SECS
#define MINS
#define HOURS
#define DAYS

static const unsigned int tcp_timeouts[TCP_CONNTRACK_TIMEOUT_MAX] =;

#define sNO
#define sSS
#define sSR
#define sES
#define sFW
#define sCW
#define sLA
#define sTW
#define sCL
#define sS2
#define sIV
#define sIG

/* What TCP flags are set from RST/SYN/FIN/ACK. */
enum tcp_bit_set {};

/*
 * The TCP state transition table needs a few words...
 *
 * We are the man in the middle. All the packets go through us
 * but might get lost in transit to the destination.
 * It is assumed that the destinations can't receive segments
 * we haven't seen.
 *
 * The checked segment is in window, but our windows are *not*
 * equivalent with the ones of the sender/receiver. We always
 * try to guess the state of the current sender.
 *
 * The meaning of the states are:
 *
 * NONE:	initial state
 * SYN_SENT:	SYN-only packet seen
 * SYN_SENT2:	SYN-only packet seen from reply dir, simultaneous open
 * SYN_RECV:	SYN-ACK packet seen
 * ESTABLISHED:	ACK packet seen
 * FIN_WAIT:	FIN packet seen
 * CLOSE_WAIT:	ACK seen (after FIN)
 * LAST_ACK:	FIN seen (after FIN)
 * TIME_WAIT:	last ACK seen
 * CLOSE:	closed connection (RST)
 *
 * Packets marked as IGNORED (sIG):
 *	if they may be either invalid or valid
 *	and the receiver may send back a connection
 *	closing RST or a SYN/ACK.
 *
 * Packets marked as INVALID (sIV):
 *	if we regard them as truly invalid packets
 */
static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] =;

#ifdef CONFIG_NF_CONNTRACK_PROCFS
/* Print out the private part of the conntrack. */
static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
{}
#endif

static unsigned int get_conntrack_index(const struct tcphdr *tcph)
{}

/* TCP connection tracking based on 'Real Stateful TCP Packet Filtering
   in IP Filter' by Guido van Rooij.

   http://www.sane.nl/events/sane2000/papers.html
   http://www.darkart.com/mirrors/www.obfuscation.org/ipf/

   The boundaries and the conditions are changed according to RFC793:
   the packet must intersect the window (i.e. segments may be
   after the right or before the left edge) and thus receivers may ACK
   segments after the right edge of the window.

	td_maxend = max(sack + max(win,1)) seen in reply packets
	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
	td_maxwin += seq + len - sender.td_maxend
			if seq + len > sender.td_maxend
	td_end    = max(seq + len) seen in sent packets

   I.   Upper bound for valid data:	seq <= sender.td_maxend
   II.  Lower bound for valid data:	seq + len >= sender.td_end - receiver.td_maxwin
   III.	Upper bound for valid (s)ack:   sack <= receiver.td_end
   IV.	Lower bound for valid (s)ack:	sack >= receiver.td_end - MAXACKWINDOW

   where sack is the highest right edge of sack block found in the packet
   or ack in the case of packet without SACK option.

   The upper bound limit for a valid (s)ack is not ignored -
   we doesn't have to deal with fragments.
*/

static inline __u32 segment_seq_plus_len(__u32 seq,
					 size_t len,
					 unsigned int dataoff,
					 const struct tcphdr *tcph)
{}

/* Fixme: what about big packets? */
#define MAXACKWINCONST
#define MAXACKWINDOW(sender)

/*
 * Simplified tcp_parse_options routine from tcp_input.c
 */
static void tcp_options(const struct sk_buff *skb,
			unsigned int dataoff,
			const struct tcphdr *tcph,
			struct ip_ct_tcp_state *state)
{}

static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
                     const struct tcphdr *tcph, __u32 *sack)
{}

static void tcp_init_sender(struct ip_ct_tcp_state *sender,
			    struct ip_ct_tcp_state *receiver,
			    const struct sk_buff *skb,
			    unsigned int dataoff,
			    const struct tcphdr *tcph,
			    u32 end, u32 win,
			    enum ip_conntrack_dir dir)
{}

__printf(6, 7)
static enum nf_ct_tcp_action nf_tcp_log_invalid(const struct sk_buff *skb,
						const struct nf_conn *ct,
						const struct nf_hook_state *state,
						const struct ip_ct_tcp_state *sender,
						enum nf_ct_tcp_action ret,
						const char *fmt, ...)
{}

static enum nf_ct_tcp_action
tcp_in_window(struct nf_conn *ct, enum ip_conntrack_dir dir,
	      unsigned int index, const struct sk_buff *skb,
	      unsigned int dataoff, const struct tcphdr *tcph,
	      const struct nf_hook_state *hook_state)
{}

static void __cold nf_tcp_handle_invalid(struct nf_conn *ct,
					 enum ip_conntrack_dir dir,
					 int index,
					 const struct sk_buff *skb,
					 const struct nf_hook_state *hook_state)
{}

/* table of valid flag combinations - PUSH, ECE and CWR are always valid */
static const u8 tcp_valid_flags[(TCPHDR_FIN|TCPHDR_SYN|TCPHDR_RST|TCPHDR_ACK|
				 TCPHDR_URG) + 1] =;

static void tcp_error_log(const struct sk_buff *skb,
			  const struct nf_hook_state *state,
			  const char *msg)
{}

/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
static bool tcp_error(const struct tcphdr *th,
		      struct sk_buff *skb,
		      unsigned int dataoff,
		      const struct nf_hook_state *state)
{}

static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
			     unsigned int dataoff,
			     const struct tcphdr *th,
			     const struct nf_hook_state *state)
{}

static bool tcp_can_early_drop(const struct nf_conn *ct)
{}

void nf_conntrack_tcp_set_closing(struct nf_conn *ct)
{}

static void nf_ct_tcp_state_reset(struct ip_ct_tcp_state *state)
{}

/* Returns verdict for packet, or -1 for invalid. */
int nf_conntrack_tcp_packet(struct nf_conn *ct,
			    struct sk_buff *skb,
			    unsigned int dataoff,
			    enum ip_conntrack_info ctinfo,
			    const struct nf_hook_state *state)
{}

#if IS_ENABLED(CONFIG_NF_CT_NETLINK)

#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>

static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
			 struct nf_conn *ct, bool destroy)
{}

static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] =;

#define TCP_NLATTR_SIZE

static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
{}

static unsigned int tcp_nlattr_tuple_size(void)
{}
#endif

#ifdef CONFIG_NF_CONNTRACK_TIMEOUT

#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h>

static int tcp_timeout_nlattr_to_obj(struct nlattr *tb[],
				     struct net *net, void *data)
{}

static int
tcp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
{}

static const struct nla_policy tcp_timeout_nla_policy[CTA_TIMEOUT_TCP_MAX+1] =;
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */

void nf_conntrack_tcp_init_net(struct net *net)
{}

const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp =;