1 #include <linux/types.h>
2 #include <linux/sched.h>
3 #include <linux/timer.h>
4 #include <linux/netfilter.h>
5 #include <linux/module.h>
6 #include <linux/in.h>
7 #include <linux/ip.h>
8 #include <linux/tcp.h>
9 #include <linux/string.h>
10 
11 #include <net/tcp.h>
12 
13 #include <linux/netfilter_ipv4/ip_conntrack.h>
14 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
15 #include <linux/netfilter_ipv4/lockhelp.h>
16 
17 #if 0
18 #define DEBUGP printk
19 #else
20 #define DEBUGP(format, args...)
21 #endif
22 
23 /* Protects conntrack->proto.tcp */
24 static DECLARE_RWLOCK(tcp_lock);
25 
26 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
27    closely.  They're more complex. --RR */
28 
29 /* Actually, I believe that neither ipmasq (where this code is stolen
30    from) nor ipfilter do it exactly right.  A new conntrack machine taking
31    into account packet loss (which creates uncertainty as to exactly
32    the conntrack of the connection) is required.  RSN.  --RR */
33 
34 static const char *tcp_conntrack_names[] = {
35 	"NONE",
36 	"ESTABLISHED",
37 	"SYN_SENT",
38 	"SYN_RECV",
39 	"FIN_WAIT",
40 	"TIME_WAIT",
41 	"CLOSE",
42 	"CLOSE_WAIT",
43 	"LAST_ACK",
44 	"LISTEN"
45 };
46 
47 #define SECS *HZ
48 #define MINS * 60 SECS
49 #define HOURS * 60 MINS
50 #define DAYS * 24 HOURS
51 
52 unsigned long ip_ct_tcp_timeout_syn_sent =      2 MINS;
53 unsigned long ip_ct_tcp_timeout_syn_recv =     60 SECS;
54 unsigned long ip_ct_tcp_timeout_established =   5 DAYS;
55 unsigned long ip_ct_tcp_timeout_fin_wait =      2 MINS;
56 unsigned long ip_ct_tcp_timeout_close_wait =   60 SECS;
57 unsigned long ip_ct_tcp_timeout_last_ack =     30 SECS;
58 unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
59 unsigned long ip_ct_tcp_timeout_close =        10 SECS;
60 
61 static unsigned long * tcp_timeouts[]
62 = { 0,                                 /*      TCP_CONNTRACK_NONE */
63     &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
64     &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
65     &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */
66     &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */
67     &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
68     &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
69     &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */
70     &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */
71     0,                                 /*      TCP_CONNTRACK_LISTEN */
72  };
73 
74 #define sNO TCP_CONNTRACK_NONE
75 #define sES TCP_CONNTRACK_ESTABLISHED
76 #define sSS TCP_CONNTRACK_SYN_SENT
77 #define sSR TCP_CONNTRACK_SYN_RECV
78 #define sFW TCP_CONNTRACK_FIN_WAIT
79 #define sTW TCP_CONNTRACK_TIME_WAIT
80 #define sCL TCP_CONNTRACK_CLOSE
81 #define sCW TCP_CONNTRACK_CLOSE_WAIT
82 #define sLA TCP_CONNTRACK_LAST_ACK
83 #define sLI TCP_CONNTRACK_LISTEN
84 #define sIV TCP_CONNTRACK_MAX
85 
86 static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = {
87 	{
88 /*	ORIGINAL */
89 /* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
90 /*syn*/	{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },
91 /*fin*/	{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },
92 /*ack*/	{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },
93 /*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },
94 /*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
95 	},
96 	{
97 /*	REPLY */
98 /* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
99 /*syn*/	{sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },
100 /*fin*/	{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },
101 /*ack*/	{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },
102 /*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },
103 /*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
104 	}
105 };
106 
tcp_pkt_to_tuple(const void * datah,size_t datalen,struct ip_conntrack_tuple * tuple)107 static int tcp_pkt_to_tuple(const void *datah, size_t datalen,
108 			    struct ip_conntrack_tuple *tuple)
109 {
110 	const struct tcphdr *hdr = datah;
111 
112 	tuple->src.u.tcp.port = hdr->source;
113 	tuple->dst.u.tcp.port = hdr->dest;
114 
115 	return 1;
116 }
117 
tcp_invert_tuple(struct ip_conntrack_tuple * tuple,const struct ip_conntrack_tuple * orig)118 static int tcp_invert_tuple(struct ip_conntrack_tuple *tuple,
119 			    const struct ip_conntrack_tuple *orig)
120 {
121 	tuple->src.u.tcp.port = orig->dst.u.tcp.port;
122 	tuple->dst.u.tcp.port = orig->src.u.tcp.port;
123 	return 1;
124 }
125 
126 /* Print out the per-protocol part of the tuple. */
tcp_print_tuple(char * buffer,const struct ip_conntrack_tuple * tuple)127 static unsigned int tcp_print_tuple(char *buffer,
128 				    const struct ip_conntrack_tuple *tuple)
129 {
130 	return sprintf(buffer, "sport=%hu dport=%hu ",
131 		       ntohs(tuple->src.u.tcp.port),
132 		       ntohs(tuple->dst.u.tcp.port));
133 }
134 
135 /* Print out the private part of the conntrack. */
tcp_print_conntrack(char * buffer,const struct ip_conntrack * conntrack)136 static unsigned int tcp_print_conntrack(char *buffer,
137 					const struct ip_conntrack *conntrack)
138 {
139 	enum tcp_conntrack state;
140 
141 	READ_LOCK(&tcp_lock);
142 	state = conntrack->proto.tcp.state;
143 	READ_UNLOCK(&tcp_lock);
144 
145 	return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
146 }
147 
get_conntrack_index(const struct tcphdr * tcph)148 static unsigned int get_conntrack_index(const struct tcphdr *tcph)
149 {
150 	if (tcph->rst) return 3;
151 	else if (tcph->syn) return 0;
152 	else if (tcph->fin) return 1;
153 	else if (tcph->ack) return 2;
154 	else return 4;
155 }
156 
157 /* Returns verdict for packet, or -1 for invalid. */
tcp_packet(struct ip_conntrack * conntrack,struct iphdr * iph,size_t len,enum ip_conntrack_info ctinfo)158 static int tcp_packet(struct ip_conntrack *conntrack,
159 		      struct iphdr *iph, size_t len,
160 		      enum ip_conntrack_info ctinfo)
161 {
162 	enum tcp_conntrack newconntrack, oldtcpstate;
163 	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
164 
165 	/* We're guaranteed to have the base header, but maybe not the
166            options. */
167 	if (len < (iph->ihl + tcph->doff) * 4) {
168 		DEBUGP("ip_conntrack_tcp: Truncated packet.\n");
169 		return -1;
170 	}
171 
172 	WRITE_LOCK(&tcp_lock);
173 	oldtcpstate = conntrack->proto.tcp.state;
174 	newconntrack
175 		= tcp_conntracks
176 		[CTINFO2DIR(ctinfo)]
177 		[get_conntrack_index(tcph)][oldtcpstate];
178 
179 	/* Invalid */
180 	if (newconntrack == TCP_CONNTRACK_MAX) {
181 		DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n",
182 		       CTINFO2DIR(ctinfo), get_conntrack_index(tcph),
183 		       conntrack->proto.tcp.state);
184 		WRITE_UNLOCK(&tcp_lock);
185 		return -1;
186 	}
187 
188 	conntrack->proto.tcp.state = newconntrack;
189 
190 	/* Poor man's window tracking: record SYN/ACK for handshake check */
191 	if (oldtcpstate == TCP_CONNTRACK_SYN_SENT
192 	    && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
193 	    && tcph->syn && tcph->ack)
194 		conntrack->proto.tcp.handshake_ack
195 			= htonl(ntohl(tcph->seq) + 1);
196 
197 	/* If only reply is a RST, we can consider ourselves not to
198 	   have an established connection: this is a fairly common
199 	   problem case, so we can delete the conntrack
200 	   immediately.  --RR */
201 	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph->rst) {
202 		WRITE_UNLOCK(&tcp_lock);
203 		if (del_timer(&conntrack->timeout))
204 			conntrack->timeout.function((unsigned long)conntrack);
205 	} else {
206 		/* Set ASSURED if we see see valid ack in ESTABLISHED after SYN_RECV */
207 		if (oldtcpstate == TCP_CONNTRACK_SYN_RECV
208 		    && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL
209 		    && tcph->ack && !tcph->syn
210 		    && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)
211 			set_bit(IPS_ASSURED_BIT, &conntrack->status);
212 
213 		WRITE_UNLOCK(&tcp_lock);
214 		ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
215 	}
216 
217 	return NF_ACCEPT;
218 }
219 
220 /* Called when a new connection for this protocol found. */
tcp_new(struct ip_conntrack * conntrack,struct iphdr * iph,size_t len)221 static int tcp_new(struct ip_conntrack *conntrack,
222 		   struct iphdr *iph, size_t len)
223 {
224 	enum tcp_conntrack newconntrack;
225 	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
226 
227 	/* Don't need lock here: this conntrack not in circulation yet */
228 	newconntrack
229 		= tcp_conntracks[0][get_conntrack_index(tcph)]
230 		[TCP_CONNTRACK_NONE];
231 
232 	/* Invalid: delete conntrack */
233 	if (newconntrack == TCP_CONNTRACK_MAX) {
234 		DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
235 		return 0;
236 	}
237 
238 	conntrack->proto.tcp.state = newconntrack;
239 	return 1;
240 }
241 
tcp_exp_matches_pkt(struct ip_conntrack_expect * exp,struct sk_buff ** pskb)242 static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp,
243 			       struct sk_buff **pskb)
244 {
245 	struct iphdr *iph = (*pskb)->nh.iph;
246 	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
247 	unsigned int datalen;
248 
249 	datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
250 
251 	return between(exp->seq, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
252 }
253 
254 struct ip_conntrack_protocol ip_conntrack_protocol_tcp
255 = { { NULL, NULL }, IPPROTO_TCP, "tcp",
256     tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
257     tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
258