Index: /trunk/include/VBox/intnet.h
===================================================================
--- /trunk/include/VBox/intnet.h	(revision 55651)
+++ /trunk/include/VBox/intnet.h	(revision 55652)
@@ -387,4 +387,24 @@
 
 
+/**
+ * Network layer address type.
+ */
+typedef enum INTNETADDRTYPE
+{
+    /** The invalid 0 entry. */
+    kIntNetAddrType_Invalid = 0,
+    /** IP version 4. */
+    kIntNetAddrType_IPv4,
+    /** IP version 6. */
+    kIntNetAddrType_IPv6,
+    /** IPX. */
+    kIntNetAddrType_IPX,
+    /** The end of the valid values. */
+    kIntNetAddrType_End,
+    /** The usual 32-bit hack. */
+    kIntNetAddrType_32BitHack = 0x7fffffff
+} INTNETADDRTYPE;
+
+
 /** Pointer to the interface side of a trunk port. */
 typedef struct INTNETTRUNKIFPORT *PINTNETTRUNKIFPORT;
@@ -577,4 +597,21 @@
 
     /**
+     * Notifications about changes to host IP addresses.
+     *
+     * This is used by networks bridged to wifi that share mac with
+     * the host.  Host reports changes to its IP addresses so that L3
+     * switching can ingore guests spoofing host's own IP addresses
+     *
+     * This callback may be null to indicate we are not interested.
+     *
+     * @param   pSwitchPort         Pointer to this structure.
+     * @param   fAdded              Whether address is added of removed.
+     * @param   enmType             Address type.
+     * @param   pvAddr              Pointer to the address.
+     */
+    DECLR0CALLBACKMEMBER(void, pfnNotifyHostAddress,(PINTNETTRUNKSWPORT pSwitchPort, bool fAdded,
+                                                     INTNETADDRTYPE enmType, const void *pvAddr));
+
+    /**
      * OS triggered trunk disconnect.
      *
@@ -603,5 +640,5 @@
 
 /** Version number for the INTNETTRUNKIFPORT::u32Version and INTNETTRUNKIFPORT::u32VersionEnd fields. */
-# define INTNETTRUNKSWPORT_VERSION   UINT32_C(0xA2CDf003)
+# define INTNETTRUNKSWPORT_VERSION   UINT32_C(0xA2CDf004)
 
 
Index: /trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp	(revision 55651)
+++ /trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp	(revision 55652)
@@ -162,25 +162,4 @@
 /** Pointer to a const destination table. */
 typedef INTNETDSTTAB const *PCINTNETDSTTAB;
-
-
-/** Network layer address type. */
-typedef enum INTNETADDRTYPE
-{
-    /** The invalid 0 entry. */
-    kIntNetAddrType_Invalid = 0,
-    /** IP version 4. */
-    kIntNetAddrType_IPv4,
-    /** IP version 6. */
-    kIntNetAddrType_IPv6,
-    /** IPX. */
-    kIntNetAddrType_IPX,
-    /** The end of the valid values. */
-    kIntNetAddrType_End,
-    /** The usual 32-bit hack. */
-    kIntNetAddrType_32BitHack = 0x7fffffff
-} INTNETADDRTYPE;
-/** Pointer to a network layer address type. */
-typedef INTNETADDRTYPE *PINTNETADDRTYPE;
-
 
 /**
@@ -356,5 +335,5 @@
     struct INTNETNETWORK   *pNext;
 
-    /** The spinlock protecting MacTab and INTNETTRUNKIF::aAddrCache.
+    /** The spinlock protecting MacTab, aAddrBlacklist and INTNETIF::aAddrCache.
      *  Interrupt safe. */
     RTSPINLOCK              hAddrSpinlock;
@@ -362,4 +341,8 @@
      * This doubles as interface collection. */
     INTNETMACTAB            MacTab;
+
+    /** The network layer address cache. (Indexed by type, 0 entry isn't used.
+     * Contains host addresses.  We don't let guests spoof them. */
+    INTNETADDRCACHE         aAddrBlacklist[kIntNetAddrType_End];
 
     /** Wait for an interface to stop being busy so it can be removed or have its
@@ -1168,17 +1151,39 @@
  * @param   pszMsg          Log message.
  */
-DECLINLINE(void) intnetR0NetworkAddrCacheDelete(PINTNETNETWORK pNetwork, PCRTNETADDRU pAddr, INTNETADDRTYPE const enmType,
-                                                uint8_t const cbAddr, const char *pszMsg)
-{
-    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
-
+DECLINLINE(void) intnetR0NetworkAddrCacheDeleteUnlocked(PINTNETNETWORK pNetwork,
+                                                        PCRTNETADDRU pAddr, INTNETADDRTYPE enmType,
+                                                        uint8_t const cbAddr,
+                                                        const char *pszMsg)
+{
     uint32_t iIf = pNetwork->MacTab.cEntries;
     while (iIf--)
     {
         PINTNETIF pIf = pNetwork->MacTab.paEntries[iIf].pIf;
+
         int i = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmType], pAddr, cbAddr);
         if (RT_UNLIKELY(i >= 0))
             intnetR0IfAddrCacheDeleteIt(pIf, &pIf->aAddrCache[enmType], i, pszMsg);
     }
