From 2ead59f44a330d6930abc9eec320c6de42e7cded Mon Sep 17 00:00:00 2001 From: "vincenzo.comito" Date: Tue, 10 Dec 2024 09:42:59 +0100 Subject: [PATCH] Add support for timestamp related options (#1656) --- Pcap++/header/PcapLiveDevice.h | 53 +++++++++++++++++++++++++++++- Pcap++/src/PcapLiveDevice.cpp | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/Pcap++/header/PcapLiveDevice.h b/Pcap++/header/PcapLiveDevice.h index e37e27d7cd..307875f723 100644 --- a/Pcap++/header/PcapLiveDevice.h +++ b/Pcap++/header/PcapLiveDevice.h @@ -186,6 +186,38 @@ namespace pcpp PCPP_OUT }; + /** + * Set which source provides timestamps associated to each captured packet + * (you can read more here: ) + */ + enum TimestampProvider + { + /** host-provided, unknown characteristics, default */ + TimestampProviderHost = 0, + /** host-provided, low precision, synced with the system clock */ + TimestampProviderHostLowPrec, + /** host-provided, high precision, synced with the system clock */ + TimestampProviderHostHighPrec, + /** device-provided, synced with the system clock */ + TimestampProviderAdapter, + /** device-provided, not synced with the system clock */ + TimestampProviderAdapterUnsynced, + /** host-provided, high precision, not synced with the system clock */ + TimestampProviderHostHighPrecUnsynced + }; + + /** + * Set the precision of timestamps associated to each captured packet + * (you can read more here: ) + */ + enum TimestampPrecision + { + /** use timestamps with microsecond precision, default */ + TimestampPrecisionMicroseconds = 0, + /** use timestamps with nanosecond precision */ + TimestampPrecisionNanoseconds, + }; + /** * @struct DeviceConfiguration * A struct that contains user configurable parameters for opening a device. All parameters have default values @@ -236,6 +268,18 @@ namespace pcpp /// In Unix-like system, use poll() for blocking mode. bool usePoll; + /** + * Set which timestamp provider is used. + * Depending on the capture device and the software on the host, different types of time stamp can be used + */ + TimestampProvider timestampProvider; + + /** + * Set which timestamp precision is used. + * Depending on the capture device and the software on the host, different precision can be used + */ + TimestampPrecision timestampPrecision; + /** * A c'tor for this struct * @param[in] mode The mode to open the device: promiscuous or non-promiscuous. Default value is promiscuous @@ -252,10 +296,15 @@ namespace pcpp * @param[in] nflogGroup NFLOG group for NFLOG devices. Default value is 0. * @param[in] usePoll use `poll()` when capturing packets in blocking more (`startCaptureBlockingMode()`) on * Unix-like system. Default value is false. + * @param[in] timestampProvider the source that will provide the timestamp associated to each captured + * packet. + * @param[in] timestampPrecision the precision of the timestamp associated to each captured packet. */ explicit DeviceConfiguration(DeviceMode mode = Promiscuous, int packetBufferTimeoutMs = 0, int packetBufferSize = 0, PcapDirection direction = PCPP_INOUT, - int snapshotLength = 0, unsigned int nflogGroup = 0, bool usePoll = false) + int snapshotLength = 0, unsigned int nflogGroup = 0, bool usePoll = false, + TimestampProvider timestampProvider = TimestampProviderHost, + TimestampPrecision timestampPrecision = TimestampPrecisionMicroseconds) { this->mode = mode; this->packetBufferTimeoutMs = packetBufferTimeoutMs; @@ -264,6 +313,8 @@ namespace pcpp this->snapshotLength = snapshotLength; this->nflogGroup = nflogGroup; this->usePoll = usePoll; + this->timestampProvider = timestampProvider; + this->timestampPrecision = timestampPrecision; } }; diff --git a/Pcap++/src/PcapLiveDevice.cpp b/Pcap++/src/PcapLiveDevice.cpp index 6eef2111d2..4ed15a814f 100644 --- a/Pcap++/src/PcapLiveDevice.cpp +++ b/Pcap++/src/PcapLiveDevice.cpp @@ -84,6 +84,38 @@ namespace pcpp } #endif + static int timestampProviderMap(const PcapLiveDevice::TimestampProvider timestampProvider) + { + switch (timestampProvider) + { + case PcapLiveDevice::TimestampProviderHost: + return PCAP_TSTAMP_HOST; + case PcapLiveDevice::TimestampProviderHostLowPrec: + return PCAP_TSTAMP_HOST_LOWPREC; + case PcapLiveDevice::TimestampProviderHostHighPrec: + return PCAP_TSTAMP_HOST_HIPREC; + case PcapLiveDevice::TimestampProviderAdapter: + return PCAP_TSTAMP_ADAPTER; + case PcapLiveDevice::TimestampProviderAdapterUnsynced: + return PCAP_TSTAMP_ADAPTER_UNSYNCED; + case PcapLiveDevice::TimestampProviderHostHighPrecUnsynced: + return PCAP_TSTAMP_HOST_HIPREC_UNSYNCED; + } + return PCAP_TSTAMP_HOST; + } + + static int timestampPrecisionMap(const PcapLiveDevice::TimestampPrecision timestampPrecision) + { + switch (timestampPrecision) + { + case PcapLiveDevice::TimestampPrecisionMicroseconds: + return PCAP_TSTAMP_PRECISION_MICRO; + case PcapLiveDevice::TimestampPrecisionNanoseconds: + return PCAP_TSTAMP_PRECISION_NANO; + } + return PCAP_TSTAMP_PRECISION_MICRO; + } + PcapLiveDevice::DeviceInterfaceDetails::DeviceInterfaceDetails(pcap_if_t* pInterface) : name(pInterface->name), isLoopback(pInterface->flags & PCAP_IF_LOOPBACK) { @@ -308,6 +340,34 @@ namespace pcpp } #endif + if (config.timestampProvider) + { + ret = pcap_set_tstamp_type(pcap, timestampProviderMap(config.timestampProvider)); + if (ret == 0) + { + PCPP_LOG_DEBUG("Timestamp provider was set"); + } + else + { + PCPP_LOG_ERROR("Failed to set timestamping provider: '" << ret << "', error message: '" + << pcap_geterr(pcap) << "'"); + } + } + + if (config.timestampPrecision) + { + ret = pcap_set_tstamp_precision(pcap, timestampPrecisionMap(config.timestampPrecision)); + if (ret == 0) + { + PCPP_LOG_DEBUG("Timestamp precision was set"); + } + else + { + PCPP_LOG_ERROR("Failed to set timestamping precision: '" << ret << "', error message: '" + << pcap_geterr(pcap) << "'"); + } + } + ret = pcap_activate(pcap); if (ret != 0) {