libtins  4.0
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 
48 namespace Tins {
49 class Sniffer;
50 class RawPDU;
51 
56 class TINS_API TCPStream {
57 public:
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);
184 private:
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 
209 class TINS_API TCPStreamFollower {
210 public:
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);
292 private:
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 
314 template<typename DataFunctor, typename EndFunctor>
315 void 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 
323 template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
324 void 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 
336 template<typename DataFunctor>
337 void TCPStreamFollower::follow_streams(BaseSniffer& sniffer, DataFunctor data_fun) {
338  return follow_streams(sniffer, data_fun, dummy_function);
339 }
340 
341 template<typename ForwardIterator, typename DataFunctor>
342 void TCPStreamFollower::follow_streams(ForwardIterator start,
343  ForwardIterator end,
344  DataFunctor data_fun) {
345  follow_streams(start, end, data_fun, dummy_function);
346 }
347 
348 template<typename DataFunctor, typename EndFunctor>
349 bool 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