VirtualBox

Changeset 11072 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Aug 1, 2008 10:24:51 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33974
Message:

IntNet,VBoxNetFlt: Implememnted ARP editing when sharing MAC address with the host (on the wire). Fixed an invalid buffer access in intnetR0SgReadPart[Slow]. Fixed multicast/broadcast mixup, broadcast was identified as multicast.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r11069 r11072  
    171171     * This may be NULL if we're orphaned? */
    172172    struct INTNETNETWORK   *pNetwork;
     173    /** The cached MAC address of the interface the trunk is attached to.
     174     * This is for the situations where we cannot take the out-bound
     175     * semaphore (the recv case) but need to make frame edits (ARP). */
     176    RTMAC                   CachedMac;
    173177    /** Whether to supply physical addresses with the outbound SGs. */
    174178    bool volatile           fPhysSG;
     
    331335
    332336/**
     337 * Worker for intnetR0SgWritePart that deals with the case where the
     338 * request doesn't fit into the first segment.
     339 *
     340 * @returns true, unless the request or SG invalid.
     341 * @param   pSG         The SG list to write to.
     342 * @param   off         Where to start writing (offset into the SG).
     343 * @param   cb          How much to write.
     344 * @param   pvBuf       The buffer to containing the bits to write.
     345 */
     346static bool intnetR0SgWritePartSlow(PCINTNETSG pSG, uint32_t off, uint32_t cb, void const *pvBuf)
     347{
     348    if (RT_UNLIKELY(off + cb > pSG->cbTotal))
     349        return false;
     350
     351    /*
     352     * Skip ahead to the segment where off starts.
     353     */
     354    unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);
     355    unsigned iSeg = 0;
     356    while (off > pSG->aSegs[iSeg].cb)
     357    {
     358        off -= pSG->aSegs[iSeg++].cb;
     359        AssertReturn(iSeg < cSegs, false);
     360    }
     361
     362    /*
     363     * Copy the data, hoping that it's all from one segment...
     364     */
     365    uint32_t cbCanCopy = pSG->aSegs[iSeg].cb - off;
     366    if (cbCanCopy >= cb)
     367        memcpy((uint8_t *)pSG->aSegs[iSeg].pv + off, pvBuf, cb);
     368    else
     369    {
     370        /* copy the portion in the current segment. */
     371        memcpy((uint8_t *)pSG->aSegs[iSeg].pv + off, pvBuf, cbCanCopy);
     372        cb -= cbCanCopy;
     373
     374        /* copy the portions in the other segments. */
     375        do
     376        {
     377            pvBuf = (uint8_t const *)pvBuf + cbCanCopy;
     378            iSeg++;
     379            AssertReturn(iSeg < cSegs, false);
     380
     381            cbCanCopy = RT_MIN(cb, pSG->aSegs[iSeg].cb);
     382            memcpy(pSG->aSegs[iSeg].pv, pvBuf, cbCanCopy);
     383
     384            cb -= cbCanCopy;
     385        } while (cb > 0);
     386    }
     387
     388    return true;
     389}
     390
     391
     392/**
     393 * Writes to a part of an SG.
     394 *
     395 * @returns true on success, false on failure (out of bounds).
     396 * @param   pSG         The SG list to write to.
     397 * @param   off         Where to start writing (offset into the SG).
     398 * @param   cb          How much to write.
     399 * @param   pvBuf       The buffer to containing the bits to write.
     400 */
     401DECLINLINE(bool) intnetR0SgWritePart(PCINTNETSG pSG, uint32_t off, uint32_t cb, void const *pvBuf)
     402{
     403    Assert(off + cb > off);
     404
     405    /* The optimized case. */
     406    if (RT_LIKELY(    pSG->cSegsUsed == 1
     407                  ||  pSG->aSegs[0].cb >= off + cb))
     408    {
     409        Assert(pSG->cbTotal == pSG->aSegs[0].cb);
     410        memcpy((uint8_t *)pSG->aSegs[0].pv + off, pvBuf, cb);
     411        return true;
     412    }
     413    return intnetR0SgWritePartSlow(pSG, off, cb, pvBuf);
     414}
     415
     416
     417/**
    333418 * Reads a byte from a SG list.
    334419 *
     
    399484
    400485            cbCanCopy = RT_MIN(cb, pSG->aSegs[iSeg].cb);
    401             memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cbCanCopy);
     486            memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv, cbCanCopy);
    402487
    403488            cb -= cbCanCopy;
     
    749834static void intnetR0IfAddrCacheDeleteIt(PINTNETIF pIf, PINTNETADDRCACHE pCache, int iEntry, const char *pszMsg)
    750835{
     836#if 0 /** @todo the inbound ARP snooping is busted. */
    751837    Log(("intnetR0IfAddrCacheDeleteIt: hIf=%RX32 type=%d #%d %.*Rhxs %s\n", pIf->hIf,
    752838         (int)(intptr_t)(pCache - &pIf->aAddrCache[0]), iEntry, pCache->cbAddress,
     
    758844                pCache->pbEntries + (iEntry + 1) * pCache->cbEntry,
    759845                (pCache->cEntries - iEntry)      * pCache->cbEntry);
     846#endif
    760847}
    761848
     
    769856 * @param   cbAddr          The address size (optimization).
    770857 */
    771 DECLINLINE(void) intnetR0IfAddrCacheDelete(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr, uint8_t const cbAddr)
     858DECLINLINE(void) intnetR0IfAddrCacheDelete(PINTNETIF pIf, PINTNETADDRCACHE pCache, PCRTNETADDRU pAddr, uint8_t const cbAddr, const char *pszMsg)
    772859{
    773860    int i = intnetR0IfAddrCacheLookup(pCache, pAddr, cbAddr);
    774861    if (RT_UNLIKELY(i >= 0))
    775         intnetR0IfAddrCacheDeleteIt(pIf, pCache, i, "if");
     862        intnetR0IfAddrCacheDeleteIt(pIf, pCache, i, pszMsg);
    776863}
    777864
     
    823910                intnetR0IfAddrCacheDeleteIt(pIf, &pIf->aAddrCache[enmType], i, pszMsg);
    824911        }
     912}
     913
     914
     915/**
     916 * Lookup an address on the network, returning the (first) interface
     917 * having it in its address cache.
     918 *
     919 * @returns Pointer to the interface on success, NULL if not found.
     920 * @param   pNetwork        The network.
     921 * @param   pAddr           The address to lookup.
     922 * @param   enmType         The address type.
     923 * @param   cbAddr          The size of the address.
     924 */
     925DECLINLINE(PINTNETIF) intnetR0NetworkAddrCacheLookupIf(PINTNETNETWORK pNetwork, PCRTNETADDRU pAddr, INTNETADDRTYPE const enmType, uint8_t const cbAddr)
     926{
     927    for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
     928    {
     929        int i = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmType], pAddr, cbAddr);
     930        if (i >= 0)
     931            return pIf;
     932    }
     933    return NULL;
    825934}
    826935
     
    10241133    if (RT_UNLIKELY(    ar_oper != RTNET_ARPOP_REQUEST
    10251134                    &&  ar_oper != RTNET_ARPOP_REPLY
     1135                 /* These doesn't interest us at the moment since they are rarely used on ethernet:
    10261136                    &&  ar_oper != RTNET_ARPOP_REVREQUEST
    10271137                    &&  ar_oper != RTNET_ARPOP_REVREPLY
    1028                     /** @todo Read up on inverse ARP. */
     1138                    &&  ar_oper != RTNET_ARPOP_INVREQUEST
     1139                    &&  ar_oper != RTNET_ARPOP_INVREPLY */
    10291140                   ))
    10301141        return;
     
    10491160        intnetR0NetworkAddrCacheDelete(pNetwork, &Addr, kIntNetAddrType_IPv4, sizeof(pReq->ar_spa), "tif/arp");
    10501161    }
    1051 #if 0 /** @todo IPv6 support */
    1052     else if (ar_ptype == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
    1053     {
    1054         /*
    1055          * IPv6.
    1056          */
    1057         PCINTNETARPIPV6 pReq = (PCINTNETARPIPV6)pHdr;
    1058         if (RT_UNLIKELY(    pHdr->ar_plen != sizeof(pReq->ar_spa)
    1059                         ||  cbPacket < sizeof(*pReq)
    1060                         ||  !intnetR0IPv6AddrIsGood(&pReq->ar_spa)))
    1061             return;
    1062 
    1063         Addr.IPv6 = pReq->ar_spa;
    1064         intnetR0NetworkAddrCacheDelete(pNetwork, &Addr, kIntNetAddrType_IPv6, sizeof(pReq->ar_spa), "tif/arp");
    1065     }
     1162#if 0 /** @todo IPv6 ARP support? Is it used at all? */
    10661163#endif
    10671164    else
     
    11981295 * @param   cbPacket        The size of the packet (migth be larger than the ARP
    11991296 *                          request 'cause of min ethernet frame size).
    1200  */
    1201 static void intnetR0IfSnoopArpAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket)
     1297 * @param   pfSgFlags       Pointer to the SG flags. This is used to tag the packet so we
     1298 *                          don't have to repeat the frame parsing in intnetR0TrunkIfSend.
     1299 */
     1300static void intnetR0IfSnoopArpAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket, uint16_t *pfSgFlags)
    12021301{
    12031302    /*
     
    12111310    if (RT_UNLIKELY(    ar_oper != RTNET_ARPOP_REQUEST
    12121311                    &&  ar_oper != RTNET_ARPOP_REPLY
     1312                 /* These doesn't interest us at the moment since they are rarely used on ethernet:
    12131313                    &&  ar_oper != RTNET_ARPOP_REVREQUEST
    12141314                    &&  ar_oper != RTNET_ARPOP_REVREPLY
    1215                     /** @todo Read up on inverse ARP. */
     1315                    &&  ar_oper != RTNET_ARPOP_INVREQUEST
     1316                    &&  ar_oper != RTNET_ARPOP_INVREPLY */
    12161317                   ))
    12171318        return;
     
    12291330        PCRTNETARPIPV4 pReq = (PCRTNETARPIPV4)pHdr;
    12301331        if (RT_UNLIKELY(    pHdr->ar_plen != sizeof(pReq->ar_spa)
    1231                         ||  cbPacket < sizeof(*pReq)
    1232                         ||  !intnetR0IPv4AddrIsGood(pReq->ar_spa)))
     1332                        ||  cbPacket < sizeof(*pReq)))
    12331333            return;
    1234 
    1235         if (    RTNET_ARPOP_IS_REPLY(RT_BE2H_U16(pHdr->ar_oper))
     1334        *pfSgFlags |= INTNETSG_FLAGS_ARP_IPV4;
     1335/** @todo should check the MAC addresses here. */
     1336        if (    RTNET_ARPOP_IS_REPLY(ar_oper)
    12361337            &&  intnetR0IPv4AddrIsGood(pReq->ar_tpa))
    12371338        {
    12381339            Addr.IPv4 = pReq->ar_tpa;
    1239             intnetR0IfAddrCacheDelete(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(pReq->ar_tpa));
     1340            intnetR0IfAddrCacheDelete(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(pReq->ar_tpa), "if/arp");
    12401341        }
    1241         Addr.IPv4 = pReq->ar_spa;
    1242         intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(pReq->ar_spa), "if/arp");
    1243     }
    1244 #if 0 /** @todo IPv6 support */
    1245     else if (ar_ptype == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
    1246     {
    1247         /*
    1248          * IPv6.
    1249          */
    1250         PCINTNETARPIPV6 pReq = (PCINTNETARPIPV6)pHdr;
    1251         if (RT_UNLIKELY(    pHdr->ar_plen != sizeof(pReq->ar_spa)
    1252                         ||  cbPacket < sizeof(*pReq)
    1253                         ||  !intnetR0IPv6AddrIsGood(&pReq->ar_spa)))
    1254             return;
    1255 
    1256         if (    RTNET_ARPOP_IS_REPLY(RT_BE2H_U16(pHdr->ar_oper))
    1257             &&  intnetR0IPv6AddrIsGood(&pReq->ar_tpa))
     1342        if (intnetR0IPv4AddrIsGood(pReq->ar_spa))
    12581343        {
    1259             Addr.IPv6 = pReq->ar_tpa;
    1260             intnetR0IfAddrCacheDelete(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, sizeof(pReq->ar_tpa));
     1344            Addr.IPv4 = pReq->ar_spa;
     1345            intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(pReq->ar_spa), "if/arp");
    12611346        }
    1262         Addr.IPv6 = pReq->ar_spa;
    1263         intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, sizeof(pReq->ar_spa), "if/arp");
    1264     }
     1347    }
     1348#if 0 /** @todo IPv6 ARP support? Is it used at all? */
    12651349#endif
    12661350    else
     
    12771361 * @param   pbFrame         The frame.
    12781362 * @param   cbFrame         The size of the frame.
    1279  */
    1280 static void intnetR0IfSnoopAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame)
     1363 * @param   pfSgFlags       Pointer to the SG flags. This is used to tag the packet so we
     1364 *                          don't have to repeat the frame parsing in intnetR0TrunkIfSend.
     1365 */
     1366static void intnetR0IfSnoopAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame, uint16_t *pfSgFlags)
    12811367{
    12821368    /*
     
    13061392#endif
    13071393        case RTNET_ETHERTYPE_ARP:
    1308             intnetR0IfSnoopArpAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1394            intnetR0IfSnoopArpAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame, pfSgFlags);
    13091395            break;
    13101396    }
     
    15211607 * @param   pThis           The trunk.
    15221608 * @param   pNetwork        The network the frame is being sent to.
     1609 * @param   pIfSender       The IF sending the frame. Used for MAC address checks in shared MAC mode.
    15231610 * @param   fDst            The destination flags.
    15241611 * @param   pSG             Pointer to the gather list.
    15251612 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
    15261613 */
    1527 static void intnetR0TrunkIfSend(PINTNETTRUNKIF pThis, PINTNETNETWORK pNetwork, uint32_t fDst, PINTNETSG pSG, bool fTrunkLocked)
     1614static void intnetR0TrunkIfSend(PINTNETTRUNKIF pThis, PINTNETNETWORK pNetwork, PINTNETIF pIfSender,
     1615                                uint32_t fDst, PINTNETSG pSG, bool fTrunkLocked)
    15281616{
    15291617    /*
     
    15371625
    15381626    /*
    1539      * If we're supposed to be sharing the MAC address with the host
    1540      * interface when hitting the wire, change INTNETTRUNKDIR_WIRE to
    1541      * INTNETTRUNKDIR_WIRE_SHARED  before calling pfnXmit.
     1627     * Do frame modifications when sharing MAC address on the wire.
     1628     *
     1629     * If the frame is headed for both the host and the wire, we'll
     1630     * have to send it to the host before making any modifications,
     1631     * and force a copy of the frame.
    15421632     */
    15431633    if (    (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
    15441634        &&  (fDst & INTNETTRUNKDIR_WIRE))
    1545         fDst = (fDst & ~INTNETTRUNKDIR_WIRE) | INTNETTRUNKDIR_WIRE_SHARED;
     1635    {
     1636        /* Dispatch it to the host before making changes. */
     1637        if (fDst & INTNETTRUNKDIR_HOST)
     1638        {
     1639            Assert(pSG->fFlags & INTNETSG_FLAGS_TEMP); /* make sure copy is forced */
     1640            intnetR0TrunkIfSend(pThis, pNetwork, pIfSender, INTNETTRUNKDIR_HOST, pSG, fTrunkLocked);
     1641            fDst &= ~INTNETTRUNKDIR_HOST;
     1642        }
     1643
     1644        /* ASSUME frame from INTNETR0IfSend! */
     1645        AssertReturnVoid(pSG->cSegsUsed == 1);
     1646        AssertReturnVoid(pSG->cbTotal >= sizeof(RTNETETHERHDR));
     1647        AssertReturnVoid(fTrunkLocked);
     1648        AssertReturnVoid(pIfSender);
     1649        PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pSG->aSegs[0].pv;
     1650
     1651        /*
     1652         * Get the host mac address and update the ethernet header.
     1653         *
     1654         * The reason for caching it in the trunk structure is because
     1655         * we cannot take the trunk out-bound semaphore when we handle
     1656         * stuff like ARP replies from the wire.
     1657         */
     1658        pThis->pIfPort->pfnGetMacAddress(pThis->pIfPort, &pThis->CachedMac);
     1659        if (!memcmp(&pEthHdr->SrcMac, &pIfSender->Mac, sizeof(RTMAC)))
     1660            pEthHdr->SrcMac = pThis->CachedMac;
     1661
     1662        /*
     1663         * Deal with tags from the snooping phase.
     1664         */
     1665        if (pSG->fFlags & INTNETSG_FLAGS_ARP_IPV4)
     1666        {
     1667            PRTNETARPIPV4 pArp = (PRTNETARPIPV4)(pEthHdr + 1);
     1668            if (!memcmp(&pArp->ar_sha, &pIfSender->Mac, sizeof(RTMAC)))
     1669            {
     1670                Log6(("tw: ar_sha %.6Rhxs -> %.6Rhxs\n", &pArp->ar_sha, &pThis->CachedMac));
     1671                pArp->ar_sha = pThis->CachedMac;
     1672            }
     1673            if (!memcmp(&pArp->ar_tha, &pIfSender->Mac, sizeof(RTMAC))) /* just in case... */
     1674            {
     1675                Log6(("tw: ar_tha %.6Rhxs -> %.6Rhxs\n", &pArp->ar_tha, &pThis->CachedMac));
     1676                pArp->ar_tha = pThis->CachedMac;
     1677            }
     1678        }
     1679    }
    15461680
    15471681    /*
     
    15991733
    16001734/**
     1735 * Edits an ARP packet arriving from the wire via the trunk connection.
     1736 *
     1737 * @param   pNetwork        The network the frame is being sent to.
     1738 * @param   pSG             Pointer to the gather list for the frame.
     1739 *                          The flags and data content may be updated.
     1740 * @param   pEthHdr         Pointer to the ethernet header. This may also be
     1741 *                          updated if it's a unicast...
     1742 */
     1743static void intnetR0NetworkEditArpFromWire(PINTNETNETWORK pNetwork, PINTNETSG pSG, PRTNETETHERHDR pEthHdr)
     1744{
     1745    /*
     1746     * Check the minimum size first.
     1747     */
     1748    if (RT_UNLIKELY(pSG->cbTotal < INTNET_ARP_MIN_LEN))
     1749        return;
     1750
     1751    /*
     1752     * Copy to temporary buffer if necessary.
     1753     */
     1754    size_t  cbPacket = RT_MIN(pSG->cbTotal, INTNET_ARP_MAX_LEN);
     1755    PCRTNETARPHDR pHdr = (PCRTNETARPHDR)((uintptr_t)pSG->aSegs[0].pv + sizeof(RTNETETHERHDR));
     1756    if (    pSG->cSegsUsed != 1
     1757        &&  pSG->aSegs[0].cb < cbPacket)
     1758    {
     1759        Log6(("fw: Copying ARP pkt %u\n", cbPacket));
     1760        if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR), cbPacket, pNetwork->pbTmp))
     1761            return;
     1762        pHdr = (PCRTNETARPHDR)pNetwork->pbTmp;
     1763        pSG->fFlags |= INTNETSG_FLAGS_PKT_CP_IN_TMP;
     1764    }
     1765
     1766    /*
     1767     * Ignore malformed packets and packets which doesn't interest us.
     1768     */
     1769    if (RT_UNLIKELY(    pHdr->ar_hlen != sizeof(RTMAC)
     1770                    ||  pHdr->ar_htype != RT_H2BE_U16(RTNET_ARP_ETHER)))
     1771        return;
     1772    uint16_t ar_oper = RT_H2BE_U16(pHdr->ar_oper);
     1773    if (RT_UNLIKELY(    ar_oper != RTNET_ARPOP_REQUEST
     1774                    &&  ar_oper != RTNET_ARPOP_REPLY
     1775                 /* These doesn't interest us at the moment since they are rarely used on ethernet:
     1776                    &&  ar_oper != RTNET_ARPOP_REVREQUEST
     1777                    &&  ar_oper != RTNET_ARPOP_REVREPLY
     1778                    &&  ar_oper != RTNET_ARPOP_INVREQUEST
     1779                    &&  ar_oper != RTNET_ARPOP_INVREPLY */
     1780                   ))
     1781        return;
     1782
     1783    /*
     1784     * Deal with the protocols.
     1785     *
     1786     * The thing we're interested in here is a reply to a query
     1787     * made by a guest since we've modified the MAC in the initial
     1788     * request the guest made.
     1789     */
     1790    bool fModified = false;
     1791    uint16_t ar_ptype = RT_H2BE_U16(pHdr->ar_ptype);
     1792    if (ar_ptype == RTNET_ETHERTYPE_IPV4)
     1793    {
     1794        /*
     1795         * IPv4.
     1796         */
     1797        PRTNETARPIPV4 pReq = (PRTNETARPIPV4)pHdr;
     1798        if (RT_UNLIKELY(    pHdr->ar_plen != sizeof(pReq->ar_spa)
     1799                        ||  cbPacket < sizeof(*pReq)))
     1800            return;
     1801        pSG->fFlags |= INTNETSG_FLAGS_ARP_IPV4;
     1802        if (    ar_oper == RTNET_ARPOP_REPLY
     1803            &&  !memcmp(&pReq->ar_tha, &pNetwork->pTrunkIF->CachedMac, sizeof(RTMAC)))
     1804        {
     1805            PINTNETIF pIf = intnetR0NetworkAddrCacheLookupIf(pNetwork, (PCRTNETADDRU)&pReq->ar_tpa,
     1806                                                             kIntNetAddrType_IPv4, sizeof(pReq->ar_tpa));
     1807            if (pIf)
     1808            {
     1809                Log6(("fw: ar_tha %.6Rhxs -> %.6Rhxs\n", &pReq->ar_tha, &pIf->Mac));
     1810                pReq->ar_tha = pIf->Mac;
     1811                if (!memcmp(&pEthHdr->DstMac, &pNetwork->pTrunkIF->CachedMac, sizeof(RTMAC)))
     1812                {
     1813                    Log6(("fw: DstMac %.6Rhxs -> %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac));
     1814                    pEthHdr->DstMac = pIf->Mac;
     1815                    if ((void *)pEthHdr != pSG->aSegs[0].pv)
     1816                        intnetR0SgWritePart(pSG, RT_OFFSETOF(RTNETETHERHDR, DstMac), sizeof(RTMAC), &pIf->Mac);
     1817                }
     1818
     1819                fModified = true;
     1820            }
     1821        }
     1822    }
     1823#if 0 /** @todo IPv6 support, does it use ARP at all? */
     1824#endif
     1825    else
     1826        Log(("intnetR0TrunkIfSnoopArp: unknown ar_ptype=%#x\n", ar_ptype));
     1827
     1828    /*
     1829     * Write back the packet if we've been making changes
     1830     * to a buffered copy.
     1831     */
     1832    if (    (pSG->fFlags & INTNETSG_FLAGS_PKT_CP_IN_TMP)
     1833        && fModified)
     1834        intnetR0SgWritePart(pSG, sizeof(RTNETETHERHDR), cbPacket, pHdr);
     1835}
     1836
     1837
     1838/**
    16011839 * Sends a broadcast frame.
    16021840 *
     
    16121850 * @param   pEthHdr         Pointer to the ethernet header.
    16131851 */
    1614 static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr)
    1615 {
     1852static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, uint32_t fSrc,
     1853                                         PINTNETSG pSG, bool fTrunkLocked, PRTNETETHERHDR pEthHdr)
     1854{
     1855    /*
     1856     * Check for ARP packets from the wire since we'll have to make
     1857     * modification to them if we're sharing the MAC address with the host.
     1858     */
     1859    if (    (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
     1860        &&  (fSrc & INTNETTRUNKDIR_WIRE)
     1861        &&  RT_BE2H_U16(pEthHdr->EtherType) == RTNET_ETHERTYPE_ARP)
     1862        intnetR0NetworkEditArpFromWire(pNetwork, pSG, pEthHdr);
     1863
    16161864    /*
    16171865     * This is a broadcast or multicast address. For the present we treat those
     
    16311879    if (    pIfSender
    16321880        &&  pTrunkIf)
    1633         intnetR0TrunkIfSend(pTrunkIf, pNetwork, INTNETTRUNKDIR_HOST | INTNETTRUNKDIR_WIRE, pSG, fTrunkLocked);
     1881        intnetR0TrunkIfSend(pTrunkIf, pNetwork, pIfSender, INTNETTRUNKDIR_HOST | INTNETTRUNKDIR_WIRE, pSG, fTrunkLocked);
    16341882
    16351883    /*
     
    16421890        if (    (   EtherType == RTNET_ETHERTYPE_IPV4       /* for DHCP */
    16431891                 && pSG->cbTotal >= sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN)
    1644             ||  EtherType == RTNET_ETHERTYPE_ARP)
     1892            ||  (pSG->fFlags & (INTNETSG_FLAGS_ARP_IPV4)) )
    16451893            intnetR0TrunkIfSnoopAddr(pNetwork, pSG, EtherType);
    16461894    }
     
    16631911 * @param   pEthHdr         Pointer to the ethernet header.
    16641912 */
    1665 static bool intnetR0NetworkSendMulticast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, uint32_t fSrc, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr)
     1913static bool intnetR0NetworkSendMulticast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, uint32_t fSrc, PINTNETSG pSG, bool fTrunkLocked, PRTNETETHERHDR pEthHdr)
    16661914{
    16671915    /** @todo implement multicast */
    1668     return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked, pEthHdr);
     1916    return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, pEthHdr);
    16691917}
    16701918
     
    16821930 * @param   pEthHdr         Pointer to the ethernet header.
    16831931 */
    1684 static bool intnetR0NetworkSendUnicastWithSharedMac(PINTNETNETWORK pNetwork, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr)
     1932static bool intnetR0NetworkSendUnicastWithSharedMac(PINTNETNETWORK pNetwork, PINTNETSG pSG, bool fTrunkLocked, PRTNETETHERHDR pEthHdr)
    16851933{
    16861934    /*
     
    17341982        case RTNET_ETHERTYPE_ARP:
    17351983            Log6(("intnetshareduni: ARP\n"));
    1736             return intnetR0NetworkSendBroadcast(pNetwork, NULL, pSG, fTrunkLocked, pEthHdr);
     1984            return intnetR0NetworkSendBroadcast(pNetwork, NULL, INTNETTRUNKDIR_WIRE, pSG, fTrunkLocked, pEthHdr);
    17371985
    17381986        /*
     
    18282076        &&  pTrunkIf->pIfPort)
    18292077    {
     2078        Assert(!fSrc);
     2079
    18302080        /* promiscuous checks first as they are cheaper than pfnIsHostMac. */
    18312081        if (    pTrunkIf->fPromiscuousWire
     
    18462096
    18472097        if (fDst)
    1848             intnetR0TrunkIfSend(pTrunkIf, pNetwork, fDst, pSG, fTrunkLocked);
     2098            intnetR0TrunkIfSend(pTrunkIf, pNetwork, pIfSender, fDst, pSG, fTrunkLocked);
    18492099    }
    18502100
     
    19442194     * Distribute the frame.
    19452195     */
    1946     if (RT_UNLIKELY(EthHdr.DstMac.au8[0] & 1))      /* multicast address */
     2196    if (   EthHdr.DstMac.au16[0] == 0xffff              /* broadcast address. */
     2197        && EthHdr.DstMac.au16[1] == 0xffff
     2198        && EthHdr.DstMac.au16[2] == 0xffff)
     2199        fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);
     2200    else if (RT_UNLIKELY(EthHdr.DstMac.au8[0] & 1))     /* multicast address */
    19472201        fRc = intnetR0NetworkSendMulticast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);
    1948     else if (   EthHdr.DstMac.au16[0] == 0xffff     /* broadcast address. */
    1949              && EthHdr.DstMac.au16[1] == 0xffff
    1950              && EthHdr.DstMac.au16[2] == 0xffff)
    1951         fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked, &EthHdr);
    19522202    else if (   !(pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
    19532203             || !(fSrc & INTNETTRUNKDIR_WIRE))
     
    20562306            if (pvCurFrame)
    20572307            {
     2308                intnetR0SgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame);
    20582309                if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
    2059                     intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame);
    2060                 intnetR0SgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame);
     2310                    intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame, (uint16_t *)&Sg.fFlags);
    20612311                intnetR0NetworkSend(pNetwork, pIf, 0, &Sg, !!pTrunkIf);
    20622312            }
     
    32403490    //pTrunkIF->fPhysSG = false;
    32413491    //pTrunkIF->fPromiscuousWire = false;
     3492    pTrunkIF->CachedMac.au8[0] = 0xfe;
     3493    pTrunkIF->CachedMac.au8[1] = 0xff;
     3494    pTrunkIF->CachedMac.au8[2] = 0xff;
     3495    pTrunkIF->CachedMac.au8[3] = 0xff;
     3496    pTrunkIF->CachedMac.au8[4] = 0xff;
     3497    pTrunkIF->CachedMac.au8[5] = 0xff;
    32423498    int rc = RTSemFastMutexCreate(&pTrunkIF->FastMutex);
    32433499    if (RT_SUCCESS(rc))
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