+}
+
+
+/**
+ * Deletes the address from all the interface caches.
+ *
+ * This is used to remove stale entries that has been reassigned to
+ * other machines on the network.
+ *
+ * @param   pNetwork        The network.
+ * @param   pAddr           The address.
+ * @param   enmType         The address type.
+ * @param   cbAddr          The address size (optimization).
+ * @param   pszMsg          Log message.
+ */
+DECLINLINE(void) intnetR0NetworkAddrCacheDelete(PINTNETNETWORK pNetwork, PCRTNETADDRU pAddr, INTNETADDRTYPE const enmType,
+                                                uint8_t const cbAddr, const char *pszMsg)
+{
+    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
+
+    intnetR0NetworkAddrCacheDeleteUnlocked(pNetwork, pAddr, enmType, cbAddr, pszMsg);
 
     RTSpinlockRelease(pNetwork->hAddrSpinlock);
@@ -1253,4 +1258,112 @@
 
 /**
+ * Look up specified address in the network's blacklist.
+ *
+ * @param pNetwork      The network. 
+ * @param enmType       The address type.
+ * @param pAddr         The address.
+ */
+static bool intnetR0NetworkBlacklistLookup(PINTNETNETWORK pNetwork,
+                                           PCRTNETADDRU pAddr, INTNETADDRTYPE enmType)
+{
+    PINTNETADDRCACHE pCache = &pNetwork->aAddrBlacklist[enmType];
+
+    if (RT_UNLIKELY(pCache->cEntriesAlloc == 0))
+        return false;
+
+    const uint8_t cbAddr = pCache->cbAddress;
+    Assert(cbAddr == intnetR0AddrSize(enmType));
+
+    for (unsigned i = 0; i < pCache->cEntries; ++i)
+    {
+        uint8_t *pbEntry = pCache->pbEntries + pCache->cbEntry * i;
+        if (intnetR0AddrUIsEqualEx((PCRTNETADDRU)pbEntry, pAddr, cbAddr))
+            return true;
+    }
+
+    return false;
+}
+
+
+/**
+ * Deletes specified address from network's blacklist.
+ *
+ * @param pNetwork      The network. 
+ * @param enmType       The address type.
+ * @param pAddr         The address.
+ */
+static void intnetR0NetworkBlacklistDelete(PINTNETNETWORK pNetwork,
+                                           PCRTNETADDRU pAddr, INTNETADDRTYPE enmType)
+{
+    PINTNETADDRCACHE pCache = &pNetwork->aAddrBlacklist[enmType];
+
+    if (RT_UNLIKELY(pCache->cEntriesAlloc == 0))
+        return;
+
+    const uint8_t cbAddr = pCache->cbAddress;
+    Assert(cbAddr == intnetR0AddrSize(enmType));
+
+    for (unsigned i = 0; i < pCache->cEntries; ++i)
+    {
+        uint8_t *pbEntry = pCache->pbEntries + pCache->cbEntry * i;
+        if (!intnetR0AddrUIsEqualEx((PCRTNETADDRU)pbEntry, pAddr, cbAddr))
+            continue;
+
+        --pCache->cEntries;
+        memmove(pCache->pbEntries + i * pCache->cbEntry,
+                pCache->pbEntries + (i + 1) * pCache->cbEntry,
+                (pCache->cEntries - i) * pCache->cbEntry);
+        return;
+    }
+}
+
+
+/**
+ * Adds specified address from network's blacklist.
+ *
+ * @param pNetwork      The network. 
+ * @param enmType       The address type.
+ * @param pAddr         The address.
+ */
+static void intnetR0NetworkBlacklistAdd(PINTNETNETWORK pNetwork,
+                                        PCRTNETADDRU pAddr, INTNETADDRTYPE enmType)
+{
+    PINTNETADDRCACHE pCache = &pNetwork->aAddrBlacklist[enmType];
+
+    if (RT_UNLIKELY(pCache->cEntriesAlloc == 0))
+        return;
+
+    const uint8_t cbAddr = pCache->cbAddress;
+    Assert(cbAddr == intnetR0AddrSize(enmType));
+
+    /* lookup */
+    for (unsigned i = 0; i < pCache->cEntries; ++i)
+    {
+        uint8_t *pbEntry = pCache->pbEntries + pCache->cbEntry * i;
+        if (RT_UNLIKELY(intnetR0AddrUIsEqualEx((PCRTNETADDRU)pbEntry, pAddr, cbAddr)))
+            return; /* already exists */
+    }
+
+    if (pCache->cEntries >= pCache->cEntriesAlloc)
+    {
+        /* shift */
+        memmove(pCache->pbEntries, pCache->pbEntries + pCache->cbEntry, 
+                pCache->cbEntry * (pCache->cEntries - 1));
+        --pCache->cEntries;
+    }
+
+    Assert(pCache->cEntries < pCache->cEntriesAlloc);
+
+    /* push */
+    uint8_t *pbEntry = pCache->pbEntries + pCache->cEntries * pCache->cbEntry;
+    memcpy(pbEntry, pAddr, cbAddr);
+    memset(pbEntry + pCache->cbAddress, '\0', pCache->cbEntry - cbAddr);
+    ++pCache->cEntries;
+
+    Assert(pCache->cEntries <= pCache->cEntriesAlloc);
+}
+
+
+/**
  * Adds an address to the cache, the caller is responsible for making sure it's
  * not already in the cache.
@@ -1263,9 +1376,41 @@
  * @param   pszMsg      log message.
  */
-static void intnetR0IfAddrCacheAddIt(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr, const char *pszMsg)
+static void intnetR0IfAddrCacheAddIt(PINTNETIF pIf, INTNETADDRTYPE enmAddrType, PCRTNETADDRU pAddr,
+                                     const char *pszMsg)
 {
     PINTNETNETWORK  pNetwork = pIf->pNetwork;
     AssertReturnVoid(pNetwork);
+
+    PINTNETADDRCACHE pCache = &pIf->aAddrCache[enmAddrType];
+
+    const uint8_t cbAddr = pCache->cbAddress;
+    Assert(cbAddr == intnetR0AddrSize(enmAddrType));
+
     RTSpinlockAcquire(pNetwork->hAddrSpinlock);
+
+    bool fBlacklisted = intnetR0NetworkBlacklistLookup(pNetwork, pAddr, enmAddrType);
+    if (fBlacklisted)
+    {
+        RTSpinlockRelease(pNetwork->hAddrSpinlock);
+
+#ifdef LOG_ENABLED
+        switch (enmAddrType)
+        {
+            case kIntNetAddrType_IPv4:
+                Log(("%s: spoofing attempt for %RTnaipv4\n",
+                     __FUNCTION__, pAddr->IPv4));
+                break;
+            case kIntNetAddrType_IPv6:
+                Log(("%s: spoofing attempt for %RTnaipv6\n",
+                     __FUNCTION__, &pAddr->IPv6));
+                break;
+            default: 
+                Log(("%s: spoofing attempt for %.*Rhxs (type %d)\n",
+                     __FUNCTION__, cbAddr, pAddr, enmAddrType));
+                break;
+        }
+#endif
+        return;
+    }
 
     if (RT_UNLIKELY(!pCache->cEntriesAlloc))
@@ -1292,6 +1437,6 @@
     memcpy(pbEntry, pAddr, pCache->cbAddress);
     memset(pbEntry + pCache->cbAddress, '\0', pCache->cbEntry - pCache->cbAddress);
+
 #ifdef LOG_ENABLED
-    INTNETADDRTYPE enmAddrType = (INTNETADDRTYPE)(uintptr_t)(pCache - &pIf->aAddrCache[0]);
     switch (enmAddrType)
     {
@@ -1326,6 +1471,12 @@
  * @param   pszMsg      Log message.
  */
-static void intnetR0IfAddrCacheAddSlow(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr, uint8_t const cbAddr, const char *pszMsg)
-{
+static void intnetR0IfAddrCacheAddSlow(PINTNETIF pIf, INTNETADDRTYPE enmAddrType, PCRTNETADDRU pAddr,
+                                       const char *pszMsg)
+{
+    PINTNETADDRCACHE pCache = &pIf->aAddrCache[enmAddrType];
+
+    const uint8_t cbAddr = pCache->cbAddress;
+    Assert(cbAddr == intnetR0AddrSize(enmAddrType));
+
     /*
      * Check all but the first and last entries, the caller
@@ -1345,5 +1496,5 @@
      * Not found, add it.
      */
-    intnetR0IfAddrCacheAddIt(pIf, pCache, pAddr, pszMsg);
+    intnetR0IfAddrCacheAddIt(pIf, enmAddrType, pAddr, pszMsg);
 }
 
@@ -1360,8 +1511,11 @@
  * @param   pszMsg      Log message.
  */
-DECLINLINE(void) intnetR0IfAddrCacheAdd(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr,
-                                        uint8_t const cbAddr, const char *pszMsg)
-{
-    Assert(pCache->cbAddress == cbAddr);
+DECLINLINE(void) intnetR0IfAddrCacheAdd(PINTNETIF pIf, INTNETADDRTYPE enmAddrType, PCRTNETADDRU pAddr,
+                                        const char *pszMsg)
+{
+    PINTNETADDRCACHE pCache = &pIf->aAddrCache[enmAddrType];
+
+    const uint8_t cbAddr = pCache->cbAddress;
+    Assert(cbAddr == intnetR0AddrSize(enmAddrType));
 
     /*
@@ -1374,5 +1528,6 @@
                           && intnetR0AddrUIsEqualEx((PCRTNETADDRU)(pCache->pbEntries + pCache->cbEntry * i), pAddr, cbAddr))) ))
         return;
-    intnetR0IfAddrCacheAddSlow(pIf, pCache, pAddr, cbAddr, pszMsg);
+
+    intnetR0IfAddrCacheAddSlow(pIf, enmAddrType, pAddr, pszMsg);
 }
 
@@ -2150,6 +2305,6 @@
                 if (pMatchingIf)
                 {
-                    intnetR0IfAddrCacheAdd(pMatchingIf, &pMatchingIf->aAddrCache[kIntNetAddrType_IPv4],
-                                           (PCRTNETADDRU)&pDhcp->bp_yiaddr, sizeof(RTNETADDRIPV4), "DHCP_MT_ACK");
+                    intnetR0IfAddrCacheAdd(pMatchingIf, kIntNetAddrType_IPv4,
+                                           (PCRTNETADDRU)&pDhcp->bp_yiaddr, "DHCP_MT_ACK");
                     intnetR0BusyDecIf(pMatchingIf);
                 }
@@ -2423,5 +2578,5 @@
         &&  intnetR0IfAddrCacheLookupLikely(&pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, sizeof(Addr.IPv6)) < 0)
     {
-        intnetR0IfAddrCacheAddIt(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, "if/ipv6");
+        intnetR0IfAddrCacheAdd(pIf, kIntNetAddrType_IPv6, &Addr, "if/ipv6");
     }
 }
@@ -2469,5 +2624,6 @@
             return;
         }
-        intnetR0IfAddrCacheAddIt(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, "if/ipv4");
+
+        intnetR0IfAddrCacheAddIt(pIf, kIntNetAddrType_IPv4, &Addr, "if/ipv4");
         fValidatedIpHdr = true;
     }
@@ -2545,6 +2701,7 @@
     if (    !memcmp(&pArpIPv4->ar_sha, &pIf->MacAddr, sizeof(RTMAC))
         &&  intnetR0IPv4AddrIsGood(pArpIPv4->ar_spa))
-        intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4],
-                               (PCRTNETADDRU)&pArpIPv4->ar_spa, sizeof(RTNETADDRIPV4), "if/arp");
+    {
+        intnetR0IfAddrCacheAdd(pIf, kIntNetAddrType_IPv4, (PCRTNETADDRU)&pArpIPv4->ar_spa, "if/arp");
+    }
 }
 
@@ -5357,4 +5514,52 @@
 
 
+/** @copydoc INTNETTRUNKSWPORT::pfnNotifyHostAddress */
+static DECLCALLBACK(void) intnetR0NetworkNotifyHostAddress(PINTNETTRUNKSWPORT pSwitchPort,
+                                                           bool fAdded,
+                                                           INTNETADDRTYPE enmType, const void *pvAddr)
+{
+    PINTNETTRUNKIF pTrunkIf = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
+    PINTNETNETWORK pNetwork = pTrunkIf->pNetwork;
+    PCRTNETADDRU pAddr = (PCRTNETADDRU)pvAddr;
+    uint8_t cbAddr;
+
+    if (enmType == kIntNetAddrType_IPv4)
+    {
+        Log(("%s: %s %RTnaipv4\n",
+             __FUNCTION__, (fAdded ? "add" : "del"),
+             pAddr->IPv4));
+        cbAddr = 4;
+    }
+    else if (enmType == kIntNetAddrType_IPv6)
+    {
+        Log(("%s: %s %RTnaipv6\n",
+             __FUNCTION__, (fAdded ? "add" : "del"),
+             pAddr));
+        cbAddr = 16;
+    }
+    else
+    {
+        Log(("%s: unexpected address type %d\n", __FUNCTION__, enmType));
+        return;
+    }
+
+    RTSpinlockAcquire(pNetwork->hAddrSpinlock);
+    if (fAdded)         /* one of host interfaces got a new address */
+    {
+        /* blacklist it to prevent spoofing by guests */
+        intnetR0NetworkBlacklistAdd(pNetwork, pAddr, enmType);
+
+        /* kick out any guest that uses it */
+        intnetR0NetworkAddrCacheDeleteUnlocked(pNetwork, pAddr, enmType, cbAddr, "tif/host");
+    }
+    else                /* address deleted from one of host interfaces */
+    {
+        /* stop blacklisting it, guests may use it now */
+        intnetR0NetworkBlacklistDelete(pNetwork, pAddr, enmType);
+    }
+    RTSpinlockRelease(pNetwork->hAddrSpinlock);
+}
+
+
 /**
  * Shutdown the trunk interface.
@@ -5520,4 +5725,6 @@
         pTrunk->SwitchPort.pfnReportGsoCapabilities   = intnetR0TrunkIfPortReportGsoCapabilities;
         pTrunk->SwitchPort.pfnReportNoPreemptDsts     = intnetR0TrunkIfPortReportNoPreemptDsts;
+        if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
+            pTrunk->SwitchPort.pfnNotifyHostAddress   = intnetR0NetworkNotifyHostAddress;
         pTrunk->SwitchPort.pfnDisconnect              = intnetR0TrunkIfPortDisconnect;
         pTrunk->SwitchPort.u32VersionEnd              = INTNETTRUNKSWPORT_VERSION;
@@ -5650,4 +5857,7 @@
      */
     RTSpinlockAcquire(pNetwork->hAddrSpinlock);
+
+    for (int i = kIntNetAddrType_Invalid + 1; i < kIntNetAddrType_End; i++)
+        intnetR0IfAddrCacheDestroy(&pNetwork->aAddrBlacklist[i]);
 
     uint32_t iIf = pNetwork->MacTab.cEntries;
@@ -6112,4 +6322,10 @@
     if (RT_SUCCESS(rc))
     {
+        for (int i = kIntNetAddrType_Invalid + 1; i < kIntNetAddrType_End && RT_SUCCESS(rc); i++)
+            rc = intnetR0IfAddrCacheInit(&pNetwork->aAddrBlacklist[i], (INTNETADDRTYPE)i,
+                                         !!(pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE));
+    }
+    if (RT_SUCCESS(rc))
+    {
         /*
          * Register the object in the current session and link it into the network list.
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h	(revision 55651)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h	(revision 55652)
@@ -154,4 +154,6 @@
             /** The MAC address of the interface. */
             RTMAC MacAddr;
+            /** PF_SYSTEM socket to listen for events (XXX: globals?) */
+            socket_t pSysSock;
             /** @} */
 # elif defined(RT_OS_LINUX)
@@ -171,5 +173,7 @@
             /** The MAC address of the interface. */
             RTMAC MacAddr;
-            struct notifier_block Notifier;
+            struct notifier_block Notifier; /* netdevice */
+            struct notifier_block NotifierIPv4;
+            struct notifier_block NotifierIPv6;
             struct packet_type    PacketType;
 #  ifndef VBOXNETFLT_LINUX_NO_XMIT_QUEUE
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp	(revision 55651)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/darwin/VBoxNetFlt-darwin.cpp	(revision 55652)
@@ -52,4 +52,5 @@
 #include <sys/errno.h>
 #include <sys/ioccom.h>
+#include <sys/filio.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
@@ -62,5 +63,11 @@
 #include <net/kpi_interfacefilter.h>
 RT_C_DECLS_END
+
+#include <sys/kpi_socket.h>
 #include <net/if.h>
+#include <net/if_var.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet6/in6_var.h>
 
 #define VBOXNETFLT_OS_SPECFIC 1
@@ -87,4 +94,6 @@
 static kern_return_t    VBoxNetFltDarwinStart(struct kmod_info *pKModInfo, void *pvData);
 static kern_return_t    VBoxNetFltDarwinStop(struct kmod_info *pKModInfo, void *pvData);
+
+static void vboxNetFltDarwinSysSockUpcall(socket_t pSysSock, void *pvData, int fWait);
 RT_C_DECLS_END
 
@@ -1294,4 +1303,10 @@
     if (pIfFilter)
         iflt_detach(pIfFilter);
+
+    if (pThis->u.s.pSysSock != NULL)
+    {
+        sock_close(pThis->u.s.pSysSock);
+        pThis->u.s.pSysSock = NULL;
+    }
 }
 
@@ -1300,5 +1315,248 @@
 {
     NOREF(pvContext);
-    return vboxNetFltDarwinAttachToInterface(pThis, false /* fRediscovery */);
+
+    int rc = vboxNetFltDarwinAttachToInterface(pThis, false /* fRediscovery */);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    if (pThis->pSwitchPort->pfnNotifyHostAddress == NULL)
+        return rc;
+
+    /*
+     * XXX: uwe
+     *
+     * Learn host's IP addresses and set up notifications for changes.
+     * To avoid racing, set up notifications first.
+     *
+     * XXX: This should probably be global, since the only thing
+     * specific to ifnet here is its IPv6 link-local address.
+     */
+    errno_t error;
+
+    error = sock_socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT,
+                        vboxNetFltDarwinSysSockUpcall, pThis,
+                        &pThis->u.s.pSysSock);
+    if (error != 0)
+    {
+        LogRel(("sock_socket(SYSPROTO_EVENT): error %d\n", error));
+        return rc;
+    }
+
+    int nbio = 1;
+    error = sock_ioctl(pThis->u.s.pSysSock, FIONBIO, &nbio);
+    if (error != 0)
+    {
+        LogRel(("FIONBIO: error %d\n", error));
+        sock_close(pThis->u.s.pSysSock);
+        return rc;
+    }
+
+    if (!sock_isnonblocking(pThis->u.s.pSysSock))
+    {
+        LogRel(("FIONBIO ok, but socket is blocking?!\n"));
+        sock_close(pThis->u.s.pSysSock);
+        return rc;        
+    }
+
+    struct kev_request req;
+    req.vendor_code = KEV_VENDOR_APPLE;
+    req.kev_class = KEV_NETWORK_CLASS;
+    req.kev_subclass = KEV_ANY_SUBCLASS; /* need both INET and INET6, so have to request all */
+
+    error = sock_ioctl(pThis->u.s.pSysSock, SIOCSKEVFILT, &req);
+    if (error != 0)
+    {
+        LogRel(("SIOCSKEVFILT: error %d\n", error));
+        sock_close(pThis->u.s.pSysSock);
+        return rc;
+    }
+
+    ifnet_t pIfNet = pThis->u.s.pIfNet; /* already retained */
+
+    ifaddr_t *pIfAddrList;
+    error = ifnet_get_address_list(/* all interfaces*/ NULL, &pIfAddrList);
+    if (error != 0)
+    {
+        LogRel(("ifnet_get_address_list: error %d\n", error));
+        return rc;
+    }
+
+    for (ifaddr_t *pIfAddr = pIfAddrList; *pIfAddr != NULL; ++pIfAddr)
+    {
+        ifaddr_t ifa = *pIfAddr;
+        sa_family_t family = ifaddr_address_family(ifa);
+        struct sockaddr_storage ss;
+
+        error = ifaddr_address(ifa, (struct sockaddr *)&ss, sizeof(ss));
+        if (error != 0)
+        {
+            LogRel(("getting address family %d: error %d\n", family, error));
+            continue;
+        }
+
+        if (family == AF_INET)
+        {
+            struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
+            u_int32_t u32Addr = ntohl(sin->sin_addr.s_addr);
+
+            if ((u32Addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+                continue;
+
+            Log(("> inet %RTnaipv4\n", sin->sin_addr.s_addr));
+            pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                /* :fAdded */ true, kIntNetAddrType_IPv4, &sin->sin_addr);
+        }
+        else if (family == AF_INET6)
+        {
+            struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
+
+            if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+                continue;
+
+            /* link-local from other interfaces are out of scope */
+            if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && ifaddr_ifnet(ifa) != pIfNet)
+                continue;
+
+            Log(("> inet6 %RTnaipv6\n", &sin6->sin6_addr));
+            pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                /* :fAdded */ true, kIntNetAddrType_IPv6, &sin6->sin6_addr);
+        }
+    }
+
+    ifnet_free_address_list(pIfAddrList);
+
+    /*
+     * Now that we've got current addresses, check for events that
+     * might have happened while we were working.
+     */
+    vboxNetFltDarwinSysSockUpcall(pThis->u.s.pSysSock, pThis, MBUF_DONTWAIT);
+
+    return rc;
+}
+
+
+static void vboxNetFltDarwinSysSockUpcall(socket_t pSysSock, void *pvData, int fWait)
+{
+    PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvData;
+    errno_t error;
+
+    NOREF(fWait);
+
+    if (RT_UNLIKELY(pSysSock != pThis->u.s.pSysSock))
+    {
+        Log(("vboxNetFltDarwinSysSockUpcall: %p != %p?\n",
+             pSysSock, pThis->u.s.pSysSock));
+        return;
+    }
+
+    for (;;) {
+        mbuf_t m;
+        size_t len = sizeof(struct kern_event_msg) - sizeof(u_int32_t)
+            + sizeof(struct kev_in6_data);
+
+        error = sock_receivembuf(pSysSock, NULL, &m, 0, &len);
+        if (error == EWOULDBLOCK)
+        {
+            Log(("vboxNetFltDarwinSysSockUpcall: EWOULDBLOCK - we are done\n"));
+            error = 0;
+            break;
+        }
+        else if (error != 0)
+        {
+            Log(("sock_receivembuf: error %d\n", error));
+            break;
+        }
+
+        if (len < sizeof(struct kern_event_msg) - sizeof(u_int32_t))
+        {
+            Log(("vboxNetFltDarwinSysSockUpcall: %u bytes is too short\n",
+                 (unsigned int)len));
+            mbuf_freem(m);
+            return;
+        }
+
+        struct kern_event_msg *msg = (struct kern_event_msg *)mbuf_data(m);
+        if (msg->kev_subclass == KEV_INET_SUBCLASS)
+        {
+            if (len - (sizeof(struct kern_event_msg) - sizeof(u_int32_t)) < sizeof(struct kev_in_data))
+            {
+                Log(("vboxNetFltDarwinSysSockUpcall: %u bytes is too short for KEV_INET_SUBCLASS\n",
+                     (unsigned int)len));
+                mbuf_freem(m);
+                return;
+            }
+
+            struct kev_in_data *iev = (struct kev_in_data *)msg->event_data;
+            PCRTNETADDRU pAddr = (PCRTNETADDRU)&iev->ia_addr;
+            switch (msg->event_code)
+            {
+                case KEV_INET_NEW_ADDR:
+                    Log(("KEV_INET_NEW_ADDR %RTnaipv4\n", pAddr->IPv4));
+                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                        /* :fAdded */ true, kIntNetAddrType_IPv4, pAddr);
+                    break;
+
+                case KEV_INET_ADDR_DELETED:
+                    Log(("KEV_INET_ADDR_DELETED %RTnaipv4\n", pAddr->IPv4));
+                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                        /* :fAdded */ false, kIntNetAddrType_IPv4, &iev->ia_addr);
+                    break;
+
+                default:
+                    Log(("KEV INET event %u addr %RTnaipv4\n", msg->event_code, pAddr->IPv4));
+                    break;
+            }
+        }
+        else if (msg->kev_subclass == KEV_INET6_SUBCLASS)
+        {
+            if (len - (sizeof(struct kern_event_msg) - sizeof(u_int32_t)) < sizeof(struct kev_in6_data))
+            {
+                Log(("vboxNetFltDarwinSysSockUpcall: %u bytes is too short for KEV_INET6_SUBCLASS\n",
+                        (unsigned int)len));
+                mbuf_freem(m);
+                return;
+            }
+
+            struct kev_in6_data *iev6 = (struct kev_in6_data *)msg->event_data;
+            PCRTNETADDRU pAddr = (PCRTNETADDRU)&iev6->ia_addr.sin6_addr;
+            switch (msg->event_code)
+            {
+                case KEV_INET6_NEW_USER_ADDR:
+                    Log(("KEV_INET6_NEW_USER_ADDR: %RTnaipv6\n", pAddr));
+                    goto kev_inet6_new;
+
+                case KEV_INET6_NEW_LL_ADDR:
+                    Log(("KEV_INET6_NEW_LL_ADDR: %RTnaipv6\n", pAddr));
+                    /* XXX: uwe: TODO: only interface we are attached to */
+                    goto kev_inet6_new;
+
+                case KEV_INET6_NEW_RTADV_ADDR:
+                    Log(("KEV_INET6_NEW_RTADV_ADDR: %RTnaipv6\n", pAddr));
+                    goto kev_inet6_new;
+
+                kev_inet6_new:
+                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                        /* :fAdded */ true, kIntNetAddrType_IPv6, pAddr);
+                    break;
+
+                case KEV_INET6_ADDR_DELETED:
+                    Log(("KEV_INET6_ADDR_DELETED: %RTnaipv6\n", pAddr));
+                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                        /* :fAdded */ false, kIntNetAddrType_IPv6, pAddr);
+                    break;
+
+                default:
+                    Log(("KEV INET6 event %u addr %RTnaipv6\n", msg->event_code, pAddr));
+                    break;
+            }
+        }
+        else
+        {
+            Log(("vboxNetFltDarwinSysSockUpcall: subclass %u ignored\n",
+                 (unsigned)msg->kev_subclass));
+        }
+
+        mbuf_freem(m);
+    }
 }
 
