/* * Paglo Crawler * Copyright (C) 2006-2008 Paglo Labs Inc. All rights reserved. * www.paglo.com * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ //--------------------------------------------------------------------------- #include "ScanARPQuery.h" #include "SniffThread.h" #include "ScanThread.h" #include "ScanAgentUtils.h" #include "Debug.h" //--------------------------------------------------------------------------- string TScanARPQuery::Description() { return "Resolving MAC address for " + TargetIP.Print(); } //--------------------------------------------------------------------------- TScanResult *TScanARPQuery::PerformScan(TPThread *Thread) { TPacket *Pkt = NULL; TPacketQueue PktQueue; TARPHeader ArpFrm, *ArpPtr = NULL; TMacAddress TargetMac, SrcMac; /* * Only process ARP frames if they are for devices on the * same logical subnet as we are. This will prevent us * from getting fooled by proxy ARP. */ TIPAddress LocalNet(_GlobalConfig.GetInterfaceNetwork()); TIPAddress LocalMask(_GlobalConfig.GetInterfaceNetmask()); TCIDRBlock LocalBlock(LocalNet, LocalMask); if (LocalBlock.Includes(TargetIP)) { DEBUG_MESSAGE(DEBUG_SCANTHREAD, ("Sending ARP request to %s to determine MAC address.", TargetIP.Print().c_str())); /* * Construct an ARP packet. */ memset(&ArpFrm, 0x00, sizeof(ArpFrm)); memset(&ArpFrm.EthDest, 0xFF, 6); SrcMac = _GlobalConfig.GetInterface()->GetMacAddress(); memcpy(&ArpFrm.EthSource, SrcMac.Value(), 6); ArpFrm.EthProto = htons(0x0806); ArpFrm.ARPHardwareType = htons(1); ArpFrm.ARPProtocolType = htons(0x0800); ArpFrm.ARPHardwareAddressLength = 6; ArpFrm.ARPProtocolAddressLength = 4; ArpFrm.ARPOpcode = htons(1); memcpy(ArpFrm.ARPSourceHW, ArpFrm.EthSource, 6); ArpFrm.ARPSourceProto = htonl(_GlobalConfig.GetInterfaceIPAddress().IPv4Value()); ArpFrm.ARPTargetProto = htonl(TargetIP.IPv4Value()); /* * Register PktQueue with the global SniffThread * so that we can get the ARP reply here. */ _SniffThread->RegisterQueue(&PktQueue); /* * Send the ARP packet and wait for the reply. */ SendRawFrame((unsigned char *)&ArpFrm, sizeof(ArpFrm)); /* * Wait for replies. */ /* TODO: This should be configurable. */ MillisecondSleep(500); /* * De-Register the PacketQueue and start looking through the sniffed packets * for an response to the ARP request we sent. */ _SniffThread->DeRegisterQueue(&PktQueue); while ((Pkt = PktQueue.Get())) { ArpPtr = (TARPHeader *)Pkt->GetData(); if (ArpPtr->EthProto == htons(0x0806) && ArpPtr->ARPOpcode == htons(2)) { DEBUG_MESSAGE(DEBUG_SCANTHREAD, ("ArpQuery: found an ARP reply!")); if (ArpPtr->ARPSourceProto == htonl(TargetIP.IPv4Value())) { TargetMac = TMacAddress(ArpPtr->ARPSourceHW); DEBUG_MESSAGE(DEBUG_SCANTHREAD, ("ArpQuery: %s is at %s", TargetIP.Print().c_str(), TargetMac.Print().c_str())); } } delete Pkt; } if (TargetMac.Valid()) { return new TScanResult(TargetMac, TargetIP); } } return new TScanResult(TargetIP); // RESULT_NONE } //---------------------------------------------------------------------------