Friday, August 24, 2007

VMWare Fusion Doesn't Play Nice With BPF

For a while now I've been avoiding a problem with NMap and OS/X w/ VMWare Fusion installed. It's been posted about a few times on the mailing list and I always say "just shut Fusion down for it to work." Yeah, it works but it's not a real solution.

So I spent a few minutes today to figure out just WHY this is happening. Turns out my original assumption of Fusion not building "valid" interfaces is partly correct. The "vmnet[x]" interfaces can not be opened with BPF! I wrote a quick program to check it out:
macpro:~ grutz$ sudo ./testbpf vmnet8
ERROR: Device not configured
ktrace validates:
2721 testbpf CALL ioctl(0x83,0x8020426c ,0xbffffb28)
2721 testbpf RET ioctl -1 errno 6 Device not configured
So VMWare isn't creating valid interfaces. No tcpdump for you (and no nmap)! The solutions so far have been to shutdown the interfaces but what if you need to keep Fusion up and running?

Here's a quick and dirty patch applied to tcpip.cc that will skip over the vmnet interfaces. Until Fusion fixes their set up this is the only way it'll work.
/* skip broken VMWare Fusion vmnet interfaces */
#ifdef MACOSX
if (strncmp(ifr->ifr_name, "vmnet", 5) == 0)
continue;
#endif
Sigh.

4 comments:

Kurt said...

Ugh... clean this part up:

if (strncmp(ifr->ifr_name, "vmnet", 5) == 0)

to read

if (!strncmp(ifr->ifr_name, "vmnet", 5))

No reason to use numeric equality on strncmp().

grutz said...

I blame copy/paste from other parts of nmap code. I wanted to conform with the other coders. :P

grutz$ grep strncmp *
config.guess: if (strncmp(un.version, "V2", 2) == 0) {
config.guess: if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
Binary file nmap matches
nmap.cc: if (strncmp(q, " scanned ports on", 17) == 0)
osscan.cc: if (!thisline || strncmp(thisline, "Class ", 6) == 1) {
osscan.cc: if (strncmp(thisline, "Fingerprint ", 12) == 0) {
osscan.cc: } else if (strncmp(thisline, "Class ", 6) == 0) {
osscan.cc: if (!strncmp(line, "FingerPrint ",12)) {
osscan.cc: } else if (strncmp(line, "Class ", 6) == 0) {
output.cc: if (strncmp(src, "\nSF:", 4) == 0) {
scan_engine.cc: if (!strncmp(recvbuf, "500", 3)) {
service_scan.cc: if (strncmp(matchtext, "softmatch ", 10) == 0) {
service_scan.cc: } else if (strncmp(matchtext, "match ", 6) == 0) {
service_scan.cc: if (strncmp(pd, "TCP ", 4) == 0)
service_scan.cc: else if (strncmp(pd, "UDP ", 4) == 0)
service_scan.cc: if (strncmp(line, "Exclude ", 8) == 0) {
service_scan.cc: if (strncmp(line, "Probe ", 6) != 0)
service_scan.cc: if (strncmp(line, "Probe ", 6) == 0) {
service_scan.cc: } else if (strncmp(line, "ports ", 6) == 0) {
service_scan.cc: } else if (strncmp(line, "sslports ", 9) == 0) {
service_scan.cc: } else if (strncmp(line, "rarity ", 7) == 0) {
service_scan.cc: } else if (strncmp(line, "fallback ", 9) == 0) {
service_scan.cc: } else if (strncmp(line, "totalwaitms ", 12) == 0) {
service_scan.cc: } else if (strncmp(line, "match ", 6) == 0 || strncmp(line, "softmatch ", 10) == 0) {
service_scan.cc: } else if (strncmp(line, "Exclude ", 8) == 0) {
service_scan.cc: if (strncmp(svc->probe_matched, "ssl/", 4) == 0) {
tcpip.cc: if (strncmp(ifr->ifr_name, "vmnet", 5) == 0)

Kurt said...

...but it's inconsistent, even there. Consider:

osscan.cc: if (!thisline || strncmp(thisline, "Class ", 6) == 1) {
osscan.cc: if (strncmp(thisline, "Fingerprint ", 12) == 0) {

Notice that the first line uses the return value of strncmp without an equality comparison. This makes sense because strncmp can return -1, 0, or 1 ... and only 0 equates to boolean false.

Kurt said...

To beat this horse even further, look here:

scan_engine.cc: if (!strncmp(recvbuf, "500", 3)) {