// ------------------------------- // // -------- Start of File -------- // // ------------------------------- // // ----------------------------------------------------------- // // C++ Source Code File Name: arpscan.cpp // C++ Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC // Produced By: DataReel Software Development Team // File Creation Date: 09/20/1999 // Date Last Modified: 06/17/2016 // Copyright (c) 2001-2024 DataReel Software Development // ----------------------------------------------------------- // // ------------- Program Description and Details ------------- // // ----------------------------------------------------------- // /* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Test program used to get the Media Access Control (MAC) addresses of all the hosts on a specified class C subnet. */ // ----------------------------------------------------------- // #include "gxdlcode.h" #if defined (__USE_ANSI_CPP__) // Use the ANSI Standard C++ library #include <iostream> #include <fstream> using namespace std; // Use unqualified names for Standard C++ library #else // Use the old iostream library by default #include <iostream.h> #include <fstream.h> #endif // __USE_ANSI_CPP__ #include <string.h> #include <stdio.h> #include <time.h> #include <stdlib.h> #include "gxsping.h" #include "gxip32.h" #include "gxmac48.h" // Platform specific include files #if defined (__UNIX__) #include <net/if_arp.h> #include <sys/ioctl.h> #endif #if defined (__WIN32__) int WIN32GetMAC(const char *ip_address, char *mac_address); #endif int GetMacAddress(const char *ip_address, char *eth_dev, char *fname = 0, fstream *outfile = 0) { // Construct a raw socket; gxSocket raw_socket; if(raw_socket.InitSocketLibrary() != 0) { cout << raw_socket.SocketExceptionMessage() << "\n" << flush; if(outfile) *(outfile) << raw_socket.SocketExceptionMessage() << "\n" << flush; return 0; } cout << ip_address << '\t' << flush; if(outfile) *(outfile) << ip_address << '\t' << flush; gxsHostNameInfo *hostnm = raw_socket.GetHostInformation((char *)ip_address); if(hostnm) { cout << hostnm->h_name << flush; if(outfile) *(outfile) << hostnm->h_name << flush; } else { cout << "no_DNS_entry" << flush; if(outfile) *(outfile) << "no_DNS_entry" << flush; } if(raw_socket.InitSocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, (char *)ip_address) < 0) { cout << raw_socket.SocketExceptionMessage() << "\n" << flush; if(outfile) *(outfile) << raw_socket.SocketExceptionMessage() << "\n" << flush; return 0; } // Ping with a specified timeout value gxsPing ping(&raw_socket); if(ping.Ping(4) != gxSOCKET_NO_ERROR) { if(raw_socket.GetSocketError() == gxSOCKET_REQUEST_TIMEOUT) { } else { cout << "\n" << flush; cout << raw_socket.SocketExceptionMessage() << "\n" << flush; if(outfile) { *(outfile) << "\n" << flush; *(outfile) << raw_socket.SocketExceptionMessage() << "\n" << flush; } delete hostnm; return 0; } } #if defined (__WIN32__) char mac_address[255]; if(!WIN32GetMAC(ip_address, mac_address)) { cout << "\n" << flush; if(outfile) *(outfile) << "\n" << flush; delete hostnm; return 0; // No entry in the arp cache } gxMAC48 mac(mac_address, '-', 2); cout << '\t' << mac.c_str(mac_address) << flush; if(outfile) *(outfile) << '\t' << mac.c_str(mac_address) << flush; #elif defined (__UNIX__) arpreq arp_data; memset(&arp_data, 0, sizeof(arp_data)); memcpy(&arp_data.arp_pa, &raw_socket.sin, sizeof(arp_data.arp_pa)); #if defined (__LINUX__) strcpy(arp_data.arp_dev, eth_dev); #endif #ifndef SIOCGARP #error SIOCGARP is not available on this platform #endif if(ioctl(raw_socket.GetSocket(), SIOCGARP, &arp_data) == -1) { cout << "\n" << flush; if(outfile) *(outfile) << "\n" << flush; delete hostnm; return 0; // No entry in the arp cache } char mac_address[255]; unsigned char *ptr = (unsigned char *)&arp_data.arp_ha.sa_data[0]; sprintf(mac_address, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",*ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)); gxMAC48 mac(mac_address, ':', 2); cout << '\t' << mac.c_str(mac_address) << flush; if(outfile) *(outfile) << '\t' << mac.c_str(mac_address) << flush; #else #error You must define a target platform: __WIN32__ or __UNIX__ #endif if(fname) { // Find the vendor information char name[255]; char comment[255]; if(FindVendor((const char *)fname, mac, name, comment)) { cout << '\t' << name << flush; if(outfile) *(outfile) << '\t' << name << flush; } } cout << "\n" << flush; if(outfile) *(outfile) << "\n" << flush; delete hostnm; return 1; } int main(int argc, char **argv) { #ifdef __UNIX__ // Raw sockets require root access on all UNIX platforms. Programs // that use raw sockets can be executed by non-root users if the // effective user ID of the executing process is set to the same as // the file's owner. In the case root must own the executable and // the effective User-ID or Group-ID on execution bit must be set // by root using the chmod command: "chmod u+s" or "chmod 4755" // Now the effective user ID of the executing process will be set to // the same user ID of the file's owner. if(geteuid() != 0) { cout << "You must be root to run this program" << "\n"; return 0; } #endif // Check the command line arguments #if defined (__WIN32__) if(argc < 2) { cout << "\n"; cout << "Usage: " << argv[0] << " subnet " << "\n"; cout << "Example 1: " << argv[0] <<" 192.168.0 " << "\n"; cout << "Example 2: " << argv[0] <<" 192.168.0 maccodes.txt" << "\n"; cout << "Example 3: " << argv[0] <<" 192.168.0.1 " << "\n"; cout << "Example 4: " << argv[0] <<" 192.168.0.1 maccodes.txt" << "\n"; cout << "Example 5: " << argv[0] <<" 192.168.0.255 maccodes.txt \ outfile.txt" << "\n"; return 1; } char *subnet = argv[1]; char *eth_dev = 0; char *fname = 0; char *ofname = 0; if(argc >= 3) fname = argv[2]; if(argc == 4) ofname = argv[3]; #elif defined (__UNIX__) if(argc < 3) { cout << "\n"; cout << "Usage: " << argv[0] << " subnet ethernet_device" << "\n"; cout << "Example 1: " << argv[0] <<" 192.168.0 eth0" << "\n"; cout << "Example 2: " << argv[0] <<" 192.168.0 eth0 maccodes.txt" << "\n"; cout << "Example 3: " << argv[0] <<" 192.168.0.1 eth0" << "\n"; cout << "Example 4: " << argv[0] <<" 192.168.0.1 eth0 maccodes.txt" << "\n"; cout << "Example 5: " << argv[0] <<" 192.168.0.255 eth0 maccodes.txt \ outfile.txt" << "\n"; return 1; } char *subnet = argv[1]; char *eth_dev = argv[2]; char *fname = 0; char *ofname = 0; if(argc >= 4) fname = argv[3]; if(argc == 5) fname = argv[4]; #else #error You must define a target platform: __WIN32__ or __UNIX__ #endif fstream outfile; int out = 0; if(ofname) { // Open the output file and truncate if it already exists out = 1; outfile.open(ofname, ios::out|ios::trunc|ios::binary); if(!outfile) { cout << "Could not open the " << ofname << " output file" << "\n"; return 1; } } gxIP32 ip32(subnet); char sbuf[255]; if((ip32.GetByte4() == 0) || (ip32.GetByte4() == 255)) { // Find the mac address of all the nodes on a specified subnet for(int i = 1; i < 255; i++) { ip32.SetByte4(i); if(out) GetMacAddress(ip32.c_str(sbuf), eth_dev, fname, &outfile); else GetMacAddress(ip32.c_str(sbuf), eth_dev, fname); } } else { // Get the mac address of a single node if(out) GetMacAddress(ip32.c_str(sbuf), eth_dev, fname, &outfile); else GetMacAddress(ip32.c_str(sbuf), eth_dev, fname); } if(out) outfile.close(); return 0; } #if defined (__WIN32__) int WIN32GetMAC(const char *ip_address, char *mac_address) // Function used to get a mac address from the WIN32 arp cache. // Returns true if an arp cache entry exists for the specified // IP address string. { system("arp -a > arpcache.txt"); ifstream infile("arpcache.txt", ios::in); if(!infile) return 0; // Cannot open the file char sbuf[255]; char ip_in[255]; while(!infile.eof()) { infile.getline(sbuf, 255); int len, offset, i = 0; int byte_count = strlen(sbuf); ip_in[0] = 0; mac_address[0] = 0; // Trim leading tabs and spaces while((sbuf[i] == ' ') || (sbuf[i] == '\t')) i++; byte_count -= i; if(byte_count <= 0) continue; memmove(sbuf, sbuf+i, byte_count); sbuf[byte_count] = 0; // Parse the IP Address for(i = 0; i < byte_count; i ++) { if((sbuf[i] == ' ') || (sbuf[i] == '\t')) break; ip_in[i] = sbuf[i]; } ip_in[i] = 0; // Null terminate the string if(strcmp(ip_in, ip_address) == 0) { // Parse the MAC Address while((sbuf[i] == ' ') || (sbuf[i] == '\t')) i++; byte_count -= i; if(byte_count <= 0) continue; memmove(sbuf, sbuf+i, byte_count); for(i = 0; i < byte_count; i ++) { if(sbuf[i] == ' ') break; mac_address[i] = sbuf[i]; } mac_address[i] = 0; // Null terminate the string if(mac_address[0] != 0) { // Remove any trailing spaces offset = len = strlen(mac_address); while(offset--) if(mac_address[offset] != ' ') break; if(offset < len) mac_address[offset+1] = 0; return 1; // Found the arp cache entry } else { return 0; } } } infile.close(); return 0; } #endif // ----------------------------------------------------------- // // ------------------------------- // // --------- End of File --------- // // ------------------------------- //