Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp	(revision 50746)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp	(revision 50747)
@@ -139,5 +139,5 @@
 static mbuf_tag_id_t g_idTag;
 
-/** the offset of the struct ifnet::if_pcount variable. */
+/** the offset of the struct ifnet::if_pcount variable (valid for Lion). */
 static unsigned g_offIfNetPCount = sizeof(void *) * (1 /*if_softc*/ + 1 /*if_name*/ + 2 /*if_link*/ + 2 /*if_addrhead*/ + 1 /*if_check_multi*/)
                                  + sizeof(u_long) /*if_refcnt*/;
@@ -145,4 +145,69 @@
 #define VBOX_GET_PCOUNT(pIfNet) ( *(int *)((uintptr_t)pIfNet + g_offIfNetPCount) )
 
+/** The size of area of ifnet structure we try to locate if_pcount in. */
+#define VBOXNETFLT_DARWIN_IFNET_SIZE 256
+
+/*
+ * Note that this implementation relies on if_pcount to be aligned on sizeof(int).
+ */
+static unsigned vboxNetFltDarwinSetAndDiff(ifnet_t pIfNet, int iPromisc)
+{
+    unsigned i;
+    int aSavedState[VBOXNETFLT_DARWIN_IFNET_SIZE/sizeof(int)];
+
+    memcpy(aSavedState, pIfNet, sizeof(aSavedState));
+    ifnet_set_promiscuous(pIfNet, iPromisc);
+
+    int offset = 0;
+    int iDiff = iPromisc ? 1 : -1;
+    /*
+     * We assume that ifnet structure will never have less members in front of if_pcount
+     * than it used to have in Lion. If this turns out to be false assumption we will
+     * have to start from zero offset.
+     */
+    for (i = g_offIfNetPCount / sizeof(int); i < sizeof(aSavedState) / sizeof(int); i++)
+        if (((int*)pIfNet)[i] - aSavedState[i] == iDiff)
+        {
+            offset = i * sizeof(int);
+            break;
+        }
+
+    return offset;
+}
+
+/**
+ * Detect and adjust the offset of ifnet::if_pcount.
+ */
+static void vboxNetFltDarwinDetectPCountOffset(ifnet_t pIfNet)
+{
+    unsigned offTry1, offTry2, offTry3, offTry4;
+    /*
+     * It would be nice to use locking at this point, but it is not available via KPI.
+     * This is why we try several times. At each attempt we modify if_pcount four times
+     * to rule out false detections.
+     */
+    for (int nAttempts = 0; nAttempts < 3; nAttempts++)
+    {
+        offTry1 = vboxNetFltDarwinSetAndDiff(pIfNet, 1);
+        offTry2 = vboxNetFltDarwinSetAndDiff(pIfNet, 1);
+        offTry3 = vboxNetFltDarwinSetAndDiff(pIfNet, 0);
+        offTry4 = vboxNetFltDarwinSetAndDiff(pIfNet, 0);
+        /* If any attempt has failed we won't continue as our algorithm is flawed. */
+        if (!offTry1 || !offTry2 || !offTry3 || !offTry4)
+            break;
+        if (offTry1 == offTry2 && offTry2 == offTry3 && offTry3 == offTry4)
+        {
+            if (g_offIfNetPCount != offTry1)
+            {
+                Log(("VBoxNetFltDarwinDetectPCountOffset: Adjusted if_pcount offset to %x from %x.\n", offTry1, g_offIfNetPCount));
+                g_offIfNetPCount = offTry1;
+            }
+            break;
+        }
+    }
+
+    if (g_offIfNetPCount != offTry1)
+        LogRel(("VBoxNetFlt: Failed to detect promiscuous count, all traffic may reach wire (%x != %x).\n", g_offIfNetPCount, offTry1));
+}
 
 /**
@@ -956,4 +1021,7 @@
     RTSpinlockReleaseNoInts(pThis->hSpinlock);
 
+    /* Adjust g_offIfNetPCount as it varies for different versions of xnu. */
+    vboxNetFltDarwinDetectPCountOffset(pIfNet);
+
     /* Prevent stuck-in-dock issue by associating interface receive thread with kernel thread. */
     vboxNetFltSendDummy(pIfNet);
