From aaf6495447cc657be46c28434a9e4342fdc8de8d Mon Sep 17 00:00:00 2001 From: fyodor Date: Wed, 11 Jan 2006 01:32:04 +0000 Subject: [PATCH] Nmap 3.97Shmoo --- CHANGELOG | 32 +++++++++++++++++++++++++++----- Makefile.in | 8 ++++---- NmapOps.cc | 6 ++++++ NmapOps.h | 4 ++++ config.h.in | 6 ++++++ configure | 5 ++++- configure.ac | 2 +- docs/nmap.1 | 19 ++++++++++++++++--- docs/nmap.usage.txt | 5 ++++- mswin32/nmap.vcproj | 10 ++++++++-- nmap.cc | 34 ++++++++++++++++++---------------- nmap_winconfig.h | 2 +- osscan.cc | 3 +++ scripts/Makefile | 2 +- scripts/sign_release.pl | 1 + targets.cc | 6 ++++++ tcpip.cc | 13 ++++++++++++- 17 files changed, 122 insertions(+), 36 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3d70e14d3..fe577daf7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,16 +1,38 @@ # Nmap Changelog ($Id$); -*-text-*- -UNRELEASED +3.97Shmoo -o Added real time status reporting, as documented at +o Reverse DNS resolution is now done in parallel rather than one at a + time. All scans of large networks (particularly list, ping and + just-a-few-ports scans) should benefit substantially from this + change. If you encounter any problems, please let us know. The new + --system_dns option was added so you can use the (slow) system + resolver if you prefer that for some reason. You can specify a + comma separated list of DNS server IP addresses for Nmap to use with + the new --dns_servers option. Otherwise, Nmap looks in + /etc/resolve.conf (UNIX) or the system registry (Windows) to obtain + the nameservers already configured for your system. This excellent + patch was written by Doug Hoyte (doug(a)hcsw.org). + +o Added run time interaction as documented at http://www.insecure.org/nmap/man/man-runtime-interaction.html . While Nmap is running, you can now press 'v' to increase verbosity, 'd' to increase the debugging level, 'p' to enable packet tracing, or the capital versions (V,D,P) to do the opposite. Any other key (such as enter) will print out a status message giving the estimated time until scan completion. This only works on UNIX for now. Do we - have any volunteers to add Windows support? This feature was - created by Paul Tarjan (ptarjan(a)stanford.edu) as part of the - Google Summer of Code. + have any volunteers to add Windows support? You would need to + change a handful of UNIX-specific termio calls with the Windows + equivalents. This feature was created by Paul Tarjan + (ptarjan(a)stanford.edu) as part of the Google Summer of Code. + +o Added the --badsum option, which causes Nmap to use invalid TCP or + UDP checksums for packets sent to target hosts. Since + virtually all host IP stacks properly drop these packets, any + responses received are likely coming from a firewall or IDS that + didn't bother to verify the checksum. For more details on this + technique, see http://www.phrack.org/phrack/60/p60-0x0c.txt . The + author of that paper, Ed3f (ed3f(a)antifork.org), is also the author + of this patch. 3.96BETA1 diff --git a/Makefile.in b/Makefile.in index a2f91c284..b3c91fb7d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -export NMAP_VERSION = 3.96BETA2 +export NMAP_VERSION = 3.97Shmoo NMAP_NAME= Nmap NMAP_URL= http://www.insecure.org/nmap/ NMAP_PLATFORM=@host@ @@ -46,11 +46,11 @@ TARGET = nmap TARGETNMAPFE=@TARGETNMAPFE@ INSTALLNMAPFE=@INSTALLNMAPFE@ -export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc tty.cc @COMPAT_SRCS@ +export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc tty.cc nmap_dns.cc @COMPAT_SRCS@ -OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o tty.o @COMPAT_OBJS@ +OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o tty.o nmap_dns.o @COMPAT_OBJS@ -export DEPS = nmap.h nmap_amigaos.h nmap_error.h targets.h idle_scan.h osscan.h output.h scan_engine.h timing.h tcpip.h utils.h global_structures.h charpool.h services.h protocols.h nmap_rpc.h portlist.h NmapOps.h TargetGroup.h Target.h FingerPrintResults.h service_scan.h NmapOutputTable.h MACLookup.h tty.h +export DEPS = nmap.h nmap_amigaos.h nmap_error.h targets.h idle_scan.h osscan.h output.h scan_engine.h timing.h tcpip.h utils.h global_structures.h charpool.h services.h protocols.h nmap_rpc.h portlist.h NmapOps.h TargetGroup.h Target.h FingerPrintResults.h service_scan.h NmapOutputTable.h MACLookup.h tty.h nmap_dns.h # %.o : %.cc -- nope this is a GNU extension diff --git a/NmapOps.cc b/NmapOps.cc index 83a99fe01..db0c2fe7c 100644 --- a/NmapOps.cc +++ b/NmapOps.cc @@ -247,6 +247,9 @@ void NmapOps::Initialize() { if (xsl_stylesheet) free(xsl_stylesheet); xsl_stylesheet = strdup(tmpxsl); spoof_mac_set = false; + mass_dns = true; + resolve_all = 0; + dns_servers = NULL; } bool NmapOps::TCPScan() { @@ -428,6 +431,9 @@ void NmapOps::ValidateOptions() { if (af() == AF_INET6 && (numdecoys|osscan|bouncescan|fragscan|ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|rpcscan|synscan|udpscan|windowscan|xmasscan)) { fatal("Sorry -- IPv6 support is currently only available for connect() scan (-sT), ping scan (-sP), and list scan (-sL). Further support is under consideration."); } + + if (af() != AF_INET) mass_dns = false; + } void NmapOps::setMaxRttTimeout(int rtt) diff --git a/NmapOps.h b/NmapOps.h index 6b50f7677..9e8f35ca3 100644 --- a/NmapOps.h +++ b/NmapOps.h @@ -281,7 +281,11 @@ class NmapOps { FILE *logfd[LOG_TYPES]; FILE *nmap_stdout; /* Nmap standard output */ int ttl; // Time to live + int badsum; char *datadir; + bool mass_dns; + int resolve_all; + char *dns_servers; // Statistics Options set in nmap.cc int numhosts_scanned; diff --git a/config.h.in b/config.h.in index ea18b9797..75da51f7c 100644 --- a/config.h.in +++ b/config.h.in @@ -143,6 +143,12 @@ #undef HAVE_SYS_SOCKIO_H +#undef HAVE_SYS_STAT_H + +#undef HAVE_FCNTL_H + +#undef HAVE_TERMIOS_H + #undef HAVE_PCRE_H #undef HAVE_PCRE_PCRE_H diff --git a/configure b/configure index a218c962c..b098105e7 100755 --- a/configure +++ b/configure @@ -3549,7 +3549,10 @@ done -for ac_header in string.h getopt.h strings.h memory.h sys/param.h sys/sockio.h bstring.h sys/time.h pwd.h unistd.h + + + +for ac_header in string.h getopt.h strings.h memory.h sys/param.h sys/sockio.h bstring.h sys/time.h sys/stat.h fcntl.h termios.h pwd.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then diff --git a/configure.ac b/configure.ac index c3cfe3e27..94e14ef36 100644 --- a/configure.ac +++ b/configure.ac @@ -196,7 +196,7 @@ esac dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(string.h getopt.h strings.h memory.h sys/param.h sys/sockio.h bstring.h sys/time.h pwd.h unistd.h ) +AC_CHECK_HEADERS(string.h getopt.h strings.h memory.h sys/param.h sys/sockio.h bstring.h sys/time.h sys/stat.h fcntl.h termios.h pwd.h unistd.h ) AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(sys/socket.h) AC_CHECK_HEADERS([net/if.h],[],[], diff --git a/docs/nmap.1 b/docs/nmap.1 index 2e1a60067..28a214070 100644 --- a/docs/nmap.1 +++ b/docs/nmap.1 @@ -2,7 +2,7 @@ .\" It was generated using the DocBook XSL Stylesheets (version 1.69.1). .\" Instead of manually editing it, you probably should edit the DocBook XML .\" source for it and then use the DocBook XSL Stylesheets to regenerate it. -.TH "NMAP" "1" "12/30/2005" "" "Nmap Reference Guide" +.TH "NMAP" "1" "01/09/2006" "" "Nmap Reference Guide" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -106,6 +106,8 @@ HOST DISCOVERY: \-PS/PA/PU [portlist]: TCP SYN/ACK or UDP discovery to given ports \-PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes \-n/\-R: Never do DNS resolution/Always resolve [default: sometimes] + \-\-dns_servers : Specify custom DNS servers + \-\-system_dns: Use OS's DNS resolver SCAN TECHNIQUES: \-sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans \-sN/sF/sX: TCP Null, FIN, and Xmas scans @@ -145,6 +147,7 @@ FIREWALL/IDS EVASION AND SPOOFING: \-\-data_length : Append random data to sent packets \-\-ttl : Set IP time\-to\-live field \-\-spoof_mac : Spoof your MAC address + \-\-badsum: Send packets with a bogus TCP/UDP checksum OUTPUT: \-oN/\-oX/\-oS/\-oG : Output scan in normal, XML, s| \fR (Servers to use for reverse DNS queries) +Normally Nmap will try to determine the DNS servers from your resolv.conf file (UNIX) or the registry (Win32). Alternatively, you may use this option to specify your own servers. This option is not honored if you are using +\fB\-\-system_dns\fR +or an IPv6 scan. Using multiple DNS servers is often faster than querying just one. .SH "PORT SCANNING BASICS" .PP While Nmap has grown in functionality over the years, it began as an efficient port scanner, and that remains its core function. The simple command @@ -982,6 +990,10 @@ Apple, deadbeefcafe, 0020F2, and Cisco. +.TP +\fB\-\-badsum\fR (Send packets with bogus TCP/UDP checksums) +Asks Nmap to use an invalid TCP or UDP checksum for packets sent to target hosts. Since virtually all host IP stacks properly drop these packets, any responses received are likely coming from a firewall or IDS that didn't bother to verify the checksum. For more details on this technique, see +\fI\%http://www.phrack.org/phrack/60/p60\-0x0c.txt\fR .SH "OUTPUT" .PP Any security tools is only as useful as the output it generates. Complex tests and algorithms are of little value if they aren't presented in an organized and comprehensible fashion. Given the number of ways Nmap is used by people and other software, no single format can please everyone. So Nmap offers several formats, including the interactive mode for humans to read directly and XML for easy parsing by software. @@ -1239,8 +1251,9 @@ Prints a short help screen with the most common command flags. Running Nmap with .nr an-break-flag 1 .br \fBNote\fR -The runtime interaction feature is not yet - supported on Windows..PP +.PP +The runtime interaction feature is not yet supported on Windows. +.PP During the execution of nmap, all key presses are captured. This allows you to interact with the program without aborting and restarting it. Certain special keys will change options, while any other keys will print out a status message telling you about the scan. The convention is that \fIlowercase letters increase\fR the amount of printing, and diff --git a/docs/nmap.usage.txt b/docs/nmap.usage.txt index ee695d6ea..efd41d676 100644 --- a/docs/nmap.usage.txt +++ b/docs/nmap.usage.txt @@ -1,4 +1,4 @@ -Nmap 3.96BETA2 ( http://www.insecure.org/nmap/ ) +Nmap 3.96BETA3 ( http://www.insecure.org/nmap/ ) Usage: nmap [Scan Type(s)] [Options] {target specification} TARGET SPECIFICATION: Can pass hostnames, IP addresses, networks, etc. @@ -14,6 +14,8 @@ HOST DISCOVERY: -PS/PA/PU [portlist]: TCP SYN/ACK or UDP discovery to given ports -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes -n/-R: Never do DNS resolution/Always resolve [default: sometimes] + --dns_servers : Specify custom DNS servers + --system_dns: Use OS's DNS resolver SCAN TECHNIQUES: -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans -sN/sF/sX: TCP Null, FIN, and Xmas scans @@ -53,6 +55,7 @@ FIREWALL/IDS EVASION AND SPOOFING: --data_length : Append random data to sent packets --ttl : Set IP time-to-live field --spoof_mac : Spoof your MAC address + --badsum: Send packets with a bogus TCP/UDP checksum OUTPUT: -oN/-oX/-oS/-oG : Output scan in normal, XML, s| + + @@ -253,6 +256,9 @@ + + diff --git a/nmap.cc b/nmap.cc index b17055bc5..12014528e 100644 --- a/nmap.cc +++ b/nmap.cc @@ -204,7 +204,7 @@ int nmap_main(int argc, char *argv[]) { size_t j, argvlen; FILE *inputfd = NULL, *excludefd = NULL; char *host_spec = NULL, *exclude_spec = NULL; - short fastscan=0, randomize=1, resolve_all=0; + short fastscan=0, randomize=1; short quashargv = 0; char **host_exp_group; char *idleProxy = NULL; /* The idle host used to "Proxy" an Idlescan */ @@ -296,11 +296,14 @@ int nmap_main(int argc, char *argv[]) { {"noninteractive", no_argument, 0, 0}, {"spoof_mac", required_argument, 0, 0}, {"thc", no_argument, 0, 0}, + {"badsum", no_argument, 0, 0}, {"ttl", required_argument, 0, 0}, /* Time to live */ {"allports", no_argument, 0, 0}, {"version_intensity", required_argument, 0, 0}, {"version_light", no_argument, 0, 0}, {"version_all", no_argument, 0, 0}, + {"system_dns", no_argument, 0, 0}, + {"dns_servers", required_argument, 0, 0}, {0, 0, 0, 0} }; @@ -448,6 +451,10 @@ int nmap_main(int argc, char *argv[]) { o.setXSLStyleSheet(optarg); } else if (strcmp(long_options[option_index].name, "no_stylesheet") == 0) { o.setXSLStyleSheet(NULL); + } else if (strcmp(long_options[option_index].name, "system_dns") == 0) { + o.mass_dns = false; + } else if (strcmp(long_options[option_index].name, "dns_servers") == 0) { + o.dns_servers = strdup(optarg); } else if (strcmp(long_options[option_index].name, "webxml") == 0) { o.setXSLStyleSheet("http://www.insecure.org/nmap/data/nmap.xsl"); } else if (strcmp(long_options[option_index].name, "oN") == 0) { @@ -472,6 +479,8 @@ int nmap_main(int argc, char *argv[]) { } else if (strcmp(long_options[option_index].name, "thc") == 0) { printf("!!Greets to Van Hauser, Plasmoid, Skyper and the rest of THC!!\n"); exit(0); + } else if (strcmp(long_options[option_index].name, "badsum") == 0) { + o.badsum = 1; } else if (strcmp(long_options[option_index].name, "iL") == 0) { if (inputfd) { @@ -542,7 +551,7 @@ int nmap_main(int argc, char *argv[]) { if (resolve(p, &o.decoys[o.numdecoys])) { o.numdecoys++; } else { - fatal("Failed to resolve decoy host: %s (must be hostname or IP address)", optarg); + fatal("Failed to resolve decoy host: %s (must be hostname or IP address)", p); } } if (q) { @@ -682,7 +691,7 @@ int nmap_main(int argc, char *argv[]) { fatal("Your port specification string is not parseable"); break; case 'q': quashargv++; break; - case 'R': resolve_all++; break; + case 'R': o.resolve_all++; break; case 'r': randomize = 0; break; @@ -758,7 +767,7 @@ int nmap_main(int argc, char *argv[]) { o.setMaxTCPScanDelay(5); o.setMaxRetransmissions(2); } else { - fatal("Unknown timing mode (-T argment). Use either \"Paranoid\", \"Sneaky\", \"Polite\", \"Normal\", \"Aggressive\", \"Insane\" or a number from 0 (Paranoid) to 5 (Insane)"); + fatal("Unknown timing mode (-T argument). Use either \"Paranoid\", \"Sneaky\", \"Polite\", \"Normal\", \"Aggressive\", \"Insane\" or a number from 0 (Paranoid) to 5 (Insane)"); } break; case 'V': @@ -1097,20 +1106,10 @@ int nmap_main(int argc, char *argv[]) { if (currenths->flags & HOST_UP && !o.listscan) o.numhosts_up++; - /* Lookup the IP */ - if (((currenths->flags & HOST_UP) || resolve_all) && !o.noresolve) { - if (currenths->TargetSockAddr(&ss, &sslen) != 0) - fatal("Failed to get target socket address."); - if (getnameinfo((struct sockaddr *)&ss, sslen, hostname, - sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) { - currenths->setHostName(hostname); - } - } - if (o.pingscan || o.listscan) { /* We're done with the hosts */ log_write(LOG_XML, ""); - write_host_status(currenths, resolve_all); + write_host_status(currenths, o.resolve_all); printmacinfo(currenths); // if (currenths->flags & HOST_UP) // log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n"); @@ -1252,7 +1251,7 @@ int nmap_main(int argc, char *argv[]) { /* Now I can do the output and such for each host */ log_write(LOG_XML, ""); - write_host_status(currenths, resolve_all); + write_host_status(currenths, o.resolve_all); if (currenths->timedOut(NULL)) { log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Skipping host %s due to host timeout\n", currenths->NameIP(hostname, sizeof(hostname))); @@ -1605,6 +1604,8 @@ printf("%s %s ( %s )\n" " -PS/PA/PU [portlist]: TCP SYN/ACK or UDP discovery to given ports\n" " -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes\n" " -n/-R: Never do DNS resolution/Always resolve [default: sometimes]\n" + " --dns_servers : Specify custom DNS servers\n" + " --system_dns: Use OS's DNS resolver\n" "SCAN TECHNIQUES:\n" " -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans\n" " -sN/sF/sX: TCP Null, FIN, and Xmas scans\n" @@ -1644,6 +1645,7 @@ printf("%s %s ( %s )\n" " --data_length : Append random data to sent packets\n" " --ttl : Set IP time-to-live field\n" " --spoof_mac : Spoof your MAC address\n" + " --badsum: Send packets with a bogus TCP/UDP checksum\n" "OUTPUT:\n" " -oN/-oX/-oS/-oG : Output scan in normal, XML, s|uh_sum = realcheck; #endif + if ( o.badsum ) + udp->uh_sum++; + /* Goodbye, pseudo header! */ memset(pseudo, 0, sizeof(*pseudo)); diff --git a/scripts/Makefile b/scripts/Makefile index 475cbff8f..4cdbe28ca 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -30,7 +30,7 @@ web: cd ../docs && cp -a nmap_gpgkeys.txt nmap_manpage-*.html nmap*.1 \ xnmap.1 nmap.usage.txt nmap.dtd nmap.xsl \ leet-nmap-ascii-art.txt $(wroot)/nmap/data/ - cp $(wroot)/nmapguide/build/man-built.xml $(wroot)/nmap/data/ + cp $(wroot)/nmapguide/build/nmap-man.xml $(wroot)/nmap/data/nmap-man.xml ./sort-prints.pl ../nmap-os-fingerprints > nos && mv nos ../nmap-os-fingerprints ./produceosclasschoosebox.pl ../nmap-os-fingerprints > $(wroot)/nmap/data/os-classes.txt cd .. && cp -a CHANGELOG HACKING COPYING COPYING.OpenSSL INSTALL \ diff --git a/scripts/sign_release.pl b/scripts/sign_release.pl index 56cfa4c6a..b6a6a01ba 100755 --- a/scripts/sign_release.pl +++ b/scripts/sign_release.pl @@ -26,6 +26,7 @@ if (! -d "$distdir/sigs/" ) { opendir DISTDIR, $distdir or die "Could not open distdir: $distdir\n"; foreach $file (readdir DISTDIR) { + if ($file eq "favicon.ico") { next; } if (-f "$distdir/$file") { my $sigfile = "$distdir/sigs/$file.gpg.txt"; my $digfile = "$distdir/sigs/$file.digest.txt"; diff --git a/targets.cc b/targets.cc index 2e2bcedde..a5cf6075d 100644 --- a/targets.cc +++ b/targets.cc @@ -108,6 +108,7 @@ #include "TargetGroup.h" #include "Target.h" #include "scan_engine.h" +#include "nmap_dns.h" #include "tty.h" using namespace std; @@ -434,6 +435,8 @@ if (hs->randomize) { else massping(hs->hostbatch, hs->current_batch_sz, ports, *pingtype); + if (!o.noresolve) nmap_mass_rdns(hs->hostbatch, hs->current_batch_sz); + return hs->hostbatch[hs->next_batch_no++]; } @@ -981,6 +984,9 @@ pingpkt.id = id; pingpkt.seq = seq; pingpkt.checksum = 0; pingpkt.checksum = in_cksum((unsigned short *)ping, icmplen); +if ( o.badsum ) + pingpkt.checksum--; + /* Now for our sock */ if (ptech.icmpscan) { diff --git a/tcpip.cc b/tcpip.cc index fc85144ed..b190a5171 100644 --- a/tcpip.cc +++ b/tcpip.cc @@ -875,6 +875,11 @@ else tcp->th_win = htons(1024 * (myttl % 4 + 1)); /* Who cares */ tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) + optlen + sizeof(struct pseudo_header) + datalen); #endif + +if ( o.badsum ) + --tcp->th_sum, + + /* Now for the ip header */ memset(packet, 0, sizeof(struct ip)); @@ -1093,6 +1098,9 @@ pingpkt.seq = seq; pingpkt.checksum = 0; pingpkt.checksum = in_cksum((unsigned short *)ping, icmplen); +if ( o.badsum ) + --pingpkt.checksum; + return build_ip_raw(source, victim, o.ttl, IPPROTO_ICMP, get_random_u16(), ping, icmplen, packetlen); } @@ -1294,6 +1302,9 @@ u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim, udp->uh_sum = in_cksum((unsigned short *)pseudo, 20 /* pseudo + UDP headers */ + datalen); #endif + if ( o.badsum ) + --udp->uh_sum; + /* Goodbye, pseudo header! */ memset(pseudo, 0, sizeof(*pseudo)); @@ -2296,7 +2307,7 @@ int sd; eth_addr_t ethaddr; if (!ethsd) - fatal("%s: Failed to open ethernet interface (%s)", __FUNCTION__, + fatal("%s: Failed to open ethernet interface (%s). A possible cause on BSD operating systems is running out of BPF devices (see http://seclists.org/lists/nmap-dev/2006/Jan-Mar/0014.html).", __FUNCTION__, mydevs[numifaces].devname); if (eth_get(ethsd, ðaddr) != 0) fatal("%s: Failed to obtain MAC address for ethernet interface (%s)",