@@ -1314,4 +1572,5 @@
     pThis->u.s.fNeedSetPromiscuous = false;
     //pThis->u.s.MacAddr = {0};
+    pThis->u.s.pSysSock = NULL;
 
     return VINF_SUCCESS;
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c	(revision 55651)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c	(revision 55652)
@@ -28,6 +28,9 @@
 #include <linux/rtnetlink.h>
 #include <linux/miscdevice.h>
+#include <linux/inetdevice.h>
 #include <linux/ip.h>
 #include <linux/if_vlan.h>
+#include <net/if_inet6.h>
+#include <net/addrconf.h>
 
 #include <VBox/log.h>
@@ -1857,4 +1860,72 @@
 }
 
+static int vboxNetFltLinuxNotifierIPv4Callback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
+{
+    PVBOXNETFLTINS     pThis = RT_FROM_MEMBER(self, VBOXNETFLTINS, u.s.NotifierIPv4);
+    struct net_device *pDev;
+    struct in_ifaddr  *ifa   = (struct in_ifaddr *)ptr;
+    int                rc    = NOTIFY_OK;
+
+    pDev = vboxNetFltLinuxRetainNetDev(pThis);
+    Log(("VBoxNetFlt: %s: IPv4 event %s(0x%lx): addr %RTnaipv4 mask %RTnaipv4\n",
+         pDev ? netdev_name(pDev) : "<???>",
+         vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType,
+         ifa->ifa_address, ifa->ifa_mask));
+
+    if (pDev != NULL)
+        vboxNetFltLinuxReleaseNetDev(pThis, pDev);
+
+    if (pThis->pSwitchPort->pfnNotifyHostAddress)
+    {
+        bool fAdded;
+        if (ulEventType == NETDEV_UP)
+            fAdded = true;
+        else if (ulEventType == NETDEV_DOWN)
+            fAdded = false;
+        else
+            return NOTIFY_OK;
+            
+        pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort, fAdded,
+                                                 kIntNetAddrType_IPv4, &ifa->ifa_local);
+    }
+
+    return rc;
+}
+
+
+static int vboxNetFltLinuxNotifierIPv6Callback(struct notifier_block *self, unsigned long ulEventType, void *ptr)
+{
+    PVBOXNETFLTINS       pThis = RT_FROM_MEMBER(self, VBOXNETFLTINS, u.s.NotifierIPv6);
+    struct net_device   *pDev;
+    struct inet6_ifaddr *ifa   = (struct inet6_ifaddr *)ptr;
+    int                  rc    = NOTIFY_OK;
+
+    pDev = vboxNetFltLinuxRetainNetDev(pThis);
+    Log(("VBoxNetFlt: %s: IPv6 event %s(0x%lx): %RTnaipv6\n",
+         pDev ? netdev_name(pDev) : "<???>",
+         vboxNetFltLinuxGetNetDevEventName(ulEventType), ulEventType,
+         &ifa->addr));
+
+    if (pDev != NULL)
+        vboxNetFltLinuxReleaseNetDev(pThis, pDev);
+
+    if (pThis->pSwitchPort->pfnNotifyHostAddress)
+    {
+        bool fAdded;
+        if (ulEventType == NETDEV_UP)
+            fAdded = true;
+        else if (ulEventType == NETDEV_DOWN)
+            fAdded = false;
+        else
+            return NOTIFY_OK;
+            
+        pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort, fAdded,
+                                                 kIntNetAddrType_IPv6, &ifa->addr);
+    }
+
+    return rc;
+}
+
+
 bool vboxNetFltOsMaybeRediscovered(PVBOXNETFLTINS pThis)
 {
@@ -2053,4 +2124,8 @@
         dev_put(pDev);
     }
