blob: 50ab50586abd883363a0af32f97e06177a80538d [file] [log] [blame]
Davide Pesaventofe0580c2017-05-12 02:02:10 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento264af772021-02-09 21:48:24 -05002/*
Davide Pesaventoa599d2a2022-02-16 18:52:43 -05003 * Copyright (c) 2014-2022, Regents of the University of California,
Davide Pesaventofe0580c2017-05-12 02:02:10 -04004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#ifndef NFD_DAEMON_FACE_PCAP_HELPER_HPP
27#define NFD_DAEMON_FACE_PCAP_HELPER_HPP
28
29#include "core/common.hpp"
30
Davide Pesavento264af772021-02-09 21:48:24 -050031#ifndef NFD_HAVE_LIBPCAP
Davide Pesaventofe0580c2017-05-12 02:02:10 -040032#error "Cannot include this file when libpcap is not available"
33#endif
34
35// forward declarations
36struct pcap;
37typedef pcap pcap_t;
38
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040039namespace nfd::face {
Davide Pesaventofe0580c2017-05-12 02:02:10 -040040
41/**
42 * @brief Helper class for dealing with libpcap handles.
43 */
44class PcapHelper : noncopyable
45{
46public:
47 class Error : public std::runtime_error
48 {
49 public:
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040050 using std::runtime_error::runtime_error;
Davide Pesaventofe0580c2017-05-12 02:02:10 -040051 };
52
53 /**
54 * @brief Create a libpcap context for live packet capture on a network interface.
55 * @throw Error on any error
56 * @sa pcap_create(3pcap)
57 */
58 explicit
59 PcapHelper(const std::string& interfaceName);
60
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -040061 ~PcapHelper() noexcept;
Davide Pesaventofe0580c2017-05-12 02:02:10 -040062
63 /**
64 * @brief Start capturing packets.
65 * @param dlt The link-layer header type to be used.
66 * @throw Error on any error
67 * @sa pcap_activate(3pcap), pcap_set_datalink(3pcap)
68 */
69 void
70 activate(int dlt);
71
72 /**
73 * @brief Stop capturing and close the handle.
74 * @sa pcap_close(3pcap)
75 */
76 void
Davide Pesaventoa599d2a2022-02-16 18:52:43 -050077 close() noexcept;
Davide Pesaventofe0580c2017-05-12 02:02:10 -040078
79 /**
80 * @brief Obtain a file descriptor that can be used in calls such as select(2) and poll(2).
81 * @pre activate() has been called.
82 * @return A selectable file descriptor. It is the caller's responsibility to close the fd.
83 * @throw Error on any error
84 * @sa pcap_get_selectable_fd(3pcap)
85 */
86 int
87 getFd() const;
88
89 /**
90 * @brief Get last error message.
91 * @return Human-readable explanation of the last libpcap error.
92 * @warning The behavior is undefined if no error occurred.
93 * @sa pcap_geterr(3pcap)
94 */
95 std::string
Davide Pesaventoa599d2a2022-02-16 18:52:43 -050096 getLastError() const noexcept;
Davide Pesaventofe0580c2017-05-12 02:02:10 -040097
98 /**
99 * @brief Get the number of packets dropped by the kernel, as reported by libpcap.
100 * @throw Error on any error
101 * @sa pcap_stats(3pcap)
102 */
103 size_t
104 getNDropped() const;
105
106 /**
107 * @brief Install a BPF filter on the receiving socket.
108 * @param filter Null-terminated string containing the BPF program source.
109 * @pre activate() has been called.
110 * @throw Error on any error
111 * @sa pcap_setfilter(3pcap), pcap-filter(7)
112 */
113 void
114 setPacketFilter(const char* filter) const;
115
116 /**
117 * @brief Read the next packet captured on the interface.
Davide Pesaventoa599d2a2022-02-16 18:52:43 -0500118 * @return If successful, returns a tuple containing a read-only view of the received
119 * packet bytes (including the link-layer header) and a second element that
120 * must be ignored. On failure, returns a tuple containing an empty span and
121 * the reason for the failure.
122 * @warning The returned span is valid only until the next call to this function.
Davide Pesaventofe0580c2017-05-12 02:02:10 -0400123 * @sa pcap_next_ex(3pcap)
124 */
Davide Pesaventoa599d2a2022-02-16 18:52:43 -0500125 std::tuple<span<const uint8_t>, std::string>
126 readNextPacket() const noexcept;
Davide Pesaventofe0580c2017-05-12 02:02:10 -0400127
Davide Pesaventoa599d2a2022-02-16 18:52:43 -0500128 operator pcap_t*() const noexcept
Davide Pesaventofe0580c2017-05-12 02:02:10 -0400129 {
130 return m_pcap;
131 }
132
133private:
Davide Pesaventoaa9e3b22022-10-21 17:00:07 -0400134 pcap_t* m_pcap = nullptr;
Davide Pesaventofe0580c2017-05-12 02:02:10 -0400135};
136
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400137} // namespace nfd::face
Davide Pesaventofe0580c2017-05-12 02:02:10 -0400138
139#endif // NFD_DAEMON_FACE_PCAP_HELPER_HPP