mirror of
https://github.com/nmap/nmap.git
synced 2026-08-04 14:49:29 +00:00
Consolidate getNextHopMAC to libnetutil
This commit is contained in:
parent
8d7038e51e
commit
738455f46c
6 changed files with 125 additions and 176 deletions
|
|
@ -518,6 +518,45 @@ int ip_is_reserved(const struct sockaddr_storage *addr)
|
|||
return addrset_contains(reserved, (struct sockaddr *)addr);
|
||||
}
|
||||
|
||||
bool getNextHopMAC(const char *iface, const u8 *srcmac, const struct sockaddr_storage *srcss,
|
||||
const struct sockaddr_storage *dstss, u8 *dstmac) {
|
||||
arp_t *a;
|
||||
struct arp_entry ae;
|
||||
|
||||
/* First, let us check the Nmap arp cache ... */
|
||||
if (mac_cache_get(dstss, dstmac))
|
||||
return true;
|
||||
|
||||
/* Maybe the system ARP cache will be more helpful */
|
||||
a = arp_open();
|
||||
if (a) {
|
||||
addr_ston((sockaddr *) dstss, &ae.arp_pa);
|
||||
if (arp_get(a, &ae) == 0) {
|
||||
mac_cache_set(dstss, ae.arp_ha.addr_eth.data);
|
||||
memcpy(dstmac, ae.arp_ha.addr_eth.data, 6);
|
||||
arp_close(a);
|
||||
return true;
|
||||
}
|
||||
arp_close(a);
|
||||
}
|
||||
|
||||
/* OK, the last choice is to send our own damn ARP request (and
|
||||
retransmissions if necessary) to determine the MAC */
|
||||
if (dstss->ss_family == AF_INET) {
|
||||
if (doArp(iface, srcmac, srcss, dstss, dstmac, NULL)) {
|
||||
mac_cache_set(dstss, dstmac);
|
||||
return true;
|
||||
}
|
||||
} else if (dstss->ss_family == AF_INET6) {
|
||||
if (doND(iface, srcmac, srcss, dstss, dstmac, NULL)) {
|
||||
mac_cache_set(dstss, dstmac);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A trivial functon that maintains a cache of IP to MAC Address
|
||||
entries. If the command is MACCACHE_GET, this func looks for the
|
||||
IPv4 address in ss and fills in the 'mac' parameter and returns
|
||||
|
|
|
|||
|
|
@ -173,7 +173,8 @@ struct addrinfo *resolve_all(const char *hostname, int pf);
|
|||
*/
|
||||
int ip_is_reserved(const struct sockaddr_storage *addr);
|
||||
|
||||
|
||||
bool getNextHopMAC(const char *iface, const u8 *srcmac, const struct sockaddr_storage *srcss,
|
||||
const struct sockaddr_storage *dstss, u8 *dstmac);
|
||||
|
||||
/* A couple of trivial functions that maintain a cache of IP to MAC
|
||||
* Address entries. Function mac_cache_get() looks for the IPv4 address
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@
|
|||
#endif
|
||||
|
||||
#include "NpingTarget.h"
|
||||
#include <dnet.h>
|
||||
#include "nbase.h"
|
||||
#include "nping.h"
|
||||
#include "output.h"
|
||||
|
|
@ -735,9 +734,7 @@ u16 NpingTarget::getICMPIdentifier(){
|
|||
bool NpingTarget::determineNextHopMACAddress() {
|
||||
struct sockaddr_storage targetss, srcss;
|
||||
size_t sslen;
|
||||
arp_t *a;
|
||||
u8 mac[6];
|
||||
struct arp_entry ae;
|
||||
|
||||
if (this->getDeviceType() != devt_ethernet)
|
||||
return false; /* Duh. */
|
||||
|
|
@ -760,57 +757,12 @@ bool NpingTarget::determineNextHopMACAddress() {
|
|||
fatal("%s: Failed to determine nextHop to target", __func__);
|
||||
}
|
||||
|
||||
/* First, let us check the ARP cache ... */
|
||||
if (mac_cache_get(&targetss, mac)) {
|
||||
this->setNextHopMACAddress(mac);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Maybe the system ARP cache will be more helpful */
|
||||
nping_print(DBG_3," > Checking system's ARP cache...");
|
||||
a = arp_open();
|
||||
if (a) {
|
||||
addr_ston((sockaddr *)&targetss, &ae.arp_pa);
|
||||
if (arp_get(a, &ae) == 0) {
|
||||
mac_cache_set(&targetss, ae.arp_ha.addr_eth.data);
|
||||
this->setNextHopMACAddress(ae.arp_ha.addr_eth.data);
|
||||
arp_close(a);
|
||||
nping_print(DBG_3," > Success: Entry found [%s]", this->getNextHopMACStr() );
|
||||
return true;
|
||||
}
|
||||
arp_close(a);
|
||||
nping_print(DBG_3," > No relevant entries found in system's ARP cache.");
|
||||
}
|
||||
else {
|
||||
nping_print(DBG_3," > Failed to open system's ARP cache.");
|
||||
}
|
||||
|
||||
|
||||
/* OK, the last choice is to send our own damn ARP request (and
|
||||
retransmissions if necessary) to determine the MAC */
|
||||
/* We first try sending the ARP with our spoofed IP address on it */
|
||||
if( this->spoofingSourceAddress() ){
|
||||
nping_print(DBG_3," > Sending ARP request using spoofed IP %s...", this->getSpoofedSourceIPStr() );
|
||||
this->getSpoofedSourceSockAddr(&srcss, NULL);
|
||||
if (doArp(this->getDeviceName(), this->getSrcMACAddress(), &srcss, &targetss, mac, NULL)) {
|
||||
mac_cache_set(&targetss, mac);
|
||||
this->setNextHopMACAddress(mac);
|
||||
nping_print(DBG_4," > Success: 1 ARP response received [%s]", this->getNextHopMACStr() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
nping_print(DBG_3," > No ARP responses received." );
|
||||
|
||||
/* If our spoofed IP address didn't work, try our real IP */
|
||||
nping_print(DBG_4," > Sending ARP request using our real IP %s...", this->getSourceIPStr() );
|
||||
this->getSourceSockAddr(&srcss, NULL);
|
||||
if (doArp(this->getDeviceName(), this->getSrcMACAddress(), &srcss, &targetss, mac, NULL)) {
|
||||
mac_cache_set(&targetss, mac);
|
||||
if (getNextHopMAC(this->getDeviceName(), this->getSrcMACAddress(),
|
||||
&srcss, &targetss, mac)) {
|
||||
this->setNextHopMACAddress(mac);
|
||||
nping_print(DBG_3," > Success: 1 ARP response received [%s]", this->getNextHopMACStr() );
|
||||
return true;
|
||||
}
|
||||
nping_print(DBG_3," > No ARP responses received" );
|
||||
|
||||
/* I'm afraid that we couldn't find it! Maybe it doesn't exist?*/
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -226,89 +226,90 @@ int NpingTargets::processSpecs(){
|
|||
|
||||
/* Get next host IP address and, if it is a named host, its hostname */
|
||||
while ( this->getNextTargetAddressAndName(&ss, &slen, buff, MAX_NPING_HOSTNAME_LEN) == OP_SUCCESS ){
|
||||
NpingTarget *mytarget = new NpingTarget();
|
||||
mytarget->setTargetSockAddr(&ss, slen);
|
||||
if( buff[0]=='\0')
|
||||
mytarget->setNamedHost(false);
|
||||
else{
|
||||
mytarget->setSuppliedHostName(buff);
|
||||
mytarget->setNamedHost(true);
|
||||
}
|
||||
|
||||
/* For the moment, we only run this code if we are not dealing with IPv6 */
|
||||
if( !o.ipv6() ){
|
||||
|
||||
/* Get all the information needed to send packets to this target.
|
||||
* (Only in case we are not in unprivileged modes) */
|
||||
if(o.getMode()!=TCP_CONNECT && o.getMode()!=UDP_UNPRIV){
|
||||
result=route_dst( &ss, &rnfo, o.getDevice(), NULL );
|
||||
if(result==false){
|
||||
nping_warning(QT_2, "Failed to determine route to host %s. Skipping it...", mytarget->getTargetIPstr() );
|
||||
delete mytarget;
|
||||
continue;
|
||||
}
|
||||
#ifdef WIN32
|
||||
if (!o.havePcap() && rnfo.ii.device_type == devt_loopback){
|
||||
nping_warning(QT_2, "Skipping %s because Windows does not allow localhost scans (try --unprivileged).", mytarget->getTargetIPstr() );
|
||||
delete mytarget;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Determine next hop */
|
||||
if( rnfo.direct_connect ){
|
||||
mytarget->setDirectlyConnected(true);
|
||||
mytarget->setNextHop(&ss, slen);
|
||||
}
|
||||
else{
|
||||
mytarget->setDirectlyConnected(false);
|
||||
mytarget->setNextHop(&rnfo.nexthop, sizeof(struct sockaddr_storage));
|
||||
}
|
||||
/* Source IP address that we should use when targeting this host */
|
||||
mytarget->setSourceSockAddr(&rnfo.srcaddr, sizeof(struct sockaddr_storage));
|
||||
|
||||
/* If user requested to spoof IP source address, set it */
|
||||
if( o.spoofSource() ){
|
||||
mytarget->setSpoofedSourceSockAddr( o.getSourceSockAddr(), sizeof(struct sockaddr_storage));
|
||||
}
|
||||
|
||||
/* Network interface */
|
||||
mytarget->setDeviceNames( rnfo.ii.devname, rnfo.ii.devfullname );
|
||||
mytarget->setDeviceType( rnfo.ii.device_type );
|
||||
|
||||
/* Set source MAC address */
|
||||
mytarget->setSrcMACAddress( rnfo.ii.mac );
|
||||
|
||||
if( rnfo.ii.device_up == false )
|
||||
nping_warning(QT_2, "Device used for target host %s seems to be down.", mytarget->getTargetIPstr());
|
||||
|
||||
/* Determine next hop MAC address and target MAC address */
|
||||
if( o.sendEth() ){
|
||||
#ifdef WIN32
|
||||
if (o.havePcap() && rnfo.ii.device_type == devt_loopback) {
|
||||
mytarget->setNextHopMACAddress(mytarget->getSrcMACAddress());
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
mytarget->determineNextHopMACAddress();
|
||||
mytarget->determineTargetMACAddress(); /* Sets Target MAC only if is directly connected to us */
|
||||
#ifdef WIN32
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* If we are in debug mode print target details */
|
||||
if(o.getDebugging() >= DBG_3)
|
||||
mytarget->printTargetDetails();
|
||||
}
|
||||
}else{
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ss;
|
||||
memset(&ss, 0, sizeof(sockaddr_storage));
|
||||
s6->sin6_family=AF_INET6;
|
||||
mytarget->setSourceSockAddr(&ss, sizeof(struct sockaddr_storage));
|
||||
NpingTarget *mytarget = new NpingTarget();
|
||||
mytarget->setTargetSockAddr(&ss, slen);
|
||||
if( buff[0]=='\0')
|
||||
mytarget->setNamedHost(false);
|
||||
else{
|
||||
mytarget->setSuppliedHostName(buff);
|
||||
mytarget->setNamedHost(true);
|
||||
}
|
||||
|
||||
/* Insert current target into targets array */
|
||||
this->Targets.push_back(mytarget);
|
||||
if (o.spoofSource()) {
|
||||
mytarget->setSourceSockAddr(o.getSourceSockAddr(), sizeof(sockaddr_storage));
|
||||
}
|
||||
|
||||
/* Get all the information needed to send packets to this target.
|
||||
* (Only in case we are not in unprivileged modes) */
|
||||
if(o.getMode()!=TCP_CONNECT && o.getMode()!=UDP_UNPRIV){
|
||||
result=route_dst( &ss, &rnfo, o.getDevice(),
|
||||
o.spoofSource() ? o.getSourceSockAddr() : NULL );
|
||||
if(result==false){
|
||||
nping_warning(QT_2, "Failed to determine route to host %s. Skipping it...", mytarget->getTargetIPstr() );
|
||||
delete mytarget;
|
||||
continue;
|
||||
}
|
||||
#ifdef WIN32
|
||||
if (!o.havePcap() && rnfo.ii.device_type == devt_loopback){
|
||||
nping_warning(QT_2, "Skipping %s because Windows does not allow localhost scans (try --unprivileged).", mytarget->getTargetIPstr() );
|
||||
delete mytarget;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
printf("%s %s", rnfo.ii.devname, rnfo.ii.devfullname);
|
||||
printf(" srcaddr %s", inet_ntop_ez(&rnfo.srcaddr, sizeof(rnfo.srcaddr)));
|
||||
if (rnfo.direct_connect)
|
||||
printf(" direct");
|
||||
else
|
||||
printf(" nexthop %s\n", inet_ntop_ez(&rnfo.nexthop, sizeof(rnfo.nexthop)));
|
||||
/* Determine next hop */
|
||||
if( rnfo.direct_connect ){
|
||||
mytarget->setDirectlyConnected(true);
|
||||
mytarget->setNextHop(&ss, slen);
|
||||
}
|
||||
else{
|
||||
mytarget->setDirectlyConnected(false);
|
||||
mytarget->setNextHop(&rnfo.nexthop, sizeof(struct sockaddr_storage));
|
||||
}
|
||||
/* Source IP address that we should use when targeting this host */
|
||||
mytarget->setSourceSockAddr(&rnfo.srcaddr, sizeof(struct sockaddr_storage));
|
||||
|
||||
/* If user requested to spoof IP source address, set it */
|
||||
if( o.spoofSource() ){
|
||||
mytarget->setSpoofedSourceSockAddr( o.getSourceSockAddr(), sizeof(struct sockaddr_storage));
|
||||
}
|
||||
|
||||
/* Network interface */
|
||||
mytarget->setDeviceNames( rnfo.ii.devname, rnfo.ii.devfullname );
|
||||
mytarget->setDeviceType( rnfo.ii.device_type );
|
||||
|
||||
/* Set source MAC address */
|
||||
mytarget->setSrcMACAddress( rnfo.ii.mac );
|
||||
|
||||
if( rnfo.ii.device_up == false )
|
||||
nping_warning(QT_2, "Device used for target host %s seems to be down.", mytarget->getTargetIPstr());
|
||||
|
||||
/* Determine next hop MAC address and target MAC address */
|
||||
if( o.sendEth() ){
|
||||
#ifdef WIN32
|
||||
if (o.havePcap() && rnfo.ii.device_type == devt_loopback) {
|
||||
mytarget->setNextHopMACAddress(mytarget->getSrcMACAddress());
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
mytarget->determineNextHopMACAddress();
|
||||
mytarget->determineTargetMACAddress(); /* Sets Target MAC only if is directly connected to us */
|
||||
#ifdef WIN32
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* If we are in debug mode print target details */
|
||||
if(o.getDebugging() >= DBG_3)
|
||||
mytarget->printTargetDetails();
|
||||
}
|
||||
|
||||
/* Insert current target into targets array */
|
||||
this->Targets.push_back(mytarget);
|
||||
}
|
||||
|
||||
/* getNextTarget() checks this to ensure user has previously called processSpecs() */
|
||||
|
|
|
|||
41
tcpip.cc
41
tcpip.cc
|
|
@ -1561,47 +1561,6 @@ bool setTargetNextHopMAC(Target *target) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Like to getTargetNextHopMAC(), but for arbitrary hosts (not Targets) */
|
||||
bool getNextHopMAC(const char *iface, const u8 *srcmac, const struct sockaddr_storage *srcss,
|
||||
const struct sockaddr_storage *dstss, u8 *dstmac) {
|
||||
arp_t *a;
|
||||
struct arp_entry ae;
|
||||
|
||||
/* First, let us check the Nmap arp cache ... */
|
||||
if (mac_cache_get(dstss, dstmac))
|
||||
return true;
|
||||
|
||||
/* Maybe the system ARP cache will be more helpful */
|
||||
a = arp_open();
|
||||
if (a) {
|
||||
addr_ston((sockaddr *) dstss, &ae.arp_pa);
|
||||
if (arp_get(a, &ae) == 0) {
|
||||
mac_cache_set(dstss, ae.arp_ha.addr_eth.data);
|
||||
memcpy(dstmac, ae.arp_ha.addr_eth.data, 6);
|
||||
arp_close(a);
|
||||
return true;
|
||||
}
|
||||
arp_close(a);
|
||||
}
|
||||
|
||||
/* OK, the last choice is to send our own damn ARP request (and
|
||||
retransmissions if necessary) to determine the MAC */
|
||||
if (dstss->ss_family == AF_INET) {
|
||||
if (doArp(iface, srcmac, srcss, dstss, dstmac, PacketTrace::traceArp)) {
|
||||
mac_cache_set(dstss, dstmac);
|
||||
return true;
|
||||
}
|
||||
} else if (dstss->ss_family == AF_INET6) {
|
||||
if (doND(iface, srcmac, srcss, dstss, dstmac, PacketTrace::traceND)) {
|
||||
mac_cache_set(dstss, dstmac);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int nmap_route_dst(const struct sockaddr_storage *dst, struct route_nfo *rnfo) {
|
||||
struct sockaddr_storage spoofss;
|
||||
size_t spoofsslen;
|
||||
|
|
|
|||
3
tcpip.h
3
tcpip.h
|
|
@ -339,9 +339,6 @@ int setTargetMACIfAvailable(Target *target, struct link_header *linkhdr,
|
|||
after an ARP scan if many directly connected machines are involved. */
|
||||
bool setTargetNextHopMAC(Target *target);
|
||||
|
||||
bool getNextHopMAC(const char *iface, const u8 *srcmac, const struct sockaddr_storage *srcss,
|
||||
const struct sockaddr_storage *dstss, u8 *dstmac);
|
||||
|
||||
/* If rcvdtime is non-null and a packet is returned, rcvd will be
|
||||
filled with the time that packet was captured from the wire by
|
||||
pcap. If linknfo is not NULL, lnkinfo->headerlen and
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue