masscan-mark-ii/src/main-initadapter.c

270 lines
11 KiB
C
Executable File

#include "masscan.h"
#include "util-logger.h"
#include "rawsock.h"
#include "rawsock-adapter.h"
#include "stack-arpv4.h"
#include "stack-ndpv6.h"
#include "stub-pcap-dlt.h"
/***************************************************************************
* Initialize the network adapter.
*
* This requires finding things like our IP address, MAC address, and router
* MAC address. The user could configure these things manually instead.
*
* Note that we don't update the "static" configuration with the discovered
* values, but instead return them as the "running" configuration. That's
* so if we pause and resume a scan, auto discovered values don't get saved
* in the configuration file.
***************************************************************************/
int
masscan_initialize_adapter(
struct Masscan *masscan,
unsigned index,
macaddress_t *source_mac,
macaddress_t *router_mac_ipv4,
macaddress_t *router_mac_ipv6
)
{
char *ifname;
char ifname2[256];
unsigned adapter_ip = 0;
unsigned is_usable_ipv4 = !massip_has_ipv4_targets(&masscan->targets); /* I don't understand this line, seems opposite */
unsigned is_usable_ipv6 = !massip_has_ipv6_targets(&masscan->targets); /* I don't understand this line, seems opposite */
ipaddress_formatted_t fmt;
/*
* ADAPTER/NETWORK-INTERFACE
*
* If no network interface was configured, we need to go hunt down
* the best Interface to use. We do this by choosing the first
* interface with a "default route" (aka. "gateway") defined
*/
if (masscan->nic[index].ifname[0])
ifname = masscan->nic[index].ifname;
else {
/* no adapter specified, so find a default one */
int err;
ifname2[0] = '\0';
err = rawsock_get_default_interface(ifname2, sizeof(ifname2));
if (err || ifname2[0] == '\0') {
LOG(0, "[-] FAIL: could not determine default interface\n");
LOG(0, " [hint] try \"--interface ethX\"\n");
return -1;
}
ifname = ifname2;
}
LOG(1, "[+] interface = %s\n", ifname);
/*
* START ADAPTER
*
* Once we've figured out which adapter to use, we now need to
* turn it on.
*/
masscan->nic[index].adapter = rawsock_init_adapter(
ifname,
masscan->is_pfring,
masscan->is_sendq,
masscan->nmap.packet_trace,
masscan->is_offline,
(void*)masscan->bpf_filter,
masscan->nic[index].is_vlan,
masscan->nic[index].vlan_id);
if (masscan->nic[index].adapter == 0) {
LOG(0, "[-] if:%s:init: failed\n", ifname);
return -1;
}
masscan->nic[index].link_type = masscan->nic[index].adapter->link_type;
LOG(1, "[+] interface-type = %u\n", masscan->nic[index].link_type);
rawsock_ignore_transmits(masscan->nic[index].adapter, ifname);
/*
* MAC ADDRESS
*
* This is the address we send packets from. It actually doesn't really
* matter what this address is, but to be a "responsible" citizen we
* try to use the hardware address in the network card.
*/
if (masscan->nic[index].link_type == PCAP_DLT_NULL) {
LOG(1, "[+] source-mac = %s\n", "none");
} else if (masscan->nic[index].link_type == PCAP_DLT_RAW) {
LOG(1, "[+] source-mac = %s\n", "none");
} else {
*source_mac = masscan->nic[index].source_mac;
if (masscan->nic[index].my_mac_count == 0) {
if (macaddress_is_zero(*source_mac)) {
rawsock_get_adapter_mac(ifname, source_mac->addr);
}
/* If still zero, then print error message */
if (macaddress_is_zero(*source_mac)) {
fprintf(stderr, "[-] FAIL: failed to detect MAC address of interface:"
" \"%s\"\n", ifname);
fprintf(stderr, " [hint] try something like "
"\"--source-mac 00-11-22-33-44-55\"\n");
return -1;
}
}
fmt = macaddress_fmt(*source_mac);
LOG(1, "[+] source-mac = %s\n", fmt.string);
}
/*
* IPv4 ADDRESS
*
* We need to figure out that IP address to send packets from. This
* is done by querying the adapter (or configured by user). If the
* adapter doesn't have one, then the user must configure one.
*/
if (massip_has_ipv4_targets(&masscan->targets)) {
adapter_ip = masscan->nic[index].src.ipv4.first;
if (adapter_ip == 0) {
adapter_ip = rawsock_get_adapter_ip(ifname);
masscan->nic[index].src.ipv4.first = adapter_ip;
masscan->nic[index].src.ipv4.last = adapter_ip;
masscan->nic[index].src.ipv4.range = 1;
}
if (adapter_ip == 0) {
/* We appear to have IPv4 targets, yet we cannot find an adapter
* to use for those targets. We are having trouble querying the
* operating system stack. */
LOG(0, "[-] FAIL: failed to detect IP of interface \"%s\"\n", ifname);
LOG(0, " [hint] did you spell the name correctly?\n");
LOG(0, " [hint] if it has no IP address, manually set with something like "
"\"--source-ip 198.51.100.17\"\n");
if (massip_has_ipv4_targets(&masscan->targets)) {
return -1;
}
}
fmt = ipv4address_fmt(adapter_ip);
LOG(1, "[+] source-ip = %s\n", fmt.string);
if (adapter_ip != 0)
is_usable_ipv4 = 1;
/*
* ROUTER MAC ADDRESS
*
* NOTE: this is one of the least understood aspects of the code. We must
* send packets to the local router, which means the MAC address (not
* IP address) of the router.
*
* Note: in order to ARP the router, we need to first enable the libpcap
* code above.
*/
*router_mac_ipv4 = masscan->nic[index].router_mac_ipv4;
if (masscan->is_offline) {
/* If we are doing offline benchmarking/testing, then create
* a fake MAC address fro the router */
memcpy(router_mac_ipv4->addr, "\x66\x55\x44\x33\x22\x11", 6);
} else if (masscan->nic[index].link_type == PCAP_DLT_NULL) {
/* If it's a VPN tunnel, then there is no Ethernet MAC address */
LOG(1, "[+] router-mac-ipv4 = %s\n", "implicit");
} else if (masscan->nic[index].link_type == PCAP_DLT_RAW) {
/* If it's a VPN tunnel, then there is no Ethernet MAC address */
LOG(1, "[+] router-mac-ipv4 = %s\n", "implicit");
} else if (macaddress_is_zero(*router_mac_ipv4)) {
ipv4address_t router_ipv4 = masscan->nic[index].router_ip;
int err = 0;
LOG(2, "[+] if(%s): looking for default gateway\n", ifname);
if (router_ipv4 == 0)
err = rawsock_get_default_gateway(ifname, &router_ipv4);
if (err == 0) {
fmt = ipv4address_fmt(router_ipv4);
LOG(1, "[+] router-ip = %s\n", fmt.string);
LOG(2, "[+] if(%s):arp: resolving IPv4 address\n", ifname);
stack_arp_resolve(
masscan->nic[index].adapter,
adapter_ip,
*source_mac,
router_ipv4,
router_mac_ipv4);
}
fmt = macaddress_fmt(*router_mac_ipv4);
LOG(1, "[+] router-mac-ipv4 = %s\n", fmt.string);
if (macaddress_is_zero(*router_mac_ipv4)) {
fmt = ipv4address_fmt(masscan->nic[index].router_ip);
LOG(0, "[-] FAIL: ARP timed-out resolving MAC address for router %s: \"%s\"\n", ifname, fmt.string);
LOG(0, " [hint] try \"--router ip 192.0.2.1\" to specify different router\n");
LOG(0, " [hint] try \"--router-mac 66-55-44-33-22-11\" instead to bypass ARP\n");
LOG(0, " [hint] try \"--interface eth0\" to change interface\n");
return -1;
}
}
}
/*
* IPv6 ADDRESS
*
* We need to figure out that IPv6 address to send packets from. This
* is done by querying the adapter (or configured by user). If the
* adapter doesn't have one, then the user must configure one.
*/
if (massip_has_ipv6_targets(&masscan->targets)) {
ipv6address adapter_ipv6 = masscan->nic[index].src.ipv6.first;
if (ipv6address_is_zero(adapter_ipv6)) {
adapter_ipv6 = rawsock_get_adapter_ipv6(ifname);
masscan->nic[index].src.ipv6.first = adapter_ipv6;
masscan->nic[index].src.ipv6.last = adapter_ipv6;
masscan->nic[index].src.ipv6.range = 1;
}
if (ipv6address_is_zero(adapter_ipv6)) {
fprintf(stderr, "[-] FAIL: failed to detect IPv6 address of interface \"%s\"\n",
ifname);
fprintf(stderr, " [hint] did you spell the name correctly?\n");
fprintf(stderr, " [hint] if it has no IP address, manually set with something like "
"\"--source-ip 2001:3b8::1234\"\n");
return -1;
}
fmt = ipv6address_fmt(adapter_ipv6);
LOG(1, "[+] source-ip = [%s]\n", fmt.string);
is_usable_ipv6 = 1;
/*
* ROUTER MAC ADDRESS
*/
*router_mac_ipv6 = masscan->nic[index].router_mac_ipv6;
if (masscan->is_offline) {
memcpy(router_mac_ipv6->addr, "\x66\x55\x44\x33\x22\x11", 6);
}
if (macaddress_is_zero(*router_mac_ipv6)) {
/* [synchronous]
* Wait for router neighbor notification. This may take
* some time */
stack_ndpv6_resolve(
masscan->nic[index].adapter,
adapter_ipv6,
*source_mac,
router_mac_ipv6);
}
fmt = macaddress_fmt(*router_mac_ipv6);
LOG(1, "[+] router-mac-ipv6 = %s\n", fmt.string);
if (macaddress_is_zero(*router_mac_ipv6)) {
fmt = ipv4address_fmt(masscan->nic[index].router_ip);
LOG(0, "[-] FAIL: NDP timed-out resolving MAC address for router %s: \"%s\"\n", ifname, fmt.string);
LOG(0, " [hint] try \"--router-mac-ipv6 66-55-44-33-22-11\" instead to bypass ARP\n");
LOG(0, " [hint] try \"--interface eth0\" to change interface\n");
return -1;
}
}
masscan->nic[index].is_usable = (is_usable_ipv4 & is_usable_ipv6);
LOG(2, "[+] if(%s): initialization done.\n", ifname);
return 0;
}