1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00

Allow layer-2 sending for non-Ethernet links; MAC addr optional

This commit is contained in:
dmiller
2025-06-26 19:03:01 +00:00
parent f2028a2007
commit fc71b7544d
5 changed files with 82 additions and 45 deletions

View File

@@ -1725,7 +1725,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id); this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id);
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
/* Mark as a timed probe. */ /* Mark as a timed probe. */
this->fp_probes[this->total_probes].setTimed(); this->fp_probes[this->total_probes].setTimed();
this->timed_probes++; this->timed_probes++;
@@ -1766,7 +1768,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID("IE1"); this->fp_probes[this->total_probes].setProbeID("IE1");
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
this->total_probes++; this->total_probes++;
/* ICMP Probe #2: Echo Request with badly ordered extension headers */ /* ICMP Probe #2: Echo Request with badly ordered extension headers */
@@ -1803,7 +1807,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID("IE2"); this->fp_probes[this->total_probes].setProbeID("IE2");
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
this->total_probes++; this->total_probes++;
/* ICMP Probe #3: Neighbor Solicitation. (only sent to on-link targets) */ /* ICMP Probe #3: Neighbor Solicitation. (only sent to on-link targets) */
@@ -1833,7 +1839,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID("NS"); this->fp_probes[this->total_probes].setProbeID("NS");
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
this->total_probes++; this->total_probes++;
} }
@@ -1862,7 +1870,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID("U1"); this->fp_probes[this->total_probes].setProbeID("U1");
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
this->total_probes++; this->total_probes++;
/* Set TECN probe */ /* Set TECN probe */
@@ -1879,7 +1889,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id); this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id);
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
this->total_probes++; this->total_probes++;
} }
i++; i++;
@@ -1904,7 +1916,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this; this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6); this->fp_probes[this->total_probes].setPacket(ip6);
this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id); this->fp_probes[this->total_probes].setProbeID(TCP_DESCS[i].id);
this->fp_probes[this->total_probes].setEthernet(this->target_host->SrcMACAddress(), this->target_host->NextHopMACAddress(), this->target_host->deviceName()); if (this->netctl->l2_frames()) {
this->fp_probes[this->total_probes].setEthernet(this->target_host);
}
this->total_probes++; this->total_probes++;
} }
@@ -2491,22 +2505,33 @@ size_t FPPacket::getLength() const {
* values, like this: instance.setEthernet(NULL, NULL, NULL); * values, like this: instance.setEthernet(NULL, NULL, NULL);
* Otherwise, pass the source address, the next hop address and the name of * Otherwise, pass the source address, the next hop address and the name of
* the network interface the packet should be injected through. */ * the network interface the packet should be injected through. */
int FPPacket::setEthernet(const u8 *src_mac, const u8 *dst_mac, const char *devname) { int FPPacket::setEthernet(const Target *target) {
if (src_mac == NULL || dst_mac == NULL) { const char *devname = target->deviceName();
memset(&(this->eth_hdr), 0, sizeof(struct eth_nfo)); this->link_eth = false;
this->link_eth = false;
return OP_FAILURE;
}
memcpy(this->eth_hdr.srcmac, src_mac, 6);
memcpy(this->eth_hdr.dstmac, dst_mac, 6);
this->link_eth = true;
if (devname != NULL) { if (devname != NULL) {
strncpy(this->eth_hdr.devname, devname, sizeof(this->eth_hdr.devname)-1); netutil_eth_t *ethsd = eth_open_cached(devname);
if ((this->eth_hdr.ethsd = eth_open_cached(devname)) == NULL) if (ethsd == NULL) {
fatal("%s: Failed to open ethernet device (%s)", __func__, devname); error("%s: Failed to open ethernet device (%s)", __func__, devname);
} else { }
this->eth_hdr.devname[0] = '\0'; else if (netutil_eth_can_send(ethsd)) {
this->eth_hdr.ethsd = NULL; this->link_eth = true;
if (netutil_eth_datalink(ethsd) == DLT_EN10MB){
const u8 *src_mac = target->SrcMACAddress();
const u8 *dst_mac = target->NextHopMACAddress();
if (src_mac == NULL || dst_mac == NULL) {
this->link_eth = false;
}
else {
memcpy(this->eth_hdr.srcmac, src_mac, 6);
memcpy(this->eth_hdr.dstmac, dst_mac, 6);
}
}
}
}
if (!this->link_eth) {
memset(&(this->eth_hdr), 0, sizeof(struct eth_nfo));
return OP_FAILURE;
} }
return OP_SUCCESS; return OP_SUCCESS;
} }

View File

@@ -167,7 +167,8 @@ class FPNetworkControl {
void response_reception_handler(nsock_pool nsp, nsock_event nse, void *arg); void response_reception_handler(nsock_pool nsp, nsock_event nse, void *arg);
bool request_slots(size_t num_packets); bool request_slots(size_t num_packets);
int cc_report_final_timeout(); int cc_report_final_timeout();
// Do we need to send l2 (ethernet) frames?
bool l2_frames() { return (rawsd < 0); }
}; };
/* +-----------+ /* +-----------+
@@ -249,7 +250,7 @@ class FPPacket {
int setTime(const struct timeval *tv = NULL); int setTime(const struct timeval *tv = NULL);
struct timeval getTime() const; struct timeval getTime() const;
int setPacket(PacketElement *pkt); int setPacket(PacketElement *pkt);
int setEthernet(const u8 *src_mac, const u8 *dst_mac, const char *devname); int setEthernet(const Target *target);
const struct eth_nfo *getEthernet() const; const struct eth_nfo *getEthernet() const;
const PacketElement *getPacket() const; const PacketElement *getPacket() const;
size_t getLength() const; size_t getLength() const;

View File

@@ -949,18 +949,23 @@ void UltraScanInfo::Init(std::vector<Target *> &Targets, const struct scan_lists
aren't doing a TCP connect scan, or if we're doing a ping scan that aren't doing a TCP connect scan, or if we're doing a ping scan that
requires it. */ requires it. */
if (isRawScan()) { if (isRawScan()) {
if (ping_scan_arp || (ping_scan_nd && o.sendpref != PACKET_SEND_IP_STRONG) || ((o.sendpref & PACKET_SEND_ETH) && const char *device = Targets[0]->deviceName();
(Targets[0]->ifType() == devt_ethernet if (ping_scan_arp || (ping_scan_nd && o.sendpref != PACKET_SEND_IP_STRONG) || (o.sendpref & PACKET_SEND_ETH)) {
#ifdef WIN32
|| (Targets[0]->ifType() == devt_loopback)
#endif
))) {
/* We'll send ethernet packets with dnet */ /* We'll send ethernet packets with dnet */
ethsd = eth_open_cached(Targets[0]->deviceName()); ethsd = eth_open_cached(device);
if (ethsd == NULL) if (ethsd == NULL) {
fatal("dnet: Failed to open device %s", Targets[0]->deviceName()); error("dnet: Failed to open device %s", device);
rawsd = -1; }
} else { else if (!netutil_eth_can_send(ethsd)) {
ethsd = NULL;
}
/* If eth failed, we can fall back to raw socket. The only exception is
* ARP ping, which needs Ethernet link. */
if (ping_scan_arp && (ethsd == NULL || netutil_eth_datalink(ethsd) != DLT_EN10MB)) {
fatal("ARP ping not supported on %s", device);
}
}
if (ethsd == NULL) {
#ifdef WIN32 #ifdef WIN32
win32_fatal_raw_sockets(Targets[0]->deviceName()); win32_fatal_raw_sockets(Targets[0]->deviceName());
#endif #endif

View File

@@ -969,13 +969,15 @@ UltraProbe *sendNDScanProbe(UltraScanInfo *USI, HostScanStats *hss,
ns_dst_ip6 = *hss->target->v6hostip(); ns_dst_ip6 = *hss->target->v6hostip();
if (USI->ethsd) { if (USI->ethsd) {
unsigned char ns_dst_mac[6] = {0x33, 0x33, 0xff}; if (netutil_eth_datalink(USI->ethsd) == DLT_EN10MB) {
ns_dst_mac[3] = ns_dst_ip6.s6_addr[13]; unsigned char ns_dst_mac[6] = {0x33, 0x33, 0xff};
ns_dst_mac[4] = ns_dst_ip6.s6_addr[14]; ns_dst_mac[3] = ns_dst_ip6.s6_addr[13];
ns_dst_mac[5] = ns_dst_ip6.s6_addr[15]; ns_dst_mac[4] = ns_dst_ip6.s6_addr[14];
ns_dst_mac[5] = ns_dst_ip6.s6_addr[15];
memcpy(eth.srcmac, hss->target->SrcMACAddress(), 6); memcpy(eth.srcmac, hss->target->SrcMACAddress(), 6);
memcpy(eth.dstmac, ns_dst_mac, 6); memcpy(eth.dstmac, ns_dst_mac, 6);
}
eth.ethsd = USI->ethsd; eth.ethsd = USI->ethsd;
eth.devname[0] = '\0'; eth.devname[0] = '\0';
ethptr = &eth; ethptr = &eth;
@@ -1159,8 +1161,10 @@ UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
u16 icmp_ident = (get_random_u16() % 0xffff) + 1; u16 icmp_ident = (get_random_u16() % 0xffff) + 1;
if (USI->ethsd) { if (USI->ethsd) {
memcpy(eth.srcmac, hss->target->SrcMACAddress(), 6); if (netutil_eth_datalink(USI->ethsd) == DLT_EN10MB) {
memcpy(eth.dstmac, hss->target->NextHopMACAddress(), 6); memcpy(eth.srcmac, hss->target->SrcMACAddress(), 6);
memcpy(eth.dstmac, hss->target->NextHopMACAddress(), 6);
}
eth.ethsd = USI->ethsd; eth.ethsd = USI->ethsd;
eth.devname[0] = '\0'; eth.devname[0] = '\0';
ethptr = &eth; ethptr = &eth;

View File

@@ -596,8 +596,10 @@ void Probe::send(int rawsd, netutil_eth_t *ethsd, struct timeval *now) {
/* Set up the Ethernet handle if we're using that. */ /* Set up the Ethernet handle if we're using that. */
if (ethsd != NULL) { if (ethsd != NULL) {
memcpy(eth.srcmac, host->target->SrcMACAddress(), 6); if (netutil_eth_datalink(ethsd) == DLT_EN10MB) {
memcpy(eth.dstmac, host->target->NextHopMACAddress(), 6); memcpy(eth.srcmac, host->target->SrcMACAddress(), 6);
memcpy(eth.dstmac, host->target->NextHopMACAddress(), 6);
}
eth.ethsd = ethsd; eth.ethsd = ethsd;
eth.devname[0] = '\0'; eth.devname[0] = '\0';
ethp = &eth; ethp = &eth;