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

📄 ip_conntrack_proto_tcp.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
字号:
#define __NO_VERSION__#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/netfilter_ipv4/ip_conntrack.h>#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>#include <linux/netfilter_ipv4/lockhelp.h>#if 0#define DEBUGP printk#else#define DEBUGP(format, args...)#endif/* Protects conntrack->proto.tcp */static DECLARE_RWLOCK(tcp_lock);/* FIXME: Examine ipfilter's timeouts and conntrack transitions more   closely.  They're more complex. --RR *//* Actually, I believe that neither ipmasq (where this code is stolen   from) nor ipfilter do it exactly right.  A new conntrack machine taking   into account packet loss (which creates uncertainty as to exactly   the conntrack of the connection) is required.  RSN.  --RR */static const char *tcp_conntrack_names[] = {	"NONE",	"ESTABLISHED",	"SYN_SENT",	"SYN_RECV",	"FIN_WAIT",	"TIME_WAIT",	"CLOSE",	"CLOSE_WAIT",	"LAST_ACK",	"LISTEN"};#define SECS *HZ#define MINS * 60 SECS#define HOURS * 60 MINS#define DAYS * 24 HOURSstatic unsigned long tcp_timeouts[]= { 30 MINS, 	/*	TCP_CONNTRACK_NONE,	*/    5 DAYS,	/*	TCP_CONNTRACK_ESTABLISHED,	*/    2 MINS,	/*	TCP_CONNTRACK_SYN_SENT,	*/    60 SECS,	/*	TCP_CONNTRACK_SYN_RECV,	*/    2 MINS,	/*	TCP_CONNTRACK_FIN_WAIT,	*/    2 MINS,	/*	TCP_CONNTRACK_TIME_WAIT,	*/    10 SECS,	/*	TCP_CONNTRACK_CLOSE,	*/    60 SECS,	/*	TCP_CONNTRACK_CLOSE_WAIT,	*/    30 SECS,	/*	TCP_CONNTRACK_LAST_ACK,	*/    2 MINS,	/*	TCP_CONNTRACK_LISTEN,	*/};#define sNO TCP_CONNTRACK_NONE#define sES TCP_CONNTRACK_ESTABLISHED#define sSS TCP_CONNTRACK_SYN_SENT#define sSR TCP_CONNTRACK_SYN_RECV#define sFW TCP_CONNTRACK_FIN_WAIT#define sTW TCP_CONNTRACK_TIME_WAIT#define sCL TCP_CONNTRACK_CLOSE#define sCW TCP_CONNTRACK_CLOSE_WAIT#define sLA TCP_CONNTRACK_LAST_ACK#define sLI TCP_CONNTRACK_LISTEN#define sIV TCP_CONNTRACK_MAXstatic enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = {	{/*	ORIGINAL *//* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*//*syn*/	{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },/*fin*/	{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },/*ack*/	{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },/*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }	},	{/*	REPLY *//* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*//*syn*/	{sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },/*fin*/	{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },/*ack*/	{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },/*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }	}};static int tcp_pkt_to_tuple(const void *datah, size_t datalen,			    struct ip_conntrack_tuple *tuple){	const struct tcphdr *hdr = datah;	tuple->src.u.tcp.port = hdr->source;	tuple->dst.u.tcp.port = hdr->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 unsigned int tcp_print_tuple(char *buffer,				    const struct ip_conntrack_tuple *tuple){	return sprintf(buffer, "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 unsigned int tcp_print_conntrack(char *buffer,					const struct ip_conntrack *conntrack){	enum tcp_conntrack state;	READ_LOCK(&tcp_lock);	state = conntrack->proto.tcp.state;	READ_UNLOCK(&tcp_lock);	return sprintf(buffer, "%s ", tcp_conntrack_names[state]);}static unsigned int get_conntrack_index(const struct tcphdr *tcph){	if (tcph->rst) return 3;	else if (tcph->syn) return 0;	else if (tcph->fin) return 1;	else if (tcph->ack) return 2;	else return 4;}/* Returns verdict for packet, or -1 for invalid. */static int tcp_packet(struct ip_conntrack *conntrack,		      struct iphdr *iph, size_t len,		      enum ip_conntrack_info ctinfo){	enum tcp_conntrack newconntrack, oldtcpstate;	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);	/* We're guaranteed to have the base header, but maybe not the           options. */	if (len < (iph->ihl + tcph->doff) * 4) {		DEBUGP("ip_conntrack_tcp: Truncated packet.\n");		return -1;	}	WRITE_LOCK(&tcp_lock);	oldtcpstate = conntrack->proto.tcp.state;	newconntrack		= tcp_conntracks		[CTINFO2DIR(ctinfo)]		[get_conntrack_index(tcph)][oldtcpstate];	/* Invalid */	if (newconntrack == TCP_CONNTRACK_MAX) {		DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n",		       CTINFO2DIR(ctinfo), get_conntrack_index(tcph),		       conntrack->proto.tcp.state);		WRITE_UNLOCK(&tcp_lock);		return -1;	}	conntrack->proto.tcp.state = newconntrack;	/* Poor man's window tracking: record SYN/ACK for handshake check */	if (oldtcpstate == TCP_CONNTRACK_SYN_SENT	    && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY	    && tcph->syn && tcph->ack)		conntrack->proto.tcp.handshake_ack			= htonl(ntohl(tcph->seq) + 1);	WRITE_UNLOCK(&tcp_lock);	/* If only reply is a RST, we can consider ourselves not to	   have an established connection: this is a fairly common	   problem case, so we can delete the conntrack	   immediately.  --RR */	if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) {		if (del_timer(&conntrack->timeout))			conntrack->timeout.function((unsigned long)conntrack);	} else {		/* Set ASSURED if we see see valid ack in ESTABLISHED after SYN_RECV */		if (oldtcpstate == TCP_CONNTRACK_SYN_RECV		    && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL		    && tcph->ack && !tcph->syn		    && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)			set_bit(IPS_ASSURED_BIT, &conntrack->status);		ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]);	}	return NF_ACCEPT;}/* Called when a new connection for this protocol found. */static int tcp_new(struct ip_conntrack *conntrack,		   struct iphdr *iph, size_t len){	enum tcp_conntrack newconntrack;	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);	/* Don't need lock here: this conntrack not in circulation yet */	newconntrack		= tcp_conntracks[0][get_conntrack_index(tcph)]		[TCP_CONNTRACK_NONE];	/* Invalid: delete conntrack */	if (newconntrack == TCP_CONNTRACK_MAX) {		DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");		return 0;	}	conntrack->proto.tcp.state = newconntrack;	return 1;}struct ip_conntrack_protocol ip_conntrack_protocol_tcp= { { NULL, NULL }, IPPROTO_TCP, "tcp",    tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,    tcp_packet, tcp_new, NULL };

⌨️ 快捷键说明

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