libtins 4.4
Loading...
Searching...
No Matches
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
49namespace Tins {
50class SnifferIterator;
51class SnifferConfiguration;
52
63class TINS_API BaseSniffer {
64public:
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;
299protected:
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;
310private:
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
324class TINS_API Sniffer : public BaseSniffer {
325public:
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
388private:
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
407class TINS_API FileSniffer : public BaseSniffer {
408public:
414 FileSniffer(const std::string& file_name, const SnifferConfiguration& configuration);
415
423 FileSniffer(const std::string& file_name, const std::string& filter = "");
424};
425
426template <typename T>
427class HandlerProxy {
428public:
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 }
438private:
439 ptr_type object_;
440 fun_type fun_;
441};
442
443template <typename T>
444HandlerProxy<T> make_sniffer_handler(T* ptr,
445 typename HandlerProxy<T>::fun_type function) {
446 return HandlerProxy<T>(ptr, function);
447}
448
452class SnifferIterator : public std::iterator<std::forward_iterator_tag, Packet> {
453public:
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 }
513private:
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
558class TINS_API SnifferConfiguration {
559public:
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);
638protected:
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
671template <typename Functor>
672void 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
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