libtins 4.5
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(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
442template <typename T>
443class HandlerProxy {
444public:
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 }
454private:
455 ptr_type object_;
456 fun_type fun_;
457};
458
459template <typename T>
460HandlerProxy<T> make_sniffer_handler(T* ptr,
461 typename HandlerProxy<T>::fun_type function) {
462 return HandlerProxy<T>(ptr, function);
463}
464
468class SnifferIterator {
469public:
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 }
535private:
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
580class TINS_API SnifferConfiguration {
581public:
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);
660protected:
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
693template <typename Functor>
694void 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