libtins  4.0
sniffer.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 
31 #ifndef TINS_SNIFFER_H
32 #define TINS_SNIFFER_H
33 
34 #include <string>
35 #include <memory>
36 #include <iterator>
37 #include <tins/pdu.h>
38 #include <tins/packet.h>
39 #include <tins/cxxstd.h>
40 #include <tins/macros.h>
41 #include <tins/exceptions.h>
42 #include <tins/detail/type_traits.h>
43 
44 #ifdef TINS_HAVE_PCAP
45 
46 #include <pcap.h>
47 
48 
49 namespace Tins {
50 class SnifferIterator;
51 class SnifferConfiguration;
52 
63 class TINS_API BaseSniffer {
64 public:
68  typedef SnifferIterator iterator;
69 
70  #if TINS_IS_CXX11
71 
75  BaseSniffer(BaseSniffer &&rhs) TINS_NOEXCEPT
76  : handle_(0), mask_(), extract_raw_(false),
77  pcap_sniffing_method_(pcap_loop) {
78  *this = std::move(rhs);
79  }
80 
85  BaseSniffer& operator=(BaseSniffer &&rhs) TINS_NOEXCEPT {
86  using std::swap;
87  swap(handle_, rhs.handle_);
88  swap(mask_, rhs.mask_);
89  swap(extract_raw_, rhs.extract_raw_);
90  swap(pcap_sniffing_method_, rhs.pcap_sniffing_method_);
91  return* this;
92  }
93  #endif
94 
99  virtual ~BaseSniffer();
100 
134  PtrPacket next_packet();
135 
188  template <typename Functor>
189  void sniff_loop(Functor function, uint32_t max_packets = 0);
190 
196  bool set_filter(const std::string& filter);
197 
204  void stop_sniff();
205 
209  int get_fd();
210 
217  bool set_direction(pcap_direction_t d);
218 
225  void set_timeout(int ms);
226 
241  void set_extract_raw_pdus(bool value);
242 
254  typedef int(*PcapSniffingMethod)(pcap_t*, int, pcap_handler, u_char*);
255 
270  void set_pcap_sniffing_method(PcapSniffingMethod method);
271 
278  int link_type() const;
279 
283  iterator begin();
284 
288  iterator end();
289 
293  pcap_t* get_pcap_handle();
294 
298  const pcap_t* get_pcap_handle() const;
299 protected:
303  BaseSniffer();
304 
305  void set_pcap_handle(pcap_t* pcap_handle);
306 
307  void set_if_mask(bpf_u_int32 if_mask);
308 
309  bpf_u_int32 get_if_mask() const;
310 private:
311  BaseSniffer(const BaseSniffer&);
312  BaseSniffer& operator=(const BaseSniffer&);
313 
314  pcap_t* handle_;
315  bpf_u_int32 mask_;
316  bool extract_raw_;
317  PcapSniffingMethod pcap_sniffing_method_;
318 };
319 
324 class TINS_API Sniffer : public BaseSniffer {
325 public:
330  enum promisc_type {
331  NON_PROMISC,
332  PROMISC
333  };
334 
340  Sniffer(const std::string& device);
341 
353  Sniffer(const std::string& device, const SnifferConfiguration& configuration);
354 
369  TINS_DEPRECATED(Sniffer(const std::string& device, unsigned max_packet_size,
370  bool promisc = false, const std::string& filter = "", bool rfmon = false));
371 
385  TINS_DEPRECATED(Sniffer(const std::string& device, promisc_type promisc,
386  const std::string& filter = "", bool rfmon = false));
387 
388 private:
389  friend class SnifferConfiguration;
390 
391  void init(const std::string& device, const SnifferConfiguration& configuration);
392  void set_snap_len(unsigned snap_len);
393  void set_buffer_size(unsigned buffer_size);
394  void set_promisc_mode(bool promisc_enabled);
395  void set_rfmon(bool rfmon_enabled);
396  void set_immediate_mode(bool enabled);
397  void set_timestamp_precision(int value);
398 };
399 
407 class TINS_API FileSniffer : public BaseSniffer {
408 public:
414  FileSniffer(const std::string& file_name, const SnifferConfiguration& configuration);
415 
423  FileSniffer(const std::string& file_name, const std::string& filter = "");
424 };
425 
426 template <typename T>
427 class HandlerProxy {
428 public:
429  typedef T* ptr_type;
430  typedef bool (T::*fun_type)(PDU&) ;
431 
432  HandlerProxy(ptr_type ptr, fun_type function)
433  : object_(ptr), fun_(function) {}
434 
435  bool operator()(PDU& pdu) {
436  return (object_->*fun_)(pdu);
437  }
438 private:
439  ptr_type object_;
440  fun_type fun_;
441 };
442 
443 template <typename T>
444 HandlerProxy<T> make_sniffer_handler(T* ptr,
445  typename HandlerProxy<T>::fun_type function) {
446  return HandlerProxy<T>(ptr, function);
447 }
448 
452 class SnifferIterator : public std::iterator<std::forward_iterator_tag, Packet> {
453 public:
458  SnifferIterator(BaseSniffer* sniffer = 0)
459  : sniffer_(sniffer) {
460  if (sniffer_) {
461  advance();
462  }
463  }
464 
468  SnifferIterator& operator++() {
469  advance();
470  return* this;
471  }
472 
476  SnifferIterator operator++(int) {
477  SnifferIterator other(*this);
478  advance();
479  return other;
480  }
481 
486  Packet& operator*() {
487  return pkt_;
488  }
489 
494  Packet* operator->() {
495  return &(**this);
496  }
497 
502  bool operator==(const SnifferIterator& rhs) const {
503  return sniffer_ == rhs.sniffer_;
504  }
505 
510  bool operator!=(const SnifferIterator& rhs) const {
511  return !(*this == rhs);
512  }
513 private:
514  void advance() {
515  pkt_ = sniffer_->next_packet();
516  if (!pkt_) {
517  sniffer_ = 0;
518  }
519  }
520 
521  BaseSniffer* sniffer_;
522  Packet pkt_;
523 };
524 
558 class TINS_API SnifferConfiguration {
559 public:
565  static const unsigned DEFAULT_SNAP_LEN;
566 
572  static const unsigned DEFAULT_TIMEOUT;
573 
577  SnifferConfiguration();
578 
583  void set_snap_len(unsigned snap_len);
584 
589  void set_buffer_size(unsigned buffer_size);
590 
595  void set_promisc_mode(bool enabled);
596 
601  void set_filter(const std::string& filter);
602 
607  void set_pcap_sniffing_method(BaseSniffer::PcapSniffingMethod method);
608 
613  void set_rfmon(bool enabled);
614 
619  void set_timeout(unsigned timeout);
620 
625  void set_direction(pcap_direction_t direction);
626 
631  void set_immediate_mode(bool enabled);
632 
637  void set_timestamp_precision(int value);
638 protected:
639  friend class Sniffer;
640  friend class FileSniffer;
641 
642  enum Flags {
643  BUFFER_SIZE = 1,
644  PROMISCUOUS = 2,
645  RFMON = 4,
646  PACKET_FILTER = 8,
647  IMMEDIATE_MODE = 16,
648  DIRECTION = 32,
649  TIMESTAMP_PRECISION = 64,
650  PCAP_SNIFFING_METHOD = 128,
651  };
652 
653  void configure_sniffer_pre_activation(Sniffer& sniffer) const;
654  void configure_sniffer_pre_activation(FileSniffer& sniffer) const;
655 
656  void configure_sniffer_post_activation(Sniffer& sniffer) const;
657 
658  uint32_t flags_;
659  unsigned snap_len_;
660  unsigned buffer_size_;
661  std::string filter_;
662  BaseSniffer::PcapSniffingMethod pcap_sniffing_method_;
663  unsigned timeout_;
664  bool promisc_;
665  bool rfmon_;
666  bool immediate_mode_;
667  pcap_direction_t direction_;
668  int timestamp_precision_;
669 };
670 
671 template <typename Functor>
672 void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
673  for(iterator it = begin(); it != end(); ++it) {
674  try {
675  // If the functor returns false, we're done
676  #if TINS_IS_CXX11 && !defined(_MSC_VER)
677  if (!Tins::Internals::invoke_loop_cb(function, *it)) {
678  return;
679  }
680  #else
681  if (!function(*it->pdu())) {
682  return;
683  }
684  #endif
685  }
686  catch(malformed_packet&) { }
687  catch(pdu_not_found&) { }
688  if (max_packets && --max_packets == 0) {
689  return;
690  }
691  }
692 }
693 
694 } // Tins
695 
696 #endif // TINS_HAVE_PCAP
697 
698 #endif // TINS_SNIFFER_H
bool operator==(const PDUIteratorBase< Concrete > &lhs, const PDUIteratorBase< Concrete > &rhs)
Definition: pdu_iterator.h:108
The Tins namespace.
Definition: address_range.h:38
bool operator!=(const PDUIteratorBase< Concrete > &lhs, const PDUIteratorBase< Concrete > &rhs)
Definition: pdu_iterator.h:121
PacketWrapper< PDU *, Timestamp > PtrPacket
Thin wrapper over a PDU pointer and a Timestamp.
Definition: packet.h:54