1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-10 09:49:05 +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:
david
2010-03-12 05:23:50 +00:00
parent d109ff13d8
commit bc132b963c
2 changed files with 40 additions and 9 deletions

View File

@@ -2,6 +2,15 @@
[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
addresses and netmasks. For example, with this configuration:

View File

@@ -95,6 +95,7 @@
#endif
#include "portreasons.h"
#include <dnet.h>
#include <net/if_arp.h>
#include "tcpip.h"
#include "NmapOps.h"
#include "Target.h"
@@ -2522,6 +2523,20 @@ static bool NmapArpCache(int command, struct sockaddr_storage *ss, u8 *mac) {
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
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)
@@ -2538,6 +2553,7 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
u8 *p;
int timedout = 0;
int badcounter = 0;
unsigned int offset;
struct timeval tv_start, tv_end;
if (!pd)
@@ -2555,8 +2571,14 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
if ((datalink = pcap_datalink(pd)) < 0)
fatal("Cannot obtain datalink information: %s", pcap_geterr(pd));
if (datalink != DLT_EN10MB)
fatal("%s called on interfaces that is datatype %d rather than DLT_EN10MB (%d)", __func__, datalink, DLT_EN10MB);
if (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) {
gettimeofday(&tv_start, NULL);
@@ -2582,14 +2604,14 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
else
p = (u8 *) pcap_next(pd, &head);
if (p && head.caplen >= 42) { /* >= because Ethernet padding makes 60 */
/* frame type 0x0806 (arp), hw type eth (0x0001), prot ip (0x0800),
if (p && head.caplen >= offset + 28) {
/* hw type eth (0x0001), prot ip (0x0800),
hw size (0x06), prot size (0x04) */
if (memcmp(p + 12, "\x08\x06\x00\x01\x08\x00\x06\x04\x00\x02", 10) ==
0) {
memcpy(sendermac, p + 22, 6);
if (frame_is_arp(p, datalink) &&
memcmp(p + offset, "\x00\x01\x08\x00\x06\x04\x00\x02", 8) == 0) {
memcpy(sendermac, p + offset + 8, 6);
/* I think alignment should allow this ... */
memcpy(&senderIP->s_addr, p + 28, 4);
memcpy(&senderIP->s_addr, p + offset + 14, 4);
break;
}
}
@@ -2631,7 +2653,7 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
assert(head.ts.tv_sec);
#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;
}