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