VirtualBox

Changeset 11055 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Aug 1, 2008 1:29:38 AM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33950
Message:

intnet: Implemented the shared mac routing and started on the trunk address snooping.

File:
1 edited

Legend:

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

    r11053 r11055  
    271271
    272272
     273/**
     274 * Initializes a scatter / gather buffer from a simple linear buffer.
     275 *
     276 * @returns Pointer to the start of the frame.
     277 * @param   pSG         Pointer to the scatter / gather structure.
     278 *                      (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.)
     279 * @param   pvFrame     Pointer to the frame
     280 * @param   cbFrame     The size of the frame.
     281 */
     282DECLINLINE(void) intnetR0SgInitTemp(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame)
     283{
     284    pSG->pvOwnerData = NULL;
     285    pSG->pvUserData = NULL;
     286    pSG->pvUserData2 = NULL;
     287    pSG->cbTotal = cbFrame;
     288    pSG->cUsers = 1;
     289    pSG->fFlags = INTNETSG_FLAGS_TEMP;
     290    pSG->cSegsAlloc = 1;
     291    pSG->cSegsUsed = 1;
     292    pSG->aSegs[0].Phys = NIL_RTHCPHYS;
     293    pSG->aSegs[0].pv = pvFrame;
     294    pSG->aSegs[0].cb = cbFrame;
     295}
     296
     297
     298/**
     299 * Initializes a scatter / gather buffer from a internal networking packet.
     300 *
     301 * @returns Pointer to the start of the frame.
     302 * @param   pSG         Pointer to the scatter / gather structure.
     303 *                      (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.)
     304 * @param   pHdr        Pointer to the packet header.
     305 * @param   pBuf        The buffer the header is within. Only used in strict builds.
     306 */
     307DECLINLINE(void) intnetR0SgInitFromPkt(PINTNETSG pSG, PCINTNETHDR pPktHdr, PCINTNETBUF pBuf)
     308{
     309    pSG->cSegsUsed = 1;
     310    pSG->cbTotal = pSG->aSegs[0].cb = pPktHdr->cbFrame;
     311    pSG->aSegs[0].pv = INTNETHdrGetFramePtr(pPktHdr, pBuf);
     312    pSG->aSegs[0].Phys = NIL_RTHCPHYS;
     313}
     314
     315
     316/**
     317 * Reads a byte from a SG list.
     318 *
     319 * @returns The byte on success. 0xff on failure.
     320 * @param   pSG         The SG list to read.
     321 * @param   off         The offset (into the SG) off the byte.
     322 */
     323DECLINLINE(uint8_t) intnetR0SgReadByte(PCINTNETSG pSG, uint32_t off)
     324{
     325    if (RT_LIKELY(pSG->aSegs[0].cb > off))
     326        return ((uint8_t const *)pSG->aSegs[0].pv)[off];
     327
     328    unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);
     329    for (unsigned iSeg = 1; iSeg < cSegs; iSeg++)
     330    {
     331        if (pSG->aSegs[iSeg].cb > 0)
     332            return ((uint8_t const *)pSG->aSegs[iSeg].pv)[off];
     333        off -= pSG->aSegs[iSeg].cb;
     334    }
     335    return false;
     336}
     337
     338
     339/**
     340 * Worker for intnetR0SgReadPart that deals with the case where the
     341 * requested data isn't in the first segment.
     342 *
     343 * @returns true, unless the SG is invalid.
     344 * @param   pSG         The SG list to read.
     345 * @param   off         Where to start reading (offset into the SG).
     346 * @param   cb          How much to read.
     347 * @param   pvBuf       The buffer to read into.
     348 */
     349static bool intnetR0SgReadPartSlow(PCINTNETSG pSG, uint32_t off, uint32_t cb, void *pvBuf)
     350{
     351    if (RT_UNLIKELY(off + cb > pSG->cbTotal))
     352        return false;
     353
     354    /*
     355     * Skip ahead to the segment where off starts.
     356     */
     357    unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);
     358    unsigned iSeg = 0;
     359    while (off > pSG->aSegs[iSeg].cb)
     360    {
     361        off -= pSG->aSegs[iSeg++].cb;
     362        AssertReturn(iSeg < cSegs, false);
     363    }
     364
     365    /*
     366     * Copy the data, hoping that it's all from one segment...
     367     */
     368    uint32_t cbCanCopy = pSG->aSegs[iSeg].cb - off;
     369    if (cbCanCopy >= cb)
     370        memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cb);
     371    else
     372    {
     373        /* copy the portion in the current segment. */
     374        memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cbCanCopy);
     375        cb -= cbCanCopy;
     376
     377        /* copy the portions in the other segments. */
     378        do
     379        {
     380            pvBuf = (uint8_t *)pvBuf + cbCanCopy;
     381            iSeg++;
     382            AssertReturn(iSeg < cSegs, false);
     383
     384            cbCanCopy = RT_MIN(cb, pSG->aSegs[iSeg].cb);
     385            memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cbCanCopy);
     386
     387            cb -= cbCanCopy;
     388        } while (cb > 0);
     389    }
     390
     391    return true;
     392}
     393
     394
     395/**
     396 * Reads a part of an SG into a buffer.
     397 *
     398 * @returns true on success, false on failure (out of bounds).
     399 * @param   pSG         The SG list to read.
     400 * @param   off         Where to start reading (offset into the SG).
     401 * @param   cb          How much to read.
     402 * @param   pvBuf       The buffer to read into.
     403 */
     404DECLINLINE(bool) intnetR0SgReadPart(PCINTNETSG pSG, uint32_t off, uint32_t cb, void *pvBuf)
     405{
     406    Assert(off + cb > off);
     407
     408    /* The optimized case. */
     409    if (RT_LIKELY(    pSG->cSegsUsed == 1
     410                  ||  pSG->aSegs[0].cb >= off + cb))
     411    {
     412        Assert(pSG->cbTotal == pSG->aSegs[0].cb);
     413        memcpy(pvBuf, (uint8_t const *)pSG->aSegs[0].pv + off, cb);
     414        return true;
     415    }
     416    return intnetR0SgReadPartSlow(pSG, off, cb, pvBuf);
     417}
     418
     419
     420/**
     421 * Reads an entire SG into a fittingly size buffer.
     422 *
     423 * @param   pSG         The SG list to read.
     424 * @param   pvBuf       The buffer to read into (at least pSG->cbTotal in size).
     425 */
     426DECLINLINE(void) intnetR0SgRead(PCINTNETSG pSG, void *pvBuf)
     427{
     428    if (pSG->cSegsUsed == 1)
     429    {
     430        Assert(pSG->cbTotal == pSG->aSegs[0].cb);
     431        memcpy(pvBuf, pSG->aSegs[0].pv, pSG->cbTotal);
     432    }
     433    else
     434    {
     435        uint8_t       *pbDst = (uint8_t *)pvBuf;
     436        unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);
     437        for (unsigned iSeg = 0; iSeg < cSegs; iSeg++)
     438        {
     439            uint32_t cbSeg = pSG->aSegs[iSeg].cb;
     440            Assert(cbSeg <= pSG->cbTotal && (uintptr_t)(pbDst - (uint8_t *)pvBuf) + cbSeg <= pSG->cbTotal);
     441            memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg);
     442            pbDst += cbSeg;
     443        }
     444    }
     445}
     446
     447
     448
     449
     450
     451
    273452
    274453/**
     
    323502    return VINF_SUCCESS;
    324503}
     504
     505
     506
     507
    325508
    326509
     
    753936
    754937/**
    755  * Snoops IP assignments and releases from the DHCPv4 trafik.
    756  *
    757  * The caller is responsible for making sure this trafik between the
     938 * Snoops IP assignments and releases from the DHCPv4 traffic.
     939 *
     940 * The caller is responsible for making sure this traffic between the
    758941 * BOOTPS and BOOTPC ports and validate the IP header. The UDP packet
    759942 * need not be validated beyond the ports.
     
    766949 * @param   cbUdpPkt        What's left of the frame when starting at the UDP header.
    767950 */
    768 static void intnetR0NetworkSnoopDHCP(PINTNETNETWORK pNetwork, PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, uint32_t cbUdpPkt)
     951static void intnetR0NetworkSnoopDhcp(PINTNETNETWORK pNetwork, PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, uint32_t cbUdpPkt)
    769952{
    770953    /** @todo later */
     954}
     955
     956
     957static void intnetR0TrunkIfSnoopDhcp(PINTNETNETWORK pNetwork, PCINTNETSG pSG)
     958{
     959
     960}
     961
     962static void intnetR0TrunkIfSnoopArp(PINTNETNETWORK pNetwork, PCINTNETSG pSG)
     963{
     964
     965}
     966
     967
     968/**
     969 * Snoop up addresses from ARP and DHCP traffic from frames comming
     970 * over the trunk connection.
     971 *
     972 * The caller is responsible for do some basic filtering before calling
     973 * this function.
     974 * For IPv4 this means checking against the minimum DHCPv4 frame size.
     975 *
     976 * @param   pNetwork        The network.
     977 * @param   pSG             The SG list for the frame.
     978 * @param   EtherType       The Ethertype of the frame.
     979 */
     980static void intnetR0TrunkIfSnoopAddr(PINTNETNETWORK pNetwork, PCINTNETSG pSG, uint16_t EtherType)
     981{
     982    switch (EtherType)
     983    {
     984        case RTNET_ETHERTYPE_IPV4:
     985        {
     986            Assert(pSG->cbTotal >= sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN);
     987/** @todo optimize for the case where we can expect both the IP and UDP header to be in the first segment. */
     988
     989            /* check if the protocol is UDP */
     990            if (    intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + RT_OFFSETOF(RTNETIPV4, ip_p))
     991                !=  RTNETIPV4_PROT_UDP)
     992                return;
     993
     994            /* get the TCP header length */
     995            uint8_t b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + 0); /* (IPv4 first byte, a bitfield) */
     996            uint32_t cbIpHdr = (b & 0x0f) * 4;
     997            if (cbIpHdr < RTNETIPV4_MIN_LEN)
     998                return;
     999
     1000            /* get the lower byte of the UDP source port number. */
     1001            b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + cbIpHdr + RT_OFFSETOF(RTNETUDP, uh_sport) + 1);
     1002            if (    b != RTNETIPV4_PORT_BOOTPS
     1003                &&  b != RTNETIPV4_PORT_BOOTPC)
     1004                return;
     1005            b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + cbIpHdr + RT_OFFSETOF(RTNETUDP, uh_sport));
     1006            if (b)
     1007                return;
     1008            intnetR0TrunkIfSnoopDhcp(pNetwork, pSG);
     1009            break;
     1010        }
     1011
     1012        case RTNET_ETHERTYPE_ARP:
     1013            intnetR0TrunkIfSnoopArp(pNetwork, pSG);
     1014            break;
     1015    }
     1016    /** @todo soon */
    7711017}
    7721018
     
    7991045     * Ignore non good IP address (like broadcast and my network),
    8001046     * also skip packets containing address that are already in the
    801      * cache. Don't ignore potential DHCP trafik though.
     1047     * cache. Don't ignore potential DHCP traffic though.
    8021048     */
    8031049    bool fValidatedIpHdr = false;
     
    8331079            if (    fValidatedIpHdr
    8341080                ||  RTNetIPv4IsHdrValid(pIpHdr, cbPacket, cbPacket))
    835                 intnetR0NetworkSnoopDHCP(pIf->pNetwork, pIpHdr, pUdpHdr, cbPacket - cbHdr);
     1081                intnetR0NetworkSnoopDhcp(pIf->pNetwork, pIpHdr, pUdpHdr, cbPacket - cbHdr);
    8361082            else
    8371083                Log(("intnetR0IfSnoopIPv4SourceAddr: bad ip header (dhcp)\n"));
     
    8491095 *                          request 'cause of min ethernet frame size).
    8501096 */
    851 static void intnetR0IfSnoopArpSourceAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket)
     1097static void intnetR0IfSnoopArpAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket)
    8521098{
    8531099    /*
     
    9281174 * @param   cbFrame         The size of the frame.
    9291175 */
    930 static void intnetR0ISnoopSourceAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame)
     1176static void intnetR0IfSnoopAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame)
    9311177{
    9321178    /*
     
    9381184
    9391185    uint16_t EtherType = RT_H2BE_U16(((PCRTNETETHERHDR)pbFrame)->EtherType);
    940     if (EtherType == RTNET_ETHERTYPE_IPV4)
    941         intnetR0IfSnoopIPv4SourceAddr(pIf, (PCRTNETIPV4)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1186    switch (EtherType)
     1187    {
     1188        case RTNET_ETHERTYPE_IPV4:
     1189            intnetR0IfSnoopIPv4SourceAddr(pIf, (PCRTNETIPV4)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1190            break;
    9421191#if 0 /** @todo IntNet: implement IPv6 for wireless MAC sharing. */
    943     else if (EtherType == RTNET_ETHERTYPE_IPV6)
    944         intnetR0IfSnoopIPv6SourceAddr(pIf, (PCINTNETIPV6)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1192        case RTNET_ETHERTYPE_IPV6:
     1193            intnetR0IfSnoopIPv6SourceAddr(pIf, (PCINTNETIPV6)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1194            break;
    9451195#endif
    9461196#if 0 /** @todo IntNet: implement IPX for wireless MAC sharing? */
    947     else if (   EtherType == RT_H2BE_U16(0x8137) //??
    948              || EtherType == RT_H2BE_U16(0x8138) //??
    949              || EtherType == RT_H2BE_U16(0x8037) //??
    950              )
    951         intnetR0IfSnoopIpxSourceAddr(pIf, (PCINTNETIPX)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1197        case RTNET_ETHERTYPE_IPX_1:
     1198        case RTNET_ETHERTYPE_IPX_2:
     1199        case RTNET_ETHERTYPE_IPX_3:
     1200            intnetR0IfSnoopIpxSourceAddr(pIf, (PCINTNETIPX)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1201            break;
    9521202#endif
    953     else if (EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
    954         intnetR0IfSnoopArpSourceAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
    955 }
    956 
    957 
    958 /**
    959  * Initializes a scatter / gather buffer from a simple linear buffer.
    960  *
    961  * @returns Pointer to the start of the frame.
    962  * @param   pSG         Pointer to the scatter / gather structure.
    963  *                      (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.)
    964  * @param   pvFrame     Pointer to the frame
    965  * @param   cbFrame     The size of the frame.
    966  */
    967 DECLINLINE(void) intnetR0SgInitTemp(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame)
    968 {
    969     pSG->pvOwnerData = NULL;
    970     pSG->pvUserData = NULL;
    971     pSG->pvUserData2 = NULL;
    972     pSG->cbTotal = cbFrame;
    973     pSG->cUsers = 1;
    974     pSG->fFlags = INTNETSG_FLAGS_TEMP;
    975     pSG->cSegsAlloc = 1;
    976     pSG->cSegsUsed = 1;
    977     pSG->aSegs[0].Phys = NIL_RTHCPHYS;
    978     pSG->aSegs[0].pv = pvFrame;
    979     pSG->aSegs[0].cb = cbFrame;
    980 }
    981 
    982 
    983 /**
    984  * Initializes a scatter / gather buffer from a internal networking packet.
    985  *
    986  * @returns Pointer to the start of the frame.
    987  * @param   pSG         Pointer to the scatter / gather structure.
    988  *                      (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.)
    989  * @param   pHdr        Pointer to the packet header.
    990  * @param   pBuf        The buffer the header is within. Only used in strict builds.
    991  */
    992 DECLINLINE(void) intnetR0SgInitFromPkt(PINTNETSG pSG, PCINTNETHDR pPktHdr, PCINTNETBUF pBuf)
    993 {
    994     pSG->cSegsUsed = 1;
    995     pSG->cbTotal = pSG->aSegs[0].cb = pPktHdr->cbFrame;
    996     pSG->aSegs[0].pv = INTNETHdrGetFramePtr(pPktHdr, pBuf);
    997     pSG->aSegs[0].Phys = NIL_RTHCPHYS;
     1203        case RTNET_ETHERTYPE_ARP:
     1204            intnetR0IfSnoopArpAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     1205            break;
     1206    }
    9981207}
    9991208
     
    10311240}
    10321241#endif /* IN_INTNET_TESTCASE */
    1033 
    1034 
    1035 /**
    1036  * Reads an entire SG into a fittingly size buffer.
    1037  *
    1038  * @param   pSG         The SG list to read.
    1039  * @param   pvBuf       The buffer to read into (at least pSG->cbTotal in size).
    1040  */
    1041 DECLINLINE(void) intnetR0SgRead(PCINTNETSG pSG, void *pvBuf)
    1042 {
    1043     if (pSG->cSegsUsed == 1)
    1044     {
    1045         Assert(pSG->cbTotal == pSG->aSegs[0].cb);
    1046         memcpy(pvBuf, pSG->aSegs[0].pv, pSG->cbTotal);
    1047     }
    1048     else
    1049     {
    1050         uint8_t       *pbDst = (uint8_t *)pvBuf;
    1051         unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);
    1052         for (unsigned iSeg = 0; iSeg < cSegs; iSeg++)
    1053         {
    1054             uint32_t cbSeg = pSG->aSegs[iSeg].cb;
    1055             Assert(cbSeg <= pSG->cbTotal && (uintptr_t)(pbDst - (uint8_t *)pvBuf) + cbSeg <= pSG->cbTotal);
    1056             memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg);
    1057             pbDst += cbSeg;
    1058         }
    1059     }
    1060 }
    10611242
    10621243
     
    13081489 * @param   pSG             Pointer to the gather list.
    13091490 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
    1310  */
    1311 static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, PINTNETSG pSG, bool fTrunkLocked)
     1491 * @param   pEthHdr         Pointer to the ethernet header.
     1492 */
     1493static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr)
    13121494{
    13131495    /*
     
    13291511        &&  pTrunkIf)
    13301512        intnetR0TrunkIfSend(pTrunkIf, pNetwork, INTNETTRUNKDIR_HOST | INTNETTRUNKDIR_WIRE, pSG, fTrunkLocked);
     1513
     1514    /*
     1515     * Snoop address info from packet orginating from the trunk connection.
     1516     */
     1517    else if (   (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
     1518             && !pIfSender)
     1519    {
     1520        uint16_t EtherType = RT_BE2H_U16(pEthHdr->EtherType);
     1521        if (    (   EtherType == RTNET_ETHERTYPE_IPV4       /* for DHCP */
     1522                 && pSG->cbTotal >= RTNETBOOTP_DHCP_MIN_LEN)
     1523            ||  EtherType == RTNET_ETHERTYPE_ARP)
     1524            intnetR0TrunkIfSnoopAddr(pNetwork, pSG, EtherType);
     1525    }
     1526
    13311527    return false; /* broadcast frames are never dropped */
    13321528}
     
    13491545{
    13501546    /** @todo implement multicast */
    1351     return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked);
     1547    return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked, pEthHdr);
     1548}
     1549
     1550
     1551/**
     1552 * Sends a unicast frame using the network layer address instead
     1553 * of the link layer one.
     1554 *
     1555 * The caller must own the network mutex, might be abandond temporarily.
     1556 *
     1557 * @returns true if it's addressed to someone on the network, otherwise false.
     1558 * @param   pNetwork        The network the frame is being sent to.
     1559 * @param   pSG             Pointer to the gather list.
     1560 * @param   fTrunkLocked    Whether the caller owns the out-bound trunk lock.
     1561 * @param   pEthHdr         Pointer to the ethernet header.
     1562 */
     1563static bool intnetR0NetworkSendUnicastWithSharedMac(PINTNETNETWORK pNetwork, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr)
     1564{
     1565    /*
     1566     * Extract the network address from the packet.
     1567     */
     1568    RTNETADDRU      Addr;
     1569    INTNETADDRTYPE  enmAddrType;
     1570    uint8_t         cbAddr;
     1571    switch (RT_BE2H_U16(pEthHdr->EtherType))
     1572    {
     1573        case RTNET_ETHERTYPE_IPV4:
     1574            if (!intnetR0SgReadPart(pSG, RT_OFFSETOF(RTNETIPV4, ip_dst), sizeof(Addr.IPv4), &Addr))
     1575                return false;
     1576            enmAddrType = kIntNetAddrType_IPv4;
     1577            cbAddr = sizeof(Addr.IPv4);
     1578            break;
     1579
     1580#if 0 /** @todo IntNet: implement IPv6 for wireless MAC sharing. */
     1581        case RTNET_ETHERTYPE_IPV6
     1582            if (!intnetR0SgReadPart(pSG, RT_OFFSETOF(RTNETIPV6, ip6_dst), sizeof(Addr.IPv6), &Addr))
     1583                return false;
     1584            enmAddrType = kIntNetAddrType_IPv6;
     1585            cbAddr = sizeof(Addr.IPv6);
     1586            break;
     1587#endif
     1588#if 0 /** @todo IntNet: implement IPX for wireless MAC sharing? */
     1589        case RTNET_ETHERTYPE_IPX_1:
     1590        case RTNET_ETHERTYPE_IPX_2:
     1591        case RTNET_ETHERTYPE_IPX_3:
     1592            if (!intnetR0SgReadPart(pSG, RT_OFFSETOF(RTNETIPX, ipx_dstnet), sizeof(Addr.IPX), &Addr))
     1593                return false;
     1594            enmAddrType = kIntNetAddrType_IPX;
     1595            cbAddr = sizeof(Addr.IPX);
     1596            break;
     1597#endif
     1598
     1599        /*
     1600         * Treat ARP is broadcast (it shouldn't end up here normally,
     1601         * so it goes last in the switch).
     1602         */
     1603        case RTNET_ETHERTYPE_ARP:
     1604            return intnetR0NetworkSendBroadcast(pNetwork, NULL, pSG, fTrunkLocked, pEthHdr);
     1605
     1606        /*
     1607         * Unknown packets are sent do all interfaces that are in promiscuous mode.
     1608         */
     1609        default:
     1610        {
     1611            if (!(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC)))
     1612            {
     1613                for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
     1614                    if (pIf->fPromiscuous)
     1615                    {
     1616                        Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac));
     1617                        intnetR0IfSend(pIf, NULL, pSG);
     1618                    }
     1619            }
     1620            return false;
     1621        }
     1622    }
     1623
     1624    /*
     1625     * Send it to interfaces with matching network addresses.
     1626     */
     1627    bool fExactIntNetRecipient = false;
     1628    for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
     1629    {
     1630        bool fIt = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmAddrType], &Addr, cbAddr) >= 0;
     1631        if (    fIt
     1632            ||  (   pIf->fPromiscuous
     1633                 && !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))))
     1634        {
     1635            Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac));
     1636            fExactIntNetRecipient |= fIt;
     1637            intnetR0IfSend(pIf, NULL, pSG);
     1638        }
     1639    }
     1640
     1641    /*
     1642     * Perform DHCP snooping.
     1643     */
     1644    if (    enmAddrType == kIntNetAddrType_IPv4
     1645        &&  pSG->cbTotal >= RTNETBOOTP_DHCP_MIN_LEN)
     1646        intnetR0TrunkIfSnoopAddr(pNetwork, pSG, RT_BE2H_U16(pEthHdr->EtherType));
     1647
     1648    return fExactIntNetRecipient;
    13521649}
    13531650
     
    15191816             && EthHdr.DstMac.au16[1] == 0xffff
    15201817             && EthHdr.DstMac.au16[2] == 0xffff)
    1521         fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked);
     1818        fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked, &EthHdr);
     1819    else if (   !(pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
     1820             || !(fSrc & INTNETTRUNKDIR_WIRE))
     1821        fRc = intnetR0NetworkSendUnicast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);
    15221822    else
    1523         fRc = intnetR0NetworkSendUnicast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);
     1823        fRc = intnetR0NetworkSendUnicastWithSharedMac(pNetwork, pSG, fTrunkLocked, &EthHdr);
    15241824    return fRc;
    15251825}
     
    16241924            {
    16251925                if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
    1626                     intnetR0ISnoopSourceAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame);
     1926                    intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame);
    16271927                intnetR0SgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame);
    16281928                intnetR0NetworkSend(pNetwork, pIf, 0, &Sg, !!pTrunkIf);
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