⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_conntrack_proto_tcp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>: *	- Real stateful connection tracking *	- Modified state transitions table *	- Window scaling support added *	- SACK support added * * Willy Tarreau: *	- State table bugfixes *	- More robust state changes *	- Tuning timer parameters * * version 2.2 */#include <linux/config.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/netfilter.h>#include <linux/module.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/tcp.h>#include <linux/spinlock.h>#include <net/tcp.h>#include <linux/netfilter.h>#include <linux/netfilter_ipv4.h>#include <linux/netfilter_ipv4/ip_conntrack.h>#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>#if 0#define DEBUGP printk#define DEBUGP_VARS#else#define DEBUGP(format, args...)#endif/* Protects conntrack->proto.tcp */static DEFINE_RWLOCK(tcp_lock);/* "Be conservative in what you do,     be liberal in what you accept from others."     If it's non-zero, we mark only out of window RST segments as INVALID. */int ip_ct_tcp_be_liberal = 0;/* When connection is picked up from the middle, how many packets are required   to pass in each direction when we assume we are in sync - if any side uses   window scaling, we lost the game.    If it is set to zero, we disable picking up already established    connections. */int ip_ct_tcp_loose = 3;/* Max number of the retransmitted packets without receiving an (acceptable)    ACK from the destination. If this number is reached, a shorter timer    will be started. */int ip_ct_tcp_max_retrans = 3;  /* FIXME: Examine ipfilter's timeouts and conntrack transitions more     closely.  They're more complex. --RR */static const char *tcp_conntrack_names[] = {	"NONE",	"SYN_SENT",	"SYN_RECV",	"ESTABLISHED",	"FIN_WAIT",	"CLOSE_WAIT",	"LAST_ACK",	"TIME_WAIT",	"CLOSE",	"LISTEN"};  #define SECS * HZ#define MINS * 60 SECS#define HOURS * 60 MINS#define DAYS * 24 HOURSunsigned long ip_ct_tcp_timeout_syn_sent =      2 MINS;unsigned long ip_ct_tcp_timeout_syn_recv =     60 SECS;unsigned long ip_ct_tcp_timeout_established =   5 DAYS;unsigned long ip_ct_tcp_timeout_fin_wait =      2 MINS;unsigned long ip_ct_tcp_timeout_close_wait =   60 SECS;unsigned long ip_ct_tcp_timeout_last_ack =     30 SECS;unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;unsigned long ip_ct_tcp_timeout_close =        10 SECS;/* RFC1122 says the R2 limit should be at least 100 seconds.   Linux uses 15 packets as limit, which corresponds    to ~13-30min depending on RTO. */unsigned long ip_ct_tcp_timeout_max_retrans =     5 MINS; static const unsigned long * tcp_timeouts[]= { NULL,                              /*      TCP_CONNTRACK_NONE */    &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */    &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */    &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */    &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */    &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */    NULL,                              /*      TCP_CONNTRACK_LISTEN */ }; #define sNO TCP_CONNTRACK_NONE#define sSS TCP_CONNTRACK_SYN_SENT#define sSR TCP_CONNTRACK_SYN_RECV#define sES TCP_CONNTRACK_ESTABLISHED#define sFW TCP_CONNTRACK_FIN_WAIT#define sCW TCP_CONNTRACK_CLOSE_WAIT#define sLA TCP_CONNTRACK_LAST_ACK#define sTW TCP_CONNTRACK_TIME_WAIT#define sCL TCP_CONNTRACK_CLOSE#define sLI TCP_CONNTRACK_LISTEN#define sIV TCP_CONNTRACK_MAX#define sIG TCP_CONNTRACK_IGNORE/* What TCP flags are set from RST/SYN/FIN/ACK. */enum tcp_bit_set {	TCP_SYN_SET,	TCP_SYNACK_SET,	TCP_FIN_SET,	TCP_ACK_SET,	TCP_RST_SET,	TCP_NONE_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_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 * * LISTEN state is not used. * * 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 they are invalid *	or we do not support the request (simultaneous open) */static const enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {	{/* ORIGINAL *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*syn*/	   { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sIV },/* *	sNO -> sSS	Initialize a new connection *	sSS -> sSS	Retransmitted SYN *	sSR -> sIG	Late retransmitted SYN? *	sES -> sIG	Error: SYNs in window outside the SYN_SENT state *			are errors. Receiver will reply with RST  *			and close the connection. *			Or we are not in sync and hold a dead connection. *	sFW -> sIG *	sCW -> sIG *	sLA -> sIG *	sTW -> sSS	Reopened connection (RFC 1122). *	sCL -> sSS *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },/* * A SYN/ACK from the client is always invalid: *	- either it tries to set up a simultaneous open, which is  *	  not supported; *	- or the firewall has just been inserted between the two hosts *	  during the session set-up. The SYN will be retransmitted  *	  by the true client (or it'll time out). *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },/* *	sNO -> sIV	Too late and no reason to do anything... *	sSS -> sIV	Client migth not send FIN in this state: *			we enforce waiting for a SYN/ACK reply first. *	sSR -> sFW	Close started. *	sES -> sFW	 *	sFW -> sLA	FIN seen in both directions, waiting for *			the last ACK.  *			Migth be a retransmitted FIN as well... *	sCW -> sLA *	sLA -> sLA	Retransmitted FIN. Remain in the same state. *	sTW -> sTW *	sCL -> sCL *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*ack*/	   { sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV },/* *	sNO -> sES	Assumed. *	sSS -> sIV	ACK is invalid: we haven't seen a SYN/ACK yet. *	sSR -> sES	Established state is reached. *	sES -> sES	:-) *	sFW -> sCW	Normal close request answered by ACK. *	sCW -> sCW *	sLA -> sTW	Last ACK detected. *	sTW -> sTW	Retransmitted last ACK. Remain in the same state. *	sCL -> sCL *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }	},	{/* REPLY *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*syn*/	   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },/* *	sNO -> sIV	Never reached. *	sSS -> sIV	Simultaneous open, not supported *	sSR -> sIV	Simultaneous open, not supported. *	sES -> sIV	Server may not initiate a connection. *	sFW -> sIV *	sCW -> sIV *	sLA -> sIV *	sTW -> sIV	Reopened connection, but server may not do it. *	sCL -> sIV *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIV },/* *	sSS -> sSR	Standard open. *	sSR -> sSR	Retransmitted SYN/ACK. *	sES -> sIG	Late retransmitted SYN/ACK? *	sFW -> sIG	Might be SYN/ACK answering ignored SYN *	sCW -> sIG *	sLA -> sIG *	sTW -> sIG *	sCL -> sIG *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },/* *	sSS -> sIV	Server might not send FIN in this state. *	sSR -> sFW	Close started. *	sES -> sFW *	sFW -> sLA	FIN seen in both directions. *	sCW -> sLA *	sLA -> sLA	Retransmitted FIN. *	sTW -> sTW *	sCL -> sCL *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*ack*/	   { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },/* *	sSS -> sIG	Might be a half-open connection. *	sSR -> sSR	Might answer late resent SYN. *	sES -> sES	:-) *	sFW -> sCW	Normal close request answered by ACK. *	sCW -> sCW *	sLA -> sTW	Last ACK detected. *	sTW -> sTW	Retransmitted last ACK. *	sCL -> sCL *//* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*//*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }  	}};static int tcp_pkt_to_tuple(const struct sk_buff *skb,			    unsigned int dataoff,			    struct ip_conntrack_tuple *tuple){	struct tcphdr _hdr, *hp;	/* Actually only need first 8 bytes. */	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);	if (hp == NULL)		return 0;	tuple->src.u.tcp.port = hp->source;	tuple->dst.u.tcp.port = hp->dest;	return 1;}static int tcp_invert_tuple(struct ip_conntrack_tuple *tuple,			    const struct ip_conntrack_tuple *orig){	tuple->src.u.tcp.port = orig->dst.u.tcp.port;	tuple->dst.u.tcp.port = orig->src.u.tcp.port;	return 1;}/* Print out the per-protocol part of the tuple. */static int tcp_print_tuple(struct seq_file *s,			   const struct ip_conntrack_tuple *tuple){	return seq_printf(s, "sport=%hu dport=%hu ",			  ntohs(tuple->src.u.tcp.port),			  ntohs(tuple->dst.u.tcp.port));}/* Print out the private part of the conntrack. */static int tcp_print_conntrack(struct seq_file *s,			       const struct ip_conntrack *conntrack){	enum tcp_conntrack state;	read_lock_bh(&tcp_lock);	state = conntrack->proto.tcp.state;	read_unlock_bh(&tcp_lock);	return seq_printf(s, "%s ", tcp_conntrack_names[state]);}#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,			 const struct ip_conntrack *ct){	struct nfattr *nest_parms;		read_lock_bh(&tcp_lock);	nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);	NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),		&ct->proto.tcp.state);	read_unlock_bh(&tcp_lock);	NFA_NEST_END(skb, nest_parms);	return 0;nfattr_failure:	read_unlock_bh(&tcp_lock);	return -1;}static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {	[CTA_PROTOINFO_TCP_STATE-1]	= sizeof(u_int8_t),};static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct){	struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];	struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];	/* updates could not contain anything about the private	 * protocol info, in that case skip the parsing */	if (!attr)		return 0;        nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);	if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))		return -EINVAL;	if (!tb[CTA_PROTOINFO_TCP_STATE-1])		return -EINVAL;	write_lock_bh(&tcp_lock);	ct->proto.tcp.state = 		*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);	write_unlock_bh(&tcp_lock);	return 0;}#endifstatic unsigned int get_conntrack_index(const struct tcphdr *tcph){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -