libtins  3.4
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
tcp_stream.h
1 /*
2  * Copyright (c) 2016, 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 <iterator>
36 #include <vector>
37 #include <algorithm>
38 #include <stdint.h>
39 #include "sniffer.h"
40 #include "macros.h"
41 #include "tcp.h"
42 #include "utils.h"
43 #include "ip.h"
44 #include "ip_address.h"
45 
46 namespace Tins {
47 class Sniffer;
48 class RawPDU;
49 
54 class TINS_API TCPStream {
55 public:
59  struct StreamInfo {
60  IPv4Address client_addr, server_addr;
61  uint16_t client_port, server_port;
62 
63  StreamInfo() : client_port(0), server_port(0) {}
64 
65  StreamInfo(IPv4Address client, IPv4Address server,
66  uint16_t cport, uint16_t sport);
67 
68  bool operator<(const StreamInfo& rhs) const;
69  };
70 
74  typedef std::vector<uint8_t> payload_type;
75 
82  TCPStream(IP* ip, TCP* tcp, uint64_t identifier);
83 
87  TCPStream(const TCPStream& rhs);
88 
92  TCPStream& operator=(const TCPStream& rhs);
93 
97  ~TCPStream();
98 
106  const payload_type& client_payload() const {
107  return client_payload_;
108  }
109 
118  return client_payload_;
119  }
120 
128  const payload_type& server_payload() const {
129  return server_payload_;
130  }
131 
140  return server_payload_;
141  }
142 
147  uint64_t id() const {
148  return identifier_;
149  }
150 
155  const StreamInfo& stream_info() const {
156  return info_;
157  }
158 
167  bool is_finished() const {
168  return fin_sent_;
169  }
170 
181  bool update(IP* ip, TCP* tcp);
182 private:
183  typedef std::map<uint32_t, RawPDU*> fragments_type;
184 
185  static void free_fragments(fragments_type& frags);
186  static fragments_type clone_fragments(const fragments_type& frags);
187 
188  bool generic_process(uint32_t& my_seq, uint32_t& other_seq,
189  payload_type& pload, fragments_type& frags, TCP* tcp);
190 
191  void safe_insert(fragments_type& frags, uint32_t seq, RawPDU* raw);
192 
193 
194  uint32_t client_seq_, server_seq_;
195  StreamInfo info_;
196  uint64_t identifier_;
197  payload_type client_payload_, server_payload_;
198  fragments_type client_frags_, server_frags_;
199  bool syn_ack_sent_, fin_sent_;
200 };
201 
202 
207 class TINS_API TCPStreamFollower {
208 public:
213 
226  template<typename DataFunctor, typename EndFunctor>
227  void follow_streams(BaseSniffer& sniffer, DataFunctor data_fun, EndFunctor end_fun);
228 
250  template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
251  void follow_streams(ForwardIterator start, ForwardIterator end,
252  DataFunctor data_fun, EndFunctor end_fun);
253 
265  template<typename DataFunctor>
266  void follow_streams(BaseSniffer& sniffer, DataFunctor data_fun);
267 
287  template<typename ForwardIterator, typename DataFunctor>
288  void follow_streams(ForwardIterator start, ForwardIterator end,
289  DataFunctor data_fun);
290 private:
291  typedef std::map<TCPStream::StreamInfo, TCPStream> sessions_type;
292 
293  template<typename DataFunctor, typename EndFunctor>
294  struct proxy_caller {
295  bool callback(PDU& pdu) {
296  return stream->callback(pdu, data_fun, end_fun);
297  }
298 
299  TCPStreamFollower* stream;
300  DataFunctor data_fun;
301  EndFunctor end_fun;
302  };
303 
304  template<typename DataFunctor, typename EndFunctor>
305  bool callback(PDU& pdu, const DataFunctor& fun, const EndFunctor& end_fun);
306  static void dummy_function(TCPStream&) { }
307 
308  sessions_type sessions_;
309  uint64_t last_identifier_;
310 };
311 
312 template<typename DataFunctor, typename EndFunctor>
314  DataFunctor data_fun,
315  EndFunctor end_fun) {
316  typedef proxy_caller<DataFunctor, EndFunctor> proxy_type;
317  proxy_type proxy = { this, data_fun, end_fun };
318  sniffer.sniff_loop(make_sniffer_handler(&proxy, &proxy_type::callback));
319 }
320 
321 template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
322 void TCPStreamFollower::follow_streams(ForwardIterator start,
323  ForwardIterator end,
324  DataFunctor data_fun,
325  EndFunctor end_fun) {
326  while(start != end) {
327  if (!callback(Utils::dereference_until_pdu(start), data_fun, end_fun)) {
328  return;
329  }
330  start++;
331  }
332 }
333 
334 template<typename DataFunctor>
335 void TCPStreamFollower::follow_streams(BaseSniffer& sniffer, DataFunctor data_fun) {
336  return follow_streams(sniffer, data_fun, dummy_function);
337 }
338 
339 template<typename ForwardIterator, typename DataFunctor>
340 void TCPStreamFollower::follow_streams(ForwardIterator start,
341  ForwardIterator end,
342  DataFunctor data_fun) {
343  follow_streams(start, end, data_fun, dummy_function);
344 }
345 
346 template<typename DataFunctor, typename EndFunctor>
347 bool TCPStreamFollower::callback(PDU& pdu,
348  const DataFunctor& data_fun,
349  const EndFunctor& end_fun) {
350  IP* ip = pdu.find_pdu<IP>();
351  TCP* tcp = pdu.find_pdu<TCP>();
352  if (!ip || !tcp) {
353  return true;
354  }
355  TCPStream::StreamInfo info(
356  ip->src_addr(), ip->dst_addr(),
357  tcp->sport(), tcp->dport()
358  );
359  sessions_type::iterator it = sessions_.find(info);
360  if (it == sessions_.end()) {
361  std::swap(info.client_addr, info.server_addr);
362  std::swap(info.client_port, info.server_port);
363  if ((it = sessions_.find(info)) == sessions_.end()) {
364  if (tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
365  sessions_.insert(
366  std::make_pair(
367  info,
368  TCPStream(ip, tcp, last_identifier_++)
369  )
370  );
371  }
372  return true;
373  }
374  }
375  if (it->second.update(ip, tcp)) {
376  data_fun(it->second);
377  }
378  // We're done with this stream
379  if (it->second.is_finished()) {
380  end_fun(it->second);
381  sessions_.erase(it);
382  }
383  return true;
384 }
385 
386 } // Tins
387 
388 #endif // TINS_TCP_STREAM_H
const payload_type & client_payload() const
Retrieves the client payload.
Definition: tcp_stream.h:106
address_type src_addr() const
Getter for the source address field.
Definition: ip.h:388
void follow_streams(BaseSniffer &sniffer, DataFunctor data_fun, EndFunctor end_fun)
Starts following TCP streams.
Definition: tcp_stream.h:313
Represents a TCP PDU.
Definition: tcp.h:79
Class that represents an IP PDU.
Definition: ip.h:64
Base class for sniffers.
Definition: sniffer.h:61
Represents a TCP stream.
Definition: tcp_stream.h:54
std::vector< uint8_t > payload_type
Definition: tcp_stream.h:74
const payload_type & server_payload() const
Retrieves the server payload.
Definition: tcp_stream.h:128
T * find_pdu(PDUType type=T::pdu_flag)
Finds and returns the first PDU that matches the given flag.
Definition: pdu.h:339
PDU & dereference_until_pdu(PDU &pdu)
Definition: utils.h:309
uint64_t id() const
Retrieves this stream's identification number.
Definition: tcp_stream.h:147
payload_type & server_payload()
Retrieves the server payload.
Definition: tcp_stream.h:139
bool is_finished() const
Checks whether this stream is finished.
Definition: tcp_stream.h:167
payload_type & client_payload()
Retrieves the client payload.
Definition: tcp_stream.h:117
void sniff_loop(Functor function, uint32_t max_packets=0)
Starts a sniffing loop, using a callback functor for every sniffed packet.
Definition: sniffer.h:619
Abstraction of an IPv4 address.
Definition: ip_address.h:44
const StreamInfo & stream_info() const
Retrieves the stream information.
Definition: tcp_stream.h:155
address_type dst_addr() const
Getter for the destination address field.
Definition: ip.h:396
Definition: rawpdu.h:64
Follows TCP streams and notifies the user when data is available.
Definition: tcp_stream.h:207
Definition: tcp_stream.h:59
Base class for protocol data units.
Definition: pdu.h:108