mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 17:59:04 +00:00
Make read_arp_reply_pcap work with a libpcap datalink type of
DLT_LINUX_SLL, as well as the DLT_EN10MB that was formerly supported. This type is used on some interfaces where Linux doesn't reliably retain the link-layer header, and when capturing on the "any" device. On such interfaces, you would get the error read_arp_reply_pcap called on interfaces that is datatype 113 rather than DLT_EN10MB (1) For more on this datalink type, see pcap-linktype(7) http://wiki.wireshark.org/SLL I tested this by hacking scan_engine.cc to use the "any" device: --- scan_engine.cc (revision 16972) +++ scan_engine.cc (working copy) @@ -4882,7 +4882,7 @@ } } - USI->pd = my_pcap_open_live(Targets[0]->deviceName(), 100, (o.spoofsource)? 1 : 0, pcap_selectable_fd_valid()? 200 : 2); + USI->pd = my_pcap_open_live("any" /*Targets[0]->deviceName()*/, 100, (o.spoofsource)? 1 : 0, pcap_selectable_fd_valid()? 200 : 2); if (USI->ping_scan_arp){ /* Some OSs including Windows 7 and Solaris 10 have been seen to send their ARP replies to the broadcast address, not to the (unicast) address that I had to use a newer version of libpcap from git. The 1.0.0 that we ship has a bug that keeps "any" from working. You would get SIOCGIFHWADDR: No such device.
This commit is contained in:
@@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
[NOT YET RELEASED]
|
[NOT YET RELEASED]
|
||||||
|
|
||||||
|
o ARP requests now work with libpcap Linux "cooked" encapsulation.
|
||||||
|
According to http://wiki.wireshark.org/SLL, this encapsulation is
|
||||||
|
used on devices "where the native link layer header isn't available
|
||||||
|
or can't be used." Before this, attempting any ARP operation on such
|
||||||
|
an interface would fail with the error
|
||||||
|
read_arp_reply_pcap called on interfaces that is datatype 113
|
||||||
|
rather than DLT_EN10MB (1)
|
||||||
|
[David]
|
||||||
|
|
||||||
o Nmap now honors routing table entries that override interface
|
o Nmap now honors routing table entries that override interface
|
||||||
addresses and netmasks. For example, with this configuration:
|
addresses and netmasks. For example, with this configuration:
|
||||||
|
|
||||||
|
|||||||
40
tcpip.cc
40
tcpip.cc
@@ -95,6 +95,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "portreasons.h"
|
#include "portreasons.h"
|
||||||
#include <dnet.h>
|
#include <dnet.h>
|
||||||
|
#include <net/if_arp.h>
|
||||||
#include "tcpip.h"
|
#include "tcpip.h"
|
||||||
#include "NmapOps.h"
|
#include "NmapOps.h"
|
||||||
#include "Target.h"
|
#include "Target.h"
|
||||||
@@ -2522,6 +2523,20 @@ static bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true if the captured frame is ARP. This function understands the
|
||||||
|
datalink types DLT_EN10MB and DLT_LINUX_SLL. */
|
||||||
|
static bool frame_is_arp(const u8 *frame, int datalink) {
|
||||||
|
if (datalink == DLT_EN10MB) {
|
||||||
|
return ntohs(*((u16 *) (frame + 12))) == ETH_TYPE_ARP;
|
||||||
|
} else if (datalink == DLT_LINUX_SLL) {
|
||||||
|
return ntohs(*((u16 *) (frame + 2))) == ARPHRD_ETHER && /* sll_hatype */
|
||||||
|
ntohs(*((u16 *) (frame + 4))) == 6 && /* sll_halen */
|
||||||
|
ntohs(*((u16 *) (frame + 14))) == ETH_TYPE_ARP; /* sll_protocol */
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
|
/* Attempts to read one IPv4/Ethernet ARP reply packet from the pcap
|
||||||
descriptor pd. If it receives one, fills in sendermac (must pass
|
descriptor pd. If it receives one, fills in sendermac (must pass
|
||||||
in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care)
|
in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care)
|
||||||
@@ -2538,6 +2553,7 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
|
|||||||
u8 *p;
|
u8 *p;
|
||||||
int timedout = 0;
|
int timedout = 0;
|
||||||
int badcounter = 0;
|
int badcounter = 0;
|
||||||
|
unsigned int offset;
|
||||||
struct timeval tv_start, tv_end;
|
struct timeval tv_start, tv_end;
|
||||||
|
|
||||||
if (!pd)
|
if (!pd)
|
||||||
@@ -2555,8 +2571,14 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
|
|||||||
if ((datalink = pcap_datalink(pd)) < 0)
|
if ((datalink = pcap_datalink(pd)) < 0)
|
||||||
fatal("Cannot obtain datalink information: %s", pcap_geterr(pd));
|
fatal("Cannot obtain datalink information: %s", pcap_geterr(pd));
|
||||||
|
|
||||||
if (datalink != DLT_EN10MB)
|
if (datalink == DLT_EN10MB) {
|
||||||
fatal("%s called on interfaces that is datatype %d rather than DLT_EN10MB (%d)", __func__, datalink, DLT_EN10MB);
|
offset = ETH_HDR_LEN;
|
||||||
|
} else if (datalink == DLT_LINUX_SLL) {
|
||||||
|
/* The datalink type is Linux "cooked" sockets. See pcap-linktype(7). */
|
||||||
|
offset = 16;
|
||||||
|
} else {
|
||||||
|
fatal("%s called on interface that is datatype %d rather than DLT_EN10MB (%d) or DLT_LINUX_SLL (%d)", __func__, datalink, DLT_EN10MB, DLT_LINUX_SLL);
|
||||||
|
}
|
||||||
|
|
||||||
if (to_usec > 0) {
|
if (to_usec > 0) {
|
||||||
gettimeofday(&tv_start, NULL);
|
gettimeofday(&tv_start, NULL);
|
||||||
@@ -2582,14 +2604,14 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
|
|||||||
else
|
else
|
||||||
p = (u8 *) pcap_next(pd, &head);
|
p = (u8 *) pcap_next(pd, &head);
|
||||||
|
|
||||||
if (p && head.caplen >= 42) { /* >= because Ethernet padding makes 60 */
|
if (p && head.caplen >= offset + 28) {
|
||||||
/* frame type 0x0806 (arp), hw type eth (0x0001), prot ip (0x0800),
|
/* hw type eth (0x0001), prot ip (0x0800),
|
||||||
hw size (0x06), prot size (0x04) */
|
hw size (0x06), prot size (0x04) */
|
||||||
if (memcmp(p + 12, "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x02", 10) ==
|
if (frame_is_arp(p, datalink) &&
|
||||||
0) {
|
memcmp(p + offset, "\x00\x01\x08\x00\x06\x04\x00\x02", 8) == 0) {
|
||||||
memcpy(sendermac, p + 22, 6);
|
memcpy(sendermac, p + offset + 8, 6);
|
||||||
/* I think alignment should allow this ... */
|
/* I think alignment should allow this ... */
|
||||||
memcpy(&senderIP->s_addr, p + 28, 4);
|
memcpy(&senderIP->s_addr, p + offset + 14, 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2631,7 +2653,7 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
|
|||||||
assert(head.ts.tv_sec);
|
assert(head.ts.tv_sec);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
PacketTrace::traceArp(PacketTrace::RCVD, (u8 *) p + ETH_HDR_LEN, ARP_HDR_LEN + ARP_ETHIP_LEN, rcvdtime);
|
PacketTrace::traceArp(PacketTrace::RCVD, (u8 *) p + offset, ARP_HDR_LEN + ARP_ETHIP_LEN, rcvdtime);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user