Skip to content

Commit 8a753f1

Browse files
authored
Refactor PcapLiveDevice::doOpen (#1783)
1 parent f842ccb commit 8a753f1

File tree

4 files changed

+99
-86
lines changed

4 files changed

+99
-86
lines changed

Pcap++/header/PcapLiveDevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ namespace pcpp
600600
void getStatistics(IPcapDevice::PcapStats& stats) const override;
601601

602602
protected:
603-
pcap_t* doOpen(const DeviceConfiguration& config);
603+
internal::PcapHandle doOpen(const DeviceConfiguration& config);
604604

605605
private:
606606
bool isNflogDevice() const;

Pcap++/src/PcapLiveDevice.cpp

Lines changed: 93 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,14 @@ namespace pcpp
128128
#endif
129129
}
130130

131-
static bool isTimestampProviderSupportedByDevice(pcap_t* pcap,
131+
static bool isTimestampProviderSupportedByDevice(const internal::PcapHandle& pcap,
132132
const PcapLiveDevice::TimestampProvider timestampProvider)
133133
{
134134
#ifdef HAS_TIMESTAMP_TYPES_ENABLED
135135
const auto tstampType = getPcapTimestampProvider(timestampProvider);
136136

137137
int* supportedTstampTypesRaw;
138-
const int numSupportedTstampTypes = pcap_list_tstamp_types(pcap, &supportedTstampTypesRaw);
138+
const int numSupportedTstampTypes = pcap_list_tstamp_types(pcap.get(), &supportedTstampTypesRaw);
139139

140140
struct TimestampTypesDeleter
141141
{
@@ -150,7 +150,7 @@ namespace pcpp
150150
if (numSupportedTstampTypes < 0)
151151
{
152152
PCPP_LOG_ERROR("Error retrieving timestamp types - default 'Host' will be used, error message: "
153-
<< pcap_geterr(pcap) << "'");
153+
<< pcap.getLastError() << "'");
154154
return false;
155155
}
156156

@@ -161,53 +161,50 @@ namespace pcpp
161161
#endif
162162
}
163163

164-
static void setTimestampProvider(pcap_t* pcap, const PcapLiveDevice::TimestampProvider timestampProvider)
164+
static void setTimestampProvider(internal::PcapHandle& pcap,
165+
const PcapLiveDevice::TimestampProvider timestampProvider)
165166
{
166167
#ifdef HAS_TIMESTAMP_TYPES_ENABLED
167-
if (isTimestampProviderSupportedByDevice(pcap, timestampProvider))
168+
if (!isTimestampProviderSupportedByDevice(pcap, timestampProvider))
168169
{
169-
const int ret = pcap_set_tstamp_type(pcap, getPcapTimestampProvider(timestampProvider));
170-
if (ret == 0)
171-
{
172-
PCPP_LOG_DEBUG("Timestamp provider was set");
173-
}
174-
else
175-
{
176-
PCPP_LOG_ERROR("Failed to set timestamping provider: '" << ret << "', error message: '"
177-
<< pcap_geterr(pcap) << "'");
178-
}
170+
throw std::runtime_error("Selected timestamping provider is not supported");
179171
}
180-
else
172+
173+
const int ret = pcap_set_tstamp_type(pcap.get(), getPcapTimestampProvider(timestampProvider));
174+
if (ret != 0)
181175
{
182-
PCPP_LOG_ERROR("Selected timestamping provider is not supported");
176+
throw std::runtime_error("Cannot create the pcap device, error was: " + std::string(pcap.getLastError()));
183177
}
178+
184179
#else
185-
PCPP_LOG_ERROR("Error setting timestamp provider - it is available only from libpcap 1.2");
180+
throw std::runtime_error("Error setting timestamp provider - it is available only from libpcap 1.2");
186181
#endif
187182
}
188183

189-
static void setTimestampPrecision(pcap_t* pcap, const PcapLiveDevice::TimestampPrecision timestampPrecision)
184+
static void setTimestampPrecision(const internal::PcapHandle& pcap,
185+
const PcapLiveDevice::TimestampPrecision timestampPrecision)
190186
{
191187
#ifdef HAS_TIMESTAMP_PRECISION_ENABLED
192-
const int ret = pcap_set_tstamp_precision(pcap, getPcapPrecision(timestampPrecision));
193-
if (ret == 0)
188+
const int ret = pcap_set_tstamp_precision(pcap.get(), getPcapPrecision(timestampPrecision));
189+
switch (ret)
190+
{
191+
case 0:
194192
{
195-
PCPP_LOG_DEBUG("Timestamp precision was set");
196193
return;
197194
}
198-
199-
if (ret == PCAP_ERROR_TSTAMP_PRECISION_NOTSUP)
195+
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
200196
{
201-
PCPP_LOG_ERROR(
197+
throw std::runtime_error(
202198
"Failed to set timestamping precision: the capture device does not support the requested precision");
203199
}
204-
else
200+
default:
205201
{
206-
PCPP_LOG_ERROR("Failed to set timestamping precision: '" << ret << "', error message: '"
207-
<< pcap_geterr(pcap) << "'");
202+
throw std::runtime_error("Failed to set timestamping precision, error was: " +
203+
std::string(pcap.getLastError()));
204+
}
208205
}
209206
#else
210-
PCPP_LOG_ERROR("Error setting timestamp precision - it is available only from libpcap 1.5");
207+
throw std::runtime_error("Error setting timestamp precision - it is available only from libpcap 1.5");
211208
#endif
212209
}
213210

@@ -379,7 +376,7 @@ namespace pcpp
379376
PCPP_LOG_DEBUG("Ended stats thread for device '" << m_InterfaceDetails.name << "'");
380377
}
381378

382-
pcap_t* PcapLiveDevice::doOpen(const DeviceConfiguration& config)
379+
internal::PcapHandle PcapLiveDevice::doOpen(const DeviceConfiguration& config)
383380
{
384381
char errbuf[PCAP_ERRBUF_SIZE] = { '\0' };
385382
std::string device_name = m_InterfaceDetails.name;
@@ -389,49 +386,45 @@ namespace pcpp
389386
device_name += ":" + std::to_string(config.nflogGroup & 0xffff);
390387
}
391388

392-
pcap_t* pcap = pcap_create(device_name.c_str(), errbuf);
389+
auto pcap = internal::PcapHandle(pcap_create(device_name.c_str(), errbuf));
393390
if (!pcap)
394391
{
395-
PCPP_LOG_ERROR(errbuf);
396-
return pcap;
392+
throw std::runtime_error("Cannot create the pcap device, error was: " + std::string(errbuf));
397393
}
398-
int ret = pcap_set_snaplen(pcap, config.snapshotLength <= 0 ? DEFAULT_SNAPLEN : config.snapshotLength);
394+
395+
int ret = pcap_set_snaplen(pcap.get(), config.snapshotLength <= 0 ? DEFAULT_SNAPLEN : config.snapshotLength);
399396
if (ret != 0)
400397
{
401-
PCPP_LOG_ERROR(pcap_geterr(pcap));
398+
throw std::runtime_error("Cannot set snaplan, error was: " + std::string(pcap.getLastError()));
402399
}
403-
ret = pcap_set_promisc(pcap, config.mode);
400+
401+
ret = pcap_set_promisc(pcap.get(), config.mode);
404402
if (ret != 0)
405403
{
406-
PCPP_LOG_ERROR(pcap_geterr(pcap));
404+
throw std::runtime_error("Cannot set promiscuous mode, error was: " + std::string(pcap.getLastError()));
407405
}
408406

409407
int timeout = (config.packetBufferTimeoutMs <= 0 ? LIBPCAP_OPEN_LIVE_TIMEOUT : config.packetBufferTimeoutMs);
410-
ret = pcap_set_timeout(pcap, timeout);
408+
ret = pcap_set_timeout(pcap.get(), timeout);
411409
if (ret != 0)
412410
{
413-
PCPP_LOG_ERROR(pcap_geterr(pcap));
411+
throw std::runtime_error("Cannot set timeout on device, error was: " + std::string(pcap.getLastError()));
414412
}
415413

416414
if (config.packetBufferSize >= 100)
417415
{
418-
ret = pcap_set_buffer_size(pcap, config.packetBufferSize);
416+
ret = pcap_set_buffer_size(pcap.get(), config.packetBufferSize);
419417
if (ret != 0)
420418
{
421-
PCPP_LOG_ERROR(pcap_geterr(pcap));
419+
throw std::runtime_error("Cannot set buffer size, error was: " + std::string(pcap.getLastError()));
422420
}
423421
}
424422

425423
#ifdef HAS_PCAP_IMMEDIATE_MODE
426-
ret = pcap_set_immediate_mode(pcap, 1);
427-
if (ret == 0)
428-
{
429-
PCPP_LOG_DEBUG("Immediate mode is activated");
430-
}
431-
else
424+
ret = pcap_set_immediate_mode(pcap.get(), 1);
425+
if (ret != 0)
432426
{
433-
PCPP_LOG_ERROR("Failed to activate immediate mode, error code: '" << ret << "', error message: '"
434-
<< pcap_geterr(pcap) << "'");
427+
throw std::runtime_error("Cannot set immediate mode, error was: " + std::string(pcap.getLastError()));
435428
}
436429
#endif
437430

@@ -445,53 +438,52 @@ namespace pcpp
445438
setTimestampPrecision(pcap, config.timestampPrecision);
446439
}
447440