+
+    unregister_inet6addr_notifier(&pThis->u.s.NotifierIPv6);
+    unregister_inetaddr_notifier(&pThis->u.s.NotifierIPv4);
+
     Log(("vboxNetFltOsDeleteInstance: this=%p: Notifier removed.\n", pThis));
     unregister_netdevice_notifier(&pThis->u.s.Notifier);
@@ -2079,4 +2154,77 @@
         || !try_module_get(THIS_MODULE))
         return VERR_INTNET_FLT_IF_FAILED;
+
+    if (pThis->pSwitchPort->pfnNotifyHostAddress)
+    {
+        struct net *net = dev_net(pThis->u.s.pDev);
+        struct net_device *dev;
+
+        rcu_read_lock();
+        for_each_netdev_rcu(net, dev)
+        {
+            struct in_device *in_dev;
+            struct inet6_dev *in6_dev;
+
+            /*
+             * IPv4
+             */
+            in_dev = __in_dev_get_rcu(dev);
+            if (in_dev != NULL)
+            {
+                for_ifa(in_dev) {
+                    if (ifa->ifa_address == htonl(INADDR_LOOPBACK))
+                        goto continue_netdev;
+
+                    Log(("%s: %s: IPv4: addr %RTnaipv4 mask %RTnaipv4\n",
+                         __FUNCTION__, netdev_name(dev),
+                         ifa->ifa_address, ifa->ifa_mask));
+
+                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                        /* :fAdded */ true, kIntNetAddrType_IPv4, &ifa->ifa_address);
+                } endfor_ifa(in_dev);
+            }
+
+            /*
+             * IPv6
+             */
+            in6_dev = __in6_dev_get(dev);
+            if (in6_dev != NULL)
+            {
+                struct inet6_ifaddr *ifa;
+
+                read_lock_bh(&in6_dev->lock);
+                list_for_each_entry(ifa, &in6_dev->addr_list, if_list)
+                {
+                    Log(("%s: %s: IPv6: addr %RTnaipv6/%u\n",
+                         __FUNCTION__, netdev_name(dev),
+                         &ifa->addr, (unsigned)ifa->prefix_len));
+
+                    pThis->pSwitchPort->pfnNotifyHostAddress(pThis->pSwitchPort,
+                        /* :fAdded */ true, kIntNetAddrType_IPv6, &ifa->addr);
+                }
+                read_unlock_bh(&in6_dev->lock);
+            }
+
+          continue_netdev:
+            /* continue */;
+        }
+	rcu_read_unlock();
+
+        Log(("%s: pfnNotifyHostAddress is set, register notifiers\n", __FUNCTION__));
+
+        pThis->u.s.NotifierIPv4.notifier_call = vboxNetFltLinuxNotifierIPv4Callback;
+        err = register_inetaddr_notifier(&pThis->u.s.NotifierIPv4);
+        if (err)
+            LogRel(("%s: failed to register IPv4 notifier: error %d\n",
+                    __FUNCTION__, err));
+
+        pThis->u.s.NotifierIPv6.notifier_call = vboxNetFltLinuxNotifierIPv6Callback;
+        err = register_inet6addr_notifier(&pThis->u.s.NotifierIPv6);
+        if (err)
+            LogRel(("%s: failed to register IPv6 notifier: error %d\n",
+                    __FUNCTION__, err));
+    }
+    else
+        Log(("%s: uwe: pfnNotifyHostAddress is NULL\n", __FUNCTION__));
 
     return VINF_SUCCESS;
