Branch data Line data Source code
1 : : // $Id: TCP_Rewriter.cc 6008 2008-07-23 00:24:22Z vern $
2 : :
3 : : // Overview of TCP trace rewriter:
4 : : //
5 : : // 1. Timestamp: Consider every packet arrival at a certain endpoint
6 : : // in the original trace as a tick for the endpoint; a packet will be
7 : : // dumped into the new trace (possibly with different content) in the
8 : : // tick (enforced by flush_rewriter_packet). When the user writes data
9 : : // into the new trace, the packet will carry a timestamp of the
10 : : // current tick, or the next tick if data is generated between
11 : : // ticks. Users may also choose to Push data, in which case the packet
12 : : // carries a timestamp of current network time. This gives us the
13 : : // 'freshness' of timestamps.
14 : : //
15 : : // 2. Ordering of contents: user may choose to push contents in order
16 : : // to enforce ordering of contents between two directions, however,
17 : : // contents MIGHT be already dumped BEFORE they are pushed, once they
18 : : // are written into the trace. (similar to PUSH in TCP)
19 : : //
20 : : // 3. Acknowledgements: when a packet is dumped at a time when there
21 : : // is no corresponding packet in the original trace, an articial
22 : : // acknowledgement is generated from the peer with the same
23 : : // timestamp. This guarantees that additional packets will have
24 : : // acknowledgements. For those packets dumped at 'ticks', there
25 : : // should be corresponding acknowledgement packets in the original
26 : : // trace already, so we do not generate further artificial
27 : : // acknowledgement packets.
28 : : //
29 : : // 4. SYN, RST, FIN: SYN/RST packets in the new trace do not carry
30 : : // payloads -- additional packets may be generated for payloads. FIN
31 : : // packets are generated only when user calls ScheduleFIN, which by
32 : : // default corresponds to the moment that contents of the flow is
33 : : // completely delivered, which is usually when the FIN appears in the
34 : : // original trace. Change: now we will try to allow SYN/RST packets
35 : : // to carry payloads if they originally do.
36 : :
37 : : #include "config.h"
38 : :
39 : : #include <assert.h>
40 : : #include <stdlib.h>
41 : :
42 : : #include "Event.h"
43 : : #include "Net.h"
44 : : #include "TCP_Rewriter.h"
45 : :
46 : : #define MSG_PREFIX "TCP trace rewriter: "
47 : : #define DEBUG_MSG_A(x...)
48 : : // #define DEBUG_MSG_A DEBUG_MSG
49 : :
50 : : static IP_IDSet* ip_id_set = 0; // <IP, IP-ID> pairs in the output trace
51 : : int num_packets_held, num_packets_cleaned;
52 : :
53 : : TCP_TracePacket::TCP_TracePacket(TCP_Rewriter* arg_trace_rewriter,
54 : : int arg_packet_seq, double t, int arg_is_orig,
55 : : const struct pcap_pkthdr* arg_hdr,
56 : 0 : int MTU, int initial_size)
57 : : {
58 : 0 : trace_rewriter = arg_trace_rewriter;
59 : 0 : pcap_hdr = *arg_hdr;
60 : 0 : packet_seq = arg_packet_seq;
61 : 0 : timestamp = t;
62 : 0 : is_orig = arg_is_orig;
63 : 0 : mtu = MTU;
64 : 0 : pkt = new u_char[initial_size];
65 : 0 : buffer_size = initial_size;
66 : :
67 : 0 : buffer_offset = 0;
68 : 0 : ip_offset = tcp_offset = data_offset = -1;
69 : 0 : reuse = 0;
70 : 0 : FIN_scheduled = 0;
71 : 0 : on_hold = 0;
72 : 0 : seq_gap = 0;
73 : 0 : packet_val = 0;
74 : 0 : packet_val = PacketVal();
75 : 0 : has_reserved_slot = 0;
76 : 0 : predicted_as_empty_place_holder = 0;
77 : 0 : }
78 : :
79 : 0 : TCP_TracePacket::~TCP_TracePacket()
80 : : {
81 : 0 : packet_val->SetOrigin(0);
82 : 0 : Unref(packet_val);
83 [ # # # # # : 0 : if ( pkt )
# ]
84 [ # # ][ # # ]: 0 : delete [] pkt;
[ # # ]
85 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
86 : :
87 : 0 : int TCP_TracePacket::AppendLinkHeader(const u_char* chunk, int len)
88 : : {
89 [ # # ][ # # ]: 0 : if ( ip_offset >= 0 && ip_offset != buffer_offset )
90 : 0 : internal_error(MSG_PREFIX "link header must be appended before IP header");
91 : :
92 [ # # ]: 0 : if ( ! Append(chunk, len) )
93 : 0 : return 0;
94 : :
95 : 0 : ip_offset = buffer_offset;
96 : 0 : return 1;
97 : : }
98 : :
99 : 0 : int TCP_TracePacket::AppendIPHeader(const u_char* chunk, int len)
100 : : {
101 [ # # ][ # # ]: 0 : if ( tcp_offset >= 0 && tcp_offset != buffer_offset )
102 : 0 : internal_error(MSG_PREFIX "IP header must be appended before tcp header");
103 : :
104 [ # # ]: 0 : if ( ! Append(chunk, len) )
105 : 0 : return 0;
106 : :
107 : 0 : tcp_offset = buffer_offset;
108 : 0 : return 1;
109 : : }
110 : :
111 : 0 : int TCP_TracePacket::AppendTCPHeader(const u_char* chunk, int len)
112 : : {
113 [ # # ][ # # ]: 0 : if ( data_offset >= 0 && data_offset != buffer_offset )
114 : 0 : internal_error(MSG_PREFIX "tcp header must be appended before payload");
115 : :
116 [ # # ]: 0 : if ( tcp_offset == buffer_offset )
117 : : { // first TCP header chunk
118 : 0 : int extra = (tcp_offset - ip_offset) % 4;
119 [ # # ]: 0 : if ( extra )
120 : : {
121 : 0 : DEBUG_MSG(MSG_PREFIX "padding IP header");
122 [ # # ]: 0 : if ( ! AppendIPHeader(0, 4 - extra) )
123 : 0 : return 0;
124 : : }
125 : : }
126 : :
127 [ # # ]: 0 : if ( ! Append(chunk, len) )
128 : 0 : return 0;
129 : :
130 : 0 : data_offset = buffer_offset;
131 : 0 : return 1;
132 : : }
133 : :
134 : 0 : int TCP_TracePacket::AppendData(const u_char* chunk, int len)
135 : : {
136 : : // All headers must be appended before any data.
137 [ # # ][ # # ]: 0 : ASSERT(ip_offset >= 0 && tcp_offset >= 0 && data_offset >= 0);
[ # # ][ # # ]
138 : :
139 [ # # ]: 0 : if ( data_offset == buffer_offset )
140 : : { // first data chunk
141 : 0 : int extra = (data_offset - tcp_offset) % 4;
142 [ # # ]: 0 : if ( extra )
143 : : {
144 : 0 : DEBUG_MSG(MSG_PREFIX "%.6f padding tcp header -- original header range: %d - %d\n",
145 : : network_time, tcp_offset, data_offset);
146 [ # # ]: 0 : if ( ! AppendTCPHeader(0, 4 - extra) )
147 : 0 : return 0;
148 : : }
149 : : }
150 : :
151 [ # # ]: 0 : if ( ! Append(chunk, len) )
152 : 0 : return 0;
153 : :
154 : 0 : return 1;
155 : : }
156 : :
157 : 0 : int TCP_TracePacket::Append(const u_char* chunk, int len)
158 : : {
159 [ # # ]: 0 : if ( buffer_offset + len > buffer_size )
160 : : {
161 [ # # ]: 0 : if ( buffer_offset + len > mtu )
162 : 0 : return 0;
163 : :
164 : 0 : u_char* tmp = new u_char[mtu];
165 [ # # ]: 0 : for ( int i = 0 ; i < buffer_size; ++i )
166 : 0 : tmp[i] = pkt[i];
167 : :
168 [ # # ]: 0 : delete [] pkt;
169 : 0 : pkt = tmp;
170 : 0 : buffer_size = mtu;
171 : : }
172 : :
173 [ # # ]: 0 : ASSERT(buffer_offset + len <= buffer_size);
174 : :
175 [ # # ]: 0 : if ( chunk )
176 : : {
177 [ # # ]: 0 : if ( pkt + buffer_offset != chunk )
178 : 0 : memcpy(pkt + buffer_offset, chunk, len);
179 : : }
180 : : else
181 : : // Fill with 0.
182 : 0 : memset(pkt + buffer_offset, 0, len);
183 : :
184 : 0 : buffer_offset += len;
185 : 0 : return 1;
186 : : }
187 : :
188 : 0 : uint32 TCP_TracePacket::GetSeq() const
189 : : {
190 [ # # ][ # # ]: 0 : ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
[ # # ]
191 : : buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
192 : :
193 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
194 : 0 : return ntohl(tp->th_seq);
195 : : }
196 : :
197 : 0 : void TCP_TracePacket::SetSeq(uint32 seq)
198 : : {
199 [ # # ][ # # ]: 0 : ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
[ # # ]
200 : : buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
201 : :
202 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
203 : 0 : tp->th_seq = htonl(seq);
204 : 0 : }
205 : :
206 : 0 : uint32 TCP_TracePacket::GetAck() const
207 : : {
208 [ # # ][ # # ]: 0 : ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
[ # # ]
209 : : buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
210 : :
211 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
212 : 0 : return ntohl(tp->th_ack);
213 : : }
214 : :
215 : 0 : void TCP_TracePacket::SetAck(uint32 ack)
216 : : {
217 [ # # ][ # # ]: 0 : ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
[ # # ]
218 : : buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
219 : :
220 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
221 : 0 : tp->th_ack = htonl(ack);
222 : 0 : }
223 : :
224 : 0 : int TCP_TracePacket::GetTCP_Flag(int which) const
225 : : {
226 [ # # ][ # # ]: 0 : ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
[ # # ]
227 : : buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
228 : :
229 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
230 : 0 : return tp->th_flags & which;
231 : : }
232 : :
233 : 0 : void TCP_TracePacket::SetTCP_Flag(int which, int value)
234 : : {
235 [ # # ][ # # ]: 0 : ASSERT(tcp_offset >= ip_offset + int(sizeof(struct ip)) &&
[ # # ]
236 : : buffer_offset >= tcp_offset + int(sizeof(struct tcphdr)));
237 : :
238 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
239 : :
240 [ # # ]: 0 : if ( value )
241 : 0 : tp->th_flags |= which;
242 : : else
243 : 0 : tp->th_flags &= (~which);
244 : 0 : }
245 : :
246 : 0 : int TCP_TracePacket::PayloadLength() const
247 : : {
248 [ # # ]: 0 : if ( data_offset < 0 )
249 : 0 : return 0;
250 : :
251 : 0 : return buffer_offset - data_offset;
252 : : }
253 : :
254 : 0 : int TCP_TracePacket::SeqLength() const
255 : : {
256 : 0 : int len = PayloadLength();
257 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
258 : :
259 [ # # ]: 0 : if ( tp->th_flags & TH_SYN )
260 : 0 : ++len;
261 : :
262 [ # # ]: 0 : if ( tp->th_flags & TH_FIN )
263 : 0 : ++len;
264 : :
265 : 0 : return len;
266 : : }
267 : :
268 : : int TCP_TracePacket::Finish(struct pcap_pkthdr*& hdr,
269 : : const u_char*& arg_pkt, int& length,
270 : 0 : ipaddr32_t anon_src, ipaddr32_t anon_dst)
271 : : {
272 : : // Set length fields in headers and compute checksums.
273 [ # # ][ # # ]: 0 : if ( tcp_offset < ip_offset + int(sizeof(struct ip)) ||
274 : : data_offset < tcp_offset + int(sizeof(struct tcphdr)) )
275 : 0 : return 0;
276 : :
277 : 0 : struct ip* ip = (struct ip*) (pkt + ip_offset);
278 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
279 : :
280 : : // TCP header.
281 [ # # ]: 0 : ASSERT((data_offset - tcp_offset) % 4 == 0);
282 : :
283 : 0 : tp->th_off = (data_offset - tcp_offset) >> 2;
284 : 0 : tp->th_x2 = 0;
285 : :
286 : : // Shall we instead let URG flag&point stay?
287 : : // tp->th_flags &= (~TH_URG); // set URG to 0
288 : : // tp->th_urp = 0; // clear urgent pointer
289 : :
290 : : // Fix IP addresses before computing the TCP checksum
291 [ # # ]: 0 : if ( anonymize_ip_addr )
292 : : {
293 : 0 : ip->ip_src.s_addr = anon_src;
294 : 0 : ip->ip_dst.s_addr = anon_dst;
295 : : }
296 : :
297 : 0 : tp->th_sum = 0;
298 : 0 : tp->th_sum = 0xffff - tcp_checksum(ip, tp, PayloadLength());
299 : :
300 : : // IP header.
301 : :
302 : : // What to do with ip_id? One way is to choose a pseudo-random
303 : : // number as the new id. We try to keep the original ID unless
304 : : // it would cause a conflict, in which case we increment the
305 : : // ID till there is no conflict.
306 : : //
307 : : // This is too expensive -- and ID conflicts do not really
308 : : // matter because there will never be fragmentation.
309 : : // Fix: just keep the original ID.
310 : : // ip->ip_id = NextIP_ID(ip->ip_src.s_addr, ip->ip_id);
311 : :
312 [ # # ]: 0 : ASSERT((tcp_offset - ip_offset) % 4 == 0);
313 : 0 : ip->ip_hl = (tcp_offset - ip_offset) >> 2;
314 : 0 : ip->ip_len = htons(buffer_offset - ip_offset);
315 : 0 : ip->ip_off = 0; // DF = 0, MF = 0, offset = 0
316 : 0 : ip->ip_sum = 0;
317 : 0 : ip->ip_sum = 0xffff - ones_complement_checksum((const void*) ip, tcp_offset - ip_offset, 0);
318 : :
319 : : // Link level header:
320 : : // Question: what to do with the link level header? Currently we just
321 : : // keep the original header, even though the length field can
322 : : // be incorrect. ###
323 : :
324 [ # # ]: 0 : if ( timestamp < trace_rewriter->RewritePacket()->TimeStamp() )
325 : : // For out of order rewriting.
326 : 0 : timestamp = trace_rewriter->RewritePacket()->TimeStamp();
327 : :
328 : : // The below works around a potential type incompatibility
329 : : // on systems where pcap's timeval is different from the
330 : : // system-wide one. --cpk
331 : : //
332 : 0 : timeval tv_tmp = double_to_timeval(timestamp);
333 : 0 : pcap_hdr.ts.tv_sec = tv_tmp.tv_sec;
334 : 0 : pcap_hdr.ts.tv_usec = tv_tmp.tv_usec;
335 : 0 : pcap_hdr.caplen = pcap_hdr.len = buffer_offset;
336 : :
337 : 0 : hdr = &pcap_hdr;
338 : 0 : arg_pkt = pkt;
339 : 0 : length = buffer_offset;
340 : :
341 : 0 : return 1;
342 : : }
343 : :
344 : 0 : void TCP_TracePacket::Reuse()
345 : : {
346 : 0 : reuse = 1;
347 : :
348 : 0 : timestamp = trace_rewriter->RewritePacket()->TimeStamp();
349 : :
350 : : // Question 1: Shall we keep TCP options in the header? Note
351 : : // that the TCP header of a packet is sometimes replicated in
352 : : // the rewritten trace (because we reuse headers). When an
353 : : // option have idempotent semantics, it is safe to keep the
354 : : // option; otherwise we should include the option only in the
355 : : // first one among replicated copies. Currently we keep
356 : : // options for simplicity and wait for things to happen. ###
357 : :
358 : 0 : struct tcphdr* tp = (struct tcphdr*) (pkt + tcp_offset);
359 : 0 : tp->th_flags = 0;
360 : :
361 : : // Clear all TCP options.
362 : 0 : unsigned int prev_data_offset = data_offset;
363 : 0 : buffer_offset = data_offset = tcp_offset + sizeof(struct tcphdr);
364 [ # # ]: 0 : if ( prev_data_offset - tcp_offset > sizeof(*tp) )
365 : : TCP_Analyzer::ParseTCPOptions(tp,
366 : : TCP_Rewriter::RewriteTCPOption,
367 : 0 : trace_rewriter->Analyzer(), is_orig, this);
368 : 0 : }
369 : :
370 : 0 : RecordVal* TCP_TracePacket::PacketVal()
371 : : {
372 [ # # ]: 0 : if ( ! packet_val )
373 : : {
374 : 0 : packet_val = new RecordVal(packet_type);
375 : 0 : packet_val->Assign(0, TraceRewriter()->Analyzer()->BuildConnVal());
376 : 0 : packet_val->Assign(1, new Val(IsOrig(), TYPE_BOOL));
377 : 0 : packet_val->Assign(2, new Val(PacketSeq(), TYPE_COUNT));
378 : 0 : packet_val->Assign(3, new Val(TimeStamp(), TYPE_TIME));
379 : 0 : packet_val->SetOrigin(this);
380 : : }
381 : : else
382 : 0 : Ref(packet_val);
383 : :
384 : 0 : return packet_val;
385 : : }
386 : :
387 : 0 : uint16 NextIP_ID(const uint32 src_addr, const uint16 id)
388 : : {
389 [ # # ]: 0 : if ( ip_id_set == 0 )
390 : 0 : ip_id_set = new IP_IDSet();
391 : :
392 : : IP_ID ipid;
393 : 0 : ipid.ip = src_addr;
394 : 0 : ipid.id = id;
395 : :
396 [ # # ]: 0 : while ( ip_id_set->find(ipid) != ip_id_set->end() )
397 : : {
398 : 0 : ipid.id = (ipid.id + 1) & 0xffff;
399 : :
400 [ # # ]: 0 : if ( ipid.id == id )
401 : : { // clear all entries of the IP
402 : : IP_ID first_id, last_id;
403 : 0 : first_id.ip = last_id.ip = src_addr;
404 : 0 : first_id.id = 0; last_id.id = 0xffff;
405 : : ip_id_set->erase(ip_id_set->find(first_id),
406 : 0 : ip_id_set->find(last_id));
407 : : }
408 : : }
409 : :
410 : 0 : ip_id_set->insert(ipid);
411 : :
412 : 0 : return uint16(ipid.id & 0xffff);
413 : : }
414 : :
415 : 0 : TCP_RewriterEndpoint::TCP_RewriterEndpoint(TCP_Rewriter* arg_rewriter)
416 : : {
417 : 0 : rewriter = arg_rewriter;
418 : 0 : next_packet = 0;
419 : 0 : endp = 0;
420 : 0 : established = 0;
421 : 0 : end_of_data = 0;
422 : 0 : peer = 0;
423 : 0 : last_ack = 0;
424 : 0 : last_packet_time = -1;
425 : 0 : please_flush = 0;
426 : 0 : flushed = 1;
427 : 0 : flush_scheduled = 0;
428 : 0 : there_is_a_gap = 0;
429 : 0 : }
430 : :
431 : 0 : TCP_RewriterEndpoint::~TCP_RewriterEndpoint()
432 : : {
433 [ # # ][ # # ]: 0 : if ( ! prolog.empty() )
434 : : {
435 [ # # ][ # # ]: 0 : if ( ! next_packet )
436 : 0 : Weird(MSG_PREFIX "end point has data, but hasn't got any packet till destruction.");
437 : : else
438 : 0 : internal_error(MSG_PREFIX "prolog should've been purged on the very first packet.");
439 : :
440 [ # # ][ # # ]: 0 : while ( ! prolog.empty() )
441 : : {
442 [ # # ][ # # ]: 0 : delete prolog.front();
443 : 0 : prolog.pop();
444 : : }
445 : : }
446 : :
447 [ # # ][ # # ]: 0 : if ( ! end_of_data && next_packet && ! next_packet->IsEmpty() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
448 : : Weird(fmt(MSG_PREFIX "end of data missing before deleting the connection: %.6f",
449 : 0 : next_packet->TimeStamp()));
450 : :
451 [ # # ][ # # ]: 0 : if ( next_packet )
452 : 0 : Unref(next_packet);
453 : 0 : }
454 : :
455 : 0 : void TCP_RewriterEndpoint::Init()
456 : : {
457 : : // This cannot be put into the constructor because it requires
458 : : // existence of the peer.
459 : 0 : peer = rewriter->GetPeer(this);
460 : 0 : }
461 : :
462 : : // NextPacket sets 'ticks' of packet dumping according to packet
463 : : // arrival in the original sequence.
464 : 0 : void TCP_RewriterEndpoint::NextPacket(TCP_TracePacket* p)
465 : : {
466 : 0 : please_flush = 1;
467 : 0 : flushed = 0;
468 : 0 : last_packet_time = p->TimeStamp();
469 : :
470 [ # # ]: 0 : if ( ! endp )
471 : 0 : endp = rewriter->GetEndpoint(this);
472 : :
473 [ # # ]: 0 : if ( endp->state == TCP_ENDPOINT_ESTABLISHED )
474 : 0 : established = 1;
475 : :
476 [ # # ][ # # ]: 0 : if ( ! next_packet || p->GetTCP_Flag(TH_SYN) )
[ # # ]
477 : : {
478 [ # # ][ # # ]: 0 : if ( ! p->GetTCP_Flag(TH_SYN | TH_RST) &&
[ # # ]
479 : : ! rewriter->Analyzer()->IsPartial() )
480 : 0 : Weird(MSG_PREFIX "first packet is not SYN or RST");
481 : :
482 : 0 : start_seq = next_seq = p->GetSeq();
483 : : }
484 : :
485 : 0 : SetNextPacket(p);
486 : 0 : ScheduleFlush();
487 : 0 : }
488 : :
489 : 0 : void TCP_RewriterEndpoint::WriteData(int len, const u_char* data)
490 : : {
491 [ # # ]: 0 : if ( end_of_data & (END_BY_FIN | END_BY_RST) )
492 : 0 : Weird(MSG_PREFIX "write after end of data");
493 : :
494 [ # # ]: 0 : if ( ! next_packet )
495 : : {
496 : : // Till anybody really wants to use the prolog ...
497 : 0 : run_time(fmt("pushing %d bytes into prolog", len));
498 : 0 : prolog.push(new BroString(data, len, 0));
499 : : }
500 : : else
501 : : {
502 : : // Originally we did not send data along with SYN or RST.
503 : : // if ( next_packet->GetTCP_Flag(TH_SYN | TH_RST) )
504 : : // internal_error("SYN/RST packet not immediately flushed");
505 : :
506 : : // Question: shall we send data along with the ACK in the
507 : : // connection's three way handshake? Here it may do so.
508 : :
509 : 0 : DoWriteData(len, data);
510 : :
511 [ # # ]: 0 : if ( please_flush )
512 : 0 : ScheduleFlush();
513 : : }
514 : 0 : }
515 : :
516 : 0 : void TCP_RewriterEndpoint::SkipGap(int len)
517 : : {
518 : 0 : next_seq += len;
519 : 0 : there_is_a_gap = 1;
520 : :
521 [ # # ]: 0 : if ( next_packet )
522 : 0 : next_packet->SetSeqGap(0);
523 : 0 : }
524 : :
525 : 0 : void TCP_RewriterEndpoint::Push()
526 : : {
527 [ # # ]: 0 : if ( ! next_packet )
528 : 0 : return;
529 : :
530 : 0 : next_packet->SetTCP_Flag(TH_PUSH, 1);
531 : 0 : PushPacket();
532 : : }
533 : :
534 : 0 : void TCP_RewriterEndpoint::ReqAck()
535 : : {
536 [ # # ]: 0 : if ( ! next_packet )
537 : 0 : return;
538 : :
539 : 0 : PushPacket();
540 : : }
541 : :
542 : 0 : void TCP_RewriterEndpoint::Flush()
543 : : {
544 [ # # ][ # # ]: 0 : if ( ! next_packet || next_packet->OnHold() )
[ # # ]
545 : : // This may happen after the code change in
546 : : // TCP_Connection::NextPacket -- not every packet
547 : : // reaches the TCP rewriter. Also, do not dump a packet
548 : : // on hold -- the packet will be flushed later.
549 : : // internal_error(MSG_PREFIX "flush before packet arrival");
550 : 0 : return;
551 : :
552 : : DEBUG_MSG_A("preparing to flush packet %d (%.6f)\n", next_packet->PacketSeq(), next_packet->TimeStamp());
553 [ # # ]: 0 : if ( next_packet->FINScheduled() )
554 : 0 : GenerateFIN();
555 : :
556 [ # # ]: 0 : if ( please_flush )
557 : : {
558 : : DEBUG_MSG_A("Flush packet %d (%.6f)\n", next_packet->PacketSeq(), next_packet->TimeStamp());
559 : 0 : PushPacket();
560 : : }
561 : :
562 [ # # ]: 0 : if ( ! next_packet->IsEmpty() )
563 : : {
564 : 0 : internal_error(MSG_PREFIX "packet is not empty after flushing");
565 : : }
566 : :
567 : 0 : flush_scheduled = 0;
568 : : }
569 : :
570 : 0 : void TCP_RewriterEndpoint::ScheduleFlush()
571 : : {
572 [ # # ]: 0 : if ( ! flush_scheduled )
573 : : {
574 : 0 : schedule_flush(this);
575 : 0 : flush_scheduled = 1;
576 : : DEBUG_MSG_A("%.6f flush scheduled for packet %d (%.6f)\n", network_time, next_packet->PacketSeq(), next_packet->TimeStamp());
577 : : }
578 : 0 : }
579 : :
580 : 0 : void TCP_RewriterEndpoint::GenerateFIN()
581 : : {
582 [ # # ]: 0 : if ( end_of_data & END_BY_FIN )
583 : 0 : return;
584 : :
585 : : DEBUG_MSG_A("FIN at %.6f\n", next_packet->TimeStamp());
586 : 0 : end_of_data |= END_BY_FIN;
587 : :
588 [ # # ]: 0 : if ( ! next_packet )
589 : : // Weird(MSG_PREFIX "FIN before packet arrival");
590 : 0 : internal_error(MSG_PREFIX "FIN before packet arrival");
591 : : else
592 : : {
593 : 0 : next_packet->ScheduleFIN(0);
594 : 0 : next_packet->SetTCP_Flag(TH_FIN, 1);
595 : 0 : please_flush = 1;
596 : : }
597 : : }
598 : :
599 : 0 : void TCP_RewriterEndpoint::Reset(int self)
600 : : {
601 : : DEBUG_MSG_A("%.6f end by RST (empty = %d)\n", network_time, next_packet ? next_packet->IsEmpty() : -1);
602 [ # # ]: 0 : if ( self )
603 : 0 : end_of_data |= END_BY_RST;
604 : : else
605 : 0 : end_of_data |= END_BY_PEER_RST;
606 : 0 : }
607 : :
608 : 0 : void TCP_RewriterEndpoint::SetNextPacket(TCP_TracePacket* p)
609 : : {
610 [ # # ]: 0 : if ( next_packet )
611 : : {
612 [ # # ][ # # ]: 0 : if ( ! next_packet->IsEmpty() || next_packet->OnHold() )
[ # # ]
613 : 0 : internal_error(MSG_PREFIX "next packet (%.6f) arrives before the previous packet (%.6f) is flushed", p->TimeStamp(), next_packet->TimeStamp());
614 : : // PushPacket();
615 : :
616 : 0 : Unref(next_packet);
617 : : }
618 : :
619 : 0 : next_packet = p;
620 : :
621 [ # # ]: 0 : if ( next_packet->SeqGap() > 0 )
622 : 0 : peer->SkipGap(next_packet->SeqGap());
623 : :
624 : : // next_packet->SetTCP_Flag(TH_PUSH, 0);
625 : :
626 : : // Do not send FIN at this moment because FIN may arrive out
627 : : // of order -- wait till all contents are delivered
628 : 0 : next_packet->SetTCP_Flag(TH_FIN, 0);
629 : :
630 [ # # ]: 0 : if ( ! prolog.empty() )
631 : : {
632 : : // Do not put prolog into SYN/RST packets
633 [ # # ]: 0 : if ( next_packet->GetTCP_Flag(TH_SYN | TH_RST) )
634 : 0 : PushPacket();
635 : 0 : PurgeProlog();
636 : : }
637 : 0 : }
638 : :
639 : 0 : void TCP_RewriterEndpoint::PurgeProlog()
640 : : {
641 [ # # ]: 0 : while ( ! prolog.empty() )
642 : : {
643 : 0 : BroString* s = prolog.front();
644 : 0 : WriteData(s->Len(), s->Bytes());
645 : 0 : prolog.pop();
646 [ # # ]: 0 : delete s;
647 : : }
648 : 0 : }
649 : :
650 : 0 : void TCP_RewriterEndpoint::DoWriteData(int len, const u_char* data)
651 : : {
652 [ # # ]: 0 : ASSERT(next_packet);
653 : :
654 [ # # ]: 0 : while ( len > 0 )
655 : : {
656 : 0 : int left = next_packet->Space();
657 : :
658 [ # # ]: 0 : if ( ! left )
659 : : {
660 : 0 : PushPacket();
661 : 0 : left = next_packet->Space();
662 : : }
663 : :
664 [ # # ]: 0 : if ( left > len )
665 : 0 : left = len;
666 : :
667 [ # # ]: 0 : if ( ! next_packet->AppendData(data, left) )
668 : 0 : ASSERT(0);
669 : :
670 : 0 : data += left;
671 : 0 : len -= left;
672 : 0 : please_flush = 1;
673 : : }
674 : 0 : }
675 : :
676 : 0 : int TCP_RewriterEndpoint::IsPlaceHolderPacket(TCP_TracePacket* p)
677 : : {
678 : : return p->SeqLength() == 0 &&
679 : : ! p->GetTCP_Flag(TH_SYN | TH_RST | TH_FIN | TH_URG ) &&
680 [ # # ][ # # ]: 0 : ! (p->GetTCP_Flag(TH_ACK) && p->GetAck() > last_ack);
[ # # ][ # # ]
681 : : }
682 : :
683 : 0 : void TCP_RewriterEndpoint::PushPacket()
684 : : {
685 [ # # ]: 0 : if ( ! next_packet )
686 : : {
687 : 0 : internal_error(MSG_PREFIX "cannot push packet before packet arrival");
688 : : return;
689 : : }
690 : :
691 : : // Set sequence number ...
692 : 0 : next_packet->SetSeq(next_seq);
693 : 0 : int seq_len = next_packet->SeqLength();
694 : :
695 : 0 : next_seq += seq_len;
696 : :
697 : : // ... and acknowledge peer's recently dumped packet.
698 [ # # # # ]: 0 : if ( next_packet->GetTCP_Flag(TH_SYN | TH_RST) &&
[ # # ]
699 : : ! next_packet->GetTCP_Flag(TH_ACK) )
700 : : {
701 : 0 : next_packet->SetTCP_Flag(TH_ACK, 0);
702 : 0 : next_packet->SetAck(0);
703 : : }
704 : : else
705 : : {
706 : 0 : next_packet->SetTCP_Flag(TH_ACK, 1);
707 [ # # ]: 0 : if ( peer->HasPacket() )
708 : 0 : next_packet->SetAck(peer->NextSeq());
709 : : }
710 : :
711 : 0 : int RST = next_packet->GetTCP_Flag(TH_RST);
712 : :
713 : : #if 0
714 : : // With the feature of reserve_rewrite_slot, packet dumping can
715 : : // be delayed.
716 : :
717 : : // Enforce the order of timestamps; but delayed FIN is OK
718 : : // when there is a gap.
719 : : if ( next_packet->TimeStamp() < network_time &&
720 : : ! (next_packet->GetTCP_Flag(TH_FIN) && there_is_a_gap) )
721 : : {
722 : : Weird(MSG_PREFIX "delayed packet");
723 : : Weird(fmt(MSG_PREFIX "packet time %.6f, dumping time %.6f\n",
724 : : next_packet->TimeStamp(), network_time));
725 : : }
726 : : #endif
727 : :
728 [ # # # # ]: 0 : if ( ! IsPlaceHolderPacket(next_packet) ||
[ # # ]
729 : : ! omit_rewrite_place_holder )
730 : : {
731 [ # # ]: 0 : if ( next_packet->PredictedAsEmptyPlaceHolder() )
732 : : {
733 [ # # ][ # # ]: 0 : DEBUG_MSG("The packet to dump (%.6f, %d, %d, %s%s%s%s, %u > %u) was predicted to be an empty place holder.",
[ # # ][ # # ]
734 : : next_packet->TimeStamp(), next_packet->SeqLength(), next_packet->PayloadLength(),
735 : : next_packet->GetTCP_Flag(TH_SYN) ? "S" : "",
736 : : next_packet->GetTCP_Flag(TH_RST) ? "R" : "",
737 : : next_packet->GetTCP_Flag(TH_FIN) ? "F" : "",
738 : : next_packet->GetTCP_Flag(TH_URG) ? "U" : "",
739 : : next_packet->GetAck(), last_ack);
740 : : }
741 : :
742 : 0 : rewriter->DumpPacket(this, next_packet);
743 : : }
744 : :
745 [ # # ][ # # ]: 0 : if ( next_packet->GetTCP_Flag(TH_ACK) &&
[ # # ]
746 : : next_packet->GetAck() > last_ack )
747 : 0 : last_ack = next_packet->GetAck();
748 : :
749 : : // Reuse the packet headers.
750 : 0 : next_packet->Reuse();
751 : :
752 [ # # ]: 0 : if ( ! next_packet->FINScheduled() )
753 : : {
754 : 0 : please_flush = 0;
755 [ # # ]: 0 : if ( ! next_packet->IsEmpty() )
756 : 0 : internal_error("should have been cleared");
757 : : }
758 : :
759 [ # # ]: 0 : if ( RST )
760 : : {
761 : 0 : Reset(1); // itself ...
762 : 0 : peer->Reset(0); // ... and peer
763 : 0 : return;
764 : : }
765 : :
766 : : // Question: do we need to request an ACK? Yes, if the packet
767 : : // is an artificially generated packet.
768 [ # # ][ # # ]: 0 : if ( seq_len > 0 &&
[ # # ]
769 : : next_packet->TimeStamp() < rewriter->RewritePacket()->TimeStamp() )
770 : 0 : peer->ReqAck();
771 : : }
772 : :
773 : 0 : void TCP_RewriterEndpoint::Weird(const char* name) const
774 : : {
775 : : #ifdef DEBUG_BRO
776 : : rewriter->Weird(name);
777 : : #endif
778 : 0 : }
779 : :
780 : : TCP_Rewriter::TCP_Rewriter(TCP_Analyzer* arg_analyzer, PacketDumper* arg_dumper,
781 : 0 : int arg_MTU, int arg_wait_for_commitment)
782 : : {
783 : 0 : analyzer = arg_analyzer;
784 : 0 : dumper = arg_dumper;
785 : 0 : MTU = arg_MTU;
786 : 0 : wait_for_commitment = arg_wait_for_commitment;
787 : 0 : discard_packets = 0; // till AbortPackets(1);
788 : :
789 : 0 : packets_rewritten = 0;
790 : 0 : next_packet_seq = 0;
791 : 0 : pending_content_gap = 0;
792 : :
793 : 0 : orig = new TCP_RewriterEndpoint(this);
794 : 0 : resp = new TCP_RewriterEndpoint(this);
795 : :
796 : 0 : orig->Init();
797 : 0 : resp->Init();
798 : :
799 : 0 : anon_addr[0] = anon_addr[1] = 0;
800 : :
801 [ # # # # ]: 0 : if ( anonymize_ip_addr )
802 : : {
803 : : anon_addr[0] = anonymize_ip(to_v4_addr(analyzer->Conn()->OrigAddr()),
804 : 0 : ORIG_ADDR);
805 : : anon_addr[1] = anonymize_ip(to_v4_addr(analyzer->Conn()->RespAddr()),
806 : 0 : RESP_ADDR);
807 : : }
808 : :
809 : 0 : holding_packets = 0;
810 : 0 : current_packet = next_packet = 0;
811 : :
812 : 0 : current_slot = first_slot = last_slot = 0;
813 : 0 : highest_slot_number = 0;
814 : 0 : answered[0] = answered[1] = 0;
815 : 0 : }
816 : :
817 : 0 : void TCP_Rewriter::Done()
818 : : {
819 : : // The wrap-up work needs to be done *after* event processing,
820 : : // therefore we schedule a funeral to be held right before
821 : : // packets are flushed.
822 : 0 : schedule_funeral(this);
823 : 0 : }
824 : :
825 : 0 : void TCP_Rewriter::Funeral()
826 : : {
827 [ # # ]: 0 : if ( ! uncommited_packet_queue.empty() )
828 : : {
829 : : warn(fmt(MSG_PREFIX
830 : : "rewriter gets neither commit or abort, "
831 : : "and %d packets will be discarded",
832 : 0 : int(uncommited_packet_queue.size())));
833 : 0 : AbortPackets(0);
834 : : }
835 : :
836 [ # # ]: 0 : if ( ! slot_queue.empty() )
837 : : {
838 : 0 : run_time("reserved slots are not completely released at the end of rewriter %s", analyzer->Conn());
839 [ # # ]: 0 : for ( slot_map_t::iterator it = reserved_slots.begin();
840 : : it != reserved_slots.end();
841 : : ++it )
842 : : {
843 : 0 : TCP_RewriteSlot* slot = it->second;
844 : 0 : run_time(fmt("unreleased slot: %d", slot->Number()));
845 : : }
846 : :
847 [ # # ]: 0 : while ( ! slot_queue.empty() )
848 : : {
849 : 0 : TCP_RewriteSlot* slot = slot_queue.front();
850 : 0 : slot_queue.pop_front();
851 : 0 : slot->Dump();
852 [ # # ]: 0 : delete slot;
853 : : }
854 : :
855 : 0 : reserved_slots.clear();
856 : 0 : ReleasePacketsOnHold();
857 : : }
858 : :
859 [ # # ]: 0 : if ( ! packets_on_hold.empty() )
860 : : {
861 : 0 : run_time("packets on hold at the end of rewriter %s", analyzer->Conn());
862 : 0 : ReleasePacketsOnHold();
863 : : // And release the last one.
864 : 0 : Endp(next_packet->IsOrig())->Flush();
865 : : }
866 : 0 : }
867 : :
868 : 0 : TCP_Rewriter::~TCP_Rewriter()
869 : : {
870 [ # # ][ # # ]: 0 : delete orig;
[ # # ]
871 [ # # ][ # # ]: 0 : delete resp;
[ # # ]
872 [ # # ][ # # ]: 0 : }
[ # # ]
873 : :
874 : : void TCP_Rewriter::NextPacket(int is_orig, double t,
875 : : const struct pcap_pkthdr* pcap_hdr,
876 : : const u_char* pcap_pkt, int hdr_size,
877 : : const struct ip* ip,
878 : 0 : const struct tcphdr* tp)
879 : : {
880 : 0 : unsigned int ip_hdr_len = ip->ip_hl * 4;
881 : 0 : unsigned int tcp_hdr_len = tp->th_off * 4;
882 : :
883 : : TCP_TracePacket* p =
884 : : new TCP_TracePacket(this, ++next_packet_seq, t,
885 : : is_orig, pcap_hdr, MTU,
886 : 0 : hdr_size + ip_hdr_len + tcp_hdr_len);
887 : :
888 [ # # ]: 0 : if ( ! p->AppendLinkHeader(pcap_pkt, hdr_size) )
889 : 0 : internal_error(MSG_PREFIX "cannot append headers -- check MTU");
890 : :
891 [ # # ]: 0 : if ( ! p->AppendIPHeader((const u_char*)ip, sizeof(*ip)) )
892 : 0 : internal_error(MSG_PREFIX "cannot append headers -- check MTU");
893 : :
894 : : if ( ip_hdr_len > sizeof(*ip) )
895 : : {
896 : : // TODO: re-write IP options.
897 : : }
898 : :
899 [ # # ]: 0 : if ( ! p->AppendTCPHeader((const u_char*)tp, sizeof(*tp)) )
900 : 0 : internal_error(MSG_PREFIX "cannot append headers -- check MTU");
901 : :
902 : : // Rewrite TCP options.
903 [ # # ]: 0 : if ( tcp_hdr_len > sizeof(*tp) )
904 : : TCP_Analyzer::ParseTCPOptions(tp, RewriteTCPOption,
905 : 0 : analyzer, is_orig, p);
906 : :
907 : : // Pad the TCP header.
908 : 0 : p->AppendData(0, 0);
909 : :
910 : : // Before setting current_packet to p, first clean up empty
911 : : // place holders to save memory space.
912 [ # # # # ]: 0 : if ( omit_rewrite_place_holder && holding_packets )
913 : 0 : CleanUpEmptyPlaceHolders();
914 : :
915 : 0 : current_packet = p;
916 : :
917 [ # # ]: 0 : if ( pending_content_gap )
918 : : {
919 : : // A packet triggers a content gap only in the other
920 : : // direction.
921 [ # # ]: 0 : if ( current_packet->IsOrig() )
922 : 0 : pending_content_gap = -pending_content_gap;
923 : :
924 [ # # ]: 0 : if ( pending_content_gap < 0 )
925 : 0 : internal_error("content gap out of sync with packet");
926 : :
927 : 0 : current_packet->SetSeqGap(pending_content_gap);
928 : 0 : pending_content_gap = 0;
929 : : }
930 : :
931 [ # # ]: 0 : if ( current_slot )
932 : 0 : add_slot();
933 : :
934 [ # # ]: 0 : if ( ! holding_packets )
935 : : {
936 : 0 : next_packet = p;
937 : 0 : Endp(is_orig)->NextPacket(p);
938 : : }
939 : : else
940 : : {
941 : : DEBUG_MSG_A("packet %d (%.6f) on hold\n",
942 : : p->PacketSeq(), p->TimeStamp());
943 : 0 : packets_on_hold.push_back(p);
944 : 0 : ++num_packets_held;
945 : : }
946 : 0 : }
947 : :
948 : 0 : void TCP_Rewriter::ContentGap(int is_orig, int len)
949 : : {
950 [ # # ]: 0 : if ( is_orig )
951 : 0 : pending_content_gap = len;
952 : : else
953 : 0 : pending_content_gap = -len;
954 : 0 : }
955 : :
956 : 0 : void TCP_Rewriter::ScheduleFIN(int is_orig)
957 : : {
958 [ # # ][ # # ]: 0 : if ( current_packet && current_packet->IsOrig() == is_orig )
[ # # ]
959 : 0 : current_packet->ScheduleFIN();
960 : :
961 : : // Otherwise just ignore the FIN.
962 : : // Endp(is_orig)->ScheduleFIN();
963 : 0 : }
964 : :
965 : 0 : void TCP_Rewriter::WriteData(int is_orig, int len, const u_char* data)
966 : : {
967 [ # # ]: 0 : if ( ! current_slot )
968 : 0 : DoWriteData(is_orig, len, data);
969 : : else
970 : 0 : current_slot->WriteData(is_orig, len, data);
971 : 0 : }
972 : :
973 : 0 : void TCP_Rewriter::DoWriteData(int is_orig, int len, const u_char* data)
974 : : {
975 : 0 : if ( is_orig != next_packet->IsOrig() )
976 : : {
977 : : // Weird(fmt("%.6f rewriting packet on the opposite direction", network_time));
978 : : }
979 : :
980 : 0 : Endp(is_orig)->WriteData(len, data);
981 : 0 : }
982 : :
983 : 0 : void TCP_Rewriter::Push(int is_orig)
984 : : {
985 : 0 : Endp(is_orig)->Push();
986 : 0 : }
987 : :
988 : 0 : void TCP_Rewriter::DumpPacket(TCP_RewriterEndpoint* endp, TCP_TracePacket* p)
989 : : {
990 : : struct pcap_pkthdr* hdr;
991 : : const u_char* pkt;
992 : : int length;
993 : : ipaddr32_t anon_src, anon_dst; // anonymized IP addresses
994 : :
995 [ # # ]: 0 : if ( discard_packets )
996 : 0 : return;
997 : :
998 [ # # ]: 0 : if ( endp == orig )
999 : : {
1000 : 0 : anon_src = anon_addr[0];
1001 : 0 : anon_dst = anon_addr[1];
1002 : : }
1003 : : else
1004 : : {
1005 : 0 : anon_src = anon_addr[1];
1006 : 0 : anon_dst = anon_addr[0];
1007 : : }
1008 : :
1009 [ # # ]: 0 : if ( p->Finish(hdr, pkt, length, anon_src, anon_dst) )
1010 : : {
1011 : : DEBUG_MSG_A("Packet %d (%.6f) dumped at %.6f\n", p->PacketSeq(), p->TimeStamp(), network_time);
1012 : 0 : ++packets_rewritten;
1013 : :
1014 [ # # ]: 0 : if ( ! wait_for_commitment )
1015 : 0 : dumper->DumpPacket(hdr, pkt, length);
1016 : : else
1017 : : {
1018 : 0 : char* b = new char[sizeof(struct pcap_pkthdr) + length];
1019 : 0 : uncommited_packet_queue.push(b);
1020 : :
1021 : 0 : memcpy(b, hdr, sizeof(struct pcap_pkthdr));
1022 : :
1023 : 0 : b += sizeof(struct pcap_pkthdr);
1024 : 0 : memcpy(b, pkt, length);
1025 : : }
1026 : : }
1027 : : else
1028 : 0 : internal_error(MSG_PREFIX "ill formed packet for dumping");
1029 : : }
1030 : :
1031 : 0 : void TCP_Rewriter::ReleaseNextPacket()
1032 : : {
1033 [ # # ]: 0 : if ( packets_on_hold.empty() )
1034 : : {
1035 : 0 : internal_error("there is no packet on hold to release");
1036 : : return;
1037 : : }
1038 : :
1039 : 0 : next_packet->SetOnHold(0);
1040 : 0 : Endp(next_packet->IsOrig())->Flush();
1041 : 0 : packets_on_hold.pop_front();
1042 : :
1043 [ # # ]: 0 : if ( ! packets_on_hold.empty() )
1044 : : {
1045 : 0 : next_packet = packets_on_hold.front();
1046 : 0 : Endp(next_packet->IsOrig())->NextPacket(next_packet);
1047 : : }
1048 : : else
1049 : 0 : next_packet = 0;
1050 : : }
1051 : :
1052 : 0 : void TCP_Rewriter::HoldPacket(TCP_TracePacket* p)
1053 : : {
1054 [ # # ]: 0 : if ( ! next_packet )
1055 : : {
1056 : 0 : internal_error("should not try to hold a packet before packet arrival");
1057 : : return;
1058 : : }
1059 : :
1060 : 0 : holding_packets = 1;
1061 : :
1062 [ # # ][ # # ]: 0 : while ( next_packet && next_packet->PacketSeq() < p->PacketSeq() )
[ # # ]
1063 : 0 : ReleaseNextPacket();
1064 : :
1065 [ # # ][ # # ]: 0 : if ( ! next_packet ||
[ # # ]
1066 : : next_packet->PacketSeq() != p->PacketSeq() )
1067 : : {
1068 : : internal_error("packet sequence not found for hold_packet: %d",
1069 : 0 : p->PacketSeq());
1070 : : return;
1071 : : }
1072 : :
1073 : 0 : next_packet->SetOnHold(1);
1074 [ # # ]: 0 : if ( packets_on_hold.empty() )
1075 : : {
1076 : 0 : packets_on_hold.push_back(next_packet);
1077 : 0 : ++num_packets_held;
1078 : 0 : answered[0] = answered[1] = 0;
1079 : : }
1080 : : }
1081 : :
1082 : 0 : void TCP_Rewriter::ReleasePacketsOnHold()
1083 : : {
1084 : 0 : holding_packets = 0;
1085 [ # # ]: 0 : if ( packets_on_hold.empty() )
1086 : 0 : return;
1087 : :
1088 [ # # ]: 0 : while ( packets_on_hold.size() > 1 )
1089 : 0 : ReleaseNextPacket();
1090 : :
1091 : 0 : next_packet->SetOnHold(0);
1092 : 0 : packets_on_hold.pop_front();
1093 : : }
1094 : :
1095 : 0 : void TCP_Rewriter::AbortPackets(int apply_to_future)
1096 : : {
1097 [ # # ]: 0 : while ( ! uncommited_packet_queue.empty() )
1098 : : {
1099 : 0 : char* p = uncommited_packet_queue.front();
1100 : 0 : uncommited_packet_queue.pop();
1101 [ # # ]: 0 : delete [] p;
1102 : : }
1103 : :
1104 [ # # ]: 0 : if ( apply_to_future )
1105 : 0 : discard_packets = 1;
1106 : 0 : }
1107 : :
1108 : 0 : void TCP_Rewriter::CommitPackets(int apply_to_future)
1109 : : {
1110 [ # # ]: 0 : while ( ! uncommited_packet_queue.empty() )
1111 : : {
1112 : : struct pcap_pkthdr* hdr =
1113 : 0 : (struct pcap_pkthdr*) uncommited_packet_queue.front();
1114 : :
1115 : 0 : uncommited_packet_queue.pop();
1116 : :
1117 : : dumper->DumpPacket(hdr,
1118 : : ((u_char*)hdr) + sizeof(struct pcap_pkthdr),
1119 : 0 : int((hdr->caplen)));
1120 : :
1121 [ # # ]: 0 : delete [] (char*) hdr;
1122 : : }
1123 : :
1124 [ # # ]: 0 : if ( apply_to_future )
1125 : : { // dump all future packets immediately
1126 : 0 : wait_for_commitment = 0;
1127 : 0 : discard_packets = 0;
1128 : : }
1129 : 0 : }
1130 : :
1131 : 0 : void TCP_Rewriter::CleanUpEmptyPlaceHolders()
1132 : : {
1133 [ # # ]: 0 : if ( ! last_slot )
1134 : 0 : return;
1135 : :
1136 [ # # ]: 0 : if ( last_slot->Packet() != current_packet )
1137 : 0 : internal_error("Mismatch: last_slot->packet != current_packet");
1138 : :
1139 [ # # ][ # # ]: 0 : if ( packets_on_hold.empty() ||
[ # # ]
1140 : : packets_on_hold.back() != current_packet )
1141 : 0 : internal_error("Mismatch: packets_on_hold.back() != current_packet");
1142 : :
1143 [ # # ]: 0 : int is_orig = current_packet->IsOrig() ? 1 : 0;
1144 : :
1145 [ # # ]: 0 : if ( current_packet->SeqGap() > 0 )
1146 : : // This packet signals a sequence gap (on the opposite flow).
1147 : 0 : answered[is_orig] = 0;
1148 : :
1149 : : // Is the current packet an empty placeholder packet?
1150 : : int current_packet_is_empty =
1151 : : last_slot->isEmpty() &&
1152 : : current_packet->SeqLength() == 0 &&
1153 : : ! current_packet->GetTCP_Flag(TH_SYN|TH_RST|TH_FIN|TH_URG) &&
1154 [ # # ][ # # ]: 0 : ! current_packet->HasReservedSlot();
[ # # ][ # # ]
1155 : :
1156 [ # # ]: 0 : if ( current_packet_is_empty )
1157 : : {
1158 [ # # ]: 0 : if ( answered[is_orig] )
1159 : : {
1160 : : // #define DO_NOT_CLEAN_UP_ONLY_PREDICT
1161 : : #ifdef DO_NOT_CLEAN_UP_ONLY_PREDICT
1162 : : // for debugging
1163 : : current_packet->PredictAsEmptyPlaceHolder();
1164 : : #else
1165 : 0 : ++num_packets_cleaned;
1166 : 0 : packets_on_hold.pop_back();
1167 : 0 : Unref(current_packet);
1168 : 0 : current_packet = 0;
1169 : 0 : slot_queue.pop_back();
1170 [ # # ]: 0 : delete last_slot;
1171 : 0 : last_slot = slot_queue.back();
1172 : : #endif
1173 : : }
1174 : : }
1175 : : else
1176 : : // Current packet may not be empty ...
1177 : 0 : answered[1 - is_orig] = 0;
1178 : :
1179 : 0 : answered[is_orig] = 1;
1180 : : }
1181 : :
1182 : 0 : int TCP_Rewriter::LeaveAddrInTheClear(int is_orig)
1183 : : {
1184 [ # # ]: 0 : if ( packets_rewritten > 0 )
1185 : 0 : return 0;
1186 : :
1187 [ # # ]: 0 : if ( is_orig )
1188 : 0 : anon_addr[0] = to_v4_addr(analyzer->Conn()->OrigAddr());
1189 : : else
1190 : 0 : anon_addr[1] = to_v4_addr(analyzer->Conn()->RespAddr());
1191 : :
1192 : 0 : return 1;
1193 : : }
1194 : :
1195 : 0 : TCP_Endpoint* TCP_Rewriter::GetEndpoint(TCP_RewriterEndpoint* endp)
1196 : : {
1197 [ # # ]: 0 : if ( endp == orig )
1198 : 0 : return analyzer->Orig();
1199 : : else
1200 : 0 : return analyzer->Resp();
1201 : : }
1202 : :
1203 : 0 : TCP_RewriterEndpoint* TCP_Rewriter::GetPeer(TCP_RewriterEndpoint* endp)
1204 : : {
1205 [ # # ]: 0 : if ( endp == orig )
1206 : 0 : return resp;
1207 : :
1208 [ # # ]: 0 : else if ( endp == resp )
1209 : 0 : return orig;
1210 : :
1211 : : else
1212 : 0 : return 0;
1213 : : }
1214 : :
1215 : : #define KEEP_ORIG 1
1216 : : #define REUSE_OPT 1
1217 : : #define TO_NOP 0
1218 : : #define MAX_TCP_OPTION_REWRITING 9
1219 : :
1220 : : struct TCPOptionRewriting {
1221 : : int keep_orig;
1222 : : int reuse;
1223 : : } tcp_option_rewriting[MAX_TCP_OPTION_REWRITING] = {
1224 : : // 0 - End of Option List [RFC793]
1225 : : {KEEP_ORIG, REUSE_OPT},
1226 : :
1227 : : // 1 - No-Operation [RFC793]
1228 : : {KEEP_ORIG, REUSE_OPT},
1229 : :
1230 : : // 2 4 Maximum Segment Size [RFC793]
1231 : : {KEEP_ORIG, REUSE_OPT},
1232 : :
1233 : : // 3 3 WSOPT - Window Scale [RFC1323]
1234 : : {KEEP_ORIG, REUSE_OPT},
1235 : :
1236 : : // 4 2 SACK Permitted [RFC2018]
1237 : : {KEEP_ORIG, REUSE_OPT},
1238 : :
1239 : : // 5 N SACK [RFC2018]
1240 : : {TO_NOP, TO_NOP},
1241 : :
1242 : : // 6 6 Echo (obsoleted by option 8) [RFC1072]
1243 : : {TO_NOP, TO_NOP},
1244 : :
1245 : : // 7 6 Echo Reply (obsoleted by option 8)[RFC1072]
1246 : : {TO_NOP, TO_NOP},
1247 : :
1248 : : // 8 10 TSOPT - Time Stamp Option [RFC1323]
1249 : : {KEEP_ORIG, REUSE_OPT},
1250 : :
1251 : : // ** the rest is left for future work **
1252 : : // 9 2 Partial Order Connection Permitted[RFC1693]
1253 : : // 10 3 Partial Order Service Profile [RFC1693]
1254 : : // 11 CC [RFC1644]
1255 : : // 12 CC.NEW [RFC1644]
1256 : : // 13 CC.ECHO [RFC1644]
1257 : : // 14 3 TCP Alternate Checksum Request [RFC1146]
1258 : : // 15 N TCP Alternate Checksum Data [RFC1146]
1259 : : // 16 Skeeter [Knowles]
1260 : : // 17 Bubba [Knowles]
1261 : : // 18 3 Trailer Checksum Option [Subbu & Monroe]
1262 : : // 19 18 MD5 Signature Option [RFC2385]
1263 : : // 20 SCPS Capabilities [Scott]
1264 : : // 21 Selective Negative Acknowledgements [Scott]
1265 : : // 22 Record Boundaries [Scott]
1266 : : // 23 Corruption experienced [Scott]
1267 : : // 24 SNAP [Sukonnik]
1268 : : // 25 Unassigned (released 12/18/00)
1269 : : // 26 TCP Compression Filter [Bellovin]
1270 : : };
1271 : :
1272 : : int TCP_Rewriter::RewriteTCPOption(unsigned int opt, unsigned int optlen,
1273 : : const u_char* option, TCP_Analyzer* analyzer,
1274 : 0 : bool is_orig, void* cookie)
1275 : : {
1276 : 0 : TCP_TracePacket* p = (TCP_TracePacket*) cookie;
1277 : :
1278 [ # # ][ # # ]: 0 : if ( opt < MAX_TCP_OPTION_REWRITING &&
[ # # ][ # # ]
[ # # ][ # # ]
1279 : : ( (! p->IsReuse() && tcp_option_rewriting[opt].keep_orig) ||
1280 : : (p->IsReuse() && tcp_option_rewriting[opt].reuse) ) )
1281 : : // copy/reuse the TCP option
1282 : 0 : p->AppendTCPHeader(option, optlen);
1283 : :
1284 : : else
1285 : : { // replace it with nop
1286 : : static const u_char nop[16] = {
1287 : : 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1288 : : };
1289 : :
1290 [ # # ]: 0 : while ( optlen > 0 )
1291 : : {
1292 : 0 : int k = optlen > 16 ? 16 : optlen;
1293 : 0 : p->AppendTCPHeader(nop, k);
1294 : 0 : optlen -= k;
1295 : : }
1296 : : }
1297 : :
1298 : 0 : return 0;
1299 : : }
1300 : :
1301 : 0 : TCP_RewriteSlot* TCP_Rewriter::add_slot()
1302 : : {
1303 : 0 : ++highest_slot_number;
1304 : :
1305 : : DEBUG_MSG_A("add slot %u\n", highest_slot_number);
1306 : :
1307 : : last_slot = current_slot =
1308 : 0 : new TCP_RewriteSlot(current_packet, highest_slot_number);
1309 : :
1310 : 0 : slot_queue.push_back(current_slot);
1311 : :
1312 : 0 : return current_slot;
1313 : : }
1314 : :
1315 : 0 : TCP_RewriteSlot* TCP_Rewriter::find_slot(unsigned int slot)
1316 : : {
1317 : : // DEBUG_MSG_A("%d slots reserved\n", reserved_slots.size());
1318 : 0 : slot_map_t::iterator it = reserved_slots.find(slot);
1319 [ # # ]: 0 : if ( it == reserved_slots.end() )
1320 : 0 : return 0;
1321 : :
1322 : 0 : return it->second;
1323 : : }
1324 : :
1325 : 0 : unsigned int TCP_Rewriter::ReserveSlot()
1326 : : {
1327 [ # # ]: 0 : if ( ! current_packet )
1328 : : {
1329 : 0 : run_time("cannot reserve a rewrite slot before packet arrival");
1330 : 0 : return 0;
1331 : : }
1332 : :
1333 [ # # ]: 0 : if ( ! current_slot )
1334 : : {
1335 : 0 : first_slot = add_slot();
1336 : 0 : HoldPacket(current_packet);
1337 : : }
1338 : :
1339 [ # # ]: 0 : if ( current_slot != last_slot )
1340 : : {
1341 : 0 : run_time("cannot reserve a slot within a reserved slot");
1342 : 0 : return 0;
1343 : : }
1344 : :
1345 : 0 : int slot_number = current_slot->Number();
1346 : : DEBUG_MSG_A("reserved slot %d\n", slot_number);
1347 : :
1348 : 0 : reserved_slots[slot_number] = current_slot;
1349 : 0 : add_slot();
1350 : 0 : current_packet->AddReservedSlot();
1351 : :
1352 : 0 : return slot_number;
1353 : : }
1354 : :
1355 : 0 : int TCP_Rewriter::SeekSlot(unsigned int slot)
1356 : : {
1357 : 0 : TCP_RewriteSlot* s = find_slot(slot);
1358 [ # # ]: 0 : if ( ! s )
1359 : 0 : return 0;
1360 : :
1361 : 0 : current_slot = s;
1362 : 0 : return 1;
1363 : : }
1364 : :
1365 : 0 : int TCP_Rewriter::ReturnFromSlot()
1366 : : {
1367 : 0 : current_slot = last_slot;
1368 : 0 : return 1;
1369 : : }
1370 : :
1371 : 0 : int TCP_Rewriter::ReleaseSlot(unsigned int slot)
1372 : : {
1373 : 0 : slot_map_t::iterator it = reserved_slots.find(slot);
1374 [ # # ]: 0 : if ( it == reserved_slots.end() )
1375 : : {
1376 : 0 : run_time(fmt("cannot find slot %u", slot));
1377 : 0 : return 0;
1378 : : }
1379 : :
1380 : 0 : TCP_RewriteSlot* s = it->second;
1381 : 0 : reserved_slots.erase(it);
1382 : :
1383 [ # # ]: 0 : if ( s == current_slot )
1384 : 0 : ReturnFromSlot();
1385 : :
1386 : : DEBUG_MSG_A("release slot %u, slot [%u, %u]\n", s->Number(), first_slot->Number(), last_slot->Number());
1387 [ # # ]: 0 : if ( s == first_slot )
1388 : : {
1389 [ # # ]: 0 : do // release slots till we get to the next *reserved* slot
1390 : : {
1391 : : DEBUG_MSG_A("dump slot %d %.6f\n", first_slot->Number(), first_slot->Packet()->TimeStamp());
1392 : :
1393 : 0 : first_slot->Dump();
1394 : 0 : slot_queue.pop_front();
1395 [ # # ]: 0 : delete first_slot;
1396 : :
1397 [ # # ]: 0 : if ( slot_queue.empty() )
1398 : : {
1399 : 0 : first_slot = last_slot = current_slot = 0;
1400 : : DEBUG_MSG_A("release all packets on hold\n");
1401 : 0 : ReleasePacketsOnHold();
1402 : 0 : break;
1403 : : }
1404 : :
1405 : 0 : first_slot = slot_queue.front();
1406 : 0 : HoldPacket(first_slot->Packet());
1407 : : DEBUG_MSG_A("move on to packet %d (%.6f)\n", first_slot->Packet()->PacketSeq(), first_slot->Packet()->TimeStamp());
1408 : : }
1409 : : while ( ! find_slot(first_slot->Number()) );
1410 : : }
1411 : :
1412 : 0 : return 1;
1413 : : }
1414 : :
1415 : 0 : TCP_RewriteSlot::TCP_RewriteSlot(TCP_TracePacket* p, unsigned int number)
1416 : : {
1417 : 0 : packet = p;
1418 : 0 : slot_number = number;
1419 : 0 : rewriter = packet->TraceRewriter();
1420 : 0 : }
1421 : :
1422 : 0 : void TCP_RewriteSlot::WriteData(int is_orig, int len, const u_char* data)
1423 : : {
1424 [ # # ]: 0 : if ( is_orig != packet->IsOrig() )
1425 : : {
1426 : : run_time("writing data to a slot of wrong direction %s",
1427 : 0 : rewriter->analyzer->Conn());
1428 : :
1429 : 0 : BroString* tmp = new BroString(data, len, 1);
1430 : 0 : char* tmp_s = tmp->Render();
1431 : : run_time(fmt("further info: dir = %s, len = %d, data = \"%s\"",
1432 [ # # ]: 0 : is_orig ? "orig" : "resp", len, tmp_s));
1433 : 0 : delete tmp_s;
1434 [ # # ]: 0 : delete tmp;
1435 : 0 : return;
1436 : : }
1437 : :
1438 : 0 : BroString* s = new BroString((const u_char*) data, len, 1);
1439 : 0 : buf.push(s);
1440 : : }
1441 : :
1442 : 0 : void TCP_RewriteSlot::Dump()
1443 : : {
1444 [ # # ]: 0 : while ( ! buf.empty() )
1445 : : {
1446 : 0 : BroString* s = buf.front();
1447 : 0 : buf.pop();
1448 : : DEBUG_MSG_A("dump: \"%s\"\n", s->Bytes());
1449 : 0 : rewriter->DoWriteData(packet->IsOrig(), s->Len(), s->Bytes());
1450 [ # # ]: 0 : delete s;
1451 : : }
1452 : 0 : }
1453 : :
1454 : 6 : static std::queue<TCP_Rewriter*> rewriter_funerals;
1455 : 6 : static std::queue<TCP_RewriterEndpoint*> rewriters_to_flush;
1456 : :
1457 : 0 : void schedule_funeral(TCP_Rewriter* rewriter)
1458 : : {
1459 : 0 : Ref(rewriter->Analyzer()->Conn());
1460 : 0 : rewriter_funerals.push(rewriter);
1461 : 0 : }
1462 : :
1463 : 0 : void schedule_flush(TCP_RewriterEndpoint* endp)
1464 : : {
1465 : 0 : Ref(endp->Analyzer()->Conn());
1466 : 0 : rewriters_to_flush.push(endp);
1467 : 0 : }
1468 : :
1469 : 42701 : void flush_rewriter_packet()
1470 : : {
1471 [ - + ]: 42701 : while ( ! rewriter_funerals.empty() )
1472 : : {
1473 : 0 : TCP_Rewriter* rewriter = rewriter_funerals.front();
1474 : 0 : rewriter_funerals.pop();
1475 : 0 : rewriter->Funeral();
1476 : 0 : Unref(rewriter->Analyzer()->Conn());
1477 : : }
1478 : :
1479 [ - + ]: 42701 : while ( ! rewriters_to_flush.empty() )
1480 : : {
1481 : 0 : TCP_RewriterEndpoint* endp = rewriters_to_flush.front();
1482 : 0 : rewriters_to_flush.pop();
1483 : :
1484 [ # # ]: 0 : if ( endp )
1485 : : {
1486 : 0 : endp->Flush();
1487 : 0 : Unref(endp->Analyzer()->Conn());
1488 : : }
1489 : : }
1490 : :
1491 [ - + ]: 42701 : if ( mgr.HasEvents() )
1492 : 0 : internal_error("flushing packets generates additional events!");
1493 : 42701 : }
1494 : :
1495 : 0 : TCP_SourcePacket::TCP_SourcePacket(const struct pcap_pkthdr* pcap_hdr, const u_char* pcap_pkt)
1496 : : {
1497 : 0 : hdr = *pcap_hdr;
1498 [ # # ][ # # ]: 0 : if ( pcap_pkt )
1499 : : {
1500 : 0 : pkt = new u_char[hdr.caplen];
1501 : 0 : memcpy(pkt, pcap_pkt, hdr.caplen);
1502 : : }
1503 : : else
1504 : : {
1505 : 0 : hdr.caplen = 0;
1506 : 0 : pkt = 0;
1507 : : }
1508 : 0 : }
1509 : :
1510 : 0 : TCP_SourcePacket::~TCP_SourcePacket()
1511 : : {
1512 [ # # ][ # # ]: 0 : delete [] pkt;
1513 : 0 : }
1514 : :
1515 : 0 : TCP_SourcePacketWriter::TCP_SourcePacketWriter(TCP_Analyzer* analyzer, PacketDumper* arg_dumper)
1516 : : {
1517 : 0 : dumper = arg_dumper;
1518 : 0 : }
1519 : :
1520 : 0 : TCP_SourcePacketWriter::~TCP_SourcePacketWriter()
1521 : : {
1522 : : // By default discard all packets of the connection
1523 : : // if they are not explicitly dumped.
1524 : 0 : Purge(false);
1525 : 0 : }
1526 : :
1527 : : void TCP_SourcePacketWriter::NextPacket(const struct pcap_pkthdr* pcap_hdr,
1528 : 0 : const u_char* pcap_pkt)
1529 : : {
1530 : 0 : source_packets.push(new TCP_SourcePacket(pcap_hdr, pcap_pkt));
1531 : 0 : }
1532 : :
1533 : 0 : void TCP_SourcePacketWriter::Purge(bool dump)
1534 : : {
1535 [ # # ]: 0 : while ( ! source_packets.empty() )
1536 : : {
1537 : 0 : TCP_SourcePacket* p = source_packets.front();
1538 [ # # ]: 0 : if ( dump )
1539 : 0 : dumper->DumpPacket(p->Hdr(), p->Pkt(), p->Len());
1540 : 0 : source_packets.pop();
1541 [ # # ]: 0 : delete p;
1542 : : }
1543 : 0 : }
1544 : :
1545 : 0 : void TCP_SourcePacketWriter::Dump()
1546 : : {
1547 : 0 : Purge(true);
1548 : 0 : }
1549 : :
1550 : 0 : void TCP_SourcePacketWriter::Abort()
1551 : : {
1552 : 0 : Purge(false);
1553 : 0 : }
1554 : :
1555 : 0 : TCP_SourcePacketWriter* get_src_pkt_writer(TCP_Analyzer* analyzer)
1556 : : {
1557 [ # # ][ # # ]: 0 : if ( ! analyzer || analyzer->Conn()->ConnTransport() != TRANSPORT_TCP )
[ # # ]
1558 : 0 : internal_error("connection for the trace rewriter does not exist");
1559 : :
1560 : 0 : TCP_SourcePacketWriter* writer = analyzer->SourcePacketWriter();
1561 [ # # ]: 0 : if ( ! writer )
1562 : : {
1563 [ # # ]: 0 : if ( ! pkt_dumper )
1564 : 0 : return 0; // don't complain if no output file
1565 [ # # ]: 0 : else if ( ! dump_selected_source_packets )
1566 : 0 : builtin_run_time("flag dump_source_packets is not set");
1567 : : else
1568 : 0 : internal_error("source packet writer not initialized");
1569 : : }
1570 : :
1571 : 0 : return writer;
1572 : : }
1573 : :
1574 : :
1575 : : #include "common-rw.bif.func_def"
|