libtins 4.5
Loading...
Searching...
No Matches
tcp_stream.h
1/*
2 * Copyright (c) 2017, Matias Fontanini
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#ifndef TINS_TCP_STREAM_H
31#define TINS_TCP_STREAM_H
32
33#include <map>
34#include <utility>
35#include <vector>
36#include <algorithm>
37#include <stdint.h>
38#include <tins/macros.h>
39#include <tins/tcp.h>
40#include <tins/ip.h>
41#include <tins/ip_address.h>
42#include <tins/utils/pdu_utils.h>
43
44#ifdef TINS_HAVE_PCAP
45
46#include <tins/sniffer.h>
47
48namespace Tins {
49class Sniffer;
50class RawPDU;
51
56class TINS_API TCPStream {
57public:
61 struct StreamInfo {
62 IPv4Address client_addr, server_addr;
63 uint16_t client_port, server_port;
64
65 StreamInfo() : client_port(0), server_port(0) {}
66
67 StreamInfo(IPv4Address client, IPv4Address server,
68 uint16_t cport, uint16_t sport);
69
70 bool operator<(const StreamInfo& rhs) const;
71 };
72
76 typedef std::vector<uint8_t> payload_type;
77
84 TCPStream(IP* ip, TCP* tcp, uint64_t identifier);
85
89 TCPStream(const TCPStream& rhs);
90
94 TCPStream& operator=(const TCPStream& rhs);
95
99 ~TCPStream();
100
108 const payload_type& client_payload() const {
109 return client_payload_;
110 }
111
119 payload_type& client_payload() {
120 return client_payload_;
121 }
122
130 const payload_type& server_payload() const {
131 return server_payload_;
132 }
133
141 payload_type& server_payload() {
142 return server_payload_;
143 }
144
149 uint64_t id() const {
150 return identifier_;
151 }
152
157 const StreamInfo& stream_info() const {
158 return info_;
159 }
160
169 bool is_finished() const {
170 return fin_sent_;
171 }
172
183 bool update(IP* ip, TCP* tcp);
184private:
185 typedef std::map<uint32_t, RawPDU*> fragments_type;
186
187 static void free_fragments(fragments_type& frags);
188 static fragments_type clone_fragments(const fragments_type& frags);
189
190 bool generic_process(uint32_t& my_seq, uint32_t& other_seq,
191 payload_type& pload, fragments_type& frags, TCP* tcp);
192
193 void safe_insert(fragments_type& frags, uint32_t seq, RawPDU* raw);
194
195
196 uint32_t client_seq_, server_seq_;
197 StreamInfo info_;
198 uint64_t identifier_;
199 payload_type client_payload_, server_payload_;
200 fragments_type client_frags_, server_frags_;
201 bool syn_ack_sent_, fin_sent_;
202};
203
204
209class TINS_API TCPStreamFollower {
210public:
214 TCPStreamFollower();
215
228 template<typename DataFunctor, typename EndFunctor>
229 void follow_streams(BaseSniffer& sniffer, DataFunctor data_fun, EndFunctor end_fun);
230
252 template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
253 void follow_streams(ForwardIterator start, ForwardIterator end,
254 DataFunctor data_fun, EndFunctor end_fun);
255
267 template<typename DataFunctor>
268 void follow_streams(BaseSniffer& sniffer, DataFunctor data_fun);
269
289 template<typename ForwardIterator, typename DataFunctor>
290 void follow_streams(ForwardIterator start, ForwardIterator end,
291 DataFunctor data_fun);
292private:
293 typedef std::map<TCPStream::StreamInfo, TCPStream> sessions_type;
294
295 template<typename DataFunctor, typename EndFunctor>
296 struct proxy_caller {
297 bool callback(PDU& pdu) {
298 return stream->callback(pdu, data_fun, end_fun);
299 }
300
301 TCPStreamFollower* stream;
302 DataFunctor data_fun;
303 EndFunctor end_fun;
304 };
305
306 template<typename DataFunctor, typename EndFunctor>
307 bool callback(PDU& pdu, const DataFunctor& fun, const EndFunctor& end_fun);
308 static void dummy_function(TCPStream&) { }
309
310 sessions_type sessions_;
311 uint64_t last_identifier_;
312};
313
314template<typename DataFunctor, typename EndFunctor>
315void TCPStreamFollower::follow_streams(BaseSniffer& sniffer,
316 DataFunctor data_fun,
317 EndFunctor end_fun) {
318 typedef proxy_caller<DataFunctor, EndFunctor> proxy_type;
319 proxy_type proxy = { this, data_fun, end_fun };
320 sniffer.sniff_loop(make_sniffer_handler(&proxy, &proxy_type::callback));
321}
322
323template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
324void TCPStreamFollower::follow_streams(ForwardIterator start,
325 ForwardIterator end,
326 DataFunctor data_fun,
327 EndFunctor end_fun) {
328 while(start != end) {
329 if (!callback(Utils::dereference_until_pdu(start), data_fun, end_fun)) {
330 return;
331 }
332 start++;
333 }
334}
335
336template<typename DataFunctor>
337void TCPStreamFollower::follow_streams(BaseSniffer& sniffer, DataFunctor data_fun) {
338 return follow_streams(sniffer, data_fun, dummy_function);
339}
340
341template<typename ForwardIterator, typename DataFunctor>
342void TCPStreamFollower::follow_streams(ForwardIterator start,
343 ForwardIterator end,
344 DataFunctor data_fun) {
345 follow_streams(start, end, data_fun, dummy_function);
346}
347
348template<typename DataFunctor, typename EndFunctor>
349bool TCPStreamFollower::callback(PDU& pdu,
350 const DataFunctor& data_fun,
351 const EndFunctor& end_fun) {
352 IP* ip = pdu.find_pdu<IP>();
353 TCP* tcp = pdu.find_pdu<TCP>();
354 if (!ip || !tcp) {
355 return true;
356 }
357 TCPStream::StreamInfo info(
358 ip->src_addr(), ip->dst_addr(),
359 tcp->sport(), tcp->dport()
360 );
361 sessions_type::iterator it = sessions_.find(info);
362 if (it == sessions_.end()) {
363 std::swap(info.client_addr, info.server_addr);
364 std::swap(info.client_port, info.server_port);
365 if ((it = sessions_.find(info)) == sessions_.end()) {
366 if (tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
367 sessions_.insert(
368 std::make_pair(
369 info,
370 TCPStream(ip, tcp, last_identifier_++)
371 )
372 );
373 }
374 return true;
375 }
376 }
377 if (it->second.update(ip, tcp)) {
378 data_fun(it->second);
379 }
380 // We're done with this stream
381 if (it->second.is_finished()) {
382 end_fun(it->second);
383 sessions_.erase(it);
384 }
385 return true;
386}
387
388} // Tins
389
390#endif // TINS_HAVE_PCAP
391
392#endif // TINS_TCP_STREAM_H
PDU & dereference_until_pdu(PDU &pdu)
Definition pdu_utils.h:61
The Tins namespace.
Definition address_range.h:38