448-
ret = pcap_activate(pcap);
441+
ret = pcap_activate(pcap.get());
449442
if (ret != 0)
450443
{
451-
PCPP_LOG_ERROR(pcap_geterr(pcap));
452-
pcap_close(pcap);
453-
return nullptr;
444+
throw std::runtime_error("Cannot activate the device, error was: " + std::string(pcap.getLastError()));
454445
}
455446

456-
pcap_direction_t directionToSet = directionTypeMap(config.direction);
457-
ret = pcap_setdirection(pcap, directionToSet);
458-
if (ret == 0)
447+
if (config.direction != PCPP_INOUT)
459448
{
460-
if (config.direction == PCPP_IN)
461-
{
462-
PCPP_LOG_DEBUG("Only incoming traffics will be captured");
463-
}
464-
else if (config.direction == PCPP_OUT)
465-
{
466-
PCPP_LOG_DEBUG("Only outgoing traffics will be captured");
467-
}
468-
else
449+
pcap_direction_t directionToSet = directionTypeMap(config.direction);
450+
ret = pcap_setdirection(pcap.get(), directionToSet);
451+
if (ret != 0)
469452
{
470-
PCPP_LOG_DEBUG("Both incoming and outgoing traffics will be captured");
453+
throw std::runtime_error("Failed to set direction for capturing packets, error was: " +
454+
std::string(pcap.getLastError()));
471455
}
472456
}
473-
else
457+
458+
switch (config.direction)
474459
{
475-
PCPP_LOG_ERROR("Failed to set direction for capturing packets, error code: '"
476-
<< ret << "', error message: '" << pcap_geterr(pcap) << "'");
460+
case PCPP_IN:
461+
{
462+
PCPP_LOG_DEBUG("Only incoming traffics will be captured");
477463
}
478-
479-
if (pcap)
464+
case PCPP_OUT:
480465
{
481-
int dlt = pcap_datalink(pcap);
482-
const char* dlt_name = pcap_datalink_val_to_name(dlt);
483-
if (dlt_name)
484-
{
485-
PCPP_LOG_DEBUG("link-type " << dlt << ": " << dlt_name << " (" << pcap_datalink_val_to_description(dlt)
486-
<< ")");
487-
}
488-
else
489-
{
490-
PCPP_LOG_DEBUG("link-type " << dlt);
491-
}
466+
PCPP_LOG_DEBUG("Only outgoing traffics will be captured");
467+
}
468+
default:
469+
{
470+
PCPP_LOG_DEBUG("Both incoming and outgoing traffics will be captured");
471+
}
472+
}
492473

