VirtualBox

Ignore:
Timestamp:
Mar 12, 2014 2:12:22 PM (11 years ago)
Author:
vboxsync
Message:

Netflt: ifnet::if_pcount offset detection for Darwin (#7279)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp

    r50410 r50747  
    139139static mbuf_tag_id_t g_idTag;
    140140
    141 /** the offset of the struct ifnet::if_pcount variable. */
     141/** the offset of the struct ifnet::if_pcount variable (valid for Lion). */
    142142static unsigned g_offIfNetPCount = sizeof(void *) * (1 /*if_softc*/ + 1 /*if_name*/ + 2 /*if_link*/ + 2 /*if_addrhead*/ + 1 /*if_check_multi*/)
    143143                                 + sizeof(u_long) /*if_refcnt*/;
     
    145145#define VBOX_GET_PCOUNT(pIfNet) ( *(int *)((uintptr_t)pIfNet + g_offIfNetPCount) )
    146146
     147/** The size of area of ifnet structure we try to locate if_pcount in. */
     148#define VBOXNETFLT_DARWIN_IFNET_SIZE 256
     149
     150/*
     151 * Note that this implementation relies on if_pcount to be aligned on sizeof(int).
     152 */
     153static unsigned vboxNetFltDarwinSetAndDiff(ifnet_t pIfNet, int iPromisc)
     154{
     155    unsigned i;
     156    int aSavedState[VBOXNETFLT_DARWIN_IFNET_SIZE/sizeof(int)];
     157
     158    memcpy(aSavedState, pIfNet, sizeof(aSavedState));
     159    ifnet_set_promiscuous(pIfNet, iPromisc);
     160
     161    int offset = 0;
     162    int iDiff = iPromisc ? 1 : -1;
     163    /*
     164     * We assume that ifnet structure will never have less members in front of if_pcount
     165     * than it used to have in Lion. If this turns out to be false assumption we will
     166     * have to start from zero offset.
     167     */
     168    for (i = g_offIfNetPCount / sizeof(int); i < sizeof(aSavedState) / sizeof(int); i++)
     169        if (((int*)pIfNet)[i] - aSavedState[i] == iDiff)
     170        {
     171            offset = i * sizeof(int);
     172            break;
     173        }
     174
     175    return offset;
     176}
     177
     178/**
     179 * Detect and adjust the offset of ifnet::if_pcount.
     180 */
     181static void vboxNetFltDarwinDetectPCountOffset(ifnet_t pIfNet)
     182{
     183    unsigned offTry1, offTry2, offTry3, offTry4;
     184    /*
     185     * It would be nice to use locking at this point, but it is not available via KPI.
     186     * This is why we try several times. At each attempt we modify if_pcount four times
     187     * to rule out false detections.
     188     */
     189    for (int nAttempts = 0; nAttempts < 3; nAttempts++)
     190    {
     191        offTry1 = vboxNetFltDarwinSetAndDiff(pIfNet, 1);
     192        offTry2 = vboxNetFltDarwinSetAndDiff(pIfNet, 1);
     193        offTry3 = vboxNetFltDarwinSetAndDiff(pIfNet, 0);
     194        offTry4 = vboxNetFltDarwinSetAndDiff(pIfNet, 0);
     195        /* If any attempt has failed we won't continue as our algorithm is flawed. */
     196        if (!offTry1 || !offTry2 || !offTry3 || !offTry4)
     197            break;
     198        if (offTry1 == offTry2 && offTry2 == offTry3 && offTry3 == offTry4)
     199        {
     200            if (g_offIfNetPCount != offTry1)
     201            {
     202                Log(("VBoxNetFltDarwinDetectPCountOffset: Adjusted if_pcount offset to %x from %x.\n", offTry1, g_offIfNetPCount));
     203                g_offIfNetPCount = offTry1;
     204            }
     205            break;
     206        }
     207    }
     208
     209    if (g_offIfNetPCount != offTry1)
     210        LogRel(("VBoxNetFlt: Failed to detect promiscuous count, all traffic may reach wire (%x != %x).\n", g_offIfNetPCount, offTry1));
     211}
    147212
    148213/**
     
    9561021    RTSpinlockReleaseNoInts(pThis->hSpinlock);
    9571022
     1023    /* Adjust g_offIfNetPCount as it varies for different versions of xnu. */
     1024    vboxNetFltDarwinDetectPCountOffset(pIfNet);
     1025
    9581026    /* Prevent stuck-in-dock issue by associating interface receive thread with kernel thread. */
    9591027    vboxNetFltSendDummy(pIfNet);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette