mirror of
https://github.com/nmap/nmap.git
synced 2026-08-28 12:31:12 +00:00
Properly determine device name from target if possible
This commit is contained in:
parent
65ed79b280
commit
75d16aab1b
6 changed files with 72 additions and 95 deletions
|
|
@ -1411,14 +1411,17 @@ int EchoServer::start() {
|
|||
nping_fatal(QT_3, "Failed to create new nsock_iod. QUITTING.\n");
|
||||
|
||||
/* Open pcap */
|
||||
nping_print(DBG_2,"Opening pcap device %s", o.getDevice());
|
||||
Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
|
||||
const char *device = o.getDevice();
|
||||
if (!device)
|
||||
nping_fatal(QT_3, "Unable to determine device name. QUITTING.\n");
|
||||
nping_print(DBG_2,"Opening pcap device %s", device);
|
||||
Strncpy(pcapdev, device, sizeof(pcapdev));
|
||||
rc = nsock_pcap_open(nsp, pcap_nsi, pcapdev, MAX_ECHOED_PACKET_LEN, 1,
|
||||
ProbeMode::getBPFFilterString());
|
||||
if (rc)
|
||||
nping_fatal(QT_3, "Error opening capture device %s\n", o.getDevice());
|
||||
nping_fatal(QT_3, "Error opening capture device %s\n", device);
|
||||
else
|
||||
nping_print(VB_0,"Packet capture will be performed using network interface %s.", o.getDevice());
|
||||
nping_print(VB_0,"Packet capture will be performed using network interface %s.", device);
|
||||
nping_print(VB_0,"Waiting for connections...");
|
||||
|
||||
/* Get a socket suitable for an accept() call */
|
||||
|
|
|
|||
|
|
@ -701,8 +701,14 @@ int NpingOps::setDevice(char *n){
|
|||
} /* End of setDevice() */
|
||||
|
||||
|
||||
char *NpingOps::getDevice(){
|
||||
return this->device;
|
||||
const char *NpingOps::getDevice(){
|
||||
if (this->device_set)
|
||||
return this->device;
|
||||
if (this->targets.devices.empty())
|
||||
return NULL;
|
||||
if (this->targets.devices.size() > 1)
|
||||
nping_fatal(QT_3, "Nping does not support targets on multiple devices. QUITTING.\n");
|
||||
return this->targets.devices.front()->getName();
|
||||
} /* End of getDevice() */
|
||||
|
||||
|
||||
|
|
@ -2301,86 +2307,8 @@ if (this->isRoot() && this->havePcap()==false){
|
|||
nping_print(VB_0, "Warning: Payload supplied in TCP Connect mode. Payload will be ignored.");
|
||||
}
|
||||
|
||||
/** SOURCE IP, SOURCE MAC and NETWORK DEVICE *********************************/
|
||||
/* If we are in a mode where we need to craft IP packets, then we need to
|
||||
* obtain a network interface name and a source IP address. There are three
|
||||
* different possibilities:
|
||||
* 1. User did NOT specify both network interface and source IP address.
|
||||
* 2. User did specify a network interface but not a source IP address.
|
||||
* 3. User did actually supply a source IP but not a network interface name
|
||||
*
|
||||
* I know the following code is ugly but the thing is that we want to determine
|
||||
* interface and source IP without user intervention, so we try in many ways
|
||||
* until either we succeed or we run out of possibilities and fatal().
|
||||
*/
|
||||
if( this->getMode()!=TCP_CONNECT && this->getMode()!=UDP_UNPRIV && this->getRole()!=ROLE_SERVER){
|
||||
|
||||
char devbuff[32];
|
||||
char *dev;
|
||||
struct sockaddr_storage ss, ifaddr;
|
||||
struct sockaddr_in *s4=(struct sockaddr_in *)&ifaddr;
|
||||
struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ifaddr;
|
||||
size_t ss_len;
|
||||
char hostname[128];
|
||||
memset(&ss, 0, sizeof(struct sockaddr_storage));
|
||||
memset(&ifaddr, 0, sizeof(struct sockaddr_storage));
|
||||
|
||||
|
||||
/* CASE 1: User did not specify a device so we have to select one. */
|
||||
if( !this->issetDevice() ){
|
||||
if( this->ipv4() ){
|
||||
/* Ugly hack. Get the first resolvable target and determine net interface. Let's
|
||||
* hope user did not specify something that mixes localhost with
|
||||
* other targets, like "nping localhost google.com playboy.com" */
|
||||
for(int z=0; z<this->targets.getTargetSpecCount(); z++){
|
||||
if( this->targets.getNextTargetAddressAndName(&ss, &ss_len, hostname, sizeof(hostname)) == OP_SUCCESS )
|
||||
break;
|
||||
else if( z>=(this->targets.getTargetSpecCount()-1) )
|
||||
nping_fatal(QT_3,"Cannot find a valid target. Please make sure the specified hosts are either IP addresses in standard notation or hostnames that can be resolved with DNS");
|
||||
}
|
||||
this->targets.rewind();
|
||||
|
||||
/* Try to obtain a device name from the target IP */
|
||||
if ( getNetworkInterfaceName( &ss , devbuff) != OP_SUCCESS ) {
|
||||
/* If that didn't work, ask libpcap */
|
||||
if ( (dev = this->select_network_iface()) == NULL)
|
||||
nping_fatal(QT_3, "Cannot obtain device for packet capture");
|
||||
else {
|
||||
this->setDevice( dev );
|
||||
free(dev);
|
||||
}
|
||||
/* Libpcap gave us a device name, try to obtain it's IP */
|
||||
if ( devname2ipaddr(this->getDevice(), this->af(), &ifaddr) != 0 ){
|
||||
if( this->isRoot() )
|
||||
nping_fatal(QT_3,"Cannot figure out what source address to use for device %s, does it even exist?", this->getDevice());
|
||||
else
|
||||
nping_fatal(QT_3,"Cannot figure out what source address to use for device %s, are you root?", this->getDevice());
|
||||
}
|
||||
else{
|
||||
if( s4->sin_family==AF_INET )
|
||||
this->setIPv4SourceAddress(s4->sin_addr);
|
||||
else if ( s6->sin6_family==AF_INET6 )
|
||||
this->setIPv6SourceAddress(s6->sin6_addr.s6_addr);
|
||||
}
|
||||
}else{
|
||||
this->setDevice(devbuff);
|
||||
}
|
||||
}else{ /* In IPv6 we just select one in libpcap and hope is the right one */
|
||||
char *selected_iface=this->select_network_iface();
|
||||
if(selected_iface==NULL)
|
||||
nping_fatal(QT_3, "Error trying to find a suitable network interface ");
|
||||
else {
|
||||
this->setDevice( selected_iface );
|
||||
free(selected_iface);
|
||||
}
|
||||
}
|
||||
} /* CASE 2: User did actually supply a device name */
|
||||
else{
|
||||
nping_print(DBG_2, "Using network interface \"%s\"", this->getDevice() );
|
||||
}
|
||||
|
||||
/* The echo server needs to find out a network interface*/
|
||||
}else if (this->getRole()==ROLE_SERVER && this->issetDevice()==false){
|
||||
if (this->getRole()==ROLE_SERVER && this->issetDevice()==false){
|
||||
char *selected_iface=this->select_network_iface();
|
||||
if(selected_iface==NULL)
|
||||
nping_fatal(QT_3, "Error trying to find a suitable network interface ");
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ class NpingOps {
|
|||
bool sendEth();
|
||||
|
||||
int setDevice(char *n);
|
||||
char *getDevice();
|
||||
const char *getDevice();
|
||||
bool issetDevice();
|
||||
|
||||
int setSpoofSource();
|
||||
|
|
|
|||
|
|
@ -67,16 +67,33 @@
|
|||
#include "NpingTargets.h"
|
||||
#include "common_modified.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
extern NpingOps o;
|
||||
|
||||
bool NpingDevice::strEqual(const char *name) const
|
||||
{
|
||||
return 0 == std::strcmp(devname, name);
|
||||
}
|
||||
|
||||
NpingTargets::NpingTargets()
|
||||
: ready(false), current_target(0)
|
||||
{
|
||||
if (o.issetDevice()) {
|
||||
devices.push_back(new NpingDevice(o.getDevice()));
|
||||
}
|
||||
} /* End of NpingTargets constructor */
|
||||
|
||||
|
||||
NpingTargets::~NpingTargets(){
|
||||
while (!netblocks.empty()) {
|
||||
delete netblocks.back();
|
||||
netblocks.pop_back();
|
||||
}
|
||||
while (!devices.empty()) {
|
||||
delete devices.back();
|
||||
devices.pop_back();
|
||||
}
|
||||
} /* End of NpingTargets destructor */
|
||||
|
||||
|
||||
|
|
@ -91,8 +108,20 @@ int NpingTargets::addSpec(char *spec){
|
|||
return OP_FAILURE;
|
||||
netblocks.push_back(nb);
|
||||
return OP_SUCCESS;
|
||||
} /* End of NpingTargets */
|
||||
} /* End of NpingTargets::addSpec */
|
||||
|
||||
void NpingTargets::addDevice(const char *dev)
|
||||
{
|
||||
if(dev == NULL || *dev == '\0')
|
||||
return;
|
||||
for (std::vector<NpingDevice *>::iterator it=devices.begin();
|
||||
it != devices.end(); ++it) {
|
||||
NpingDevice *d = *it;
|
||||
if (d->strEqual(dev))
|
||||
return;
|
||||
}
|
||||
devices.push_back(new NpingDevice(dev));
|
||||
}
|
||||
|
||||
/** Returns next target */
|
||||
int NpingTargets::getNextTargetAddressAndName(struct sockaddr_storage *t, size_t *tlen, char *hname, size_t hlen){
|
||||
|
|
@ -309,6 +338,7 @@ int NpingTargets::processSpecs(){
|
|||
|
||||
/* Insert current target into targets array */
|
||||
this->Targets.push_back(mytarget);
|
||||
this->addDevice(mytarget->getDeviceName());
|
||||
}
|
||||
|
||||
/* getNextTarget() checks this to ensure user has previously called processSpecs() */
|
||||
|
|
|
|||
|
|
@ -72,6 +72,17 @@
|
|||
|
||||
#define MAX_NPING_HOSTNAME_LEN 512 /**< Max length for named hosts */
|
||||
|
||||
class NpingDevice {
|
||||
private:
|
||||
// Note: this class doesn't own the storage for this name;
|
||||
// it has to continue to exist elsewhere.
|
||||
const char *devname;
|
||||
public:
|
||||
NpingDevice(const char *d) : devname(d) {}
|
||||
bool strEqual(const char *name) const;
|
||||
const char *getName() const { return devname; }
|
||||
};
|
||||
|
||||
class NpingTargets {
|
||||
|
||||
private:
|
||||
|
|
@ -87,6 +98,7 @@ class NpingTargets {
|
|||
NpingTargets();
|
||||
~NpingTargets();
|
||||
int addSpec(char *spec);
|
||||
void addDevice(const char *dev);
|
||||
int getNextTargetSockAddr(struct sockaddr_storage *t, size_t *tlen);
|
||||
NpingTarget *getNextTarget();
|
||||
int rewind();
|
||||
|
|
@ -102,6 +114,7 @@ class NpingTargets {
|
|||
/* TODO: Make private */
|
||||
NpingTarget *currenths;
|
||||
std::vector<NpingTarget *> Targets;
|
||||
std::vector<NpingDevice *> devices;
|
||||
|
||||
}; /* End of class NpingTargets */
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ int ProbeMode::init_nsock(){
|
|||
if ((nsp = nsock_pool_new(NULL)) == NULL)
|
||||
nping_fatal(QT_3, "Failed to create new pool. QUITTING.\n");
|
||||
const char *device = o.getDevice();
|
||||
if (*device)
|
||||
if (device && *device)
|
||||
nsock_pool_set_device(nsp, device);
|
||||
|
||||
/* Allow broadcast addresses */
|
||||
|
|
@ -304,7 +304,7 @@ int ProbeMode::start(){
|
|||
|
||||
if( o.getMode()!=ARP && o.sendEth()==false ){
|
||||
/* Get socket descriptor. No need for it in ARP since we send at eth level */
|
||||
if ((rawipsd = netutil_raw_socket(o.issetDevice() ? o.getDevice() : NULL)) < 0 )
|
||||
if ((rawipsd = netutil_raw_socket(o.getDevice())) < 0 )
|
||||
nping_fatal(QT_3,"Couldn't acquire raw socket. Are you root?");
|
||||
}
|
||||
|
||||
|
|
@ -314,30 +314,33 @@ int ProbeMode::start(){
|
|||
|
||||
/* Set up libpcap */
|
||||
if(!o.disablePacketCapture()){
|
||||
const char *device = o.getDevice();
|
||||
if (!device)
|
||||
nping_fatal(QT_3, "Unable to determine device name. QUITTING.\n");
|
||||
/* Create new IOD for pcap */
|
||||
if ((pcap_nsi = nsock_iod_new(nsp, NULL)) == NULL)
|
||||
nping_fatal(QT_3, "Failed to create new nsock_iod. QUITTING.\n");
|
||||
|
||||
/* Open pcap */
|
||||
filterstring=getBPFFilterString();
|
||||
nping_print(DBG_2,"Opening pcap device %s", o.getDevice() );
|
||||
nping_print(DBG_2,"Opening pcap device %s", device);
|
||||
#ifdef WIN32
|
||||
/* Nping normally uses device names obtained through dnet for interfaces,
|
||||
* but Pcap has its own naming system. So the conversion is done here */
|
||||
if (!DnetName2PcapName(o.getDevice(), pcapdev, sizeof(pcapdev))) {
|
||||
if (!DnetName2PcapName(device, pcapdev, sizeof(pcapdev))) {
|
||||
/* Oh crap -- couldn't find the corresponding dev apparently.
|
||||
* Let's just go with what we have then ... */
|
||||
Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
|
||||
Strncpy(pcapdev, device, sizeof(pcapdev));
|
||||
}
|
||||
#else
|
||||
Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
|
||||
Strncpy(pcapdev, device, sizeof(pcapdev));
|
||||
#endif
|
||||
|
||||
rc = nsock_pcap_open(nsp, pcap_nsi, pcapdev, 8192,
|
||||
(o.spoofSource()) ? 1 : 0, filterstring);
|
||||
if (rc)
|
||||
nping_fatal(QT_3, "Error opening capture device %s\n", o.getDevice());
|
||||
nping_print(DBG_2,"Pcap device %s open successfully", o.getDevice());
|
||||
nping_fatal(QT_3, "Error opening capture device %s\n", device);
|
||||
nping_print(DBG_2,"Pcap device %s open successfully", device);
|
||||
}
|
||||
|
||||
/* Ready? Go! */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue