1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 12:41:29 +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].setPacket(ip6);
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. */
this->fp_probes[this->total_probes].setTimed();
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].setPacket(ip6);
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++;
/* 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].setPacket(ip6);
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++;
/* 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].setPacket(ip6);
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++;
}
@@ -1862,7 +1870,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this;
this->fp_probes[this->total_probes].setPacket(ip6);
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++;
/* 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].setPacket(ip6);
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++;
}
i++;
@@ -1904,7 +1916,9 @@ int FPHost6::build_probe_list() {
this->fp_probes[this->total_probes].host = this;
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].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++;
}
@@ -2491,22 +2505,33 @@ size_t FPPacket::getLength() const {
* values, like this: instance.setEthernet(NULL, NULL, NULL);
* Otherwise, pass the source address, the next hop address and the name of
* the network interface the packet should be injected through. */
int FPPacket::setEthernet(const u8 *src_mac, const u8 *dst_mac, const char *devname) {
if (src_mac == NULL || dst_mac == NULL) {
memset(&(this->eth_hdr), 0, sizeof(struct eth_nfo));
int FPPacket::setEthernet(const Target *target) {
const char *devname = target->deviceName();
this->link_eth = false;
return OP_FAILURE;
if (devname != NULL) {
netutil_eth_t *ethsd = eth_open_cached(devname);
if (ethsd == NULL) {
error("%s: Failed to open ethernet device (%s)", __func__, devname);
}
else if (netutil_eth_can_send(ethsd)) {
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);
this->link_eth = true;
if (devname != NULL) {
strncpy(this->eth_hdr.devname, devname, sizeof(this->eth_hdr.devname)-1);
if ((this->eth_hdr.ethsd = eth_open_cached(devname)) == NULL)
fatal("%s: Failed to open ethernet device (%s)", __func__, devname);
} else {
this->eth_hdr.devname[0] = '\0';
this->eth_hdr.ethsd = NULL;
}
}
}
}
if (!this->link_eth) {
memset(&(this->eth_hdr), 0, sizeof(struct eth_nfo));
return OP_FAILURE;
}
return OP_SUCCESS;
}

View File

@@ -167,7 +167,8 @@ class FPNetworkControl {
void response_reception_handler(nsock_pool nsp, nsock_event nse, void *arg);
bool request_slots(size_t num_packets);
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);
struct timeval getTime() const;
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 PacketElement *getPacket() 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
requires it. */
if (isRawScan()) {
if (ping_scan_arp || (ping_scan_nd && o.sendpref != PACKET_SEND_IP_STRONG) || ((o.sendpref & PACKET_SEND_ETH) &&
(Targets[0]->ifType() == devt_ethernet
#ifdef WIN32
|| (Targets[0]->ifType() == devt_loopback)
#endif
))) {
const char *device = Targets[0]->deviceName();
if (ping_scan_arp || (ping_scan_nd && o.sendpref != PACKET_SEND_IP_STRONG) || (o.sendpref & PACKET_SEND_ETH)) {
/* We'll send ethernet packets with dnet */
ethsd = eth_open_cached(Targets[0]->deviceName());
if (ethsd == NULL)
fatal("dnet: Failed to open device %s", Targets[0]->deviceName());
rawsd = -1;
} else {
ethsd = eth_open_cached(device);
if (ethsd == NULL) {
error("dnet: Failed to open device %s", device);
}
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
win32_fatal_raw_sockets(Targets[0]->deviceName());
#endif

View File

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