Branch data Line data Source code
1 : : // $Id: TCP_Endpoint.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "Net.h"
6 : : #include "NetVar.h"
7 : : #include "TCP.h"
8 : : #include "TCP_Rewriter.h"
9 : : #include "TCP_Reassembler.h"
10 : : #include "Sessions.h"
11 : : #include "Event.h"
12 : : #include "File.h"
13 : : #include "Val.h"
14 : :
15 : 1876 : TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig)
16 : : {
17 : 1876 : contents_processor = 0;
18 : 1876 : prev_state = state = TCP_ENDPOINT_INACTIVE;
19 : 1876 : peer = 0;
20 : 1876 : start_time = last_time = 0.0;
21 : 1876 : start_seq = last_seq = ack_seq = 0;
22 : 1876 : last_seq_high = ack_seq_high = 0;
23 : 1876 : window = 0;
24 : 1876 : window_scale = 0;
25 : 1876 : window_seq = window_ack_seq = 0;
26 : 1876 : contents_start_seq = 0;
27 : 1876 : SYN_cnt = FIN_cnt = RST_cnt = 0;
28 : 1876 : did_close = 0;
29 : 1876 : contents_file = 0;
30 : 1876 : tcp_analyzer = arg_analyzer;
31 : 1876 : is_orig = arg_is_orig;
32 : :
33 : : src_addr = is_orig ? tcp_analyzer->Conn()->RespAddr() :
34 [ + + ][ # # ]: 1876 : tcp_analyzer->Conn()->OrigAddr();
35 : : dst_addr = is_orig ? tcp_analyzer->Conn()->OrigAddr() :
36 [ + + ][ # # ]: 1876 : tcp_analyzer->Conn()->RespAddr();
37 : :
38 : : #ifdef BROv6
39 : : checksum_base = ones_complement_checksum((void*) src_addr, 16, 0);
40 : : checksum_base = ones_complement_checksum((void*) dst_addr, 16, checksum_base);
41 : : #else
42 : 1876 : checksum_base = ones_complement_checksum((void*) src_addr, 4, 0);
43 : 1876 : checksum_base = ones_complement_checksum((void*) dst_addr, 4, checksum_base);
44 : : #endif
45 : : // Note, for IPv6, strictly speaking this field is 32 bits
46 : : // rather than 16 bits. But because the upper bits are all zero,
47 : : // we get the same checksum either way. The same applies to
48 : : // later when we add in the data length in ValidChecksum().
49 : 1876 : checksum_base += htons(IPPROTO_TCP);
50 : 1876 : }
51 : :
52 : 1876 : TCP_Endpoint::~TCP_Endpoint()
53 : : {
54 [ + - ][ # # ]: 1876 : delete contents_processor;
55 : 1876 : Unref(contents_file);
56 : 1876 : }
57 : :
58 : 1876 : void TCP_Endpoint::Done()
59 : : {
60 [ + - ]: 1876 : if ( contents_processor )
61 : 1876 : contents_processor->Done();
62 : 1876 : }
63 : :
64 : 1876 : void TCP_Endpoint::SetPeer(TCP_Endpoint* p)
65 : : {
66 : 1876 : peer = p;
67 [ + + ]: 1876 : if ( IsOrig() )
68 : : // Only one Endpoint adds the initial state to the counter.
69 : 938 : sessions->tcp_stats.StateEntered(state, peer->state);
70 : 1876 : }
71 : :
72 : 0 : int TCP_Endpoint::HadGap() const
73 : : {
74 [ # # ][ # # ]: 0 : return contents_processor && contents_processor->HadGap();
75 : : }
76 : :
77 : 1876 : void TCP_Endpoint::AddReassembler(TCP_Reassembler* arg_contents_processor)
78 : : {
79 [ + - ]: 1876 : if ( contents_processor != arg_contents_processor )
80 [ - + ]: 1876 : delete contents_processor;
81 : 1876 : contents_processor = arg_contents_processor;
82 : :
83 [ - + ]: 1876 : if ( contents_file )
84 : 0 : contents_processor->SetContentsFile(contents_file);
85 : 1876 : }
86 : :
87 : 1139 : int TCP_Endpoint::DataPending() const
88 : : {
89 [ + - ]: 1139 : if ( contents_processor )
90 : 1139 : return contents_processor->DataPending();
91 : : else
92 : 1139 : return 0;
93 : : }
94 : :
95 : 1978 : int TCP_Endpoint::HasUndeliveredData() const
96 : : {
97 [ + - ]: 1978 : if ( contents_processor )
98 : 1978 : return contents_processor->HasUndeliveredData();
99 : : else
100 : 1978 : return 0;
101 : : }
102 : :
103 : 17976 : void TCP_Endpoint::CheckEOF()
104 : : {
105 [ + - ]: 17976 : if ( contents_processor )
106 : 17976 : contents_processor->CheckEOF();
107 : 17976 : }
108 : :
109 : 0 : void TCP_Endpoint::SizeBufferedData(int& waiting_on_hole, int& waiting_on_ack)
110 : : {
111 [ # # ]: 0 : if ( contents_processor )
112 : 0 : contents_processor->SizeBufferedData(waiting_on_hole, waiting_on_ack);
113 : : else
114 : 0 : waiting_on_hole = waiting_on_ack = 0;
115 : 0 : }
116 : :
117 : 17976 : int TCP_Endpoint::ValidChecksum(const struct tcphdr* tp, int len) const
118 : : {
119 : 17976 : uint32 sum = checksum_base;
120 : 17976 : int tcp_len = tp->th_off * 4 + len;
121 : :
122 [ + + ]: 17976 : if ( len % 2 == 1 )
123 : : // Add in pad byte.
124 : 1995 : sum += htons(((const u_char*) tp)[tcp_len - 1] << 8);
125 : :
126 : 17976 : sum += htons((unsigned short) tcp_len); // fill out pseudo header
127 : 17976 : sum = ones_complement_checksum((void*) tp, tcp_len, sum);
128 : :
129 : 17976 : return sum == 0xffff;
130 : : }
131 : :
132 : 7276 : static inline bool is_handshake(EndpointState state)
133 : : {
134 : : return state == TCP_ENDPOINT_INACTIVE ||
135 : : state == TCP_ENDPOINT_SYN_SENT ||
136 [ + + ][ + + ]: 7276 : state == TCP_ENDPOINT_SYN_ACK_SENT;
[ + + ]
137 : : }
138 : :
139 : 3029 : void TCP_Endpoint::SetState(EndpointState new_state)
140 : : {
141 [ + - ]: 3029 : if ( new_state != state )
142 : : {
143 : : // Activate inactivity timer if this transition finishes the
144 : : // handshake.
145 [ + + ]: 3029 : if ( ! is_handshake(new_state) )
146 [ + + ][ + + ]: 2550 : if ( is_handshake(state) && is_handshake(peer->state) )
[ + + ]
147 : 927 : tcp_analyzer->Conn()->SetInactivityTimeout(tcp_inactivity_timeout);
148 : :
149 : 3029 : prev_state = state;
150 : 3029 : state = new_state;
151 [ + + ]: 3029 : if ( IsOrig() )
152 : : sessions->tcp_stats.ChangeState(prev_state, state,
153 : 1657 : peer->state, peer->state);
154 : : else
155 : : sessions->tcp_stats.ChangeState(peer->state, peer->state,
156 : 1372 : prev_state, state);
157 : : }
158 : 3029 : }
159 : :
160 : 33088 : bro_int_t TCP_Endpoint::Size() const
161 : : {
162 : : bro_int_t size;
163 : :
164 : 33088 : uint64 last_seq_64 = (uint64(last_seq_high) << 32) | last_seq;
165 : 33088 : uint64 ack_seq_64 = (uint64(ack_seq_high) << 32) | ack_seq;
166 [ + + ]: 33088 : if ( last_seq_64 > ack_seq_64 )
167 : 16110 : size = last_seq_64 - start_seq;
168 : : else
169 : 16978 : size = ack_seq_64 - start_seq;
170 : :
171 : : // Don't include SYN octet in sequence space. For partial connections
172 : : // (no SYN seen), we're still careful to adjust start_seq as though
173 : : // there was an initial SYN octet, because if we don't then the
174 : : // packet reassembly code gets confused.
175 [ + + ]: 33088 : if ( size != 0 )
176 : 31642 : --size;
177 : :
178 [ + + ][ + + ]: 33088 : if ( FIN_cnt > 0 && size != 0 )
179 : 2328 : --size; // don't include FIN octet.
180 : :
181 : 33088 : return size;
182 : : }
183 : :
184 : : int TCP_Endpoint::DataSent(double t, int seq, int len, int caplen,
185 : : const u_char* data,
186 : 9174 : const IP_Hdr* ip, const struct tcphdr* tp)
187 : : {
188 : 9174 : int status = 0;
189 : :
190 [ + - ][ + - ]: 9174 : if ( contents_processor && caplen >= len )
191 : 9174 : status = contents_processor->DataSent(t, seq, len, data);
192 : :
193 [ - + ]: 9174 : if ( caplen <= 0 )
194 : 0 : return status;
195 : :
196 [ - + ][ # # ]: 9174 : if ( contents_file && ! contents_processor &&
[ # # ]
197 : : seq + len > contents_start_seq )
198 : : {
199 : 0 : int under_seq = contents_start_seq - seq;
200 [ # # ]: 0 : if ( under_seq > 0 )
201 : : {
202 : 0 : seq += under_seq;
203 : 0 : data += under_seq;
204 : 0 : len -= under_seq;
205 : : }
206 : :
207 : : // DEBUG_MSG("%d: seek %d, data=%02x len=%d\n", IsOrig(), seq - contents_start_seq, *data, len);
208 : 0 : FILE* f = contents_file->Seek(seq - contents_start_seq);
209 : :
210 [ # # ]: 0 : if ( fwrite(data, 1, len, f) < unsigned(len) )
211 : : // ### this should really generate an event
212 : 0 : internal_error("contents write failed");
213 : : }
214 : :
215 : 9174 : return status;
216 : : }
217 : :
218 : 17321 : void TCP_Endpoint::AckReceived(int seq)
219 : : {
220 [ + - ]: 17321 : if ( contents_processor )
221 : 17321 : contents_processor->AckReceived(seq);
222 : 17321 : }
223 : :
224 : 0 : void TCP_Endpoint::SetContentsFile(BroFile* f)
225 : : {
226 : 0 : Ref(f);
227 : 0 : contents_file = f;
228 : 0 : contents_start_seq = last_seq - start_seq;
229 : :
230 [ # # ]: 0 : if ( contents_start_seq == 0 )
231 : 0 : contents_start_seq = 1; // skip SYN
232 : :
233 [ # # ]: 0 : if ( contents_processor )
234 : 0 : contents_processor->SetContentsFile(contents_file);
235 : 0 : }
236 : :
237 : 17976 : int TCP_Endpoint::CheckHistory(uint32 mask, char code)
238 : : {
239 [ + + ]: 17976 : if ( ! IsOrig() )
240 : : {
241 : 9919 : mask <<= 16;
242 : 9919 : code = tolower(code);
243 : : }
244 : :
245 : 17976 : return tcp_analyzer->Conn()->CheckHistory(mask, code);
246 : : }
247 : :
248 : 99 : void TCP_Endpoint::AddHistory(char code)
249 : : {
250 [ + + ]: 99 : if ( ! IsOrig() )
251 : 56 : code = tolower(code);
252 : :
253 : 99 : tcp_analyzer->Conn()->AddHistory(code);
254 [ + - ][ + - ]: 105 : }
255 : 3 :
|