493-
m_LinkType = static_cast<LinkLayerType>(dlt);
474+
int dlt = pcap_datalink(pcap.get());
475+
const char* dlt_name = pcap_datalink_val_to_name(dlt);
476+
if (dlt_name)
477+
{
478+
PCPP_LOG_DEBUG("link-type " << dlt << ": " << dlt_name << " (" << pcap_datalink_val_to_description(dlt)
479+
<< ")");
480+
}
481+
else
482+
{
483+
PCPP_LOG_DEBUG("link-type " << dlt);
494484
}
485+
486+
m_LinkType = static_cast<LinkLayerType>(dlt);
495487
return pcap;
496488
}
497489

@@ -503,7 +495,16 @@ namespace pcpp
503495
return true;
504496
}
505497

506-
auto pcapDescriptor = internal::PcapHandle(doOpen(config));
498+
internal::PcapHandle pcapDescriptor;
499+
try
500+
{
501+
pcapDescriptor = doOpen(config);
502+
}
503+
catch (std::exception& ex)
504+
{
505+
PCPP_LOG_ERROR(ex.what());
506+
}
507+
507508
internal::PcapHandle pcapSendDescriptor;
508509

509510
// It's not possible to have two open instances of the same NFLOG device:group
@@ -513,7 +514,14 @@ namespace pcpp
513514
}
514515
else
515516
{
516-
pcapSendDescriptor = internal::PcapHandle(doOpen(config));
517+
try
518+
{
519+
pcapSendDescriptor = doOpen(config);
520+
}
521+
catch (std::exception& ex)
522+
{
523+
PCPP_LOG_ERROR(ex.what());
524+
}
517525
}
518526

