2#include <QLoggingCategory>
5#ifdef HAVE_PCAPPLUSPLUS
9#include <PcapLiveDeviceList.h>
10#include <PcapFilter.h>
12#include <SystemUtils.h>
19#include "RabbitCommonTools.h"
23static Q_LOGGING_CATEGORY(log,
"WOL")
24CArp::
CArp(QObject *parent) : QObject(parent)
26 qDebug(log) << Q_FUNC_INFO;
28 m_Timer.setInterval(1000);
29 bool check = connect(&m_Timer, SIGNAL(timeout()),
30 this, SLOT(slotProcess()));
36 qDebug(log) << Q_FUNC_INFO;
37#ifdef HAVE_PCAPPLUSPLUS
42int CArp::WakeOnLan(QSharedPointer<CParameterWakeOnLan> para)
49 if(para->GetMac().isEmpty())
51 qCritical(log) <<
"The mac address is empty";
54#ifdef HAVE_PCAPPLUSPLUS
55 auto it = m_Para.find(para->m_Net.GetHost().toStdString());
56 if(it != m_Para.end())
58 if((*it)->bWakeOnLan) {
59 qDebug(log) <<
"The wake on lan is existed"
60 << (*it)->para->m_Net.GetHost();
65 m_Wol.SetBroadcastAddress(para->GetBroadcastAddress());
66 if(para->GetPassword().isEmpty())
72 if(RabbitCommon::CTools::HasAdministratorPrivilege())
74 QSharedPointer<ArpRequest> aq(
new ArpRequest(para));
76 qCritical(log) <<
"new ArpRequest fail";
79 aq->bWakeOnLan =
true;
80 nRet = GetMac(para, aq);
83 QSharedPointer<ArpRequest> aq(
new ArpRequest(para));
85 qCritical(log) <<
"new ArpRequest fail";
88 aq->bWakeOnLan =
true;
89 nRet = GetMac(para, aq);
93 qDebug(log) <<
"There is not pcapplusplus";
98#ifdef HAVE_PCAPPLUSPLUS
99int CArp::StopCapture()
101 const std::vector<pcpp::PcapLiveDevice*>& devList =
102 pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList();
104 qDebug(log) << Q_FUNC_INFO;
105 for (
const auto& dev : devList)
107 if(dev->captureActive())
115int CArp::SendArpPackage(pcpp::PcapLiveDevice* device,
116 std::string szSourceIp, std::string szTargetIp)
118 pcpp::MacAddress sourceMac;
119 pcpp::IPv4Address sourceIP(szSourceIp);
120 pcpp::IPv4Address targetIP(szTargetIp);
122 if(!device || szSourceIp.empty() || szTargetIp.empty())
124 if(!pcpp::IPv4Address::isValidIPv4Address(szSourceIp))
125 sourceIP = device->getIPv4Address();
126 sourceMac = device->getMacAddress();
129 pcpp::Packet arpRequest(100);
130 pcpp::MacAddress destMac(0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
131 pcpp::EthLayer ethLayer(sourceMac, destMac);
132 pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST,
133 sourceMac, destMac, sourceIP, targetIP);
134 if (!arpRequest.addLayer(ðLayer))
136 qCritical(log) <<
"Couldn't build Eth layer for ARP request";
139 if (!arpRequest.addLayer(&arpLayer))
141 qCritical(log) <<
"Couldn't build ARP layer for ARP request";
144 arpRequest.computeCalculateFields();
146 bool bRet = device->sendPacket(&arpRequest);
151static void cbArpPacketReceived(pcpp::RawPacket* rawPacket,
152 pcpp::PcapLiveDevice*,
void* userCookie)
154 using namespace pcpp;
157 Packet packet(rawPacket);
161 if (!packet.isPacketOfType(ARP))
165 ArpLayer* arpReplyLayer = packet.getLayerOfType<ArpLayer>(
true);
166 if (arpReplyLayer ==
nullptr)
170 if (arpReplyLayer->getArpHeader()->hardwareType != htons(1)
171 || arpReplyLayer->getArpHeader()->protocolType != htons(PCPP_ETHERTYPE_IP))
175 CArp* pThis =
reinterpret_cast<CArp*
>(userCookie);
178 qDebug(log) <<
"The use data is nullptr";
184 std::string szTarget = arpReplyLayer->getSenderIpAddr().toString();
185 QMutexLocker lock(&pThis->m_Mutex);
186 auto it = pThis->m_Para.find(szTarget);
187 if(pThis->m_Para.end() == it)
190 auto para = it.value()->para;
191 para->SetMac(arpReplyLayer->getSenderMacAddress().toString().c_str());
192 para->SetHostState(CParameterWakeOnLan::HostState::Online);
193 it.value()->nTimeout = 0;
196void CArp::ListInterfaces()
198 const std::vector<pcpp::PcapLiveDevice*>& devList =
199 pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList();
201 qDebug(log) <<
"Network interfaces:";
202 for (
const auto& dev : devList)
204 qDebug(log) <<
" -> Name:" << dev->getName().c_str();
205 for(
auto addr: dev->getIPAddresses())
206 qDebug(log) <<
" " << addr.toString().c_str();
212int CArp::GetMac(QSharedPointer<CParameterWakeOnLan> para
213#ifdef HAVE_PCAPPLUSPLUS
214 , QSharedPointer<ArpRequest> ar
218 qDebug(log) << Q_FUNC_INFO << para;
221#ifdef HAVE_PCAPPLUSPLUS
222 std::string szSourceIp;
223 if(!para->GetNetworkInterface().isEmpty())
224 szSourceIp = para->GetNetworkInterface().toStdString();
225 std::string szTargetIp;
226 if(!para->m_Net.GetHost().isEmpty())
227 szTargetIp = para->m_Net.GetHost().toStdString();
229 pcpp::PcapLiveDevice* device =
nullptr;
233 if(!pcpp::IPv4Address::isValidIPv4Address(szTargetIp)) {
234 qCritical(log) <<
"Target ip is invalid:" << szTargetIp.c_str();
238 device = pcpp::PcapLiveDeviceList::getInstance()
239 .getPcapLiveDeviceByIpOrName(szSourceIp);
240 if (device ==
nullptr) {
242 <<
"Couldn't find interface by provided IP address or name"
243 << szSourceIp.c_str();
247 if(!device->isOpened())
248 if(!device->open()) {
249 qCritical(log) <<
"Open device fail" << szSourceIp.c_str();
253 if(!device->captureActive()) {
255 pcpp::ArpFilter arpFilter(pcpp::ARP_REPLY);
256 if (!device->setFilter(arpFilter))
258 qCritical(log) <<
"Couldn't set ARP filter for device";
263 device->startCapture(cbArpPacketReceived,
this);
266 if(m_Para.end() == m_Para.find(szTargetIp)) {
268 auto ar = QSharedPointer<ArpRequest>(
new ArpRequest(para));
269 m_Para.insert(szTargetIp, ar);
272 nRet = SendArpPackage(device, szSourceIp, szTargetIp);
273 if(!m_Timer.isActive())
277 }
catch(std::exception e) {
278 qDebug(log) <<
"std::exception" << e.what();
280 qDebug(log) <<
"Exception";
283 qDebug(log) <<
"There is not pcapplusplus";
288void CArp::slotProcess()
290 qDebug(log) << Q_FUNC_INFO;
291#ifdef HAVE_PCAPPLUSPLUS
293 for(
auto it = m_Para.begin(); it != m_Para.end();)
299 if(a->tmStart.msecsTo(QTime::currentTime()) > a->nTimeout) {
300 qDebug(log) <<
"Get mac address fail" << para->m_Net.GetHost()
305 para->SetHostState(CParameterWakeOnLan::HostState::Offline);
310 if(a->bWakeOnLan && a->nRepeat > 0
311 && a->tmRepeat.msecsTo(QTime::currentTime()) > para->GetInterval())
313 qDebug(log) <<
"Repeat wake on lan" << para->m_Net.GetHost()
315 m_Wol.SetBroadcastAddress(para->GetBroadcastAddress());
316 if(para->GetPassword().isEmpty())
323 && a->tmRepeat.msecsTo(QTime::currentTime()) > para->GetInterval())
325 qDebug(log) <<
"Repeat get mac address" << para->m_Net.GetHost()
330 a->tmRepeat = QTime::currentTime();
335 if(m_Para.isEmpty()) {
bool SendMagicPacket(const QString &szMac, uint16_t portNum=9)
SendMagicPacket.
bool SendSecureMagicPacket(const QString &szMac, const QString &szPassword, uint16_t portNum=9)
SendSecureMagicPacket.