VirtualBox

Changeset 52543 in vbox


Ignore:
Timestamp:
Aug 31, 2014 11:48:41 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95798
Message:

IntNet: follow up to r85262 - refactor rewriting of link-level address
option in IPv6 Neighbor Discovery datagrams when bridging to wireless.

Ok bird@

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/net.h

    r52519 r52543  
    801801
    802802
    803 /** @todo add ICMPv6 when needed. */
     803/**
     804 * IPv6 ICMP packet header.
     805 */
     806#pragma pack(1)
     807typedef struct RTNETICMPV6HDR
     808{
     809    /** 00 - The ICMPv6 message type. */
     810    uint8_t         icmp6_type;
     811    /** 01 - Type specific code that further qualifies the message. */
     812    uint8_t         icmp6_code;
     813    /** 02 - Checksum of the ICMPv6 message. */
     814    uint16_t        icmp6_cksum;
     815} RTNETICMPV6HDR;
     816#pragma pack()
     817AssertCompileSize(RTNETICMPV6HDR, 4);
     818/** Pointer to an ICMPv6 packet header. */
     819typedef RTNETICMPV6HDR *PRTNETICMPV6HDR;
     820/** Pointer to a const ICMP packet header. */
     821typedef RTNETICMPV6HDR const *PCRTNETICMPV6HDR;
    804822
    805823#define RTNETIPV6_PROT_ICMPV6       (58)
    806 #define RTNETIPV6_ICMPV6_CODE_0     (0)
    807824
    808825/** @name Internet Control Message Protocol version 6 (ICMPv6) message types.
     
    815832/** @} */
    816833
    817 /** @deprecated */
    818 #define RTNETIPV6_ICMP_NS_TYPE      (RTNETIPV6_ICMP_TYPE_NS)
    819 /** @deprecated */
    820 #define RTNETIPV6_ICMP_NA_TYPE      (RTNETIPV6_ICMP_TYPE_NA)
    821 
     834/** @name Neighbor Discovery option types
     835 * @{ */
    822836#define RTNETIPV6_ICMP_ND_SLLA_OPT  (1)
    823837#define RTNETIPV6_ICMP_ND_TLLA_OPT  (2)
    824 #define RTNETIPV6_ICMP_ND_LLA_LEN   (1)
    825 
    826 /** ICMPv6 ND Source Link Layer Address option */
    827 #pragma pack(1)
    828 typedef struct RTNETNDP_SLLA_OPT
     838/** @} */
     839
     840/** ICMPv6 ND Source/Target Link Layer Address option */
     841#pragma pack(1)
     842typedef struct RTNETNDP_LLA_OPT
    829843{
    830844    uint8_t type;
    831845    uint8_t len;
    832     RTMAC slla;
    833 } RTNETNDP_SLLA_OPT;
    834 #pragma pack()
    835 
    836 AssertCompileSize(RTNETNDP_SLLA_OPT, 1+1+6);
    837 
    838 typedef RTNETNDP_SLLA_OPT *PRTNETNDP_SLLA_OPT;
    839 typedef RTNETNDP_SLLA_OPT const *PCRTNETNDP_SLLA_OPT;
     846    RTMAC lla;
     847} RTNETNDP_LLA_OPT;
     848#pragma pack()
     849
     850AssertCompileSize(RTNETNDP_LLA_OPT, 1+1+6);
     851
     852typedef RTNETNDP_LLA_OPT *PRTNETNDP_LLA_OPT;
     853typedef RTNETNDP_LLA_OPT const *PCRTNETNDP_LLA_OPT;
    840854
    841855/** ICMPv6 ND Neighbor Sollicitation */
     
    843857typedef struct RTNETNDP
    844858{
    845     /** ICMPv6 type. */
    846     uint8_t icmp6_type;
    847     /** ICMPv6 code. */
    848     uint8_t icmp6_code;
    849     /** ICMPv6 checksum */
    850     uint16_t icmp6_cksum;
    851     /** reserved */
     859    /** 00 - The ICMPv6 header. */
     860    RTNETICMPV6HDR Hdr;
     861    /** 04 - reserved */
    852862    uint32_t reserved;
    853     /** target address */
     863    /** 08 - target address */
    854864    RTNETADDRIPV6 target_address;
    855865} RTNETNDP;
    856866#pragma pack()
    857 AssertCompileSize(RTNETNDP, 1+1+2+4+16);
     867AssertCompileSize(RTNETNDP, 4+4+16);
    858868/** Pointer to a NDP ND packet. */
    859869typedef RTNETNDP *PRTNETNDP;
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r52518 r52543  
    28092809}
    28102810
     2811
     2812/**
     2813 * Rewrite VM MAC address with shared host MAC address inside IPv6
     2814 * Neighbor Discovery datagrams.
     2815 */
     2816static void intnetR0TrunkSharedMacEditIPv6FromIntNet(PINTNETTRUNKIF pThis, PINTNETIF pIfSender,
     2817                                                     PRTNETETHERHDR pEthHdr, uint32_t cb)
     2818{
     2819    if (RT_UNLIKELY(cb < sizeof(*pEthHdr)))
     2820        return;
     2821
     2822    /* have IPv6 header */
     2823    PRTNETIPV6 pIPv6 = (PRTNETIPV6)(pEthHdr + 1);
     2824    cb -= sizeof(*pEthHdr);
     2825    if (RT_UNLIKELY(cb < sizeof(*pIPv6)))
     2826        return;
     2827
     2828    if (   pIPv6->ip6_nxt  != RTNETIPV6_PROT_ICMPV6
     2829        || pIPv6->ip6_hlim != 0xff)
     2830        return;
     2831
     2832    PRTNETICMPV6HDR pICMPv6 = (PRTNETICMPV6HDR)(pIPv6 + 1);
     2833    cb -= sizeof(*pIPv6);
     2834    if (RT_UNLIKELY(cb < sizeof(*pICMPv6)))
     2835        return;
     2836
     2837    size_t hdrlen = 0;
     2838    uint8_t llaopt = RTNETIPV6_ICMP_ND_SLLA_OPT;
     2839
     2840    uint8_t type = pICMPv6->icmp6_type;
     2841    switch (type)
     2842    {
     2843        case RTNETIPV6_ICMP_TYPE_RS:
     2844            hdrlen = 8;
     2845            break;
     2846
     2847        case RTNETIPV6_ICMP_TYPE_RA:
     2848            hdrlen = 16;
     2849            break;
     2850
     2851        case RTNETIPV6_ICMP_TYPE_NS:
     2852            hdrlen = 24;
     2853            break;
     2854
     2855        case RTNETIPV6_ICMP_TYPE_NA:
     2856            hdrlen = 24;
     2857            llaopt = RTNETIPV6_ICMP_ND_TLLA_OPT;
     2858            break;
     2859
     2860        default:
     2861            return;
     2862    }
     2863
     2864    AssertReturnVoid(hdrlen > 0);
     2865    if (RT_UNLIKELY(cb < hdrlen))
     2866        return;
     2867
     2868    if (RT_UNLIKELY(pICMPv6->icmp6_code != 0))
     2869        return;
     2870
     2871    PRTNETNDP_LLA_OPT pLLAOpt = NULL;
     2872    char *pOpt = (char *)pICMPv6 + hdrlen;
     2873    cb -= hdrlen;
     2874
     2875    while (cb >= 8)
     2876    {
     2877        uint8_t opt = ((uint8_t *)pOpt)[0];
     2878        size_t optlen = (size_t)((uint8_t *)pOpt)[1] * 8;
     2879        if (RT_UNLIKELY(cb < optlen))
     2880            return;
     2881
     2882        if (opt == llaopt)
     2883        {
     2884            if (RT_UNLIKELY(optlen != 8))
     2885                return;
     2886            pLLAOpt = (PRTNETNDP_LLA_OPT)pOpt;
     2887            break;
     2888        }
     2889
     2890        pOpt += optlen;
     2891        cb -= optlen;
     2892    }
     2893
     2894    if (pLLAOpt == NULL)
     2895        return;
     2896
     2897    if (memcmp(&pLLAOpt->lla, &pIfSender->MacAddr, sizeof(RTMAC)) != 0)
     2898        return;
     2899
     2900    /* overwrite VM's MAC with host's MAC */
     2901    pLLAOpt->lla = pThis->MacAddr;
     2902
     2903    /* recompute the checksum */
     2904    pICMPv6->icmp6_cksum = 0;
     2905    pICMPv6->icmp6_cksum = computeIPv6FullChecksum(pIPv6);
     2906}
     2907
     2908
    28112909/**
    28122910 * Sends a frame down the trunk.
     
    28882986            }
    28892987        }
    2890         else if (pEthHdr->EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_IPV6))
     2988        else if (pEthHdr->EtherType == RT_H2N_U16_C(RTNET_ETHERTYPE_IPV6))
    28912989        {
    2892             /*
    2893              * IPV6 ICMP Neighbor Discovery : replace
    2894              * 1) the advertised source mac address in outgoing neighbor sollicitations
    2895              *    with the HW MAC address of the trunk interface,
    2896              * 2) the advertised target mac address in outgoing neighbor advertisements
    2897              *    with the HW mac address of the trunk interface.
    2898              *
    2899              * Note that this only applies to traffic going out on the trunk. Incoming
    2900              * NS/NA will never advertise any VM mac address, so we do not need to touch
    2901              * them. Other VMs on this bridge as well as the host will see and use the VM's
    2902              * actual mac addresses.
    2903              *
    2904              */
    2905 
    2906             PRTNETIPV6 pIPv6            = (PRTNETIPV6)(pEthHdr + 1);
    2907             PRTNETNDP pNd               = (PRTNETNDP)(pIPv6 + 1);
    2908             PRTNETNDP_SLLA_OPT pLLAOpt  = (PRTNETNDP_SLLA_OPT)(pNd + 1);
    2909 
    2910             /* make sure we have enough bytes to work with */
    2911             if(pSG->cbTotal >= (RTNETIPV6_MIN_LEN + RTNETIPV6_ICMPV6_ND_WITH_LLA_OPT_MIN_LEN) &&
    2912                /* ensure the packet came from our LAN (not gone through any router) */
    2913                pIPv6->ip6_hlim == 0xff &&
    2914                /* protocol has to be icmpv6 */
    2915                 pIPv6->ip6_nxt == RTNETIPV6_PROT_ICMPV6 &&
    2916                /* we either have a sollicitation with source link layer addr. opt, or */
    2917                 ((pNd->icmp6_type == RTNETIPV6_ICMP_NS_TYPE &&
    2918                             pNd->icmp6_code == RTNETIPV6_ICMPV6_CODE_0 &&
    2919                             pLLAOpt->type == RTNETIPV6_ICMP_ND_SLLA_OPT) ||
    2920                  /* an advertisement with target link layer addr. option */
    2921                 ((pNd->icmp6_type == RTNETIPV6_ICMP_NA_TYPE &&
    2922                             pNd->icmp6_code == RTNETIPV6_ICMPV6_CODE_0 &&
    2923                             pLLAOpt->type == RTNETIPV6_ICMP_ND_TLLA_OPT)) ) &&
    2924                 pLLAOpt->len == RTNETIPV6_ICMP_ND_LLA_LEN)
    2925             {
    2926                 /* swap the advertised VM MAC address with the trunk's */
    2927                 pLLAOpt->slla   = pThis->MacAddr;
    2928 
    2929                 /* recompute the checksum since we changed the packet */
    2930                 pNd->icmp6_cksum = 0;
    2931                 pNd->icmp6_cksum = computeIPv6FullChecksum(pIPv6);
    2932             }
    2933 
     2990            intnetR0TrunkSharedMacEditIPv6FromIntNet(pThis, pIfSender, pEthHdr, pSG->cbTotal);
    29342991        }
    29352992    }
    29362993
    29372994    /*
    2938      * Send the frame, handling the GSO fallback                                                                                           .
    2939      *                                                                                                                                     .
    2940      * Note! The trunk implementation will re-check that the trunk is active                                                               .
     2995     * Send the frame, handling the GSO fallback.
     2996     *
     2997     * Note! The trunk implementation will re-check that the trunk is active
    29412998     *       before sending, so we don't have to duplicate that effort here.
    29422999     */
     
    30993156    if (    pIPv6->ip6_hlim == 0xff
    31003157        &&  pIPv6->ip6_nxt  == RTNETIPV6_PROT_ICMPV6
    3101         &&  pNd->icmp6_type == RTNETIPV6_ICMP_NS_TYPE
    3102         &&  pNd->icmp6_code == RTNETIPV6_ICMPV6_CODE_0
     3158        &&  pNd->Hdr.icmp6_type == RTNETIPV6_ICMP_TYPE_NS
     3159        &&  pNd->Hdr.icmp6_code == 0
    31033160        &&  pIPv6->ip6_src.QWords.qw0 == 0
    31043161        &&  pIPv6->ip6_src.QWords.qw1 == 0)
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