519527
if (pcapDescriptor == nullptr || (!isNflogDevice() && pcapSendDescriptor == nullptr))

Tests/Pcap++Test/Tests/FileTests.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ PTF_TEST_CASE(TestPcapFilePrecision)
111111
pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported());
112112

113113
// Write nano precision file
114+
pcpp::Logger::getInstance().suppressLogs();
114115
pcpp::PcapFileWriterDevice writerDevNano(EXAMPLE_PCAP_NANO_PATH, pcpp::LINKTYPE_ETHERNET, true);
116+
pcpp::Logger::getInstance().enableLogs();
115117
PTF_ASSERT_EQUAL(writerDevNano.getTimestampPrecision(),
116118
pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported()
117119
? pcpp::FileTimestampPrecision::Nanoseconds

Tests/Pcap++Test/Tests/LiveDeviceTests.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,8 @@ PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg)
681681

682682
packetCount = 0;
683683

684+
// Setting direction isn't available on Windows, and setting "outgoing only" isn't available on macOS
685+
#if !defined(_WIN32) && !defined(__APPLE__)
684686
// create a non-default configuration with only capturing incoming packets and open the device again
685687
pcpp::PcapLiveDevice::DeviceConfiguration devConfigWithDirection(pcpp::PcapLiveDevice::Promiscuous, 10, 2000000,
686688
pcpp::PcapLiveDevice::PCPP_OUT);
@@ -694,6 +696,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg)
694696
PTF_ASSERT_FALSE(liveDev->isOpened());
695697

696698
PTF_ASSERT_GREATER_THAN(packetCount, 0);
699+
#endif
697700

698701
// create a non-default configuration with a snapshot length of 10 bytes
699702
int snaplen = 20;

0 commit comments

Comments
 (0)