VirtualBox

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


Ignore:
Timestamp:
Jul 31, 2008 11:22:56 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
33948
Message:

intnet: Finished ARP, IP and DHCP snooping in the INTNETR0IfSend path.

File:
1 edited

Legend:

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

    r10978 r11053  
    326326
    327327/**
     328 * Checks if the IPv4 address is a broadcast address.
     329 * @returns true/false.
     330 * @param   Addr        The address, network endian.
     331 */
     332DECLINLINE(bool) intnetR0IPv4AddrIsBroadcast(RTNETADDRIPV4 Addr)
     333{
     334    /* Just check for 255.255.255.255 atm. */
     335    return Addr.u == UINT32_MAX;
     336}
     337
     338
     339/**
     340 * Checks if the IPv4 address is a good interface address.
     341 * @returns true/false.
     342 * @param   Addr        The address, network endian.
     343 */
     344DECLINLINE(bool) intnetR0IPv4AddrIsGood(RTNETADDRIPV4 Addr)
     345{
     346    /* Usual suspects. */
     347    if (    Addr.u == UINT32_MAX    /* 255.255.255.255 - broadcast. */
     348        ||  Addr.au8[0] == 0)       /* Current network, can be used as source address. */
     349        return false;
     350
     351    /* Unusual suspects. */
     352    if (RT_UNLIKELY(     Addr.au8[0]        == 127  /* Loopback */
     353                    ||  (Addr.au8[0] & 0xf0 == 224) /* Multicast */
     354                    ))
     355        return false;
     356    return true;
     357}
     358
     359
     360/**
    328361 * Gets the address size of a network layer type.
    329362 *
     
    720753
    721754/**
     755 * Snoops IP assignments and releases from the DHCPv4 trafik.
     756 *
     757 * The caller is responsible for making sure this trafik between the
     758 * BOOTPS and BOOTPC ports and validate the IP header. The UDP packet
     759 * need not be validated beyond the ports.
     760 *
     761 * @param   pNetwork        The network this frame was seen on.
     762 * @param   pIpHdr          Pointer to a valid IP header. This is for pseudo
     763 *                          header validation, so only the minimum header size
     764 *                          needs to be available and valid here.
     765 * @param   pUdpHdr         Pointer to the UDP header in the frame.
     766 * @param   cbUdpPkt        What's left of the frame when starting at the UDP header.
     767 */
     768static void intnetR0NetworkSnoopDHCP(PINTNETNETWORK pNetwork, PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, uint32_t cbUdpPkt)
     769{
     770    /** @todo later */
     771}
     772
     773
     774/**
    722775 * Deals with an IPv4 packet.
    723776 *
     
    727780 *
    728781 * @param   pIf             The interface that's sending the frame.
    729  * @param   pHdr            Pointer to the IPv4 header in the frame.
     782 * @param   pIpHdr          Pointer to the IPv4 header in the frame.
    730783 * @param   cbPacket        The size of the packet, or more correctly the
    731784 *                          size of the frame without the ethernet header.
    732785 */
    733 static void intnetR0IfSniffIPv4SourceAddr(PINTNETIF pIf, PCRTNETIPV4 pHdr, uint32_t cbPacket)
    734 {
    735     /*
    736      * Check the header size.
    737      */
    738     if (cbPacket < RT_UOFFSETOF(RTNETIPV4, ip_options)) /** @todo check minimum size requirements here. */
     786static void intnetR0IfSnoopIPv4SourceAddr(PINTNETIF pIf, PCRTNETIPV4 pIpHdr, uint32_t cbPacket)
     787{
     788    /*
     789     * Check the header size first to prevent access invalid data.
     790     */
     791    if (cbPacket < RTNETIPV4_MIN_LEN)
    739792        return;
    740     uint32_t cbHdr = (uint32_t)pHdr->ip_hl * 4;
     793    uint32_t cbHdr = (uint32_t)pIpHdr->ip_hl * 4;
    741794    if (    cbHdr < RT_UOFFSETOF(RTNETIPV4, ip_options)
    742795        ||  cbPacket < cbHdr)
     
    744797
    745798    /*
    746      * Ignore 255.255.255.255 (broadcast), 0.0.0.0 (null) and already cached addresses.
    747      */
     799     * Ignore non good IP address (like broadcast and my network),
     800     * also skip packets containing address that are already in the
     801     * cache. Don't ignore potential DHCP trafik though.
     802     */
     803    bool fValidatedIpHdr = false;
    748804    RTNETADDRU Addr;
    749     Addr.IPv4 = pHdr->ip_src;
    750     if (Addr.au32[0] == UINT32_C(0xffffffff))
    751         return;
    752 
    753     int i = -1;
    754     if (    Addr.au32[0] == 0
    755         || (i = intnetR0IfAddrCacheLookupLikely(&pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(pHdr->ip_src))) >= 0)
    756     {
    757 #if 0 /** @todo quick DHCP check? */
    758         if (pHdr->ip_p != RTNETIPV4_PROT_UDP)
     805    Addr.IPv4 = pIpHdr->ip_src;
     806    if (    intnetR0IPv4AddrIsGood(Addr.IPv4)
     807        &&  intnetR0IfAddrCacheLookupLikely(&pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(Addr.IPv4)) < 0)
     808    {
     809        /*
     810         * Got a candidate, check that the IP header is valid before adding it.
     811         */
     812        if (!RTNetIPv4IsHdrValid(pIpHdr, cbPacket, cbPacket))
     813        {
     814            Log(("intnetR0IfSnoopIPv4SourceAddr: bad ip header\n"));
    759815            return;
    760 #endif
    761         return;
    762     }
    763 
    764     /*
    765      * Check the header checksum.
    766      */
    767     /** @todo IP checksumming */
    768 
    769     /*
    770      * Add the source address.
    771      */
    772     if (i < 0)
     816        }
    773817        intnetR0IfAddrCacheAddIt(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr);
    774 
    775     /*
    776      * Check for DHCP (properly this time).
    777      */
    778     /** @todo DHCPRELEASE request? */
    779 }
    780 
    781 
    782 
    783 /**
    784  * Sniff up source addresses from an ARP request or reply.
     818        fValidatedIpHdr = true;
     819    }
     820
     821    /*
     822     * Check for potential DHCP packets.
     823     */
     824    if (    pIpHdr->ip_p == RTNETIPV4_PROT_UDP                              /* DHCP is UDP. */
     825        &&  cbPacket >= cbHdr + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN) /* Min DHCP packet len */
     826    {
     827        PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint8_t const *)pIpHdr + cbHdr);
     828        if (    (   RT_BE2H_U16(pUdpHdr->uh_dport) == RTNETIPV4_PORT_BOOTPS
     829                 || RT_BE2H_U16(pUdpHdr->uh_sport) == RTNETIPV4_PORT_BOOTPS)
     830            &&  (   RT_BE2H_U16(pUdpHdr->uh_sport) == RTNETIPV4_PORT_BOOTPC
     831                 || RT_BE2H_U16(pUdpHdr->uh_dport) == RTNETIPV4_PORT_BOOTPC))
     832        {
     833            if (    fValidatedIpHdr
     834                ||  RTNetIPv4IsHdrValid(pIpHdr, cbPacket, cbPacket))
     835                intnetR0NetworkSnoopDHCP(pIf->pNetwork, pIpHdr, pUdpHdr, cbPacket - cbHdr);
     836            else
     837                Log(("intnetR0IfSnoopIPv4SourceAddr: bad ip header (dhcp)\n"));
     838        }
     839    }
     840}
     841
     842
     843/**
     844 * Snoop up source addresses from an ARP request or reply.
    785845 *
    786846 * @param   pIf             The interface that's sending the frame.
     
    789849 *                          request 'cause of min ethernet frame size).
    790850 */
    791 static void intnetR0IfSniffArpSourceAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket)
    792 {
    793     /*
    794      * Ignore malformed packets and packets which doesn't interrest us.
     851static void intnetR0IfSnoopArpSourceAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket)
     852{
     853    /*
     854     * Ignore malformed packets and packets which doesn't interest us.
    795855     */
    796856    if (RT_UNLIKELY(    cbPacket <= sizeof(*pHdr)
    797857                    ||  pHdr->ar_hlen != sizeof(PDMMAC)
    798                     ||  pHdr->ar_htype != RT_H2BE_U16(RTNET_ARP_ETHER)
    799                     ||  (   pHdr->ar_oper != RT_H2BE_U16(RTNET_ARPOP_REQUEST)
    800                          && pHdr->ar_oper != RT_H2BE_U16(RTNET_ARPOP_REPLY)
    801                          && pHdr->ar_oper != RT_H2BE_U16(RTNET_ARPOP_REVREQUEST)
    802                          && pHdr->ar_oper != RT_H2BE_U16(RTNET_ARPOP_REVREPLY)
    803                          /** @todo Read up on inverse ARP. */
    804                         )
    805                    )
    806        )
     858                    ||  pHdr->ar_htype != RT_H2BE_U16(RTNET_ARP_ETHER)))
    807859        return;
     860    uint16_t ar_oper = RT_H2BE_U16(pHdr->ar_oper);
     861    if (RT_UNLIKELY(    ar_oper != RTNET_ARPOP_REQUEST
     862                    &&  ar_oper != RTNET_ARPOP_REPLY
     863                    &&  ar_oper != RTNET_ARPOP_REVREQUEST
     864                    &&  ar_oper != RTNET_ARPOP_REVREPLY
     865                    /** @todo Read up on inverse ARP. */
     866                   ))
     867        return;
    808868
    809869    /*
     
    811871     */
    812872    RTNETADDRU Addr;
    813     if (pHdr->ar_ptype == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
     873    uint16_t ar_ptype = RT_H2BE_U16(pHdr->ar_ptype);
     874    if (ar_ptype == RTNET_ETHERTYPE_IPV4)
    814875    {
    815876        /*
     
    819880        if (RT_UNLIKELY(    pHdr->ar_plen == sizeof(pReq->ar_spa)
    820881                        ||  cbPacket < sizeof(*pReq)
    821                         ||  pReq->ar_spa.u == 0 /** @todo add an inline function for checking that an IP address is worth caching. */
    822                         ||  pReq->ar_spa.u == UINT32_C(0xffffffff)))
     882                        ||  !intnetR0IPv4AddrIsGood(pReq->ar_spa)))
    823883            return;
    824884
    825         if (RTNET_ARPOP_IS_REPLY(RT_BE2H_U16(pHdr->ar_oper)))
     885        if (    RTNET_ARPOP_IS_REPLY(RT_BE2H_U16(pHdr->ar_oper))
     886            &&  intnetR0IPv4AddrIsGood(pReq->ar_tpa))
    826887        {
    827888            Addr.IPv4 = pReq->ar_tpa;
     
    831892        intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(pReq->ar_spa));
    832893    }
    833     else if (pHdr->ar_ptype == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
     894#if 0 /** @todo IPv6 support */
     895    else if (ar_ptype == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
    834896    {
    835897        /*
     
    839901        if (RT_UNLIKELY(    pHdr->ar_plen == sizeof(pReq->ar_spa)
    840902                        ||  cbPacket < sizeof(*pReq)
    841                         /** @todo IPv6 ||  pReq->ar_spa.au32[0] == 0 or something
    842                         ||  pReq->ar_spa.au32[0] == UINT32_C(0xffffffff)*/))
     903                        ||  !intnetR0IPv6AddrIsGood(&pReq->ar_spa)))
    843904            return;
    844905
    845         if (RTNET_ARPOP_IS_REPLY(RT_BE2H_U16(pHdr->ar_oper)))
     906        if (    RTNET_ARPOP_IS_REPLY(RT_BE2H_U16(pHdr->ar_oper))
     907            &&  intnetR0IPv6AddrIsGood(&pReq->ar_tpa))
    846908        {
    847909            Addr.IPv6 = pReq->ar_tpa;
     
    851913        intnetR0IfAddrCacheAdd(pIf, &pIf->aAddrCache[kIntNetAddrType_IPv6], &Addr, sizeof(pReq->ar_spa));
    852914    }
     915#endif
    853916    else
    854         Log(("intnetR0IfSniffArpSourceAddr: unknown ar_ptype=%#x\n", RT_BE2H_U16(pHdr->ar_ptype)));
     917        Log(("intnetR0IfSnoopArpSourceAddr: unknown ar_ptype=%#x\n", ar_ptype));
    855918}
    856919
     
    865928 * @param   cbFrame         The size of the frame.
    866929 */
    867 static void intnetR0IfSniffSourceAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame)
     930static void intnetR0ISnoopSourceAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame)
    868931{
    869932    /*
     
    874937    cbFrame -= sizeof(RTNETETHERHDR);
    875938
    876     uint16_t EtherType = ((PCRTNETETHERHDR)pbFrame)->EtherType;
    877     if (EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV4))
    878         intnetR0IfSniffIPv4SourceAddr(pIf, (PCRTNETIPV4)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     939    uint16_t EtherType = RT_H2BE_U16(((PCRTNETETHERHDR)pbFrame)->EtherType);
     940    if (EtherType == RTNET_ETHERTYPE_IPV4)
     941        intnetR0IfSnoopIPv4SourceAddr(pIf, (PCRTNETIPV4)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
    879942#if 0 /** @todo IntNet: implement IPv6 for wireless MAC sharing. */
    880     else if (EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
    881         intnetR0IfSniffIPv6SourceAddr(pIf, (PCINTNETIPV6)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     943    else if (EtherType == RTNET_ETHERTYPE_IPV6)
     944        intnetR0IfSnoopIPv6SourceAddr(pIf, (PCINTNETIPV6)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
    882945#endif
    883946#if 0 /** @todo IntNet: implement IPX for wireless MAC sharing? */
    884     else if (   EtherType == RT_H2BE_U16(0x8037) //??
    885              || EtherType == RT_H2BE_U16(0x8137) //??
     947    else if (   EtherType == RT_H2BE_U16(0x8137) //??
    886948             || EtherType == RT_H2BE_U16(0x8138) //??
     949             || EtherType == RT_H2BE_U16(0x8037) //??
    887950             )
    888         intnetR0IfSniffIpxSourceAddr(pIf, (PCINTNETIPX)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     951        intnetR0IfSnoopIpxSourceAddr(pIf, (PCINTNETIPX)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
    889952#endif
    890953    else if (EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP))
    891         intnetR0IfSniffArpSourceAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
     954        intnetR0IfSnoopArpSourceAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);
    892955}
    893956
     
    15611624            {
    15621625                if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE)
    1563                     intnetR0IfSniffSourceAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame);
     1626                    intnetR0ISnoopSourceAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame);
    15641627                intnetR0SgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame);
    15651628                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