Branch data Line data Source code
1 : : // $Id: TCP_Rewriter.h 6916 2009-09-24 20:48:36Z vern $
2 : :
3 : : #ifndef tcp_rewriter_h
4 : : #define tcp_rewriter_h
5 : :
6 : : #include <queue>
7 : : #include <set>
8 : : using namespace std;
9 : :
10 : : #include <pcap.h>
11 : :
12 : : #include "Val.h"
13 : : #include "TCP.h"
14 : : #include "Anon.h"
15 : : #include "Analyzer.h"
16 : :
17 : : #include "PacketDumper.h"
18 : : #include "Rewriter.h"
19 : :
20 : : class TCP_Rewriter;
21 : :
22 : : class TCP_TracePacket : public BroObj, virtual public TracePacket {
23 : : public:
24 : : TCP_TracePacket(TCP_Rewriter* trace_rewriter,
25 : : int packet_seq, double t, int is_orig,
26 : : const struct pcap_pkthdr* hdr,
27 : : int MTU, int initial_size);
28 : : ~TCP_TracePacket();
29 : :
30 : : int AppendLinkHeader(const u_char* chunk, int len);
31 : : int AppendIPHeader(const u_char* chunk, int len);
32 : : int AppendTCPHeader(const u_char* chunk, int len);
33 : : int AppendData(const u_char* chunk, int len);
34 : :
35 : : // Finish() is called before dumping the packet. It sets length
36 : : // fields and computes checksums in TCP/IP headers.
37 : : int Finish(struct pcap_pkthdr*& hdr, const u_char*& pkt, int& length,
38 : : ipaddr32_t anon_src, ipaddr32_t anon_dst);
39 : :
40 : : void Reuse();
41 : 0 : int IsReuse() const { return reuse; }
42 : :
43 : 0 : double TimeStamp() const { return timestamp; }
44 : 0 : int IsOrig() const { return is_orig; }
45 : :
46 : : const struct pcap_pkthdr* Header() const { return &pcap_hdr; }
47 : :
48 : : const u_char* Buffer() const { return pkt; }
49 : : int Length() const { return buffer_offset; }
50 : :
51 : : // Note that Space() does not depend on buffer_size, but depends on MTU.
52 : 0 : int Space() const { return mtu - buffer_offset; }
53 : 0 : int IsEmpty() const
54 [ # # ][ # # ]: 0 : { return SeqLength() == 0 && ! GetTCP_Flag(TH_RST); }
55 : :
56 : : uint32 GetSeq() const;
57 : : void SetSeq(uint32 seq);
58 : :
59 : : uint32 GetAck() const;
60 : : void SetAck(uint32 ack);
61 : :
62 : : int GetTCP_Flag(int which) const;
63 : : void SetTCP_Flag(int which, int value);
64 : :
65 : : int SeqLength() const;
66 : : int PayloadLength() const;
67 : :
68 : 0 : int FINScheduled() const { return FIN_scheduled; }
69 : 0 : void ScheduleFIN(int fin = 1) { FIN_scheduled = fin; }
70 : :
71 : 0 : int OnHold() const { return on_hold; }
72 : 0 : void SetOnHold(int x) { on_hold = x; }
73 : :
74 : 0 : int HasReservedSlot() const { return has_reserved_slot; }
75 : 0 : void AddReservedSlot() { ++has_reserved_slot; }
76 : :
77 : 0 : int PredictedAsEmptyPlaceHolder() const
78 : 0 : { return predicted_as_empty_place_holder; }
79 : : void PredictAsEmptyPlaceHolder()
80 : : { predicted_as_empty_place_holder = 1; }
81 : :
82 : : // Whether the ACK on this packet confirms a content gap on
83 : : // the opposite direction.
84 : 0 : int SeqGap() const { return seq_gap; }
85 : 0 : void SetSeqGap(int len) { seq_gap = len; }
86 : :
87 : 0 : int PacketSeq() const { return packet_seq; }
88 : 0 : TCP_Rewriter* TraceRewriter() const { return trace_rewriter; }
89 : :
90 : : RecordVal* PacketVal();
91 : 0 : void Describe(ODesc* d) const { packet_val->Describe(d); }
92 : :
93 : : protected:
94 : : int Append(const u_char* chunk, int len);
95 : :
96 : : RecordVal* packet_val;
97 : : TCP_Rewriter* trace_rewriter;
98 : : double timestamp;
99 : : int packet_seq;
100 : : int is_orig;
101 : : struct pcap_pkthdr pcap_hdr;
102 : : int mtu;
103 : : u_char* pkt; // of maximal length MTU
104 : : int ip_offset, tcp_offset, data_offset;
105 : : int buffer_size;
106 : : int buffer_offset;
107 : : int reuse; // whether it is an artificially replicated packet
108 : : int FIN_scheduled;
109 : : int on_hold; // do not dump it in Flush()
110 : : int seq_gap;
111 : : int has_reserved_slot;
112 : : int predicted_as_empty_place_holder;
113 : : };
114 : :
115 : : // How a unidirectional flow ends.
116 : : #define END_BY_FIN 1
117 : : #define END_BY_RST 2
118 : : #define END_BY_PEER_RST 4
119 : :
120 : : class TCP_RewriterEndpoint {
121 : : public:
122 : : TCP_RewriterEndpoint(TCP_Rewriter* rewriter);
123 : : ~TCP_RewriterEndpoint();
124 : :
125 : : void Init();
126 : :
127 : : // A packet that contains a TCP segment.
128 : : void NextPacket(TCP_TracePacket* p);
129 : : void WriteData(int len, const u_char* data);
130 : : void SkipGap(int len);
131 : :
132 : : void Push();
133 : : void ReqAck();
134 : : void Flush();
135 : : void Reset(int self);
136 : :
137 : 0 : uint32 NextSeq() const { return next_seq; }
138 : 0 : int HasPacket() const { return next_packet != 0; }
139 : : inline TCP_Analyzer* Analyzer() const;
140 : :
141 : : protected:
142 : : TCP_Rewriter* rewriter; // TCP rewriter for the connection
143 : : TCP_RewriterEndpoint* peer; // the peer TCP rewriter endpoint
144 : : TCP_Endpoint* endp; // the corresponding TCP endpoint
145 : :
146 : : TCP_TracePacket* next_packet;
147 : : std::queue<BroString*> prolog;
148 : :
149 : : double last_packet_time;
150 : : uint32 start_seq; // start seq -- sent in SYN
151 : : uint32 next_seq; // seq of next packet
152 : : uint32 last_ack; // last acknowledgement seq
153 : :
154 : : int please_flush;
155 : : int flush_scheduled;
156 : : int flushed;
157 : : int established;
158 : : int end_of_data; // is it really useful?
159 : : int there_is_a_gap;
160 : :
161 : : // Move onto the next packet header.
162 : : void SetNextPacket(TCP_TracePacket* p);
163 : :
164 : : void PurgeProlog();
165 : :
166 : : // Pour data into the current packet (next_packet).
167 : : void DoWriteData(int len, const u_char* data);
168 : :
169 : : // Push the current packet (next_packet) to dumper.
170 : : void PushPacket();
171 : :
172 : : // Please flush this endpoint after draining events.
173 : : void ScheduleFlush();
174 : :
175 : : void GenerateFIN();
176 : :
177 : : // Whether the packet is a "place holder" packet, i.e. it's
178 : : // harmless to omit the packet (except missing the timestamp
179 : : // it contains).
180 : : int IsPlaceHolderPacket(TCP_TracePacket* p);
181 : :
182 : : void Weird(const char* name) const;
183 : : };
184 : :
185 : 0 : class TCP_RewriteSlot {
186 : : public:
187 : : TCP_RewriteSlot(TCP_TracePacket* p, unsigned int slot_number);
188 : :
189 : : void WriteData(int is_orig, int len, const u_char* data);
190 : :
191 : : void Dump();
192 : :
193 : 0 : unsigned int Number() const { return slot_number; }
194 : 0 : TCP_TracePacket* Packet() const { return packet; }
195 : :
196 : 0 : bool isEmpty() const { return buf.empty(); }
197 : : protected:
198 : : TCP_Rewriter* rewriter;
199 : : TCP_TracePacket* packet;
200 : : unsigned int slot_number;
201 : : std::queue<BroString*> buf;
202 : : };
203 : :
204 : : class TCP_Rewriter : public Rewriter {
205 : : public:
206 : : TCP_Rewriter(TCP_Analyzer* analyzer, PacketDumper* dumper, int MTU,
207 : : int wait_for_commitment = 0);
208 : : virtual ~TCP_Rewriter();
209 : : virtual void Done();
210 : : void Funeral();
211 : :
212 : : // Phase 1 methods: called in packet processing.
213 : :
214 : : // A TCP/IP packet.
215 : : void NextPacket(int is_orig, double t,
216 : : const struct pcap_pkthdr* pcap_hdr,
217 : : const u_char* pcap_pkt, // link level header
218 : : int hdr_size, // link level header size
219 : : const struct ip* ip,
220 : : const struct tcphdr* tp);
221 : : void ContentGap(int is_orig, int len);
222 : : void ScheduleFIN(int is_orig);
223 : :
224 : :
225 : : // Phase 2 methods: called in event processing.
226 : :
227 : : void WriteData(int is_orig, int len, const u_char* data);
228 : 0 : void WriteData(int is_orig, const char* data)
229 : 0 : { WriteData(is_orig, strlen(data), data); }
230 : 0 : void WriteData(int is_orig, int len, const char* data)
231 : 0 : { WriteData(is_orig, len, (const u_char*) data); }
232 : 0 : void WriteData(int is_orig, const BroString* str)
233 : 0 : { WriteData(is_orig, str->Len(), str->Bytes()); }
234 : : void WriteData(int is_orig, StringVal* str)
235 : : { WriteData(is_orig, str->AsString()); }
236 : : void Push(int is_orig);
237 : :
238 : : // When wait_for_commitment = 1, packets are not dumped until
239 : : // CommitPackets().
240 : : // When apply_to_future = 1, the same decision holds for future
241 : : // packets as well.
242 : : //
243 : : // Regarding why AbortPackets() takes an apply_to_future flag:
244 : : //
245 : : // The model is that there can be multiple commit/abort stages
246 : : // during the course of a connection. At the end of each
247 : : // stage, a commit or abort decision is made for packets
248 : : // generated during the stage. A possible scenario is that
249 : : // user may want to delete a middle part of a conversation
250 : : // while keeping the parts before and after intact, and cannot
251 : : // make the decision until the end of the middle part.
252 : :
253 : : void AbortPackets(int apply_to_future);
254 : : void CommitPackets(int apply_to_future);
255 : :
256 : : unsigned int ReserveSlot();
257 : : int SeekSlot(unsigned int slot);
258 : : int ReturnFromSlot();
259 : : int ReleaseSlot(unsigned int slot);
260 : :
261 : : // Do not anonymize client/server IP address
262 : : int LeaveAddrInTheClear(int is_orig);
263 : :
264 : :
265 : : // Phase 3 methods: called in flushing after events.
266 : : // (None, because flushing is done through accessing endpoints directly.)
267 : :
268 : : // Other methods.
269 : :
270 : : void DumpPacket(TCP_RewriterEndpoint* endp, TCP_TracePacket* p);
271 : :
272 : : void Weird(const char* name) const { analyzer->Weird(name); }
273 : 0 : TCP_Analyzer* Analyzer() const { return analyzer; }
274 : :
275 : : TCP_Endpoint* GetEndpoint(TCP_RewriterEndpoint* endp);
276 : : TCP_RewriterEndpoint* GetPeer(TCP_RewriterEndpoint* endp);
277 : :
278 [ # # ]: 0 : TracePacket* CurrentPacket() const { return current_packet; }
279 [ # # ]: 0 : TracePacket* RewritePacket() const { return next_packet; }
280 : :
281 : : // Needs to be static because it's passed as a pointer-to-function
282 : : // rather than pointer-to-member-function.
283 : : static int RewriteTCPOption(unsigned int opt, unsigned int optlen,
284 : : const u_char* option, TCP_Analyzer* analyzer,
285 : : bool is_orig, void* cookie);
286 : :
287 : : protected:
288 : : // Under normal circumstances, we always rewrite into the
289 : : // "current packet" of the connection. However, sometimes we'd
290 : : // want to look a few packets ahead before deciding what to
291 : : // rewrite, in which case we may use {hold,release}_packet to
292 : : // specify the packet we are writing to.
293 : :
294 : : // rewrite_packet (next_packet) always equals to
295 : : // current_packet under *normal mode*. hold_packet(p) dumps
296 : : // all packets *before* p, fixes rewrite_packet at p and turns
297 : : // the connection into *look-ahead* mode. Under look-ahead
298 : : // mode, release_packet(c) dumps all packets of on hold
299 : : // connection and makes the connection returns to normal mode
300 : : // so that rewrite_packet changes along with current_packet.
301 : :
302 : : // When a packet is held, it is illegal to write to packets on
303 : : // the other half of the connection.
304 : :
305 : : // Release next_packet
306 : : void ReleaseNextPacket();
307 : :
308 : : // Hold packet p and release all packets before p.
309 : : void HoldPacket(TCP_TracePacket* p);
310 : :
311 : : // Release all packets on hold and dump all the packets except
312 : : // the last one, which will be flushed at the end of the event.
313 : : void ReleasePacketsOnHold();
314 : :
315 : : void CleanUpEmptyPlaceHolders();
316 : : void DoWriteData(int is_orig, int len, const u_char* data);
317 : :
318 : 0 : TCP_RewriterEndpoint* Endp(int is_orig) const
319 [ # # ]: 0 : { return is_orig ? orig : resp; }
320 : :
321 : : TCP_Analyzer* analyzer;
322 : : PacketDumper* dumper;
323 : : TCP_RewriterEndpoint* orig;
324 : : TCP_RewriterEndpoint* resp;
325 : : int MTU;
326 : : int wait_for_commitment;
327 : : int discard_packets;
328 : : std::queue<char*> uncommited_packet_queue;
329 : : int next_packet_seq;
330 : : int packets_rewritten;
331 : : ipaddr32_t anon_addr[2];
332 : : int pending_content_gap;
333 : :
334 : : TCP_TracePacket* current_packet;
335 : : TCP_TracePacket* next_packet;
336 : : std::deque<TCP_TracePacket*> packets_on_hold;
337 : : int holding_packets;
338 : :
339 : : TCP_RewriteSlot* current_slot;
340 : : TCP_RewriteSlot* first_slot;
341 : : TCP_RewriteSlot* last_slot;
342 : : std::deque<TCP_RewriteSlot*> slot_queue;
343 : : typedef map<unsigned int, TCP_RewriteSlot*> slot_map_t;
344 : : slot_map_t reserved_slots;
345 : : int highest_slot_number;
346 : :
347 : : TCP_RewriteSlot* add_slot();
348 : : TCP_RewriteSlot* find_slot(unsigned int slot);
349 : :
350 : : friend class TCP_RewriteSlot;
351 : : int answered[2];
352 : : };
353 : :
354 : 0 : inline TCP_Analyzer* TCP_RewriterEndpoint::Analyzer() const
355 : : {
356 : 0 : return rewriter->Analyzer();
357 : : }
358 : :
359 : : // "Please flush the rewriter endpoint after event processing."
360 : : extern void schedule_flush(TCP_RewriterEndpoint* endp);
361 : :
362 : : // "Please call rewriter->Funeral() after event processing."
363 : : extern void schedule_funeral(TCP_Rewriter* rewriter);
364 : :
365 : : extern void flush_rewriter_packet();
366 : :
367 : : class TCP_SourcePacket {
368 : : public:
369 : : TCP_SourcePacket(const struct pcap_pkthdr* pcap_hdr, const u_char* pcap_pkt);
370 : : ~TCP_SourcePacket();
371 : :
372 : 0 : int Len() const { return hdr.caplen; }
373 : 0 : const u_char* Pkt() const { return pkt; }
374 : 0 : const struct pcap_pkthdr* Hdr() const { return &hdr; }
375 : :
376 : : protected:
377 : : struct pcap_pkthdr hdr;
378 : : u_char* pkt;
379 : : };
380 : :
381 : : // Write selected original packets to the trace
382 : : class TCP_SourcePacketWriter {
383 : : public:
384 : : TCP_SourcePacketWriter(TCP_Analyzer* /* analyzer */,
385 : : PacketDumper* arg_dumper);
386 : : ~TCP_SourcePacketWriter();
387 : :
388 : : void NextPacket(const struct pcap_pkthdr* pcap_hdr,
389 : : const u_char* pcap_pkt);
390 : : void Dump();
391 : : void Abort();
392 : :
393 : : protected:
394 : : PacketDumper* dumper;
395 : : std::queue<TCP_SourcePacket*> source_packets;
396 : : void Purge(bool dump);
397 : : };
398 : :
399 : : extern TCP_SourcePacketWriter* get_src_pkt_writer(TCP_Analyzer* analyzer);
400 : :
401 : : #endif
|