libtins  4.5
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
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(FILE *fp, const SnifferConfiguration& configuration);
415 
421  FileSniffer(const std::string& file_name, const SnifferConfiguration& configuration);
422 
430  FileSniffer(const std::string& file_name, const std::string& filter = "");
431 
439  FileSniffer(FILE *fp, const std::string& filter = "");
440 };
441 
442 template <typename T>
443 class HandlerProxy {
444 public:
445  typedef T* ptr_type;
446  typedef bool (T::*fun_type)(PDU&) ;
447 
448  HandlerProxy(ptr_type ptr, fun_type function)
449  : object_(ptr), fun_(function) {}
450 
451  bool operator()(PDU& pdu) {
452  return (object_->*fun_)(pdu);
453  }
454 private:
455  ptr_type object_;
456  fun_type fun_;
457 };
458 
459 template <typename T>
460 HandlerProxy<T> make_sniffer_handler(T* ptr,
461  typename HandlerProxy<T>::fun_type function) {
462  return HandlerProxy<T>(ptr, function);
463 }
464 
468 class SnifferIterator {
469 public:
470  typedef std::forward_iterator_tag iterator_category;
471  typedef Packet value_type;
472  typedef std::ptrdiff_t difference_type;
473  typedef Packet* pointer;
474  typedef Packet& reference;
475 
480  SnifferIterator(BaseSniffer* sniffer = 0)
481  : sniffer_(sniffer) {
482  if (sniffer_) {
483  advance();
484  }
485  }
486 
490  SnifferIterator& operator++() {
491  advance();
492  return* this;
493  }
494 
498  SnifferIterator operator++(int) {
499  SnifferIterator other(*this);
500  advance();
501  return other;
502  }
503 
508  Packet& operator*() {
509  return pkt_;
510  }
511 
516  Packet* operator->() {
517  return &(**this);
518  }
519 
524  bool operator==(const SnifferIterator& rhs) const {
525  return sniffer_ == rhs.sniffer_;
526  }
527 
532  bool operator!=(const SnifferIterator& rhs) const {
533  return !(*this == rhs);
534  }
535 private:
536  void advance() {
537  pkt_ = sniffer_->next_packet();
538  if (!pkt_) {
539  sniffer_ = 0;
540  }
541  }
542 
543  BaseSniffer* sniffer_;
544  Packet pkt_;
545 };
546 
580 class TINS_API SnifferConfiguration {
581 public:
587  static const unsigned DEFAULT_SNAP_LEN;
588 
594  static const unsigned DEFAULT_TIMEOUT;
595 
599  SnifferConfiguration();
600 
605  void set_snap_len(unsigned snap_len);
606 
611  void set_buffer_size(unsigned buffer_size);
612 
617  void set_promisc_mode(bool enabled);
618 
623  void set_filter(const std::string& filter);
624 
629  void set_pcap_sniffing_method(BaseSniffer::PcapSniffingMethod method);
630 
635  void set_rfmon(bool enabled);
636 
641  void set_timeout(unsigned timeout);
642 
647  void set_direction(pcap_direction_t direction);
648 
653  void set_immediate_mode(bool enabled);
654 
659  void set_timestamp_precision(int value);
660 protected:
661  friend class Sniffer;
662  friend class FileSniffer;
663 
664  enum Flags {
665  BUFFER_SIZE = 1,
666  PROMISCUOUS = 2,
667  RFMON = 4,
668  PACKET_FILTER = 8,
669  IMMEDIATE_MODE = 16,
670  DIRECTION = 32,
671  TIMESTAMP_PRECISION = 64,
672  PCAP_SNIFFING_METHOD = 128,
673  };
674 
675  void configure_sniffer_pre_activation(Sniffer& sniffer) const;
676  void configure_sniffer_pre_activation(FileSniffer& sniffer) const;
677 
678  void configure_sniffer_post_activation(Sniffer& sniffer) const;
679 
680  uint32_t flags_;
681  unsigned snap_len_;
682  unsigned buffer_size_;
683  std::string filter_;
684  BaseSniffer::PcapSniffingMethod pcap_sniffing_method_;
685  unsigned timeout_;
686  bool promisc_;
687  bool rfmon_;
688  bool immediate_mode_;
689  pcap_direction_t direction_;
690  int timestamp_precision_;
691 };
692 
693 template <typename Functor>
694 void Tins::BaseSniffer::sniff_loop(Functor function, uint32_t max_packets) {
695  for(iterator it = begin(); it != end(); ++it) {
696  try {
697  // If the functor returns false, we're done
698  #if TINS_IS_CXX11 && !defined(_MSC_VER)
699  if (!Tins::Internals::invoke_loop_cb(function, *it)) {
700  return;
701  }
702  #else
703  if (!function(*it->pdu())) {
704  return;
705  }
706  #endif
707  }
708  catch(malformed_packet&) { }
709  catch(pdu_not_found&) { }
710  if (max_packets && --max_packets == 0) {
711  return;
712  }
713  }
714 }
715 
716 } // Tins
717 
718 #endif // TINS_HAVE_PCAP
719 
720 #endif // TINS_SNIFFER_H
The Tins namespace.
Definition: address_range.h:38
bool operator==(const PDUIteratorBase< Concrete > &lhs, const PDUIteratorBase< Concrete > &rhs)
Definition: pdu_iterator.h:108
PacketWrapper< PDU *, Timestamp > PtrPacket
Thin wrapper over a PDU pointer and a Timestamp.
Definition: packet.h:54
bool operator!=(const PDUIteratorBase< Concrete > &lhs, const PDUIteratorBase< Concrete > &rhs)
Definition: pdu_iterator.h:121